From a2b4847ca404d1157a85f2353e9ff8a6cbec3548 Mon Sep 17 00:00:00 2001 From: Pim Hutting Date: Thu, 8 Jan 2026 09:54:48 +0100 Subject: [PATCH] Merge remote-tracking branch 'origin/demo' into feat/monitoringpage-pim --- package-lock.json | 13 +- package.json | 1 + src/components/MultilineTextField.tsx | 75 +++ src/components/TextField.module.css | 12 + src/components/TextField.tsx | 2 +- src/index.css | 13 + src/pages/MonitoringPage/Components.tsx | 60 +- src/pages/MonitoringPage/MonitoringPage.tsx | 118 +++- src/pages/MonitoringPage/MonitoringPageAPI.ts | 17 +- src/pages/VisProgPage/VisProg.module.css | 6 + src/pages/VisProgPage/VisProg.tsx | 7 +- .../visualProgrammingUI/HandleRuleLogic.ts | 110 ++++ .../visualProgrammingUI/HandleRules.ts | 45 ++ .../visualProgrammingUI/VisProgStores.tsx | 106 ++- .../visualProgrammingUI/VisProgTypes.tsx | 45 +- .../components/CustomNodeHandles.tsx | 30 - .../components/DragDropSidebar.tsx | 16 +- .../components/GestureValueEditor.module.css | 164 +++++ .../components/GestureValueEditor.tsx | 611 ++++++++++++++++++ .../components/Plan.default.ts | 7 + .../visualProgrammingUI/components/Plan.tsx | 101 +++ .../components/PlanEditor.module.css | 71 ++ .../components/PlanEditor.tsx | 243 +++++++ .../components/RuleBasedHandle.module.css | 34 + .../components/RuleBasedHandle.tsx | 88 +++ .../nodes/BasicBeliefNode.default.ts | 2 +- .../nodes/BasicBeliefNode.tsx | 52 +- .../visualProgrammingUI/nodes/EndNode.tsx | 14 +- .../nodes/GoalNode.default.ts | 4 +- .../visualProgrammingUI/nodes/GoalNode.tsx | 76 ++- .../nodes/NormNode.default.ts | 2 +- .../visualProgrammingUI/nodes/NormNode.tsx | 50 +- .../visualProgrammingUI/nodes/PhaseNode.tsx | 34 +- .../visualProgrammingUI/nodes/StartNode.tsx | 13 +- .../nodes/TriggerNode.default.ts | 2 - .../visualProgrammingUI/nodes/TriggerNode.tsx | 174 ++--- .../HandleRuleLogic.test.ts | 86 +++ .../visualProgrammingUI/HandleRules.test.ts | 84 +++ .../VisProgStores.test.tsx | 46 +- .../components/DragDropSidebar.test.tsx | 6 +- .../components/GestureValueEditor.test.tsx | 132 ++++ .../components/PlanEditor.test.tsx | 505 +++++++++++++++ .../nodes/BeliefNode.test.tsx | 19 +- .../nodes/NormNode.test.tsx | 41 +- .../nodes/PhaseNode.test.tsx | 6 +- .../nodes/TriggerNode.test.tsx | 200 ++---- .../nodes/UniversalNodes.test.tsx | 2 +- test/setupFlowTests.ts | 20 +- 48 files changed, 3038 insertions(+), 527 deletions(-) create mode 100644 src/components/MultilineTextField.tsx create mode 100644 src/pages/VisProgPage/visualProgrammingUI/HandleRuleLogic.ts create mode 100644 src/pages/VisProgPage/visualProgrammingUI/HandleRules.ts delete mode 100644 src/pages/VisProgPage/visualProgrammingUI/components/CustomNodeHandles.tsx create mode 100644 src/pages/VisProgPage/visualProgrammingUI/components/GestureValueEditor.module.css create mode 100644 src/pages/VisProgPage/visualProgrammingUI/components/GestureValueEditor.tsx create mode 100644 src/pages/VisProgPage/visualProgrammingUI/components/Plan.default.ts create mode 100644 src/pages/VisProgPage/visualProgrammingUI/components/Plan.tsx create mode 100644 src/pages/VisProgPage/visualProgrammingUI/components/PlanEditor.module.css create mode 100644 src/pages/VisProgPage/visualProgrammingUI/components/PlanEditor.tsx create mode 100644 src/pages/VisProgPage/visualProgrammingUI/components/RuleBasedHandle.module.css create mode 100644 src/pages/VisProgPage/visualProgrammingUI/components/RuleBasedHandle.tsx create mode 100644 test/pages/visProgPage/visualProgrammingUI/HandleRuleLogic.test.ts create mode 100644 test/pages/visProgPage/visualProgrammingUI/HandleRules.test.ts create mode 100644 test/pages/visProgPage/visualProgrammingUI/components/GestureValueEditor.test.tsx create mode 100644 test/pages/visProgPage/visualProgrammingUI/components/PlanEditor.test.tsx diff --git a/package-lock.json b/package-lock.json index b225239..a52343e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -24,6 +24,7 @@ "@types/react": "^19.1.13", "@types/react-dom": "^19.1.9", "@vitejs/plugin-react": "^5.0.3", + "baseline-browser-mapping": "^2.9.11", "eslint": "^9.36.0", "eslint-plugin-react-hooks": "^5.2.0", "eslint-plugin-react-refresh": "^0.4.20", @@ -3698,9 +3699,9 @@ "license": "MIT" }, "node_modules/baseline-browser-mapping": { - "version": "2.8.6", - "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.8.6.tgz", - "integrity": "sha512-wrH5NNqren/QMtKUEEJf7z86YjfqW/2uw3IL3/xpqZUC95SSVIFXYQeeGjL6FT/X68IROu6RMehZQS5foy2BXw==", + "version": "2.9.11", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.9.11.tgz", + "integrity": "sha512-Sg0xJUNDU1sJNGdfGWhVHX0kkZ+HWcvmVymJbj6NSgZZmW/8S9Y2HQ5euytnIgakgxN6papOAWiwDo1ctFDcoQ==", "dev": true, "license": "Apache-2.0", "bin": { @@ -4869,9 +4870,9 @@ } }, "node_modules/glob": { - "version": "10.4.5", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", - "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz", + "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==", "dev": true, "license": "ISC", "dependencies": { diff --git a/package.json b/package.json index cd08dca..45f66df 100644 --- a/package.json +++ b/package.json @@ -28,6 +28,7 @@ "@types/react": "^19.1.13", "@types/react-dom": "^19.1.9", "@vitejs/plugin-react": "^5.0.3", + "baseline-browser-mapping": "^2.9.11", "eslint": "^9.36.0", "eslint-plugin-react-hooks": "^5.2.0", "eslint-plugin-react-refresh": "^0.4.20", diff --git a/src/components/MultilineTextField.tsx b/src/components/MultilineTextField.tsx new file mode 100644 index 0000000..ad88513 --- /dev/null +++ b/src/components/MultilineTextField.tsx @@ -0,0 +1,75 @@ +import { useEffect, useRef, useState } from "react"; +import styles from "./TextField.module.css"; + +export function MultilineTextField({ + value = "", + setValue, + placeholder, + className, + id, + ariaLabel, + invalid = false, + minRows = 3, +}: { + value: string; + setValue: (value: string) => void; + placeholder?: string; + className?: string; + id?: string; + ariaLabel?: string; + invalid?: boolean; + minRows?: number; +}) { + const [readOnly, setReadOnly] = useState(true); + const [inputValue, setInputValue] = useState(value); + const textareaRef = useRef(null); + + useEffect(() => { + setInputValue(value); + }, [value]); + + // Auto-grow logic + useEffect(() => { + const el = textareaRef.current; + if (!el) return; + + el.style.height = "auto"; + el.style.height = `${el.scrollHeight}px`; + }, [inputValue]); + + const onCommit = () => { + setReadOnly(true); + setValue(inputValue); + }; + + const onKeyDown = (e: React.KeyboardEvent) => { + if (e.key === "Enter" && (e.ctrlKey || e.metaKey)) { + e.preventDefault(); + (e.target as HTMLTextAreaElement).blur(); + } + }; + + return ( +