@kiberon-labs/behave-graph-flow 1.0.0 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.fallowrc.json +16 -0
- package/.storybook/main.ts +32 -0
- package/.storybook/manager.ts +6 -0
- package/.storybook/preview.ts +64 -0
- package/.storybook/styles.css +16 -0
- package/.turbo/turbo-build.log +7 -0
- package/CHANGELOG.md +368 -0
- package/LICENSE +6 -0
- package/README.md +2 -2
- package/data/Polynomial.json +510 -0
- package/data/sequence.json +337 -0
- package/data/trigger-event.json +241 -0
- package/data/variable-change.json +210 -0
- package/dist/AnyControlImpl-Ds-CShIB.js +20 -0
- package/dist/AnyControlImpl-Ds-CShIB.js.map +1 -0
- package/dist/DocumentationBrowserPanelImpl-deZNzFX8.js +166 -0
- package/dist/DocumentationBrowserPanelImpl-deZNzFX8.js.map +1 -0
- package/dist/entry.css +4 -0
- package/dist/index.css +42 -0
- package/dist/index.css.map +1 -0
- package/dist/index.d.ts +3597 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +18009 -0
- package/dist/index.js.map +1 -0
- package/dist/noteImpl-KkrrWgJd.js +242 -0
- package/dist/noteImpl-KkrrWgJd.js.map +1 -0
- package/dist/styles.module-CvmpDkZj.css +3 -0
- package/dist/styles.module-CvmpDkZj.css.map +1 -0
- package/dist/styles.module-DZxg8aW9.js +271 -0
- package/dist/styles.module-DZxg8aW9.js.map +1 -0
- package/dist/useChangeNodeData-ChQGK7AI.js +23 -0
- package/dist/useChangeNodeData-ChQGK7AI.js.map +1 -0
- package/docs/notifications.md +246 -0
- package/docs/protocol.md +702 -0
- package/docs/specifics.md +191 -0
- package/package.json +82 -22
- package/postcss.config.ts +3 -4
- package/src/annotations/index.ts +32 -0
- package/src/components/FloatingToolbar/index.module.css +37 -0
- package/src/components/FloatingToolbar/index.tsx +256 -0
- package/src/components/Flow.tsx +287 -75
- package/src/components/contextMenus/DynamicContextMenu.tsx +85 -0
- package/src/components/contextMenus/NodePicker.module.css +274 -0
- package/src/components/contextMenus/NodePicker.tsx +481 -0
- package/src/components/contextMenus/edge.tsx +22 -0
- package/src/components/contextMenus/node.tsx +15 -0
- package/src/components/contextMenus/selection.tsx +11 -0
- package/src/components/controls/any/AnyControlImpl.tsx +14 -0
- package/src/components/controls/any/index.tsx +19 -0
- package/src/components/controls/boolean/index.tsx +13 -0
- package/src/components/controls/colorPicker/InputPopover.module.css +100 -0
- package/src/components/controls/colorPicker/InputPopover.tsx +31 -0
- package/src/components/controls/colorPicker/index.module.css +18 -0
- package/src/components/controls/colorPicker/index.tsx +61 -0
- package/src/components/controls/number/index.tsx +35 -0
- package/src/components/controls/string/index.tsx +16 -0
- package/src/components/edges/index.tsx +475 -0
- package/src/components/edges/offsetBezier.ts +134 -0
- package/src/components/hotKeys.tsx +20 -0
- package/src/components/layoutController/index.module.css +13 -0
- package/src/components/layoutController/index.tsx +140 -0
- package/src/components/layoutController/utils.ts +248 -0
- package/src/components/menubar/defaults.tsx +516 -0
- package/src/components/menubar/index.tsx +49 -0
- package/src/components/menubar/menuItem.module.css +31 -0
- package/src/components/menubar/menuItem.tsx +65 -0
- package/src/components/nodes/behave/Node.module.css +23 -0
- package/src/components/nodes/behave/Node.tsx +176 -0
- package/src/components/nodes/behave/NodeContainer.module.css +88 -0
- package/src/components/nodes/behave/NodeContainer.tsx +46 -0
- package/src/components/nodes/behave/index.tsx +14 -0
- package/src/components/nodes/group/index.tsx +109 -0
- package/src/components/nodes/wrapper/index.tsx +73 -0
- package/src/components/nodes/wrapper/styles.module.css +87 -0
- package/src/components/notifications/NotificationProvider.tsx +81 -0
- package/src/components/notifications/index.ts +2 -0
- package/src/components/notifications/utils.ts +71 -0
- package/src/components/panels/alignment/index.module.css +10 -0
- package/src/components/panels/alignment/index.tsx +244 -0
- package/src/components/panels/base/index.tsx +5 -0
- package/src/components/panels/base/styles.module.css +12 -0
- package/src/components/panels/common/PanelHeader.module.css +24 -0
- package/src/components/panels/common/PanelHeader.tsx +22 -0
- package/src/components/panels/common/SectionTitle.module.css +13 -0
- package/src/components/panels/common/SectionTitle.tsx +10 -0
- package/src/components/panels/events/EditEventPanel.tsx +324 -0
- package/src/components/panels/events/ManageEventsPanel.tsx +101 -0
- package/src/components/panels/events/index.tsx +23 -0
- package/src/components/panels/events/styles.module.css +178 -0
- package/src/components/panels/graphProperties/index.tsx +125 -0
- package/src/components/panels/history/index.tsx +92 -0
- package/src/components/panels/history/styles.module.css +97 -0
- package/src/components/panels/keymaps/index.module.css +68 -0
- package/src/components/panels/keymaps/index.tsx +166 -0
- package/src/components/panels/layers/index.tsx +245 -0
- package/src/components/panels/layers/styles.module.css +107 -0
- package/src/components/panels/legend/index.module.css +6 -0
- package/src/components/panels/legend/index.tsx +76 -0
- package/src/components/panels/logs/index.module.css +218 -0
- package/src/components/panels/logs/index.tsx +288 -0
- package/src/components/panels/nodeInputs/InputControl.tsx +63 -0
- package/src/components/panels/nodeInputs/InputsGroup.tsx +65 -0
- package/src/components/panels/nodeInputs/MultipleNodesView.tsx +37 -0
- package/src/components/panels/nodeInputs/NodeSettings.tsx +92 -0
- package/src/components/panels/nodeInputs/NodeTitleEditor.tsx +125 -0
- package/src/components/panels/nodeInputs/OutputsGroup.tsx +55 -0
- package/src/components/panels/nodeInputs/SocketGenerators.tsx +32 -0
- package/src/components/panels/nodeInputs/index.module.css +308 -0
- package/src/components/panels/nodeInputs/index.tsx +349 -0
- package/src/components/panels/nodeInputs/useNodeHandlers.ts +76 -0
- package/src/components/panels/nodeInputs/useNodeInputsData.ts +153 -0
- package/src/components/panels/nodePicker/index.tsx +115 -0
- package/src/components/panels/panel/index.module.css +66 -0
- package/src/components/panels/panel/index.tsx +88 -0
- package/src/components/panels/search/index.module.css +16 -0
- package/src/components/panels/search/index.tsx +215 -0
- package/src/components/panels/systemSettings/ConversionsSettings.tsx +203 -0
- package/src/components/panels/systemSettings/index.tsx +251 -0
- package/src/components/panels/systemSettings/styles.module.css +138 -0
- package/src/components/panels/traces/GridLines.tsx +38 -0
- package/src/components/panels/traces/TimeGrid.tsx +48 -0
- package/src/components/panels/traces/TraceLane.tsx +62 -0
- package/src/components/panels/traces/TraceTooltip.tsx +22 -0
- package/src/components/panels/traces/TracesHeader.tsx +56 -0
- package/src/components/panels/traces/index.module.css +159 -0
- package/src/components/panels/traces/index.tsx +298 -0
- package/src/components/panels/traces/types.ts +48 -0
- package/src/components/panels/traces/useDerivedSpans.ts +307 -0
- package/src/components/panels/traces/utils.ts +33 -0
- package/src/components/panels/variables/CreateVariableScreen.tsx +162 -0
- package/src/components/panels/variables/ManageVariablesScreen.tsx +147 -0
- package/src/components/panels/variables/index.tsx +125 -0
- package/src/components/panels/variables/styles.module.css +149 -0
- package/src/components/primitives/icon.module.css +45 -0
- package/src/components/primitives/icon.tsx +38 -0
- package/src/components/sockets/input/index.tsx +83 -0
- package/src/components/sockets/input/styles.module.css +26 -0
- package/src/components/sockets/output/index.tsx +68 -0
- package/src/components/sockets/output/styles.module.css +22 -0
- package/src/css/notes.css +135 -0
- package/src/css/prosemirror.css +57 -0
- package/src/css/rc-dock.css +212 -0
- package/src/css/rc-menu.css +101 -0
- package/src/css/themes/kiberon.css +127 -0
- package/src/css/vars.css +198 -0
- package/src/css/vscode-elements.css +124 -0
- package/src/entry.css +4 -0
- package/src/generators/CallSubgraphGenerator.tsx +136 -0
- package/src/generators/CustomEventOnTriggeredGenerator.tsx +85 -0
- package/src/generators/GraphBoundaryGenerator.module.css +32 -0
- package/src/generators/GraphBoundaryGenerator.tsx +193 -0
- package/src/generators/SequenceGenerator.tsx +104 -0
- package/src/generators/SwitchOnIntegerGenerator.tsx +256 -0
- package/src/generators/SwitchOnStringGenerator.tsx +263 -0
- package/src/generators/callSubgraphSync.ts +126 -0
- package/src/generators/registerDefaultGenerators.ts +55 -0
- package/src/generators/registerDefaults.ts +26 -0
- package/src/hooks/useBehaveGraphFlow.ts +17 -16
- package/src/hooks/useFlowHandlers.ts +154 -30
- package/src/hooks/useWasdPan.ts +210 -0
- package/src/index.css +134 -0
- package/src/index.ts +53 -18
- package/src/manifest/contributionRegistry.ts +93 -0
- package/src/manifest/index.ts +4 -0
- package/src/manifest/loadManifest.ts +82 -0
- package/src/manifest/manifestPlugin.ts +29 -0
- package/src/manifest/passthroughValueType.ts +40 -0
- package/src/plugin/alignment/index.ts +91 -0
- package/src/plugin/autosave/controller.ts +366 -0
- package/src/plugin/autosave/index.tsx +114 -0
- package/src/plugin/autosave/panel/BackupPanel.tsx +141 -0
- package/src/plugin/autosave/panel/index.tsx +1 -0
- package/src/plugin/autosave/panel/styles.module.css +56 -0
- package/src/plugin/autosave/settings.ts +65 -0
- package/src/plugin/autosave/storage.ts +147 -0
- package/src/plugin/docs/index.tsx +297 -0
- package/src/plugin/docs/panel/DocumentationBrowserPanelImpl.tsx +200 -0
- package/src/plugin/docs/panel/index.tsx +21 -0
- package/src/plugin/docs/panel/styles.module.css +174 -0
- package/src/plugin/graphrunner/actions.ts +326 -0
- package/src/plugin/graphrunner/buttons.tsx +95 -0
- package/src/plugin/graphrunner/client.ts +707 -0
- package/src/plugin/graphrunner/index.tsx +184 -0
- package/src/plugin/graphrunner/panel.tsx +386 -0
- package/src/plugin/graphrunner/runController.ts +283 -0
- package/src/plugin/graphrunner/runner.ts +187 -0
- package/src/plugin/graphrunner/session.ts +243 -0
- package/src/plugin/graphrunner/store.ts +196 -0
- package/src/plugin/graphrunner/styles.module.css +171 -0
- package/src/plugin/graphrunner/transport.ts +250 -0
- package/src/plugin/graphrunner/types.ts +693 -0
- package/src/plugin/graphrunner-local/execution-utils.ts +637 -0
- package/src/plugin/graphrunner-local/index.tsx +172 -0
- package/src/plugin/graphrunner-local/panel.tsx +187 -0
- package/src/plugin/graphrunner-local/store.ts +41 -0
- package/src/plugin/graphrunner-local/styles.module.css +82 -0
- package/src/plugin/graphrunner-local/transport.ts +1339 -0
- package/src/plugin/graphrunner-local/types.ts +10 -0
- package/src/plugin/graphrunner-webworker/graph-executor.worker.ts +635 -0
- package/src/plugin/graphrunner-webworker/index.tsx +140 -0
- package/src/plugin/graphrunner-webworker/panel.tsx +173 -0
- package/src/plugin/graphrunner-webworker/store.ts +98 -0
- package/src/plugin/graphrunner-webworker/worker-transport.ts +123 -0
- package/src/plugin/kitchen-sink/index.ts +38 -0
- package/src/plugin/layout/dagre.ts +131 -0
- package/src/plugin/layout/elk.ts +216 -0
- package/src/plugin/layout/index.ts +80 -0
- package/src/plugin/notes/FormatToolbar.tsx +200 -0
- package/src/plugin/notes/index.tsx +191 -0
- package/src/plugin/notes/nodeActions.ts +100 -0
- package/src/plugin/notes/note.tsx +20 -0
- package/src/plugin/notes/noteImpl.tsx +89 -0
- package/src/plugin/realtime/realtimeRunner.ts +624 -0
- package/src/specifics/CustomEventOnTriggeredSpecific.tsx +92 -0
- package/src/specifics/CustomEventTriggerSpecific.tsx +141 -0
- package/src/specifics/VariableGetSpecific.tsx +110 -0
- package/src/specifics/VariableSetSpecific.tsx +110 -0
- package/src/store/actions.tsx +698 -0
- package/src/store/commands.ts +278 -0
- package/src/store/contextMenu.ts +192 -0
- package/src/store/controls.tsx +62 -0
- package/src/store/conversions.ts +47 -0
- package/src/store/documentation.tsx +69 -0
- package/src/store/events.tsx +116 -0
- package/src/store/flow.tsx +230 -0
- package/src/store/graphMeta.ts +39 -0
- package/src/store/hotKeys.tsx +364 -0
- package/src/store/layers.ts +259 -0
- package/src/store/legend.tsx +76 -0
- package/src/store/logs.ts +28 -0
- package/src/store/menubar.ts +41 -0
- package/src/store/refs.ts +84 -0
- package/src/store/registry.ts +51 -0
- package/src/store/selection.ts +22 -0
- package/src/store/settings.ts +99 -0
- package/src/store/settingsSchema.ts +210 -0
- package/src/store/socketGenerator.tsx +54 -0
- package/src/store/specific.tsx +75 -0
- package/src/store/specs.tsx +35 -0
- package/src/store/tabs.ts +282 -0
- package/src/store/toolbar.tsx +45 -0
- package/src/store/traces.ts +240 -0
- package/src/store/variables.ts +37 -0
- package/src/system/graph.ts +131 -0
- package/src/system/graphSession.ts +172 -0
- package/src/system/index.ts +6 -0
- package/src/system/notifications.ts +111 -0
- package/src/system/persistence.ts +82 -0
- package/src/system/plugin.ts +55 -0
- package/src/system/provider.tsx +86 -0
- package/src/system/pubsub.ts +323 -0
- package/src/system/system.ts +653 -0
- package/src/system/tabLoader.tsx +303 -0
- package/src/system/undoRedo.ts +103 -0
- package/src/transformers/Uigraph.ts +61 -0
- package/src/transformers/behaveToFlow.ts +16 -4
- package/src/transformers/contract.ts +87 -0
- package/src/transformers/flowToBehave.ts +40 -12
- package/src/types/NodeMetadata.ts +27 -0
- package/src/types/graph.ts +49 -0
- package/src/types/nodes.ts +50 -0
- package/src/types.ts +18 -0
- package/src/util/autoConvert.ts +200 -0
- package/src/util/colors.ts +1 -29
- package/src/util/downloadJson.ts +18 -0
- package/src/util/extractNodeMetadata.ts +16 -0
- package/src/util/getPickerFilters.ts +1 -1
- package/src/util/isBehaveNode.ts +6 -0
- package/src/util/isValidConnection.ts +51 -17
- package/src/util/mergeSockets.ts +29 -0
- package/src/util/serializeVariables.ts +66 -0
- package/src/util/sockets.ts +43 -0
- package/stories/apex/layoutController/example-graph.worker.ts +39 -0
- package/stories/apex/layoutController/index.stories.tsx +48 -0
- package/stories/apex/layoutController/webworker.stories.tsx +103 -0
- package/stories/apex/menubar/menubar.stories.tsx +19 -0
- package/stories/components/colorpicker/index.stories.tsx +20 -0
- package/stories/components/contextMenus/edge.stories.tsx +32 -0
- package/stories/components/contextMenus/node.stories.tsx +26 -0
- package/stories/components/contextMenus/nodePicker.stories.tsx +115 -0
- package/stories/components/controls/any/index.stories.tsx +19 -0
- package/stories/components/controls/boolean/index.stories.tsx +19 -0
- package/stories/components/controls/colorPicker/index.stories.tsx +49 -0
- package/stories/components/controls/number/index.stories.tsx +19 -0
- package/stories/components/controls/string/index.stories.tsx +19 -0
- package/stories/components/nodes/behaveNode.stories.tsx +108 -0
- package/stories/components/panels/alignment.stories.tsx +24 -0
- package/stories/components/panels/events.stories.tsx +38 -0
- package/stories/components/panels/graphRunner.stories.tsx +317 -0
- package/stories/components/panels/history.stories.tsx +37 -0
- package/stories/components/panels/keymaps.stories.tsx +21 -0
- package/stories/components/panels/legend.stories.tsx +37 -0
- package/stories/components/panels/logs.stories.tsx +24 -0
- package/stories/components/panels/nodeInputs.stories.tsx +21 -0
- package/stories/components/panels/nodePicker.stories.tsx +37 -0
- package/stories/components/panels/panel.stories.tsx +39 -0
- package/stories/components/panels/search.stories.tsx +24 -0
- package/stories/components/panels/systemSettings.stories.tsx +26 -0
- package/stories/components/panels/traces.stories.tsx +225 -0
- package/stories/components/panels/variables.stories.tsx +24 -0
- package/stories/defaults/defaultStoryProvider.tsx +170 -0
- package/stories/defaults/systemGenerator.ts +43 -0
- package/stories/plugins/notes.stories.tsx +100 -0
- package/tests/autoConvert.test.ts +329 -0
- package/tests/autosavePlugin.test.ts +204 -0
- package/tests/callSubgraphSync.test.ts +148 -0
- package/tests/commandRegistry.test.ts +137 -0
- package/tests/components/edges/offsetBezier.test.ts +51 -0
- package/tests/components/layoutController/utils.test.ts +68 -0
- package/tests/components/panels/traces/utils.test.ts +52 -0
- package/tests/contract.test.ts +51 -0
- package/tests/contractSerialize.test.ts +62 -0
- package/tests/deriveSpans.test.ts +71 -0
- package/tests/flowToBehave.test.ts +27 -4
- package/tests/hotkeys.test.ts +79 -0
- package/tests/keepAliveLifecycle.test.ts +167 -0
- package/tests/loadManifest.test.ts +113 -0
- package/tests/noteMarkdown.test.ts +65 -0
- package/tests/notesPlugin.test.ts +162 -0
- package/tests/notifications.test.ts +87 -0
- package/tests/persistence.test.ts +51 -0
- package/tests/saveLoad.test.ts +373 -0
- package/tests/settings.test.ts +178 -0
- package/tests/traceStore.test.ts +46 -0
- package/tests/util/calculateNewEdge.test.ts +98 -0
- package/tests/util/getSocketsByNodeTypeAndHandleType.test.ts +31 -0
- package/tests/util/hasPositionMetaData.test.ts +33 -0
- package/tests/util/isBehaveNode.test.ts +22 -0
- package/tests/util/isHandleConnected.test.ts +37 -0
- package/tests/util/mergeSockets.test.ts +43 -0
- package/tests/visual/README.md +64 -0
- package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-alignment-chromium-win32.png +0 -0
- package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-conversation-chromium-win32.png +0 -0
- package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-events-chromium-win32.png +0 -0
- package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-history-chromium-win32.png +0 -0
- package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-keymaps-chromium-win32.png +0 -0
- package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-layers-chromium-win32.png +0 -0
- package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-legend-chromium-win32.png +0 -0
- package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-localGraphRunner-chromium-win32.png +0 -0
- package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-logs-chromium-win32.png +0 -0
- package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-nodeInputs-chromium-win32.png +0 -0
- package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-nodePicker-chromium-win32.png +0 -0
- package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-panel-chromium-win32.png +0 -0
- package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-search-chromium-win32.png +0 -0
- package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-systemSettings-chromium-win32.png +0 -0
- package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-traces-chromium-win32.png +0 -0
- package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-variables-chromium-win32.png +0 -0
- package/tests/visual/panels.visual.test.tsx +76 -0
- package/tests/wasdPan.test.ts +71 -0
- package/tsconfig.base.json +39 -0
- package/tsconfig.json +18 -59
- package/tsconfig.prod.json +23 -0
- package/tsdown.config.ts +15 -3
- package/typedoc.json +7 -7
- package/vite.config.js +7 -0
- package/vitest.config.ts +5 -2
- package/vitest.visual.config.ts +55 -0
- package/src/components/AutoSizeInput.tsx +0 -65
- package/src/components/Controls.tsx +0 -87
- package/src/components/InputSocket.tsx +0 -142
- package/src/components/Node.tsx +0 -68
- package/src/components/NodeContainer.tsx +0 -46
- package/src/components/NodePicker.tsx +0 -77
- package/src/components/OutputSocket.tsx +0 -58
- package/src/components/modals/ClearModal.tsx +0 -40
- package/src/components/modals/HelpModal.tsx +0 -36
- package/src/components/modals/LoadModal.tsx +0 -96
- package/src/components/modals/Modal.tsx +0 -64
- package/src/components/modals/SaveModal.tsx +0 -60
- package/src/hooks/useCustomNodeTypes.tsx +0 -31
- package/src/hooks/useGraphRunner.ts +0 -104
- package/src/hooks/useMergeMap.ts +0 -14
- package/src/hooks/useNodeSpecJson.ts +0 -20
- package/src/hooks/useQueriableDefinitions.ts +0 -22
- package/src/styles.css +0 -8
- package/tailwind.config.ts +0 -19
- package/tests/tsconfig.json +0 -10
- /package/src/{types.d.ts → types-declarations.d.ts} +0 -0
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { LogSeverity } from '@kiberon-labs/behave-graph';
|
|
2
|
+
import { create } from 'zustand';
|
|
3
|
+
|
|
4
|
+
interface ILogMessage {
|
|
5
|
+
message: string;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export interface ILog {
|
|
9
|
+
data: ILogMessage;
|
|
10
|
+
time: Date;
|
|
11
|
+
type: LogSeverity;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export type LogStore = {
|
|
15
|
+
logs: ILog[];
|
|
16
|
+
append: (log: ILog) => void;
|
|
17
|
+
clear: () => void;
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export const logStoreFactory = () =>
|
|
21
|
+
create<LogStore>((set) => ({
|
|
22
|
+
logs: [],
|
|
23
|
+
append: (log: ILog) =>
|
|
24
|
+
set((state) => {
|
|
25
|
+
return { logs: [...state.logs, log] };
|
|
26
|
+
}),
|
|
27
|
+
clear: () => set(() => ({ logs: [] }))
|
|
28
|
+
}));
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { defaultMenuDataFactory } from '@/components/menubar';
|
|
2
|
+
import { createStore } from 'zustand';
|
|
3
|
+
|
|
4
|
+
export type IMenuItem = {
|
|
5
|
+
name: string;
|
|
6
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
7
|
+
render: (rest: { [key: string]: any }) => React.ReactNode;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export type ISubMenu = {
|
|
11
|
+
title: string;
|
|
12
|
+
name: string;
|
|
13
|
+
items: (IMenuItem | Seperator)[];
|
|
14
|
+
};
|
|
15
|
+
export type IMenu = {
|
|
16
|
+
items: ISubMenu[];
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
export class Seperator {}
|
|
20
|
+
|
|
21
|
+
export type MenuBarStore = {
|
|
22
|
+
show: boolean;
|
|
23
|
+
setShow: (show: boolean) => void;
|
|
24
|
+
items: ISubMenu[];
|
|
25
|
+
setItems: (items: ISubMenu[]) => void;
|
|
26
|
+
setSubMenuItems: (menuName: string, items: (IMenuItem | Seperator)[]) => void;
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
export const menubarStoreFactory = () =>
|
|
30
|
+
createStore<MenuBarStore>((set) => ({
|
|
31
|
+
show: true,
|
|
32
|
+
setShow: (show) => set({ show }),
|
|
33
|
+
items: defaultMenuDataFactory().items,
|
|
34
|
+
setItems: (items) => set({ items }),
|
|
35
|
+
setSubMenuItems: (menuName, items) =>
|
|
36
|
+
set((state) => ({
|
|
37
|
+
items: state.items.map((subMenu) =>
|
|
38
|
+
subMenu.name === menuName ? { ...subMenu, items } : subMenu
|
|
39
|
+
)
|
|
40
|
+
}))
|
|
41
|
+
}));
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import type { ReactFlowInstance } from 'reactflow';
|
|
2
|
+
import { create, useStore, type StoreApi } from 'zustand';
|
|
3
|
+
import { subscribeWithSelector } from 'zustand/middleware';
|
|
4
|
+
import type { XYPosition } from 'reactflow';
|
|
5
|
+
|
|
6
|
+
export type Refs = {
|
|
7
|
+
reactflow: ReactFlowInstance;
|
|
8
|
+
nodePickerPosition?: XYPosition;
|
|
9
|
+
selectedDocumentationType?: string;
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
export type RefStore = {
|
|
13
|
+
refs: Refs;
|
|
14
|
+
setRef: <T extends keyof Refs>(key: T, ref: Refs[T]) => void;
|
|
15
|
+
getRef: <T extends keyof Refs>(key: T) => Refs[T] | undefined;
|
|
16
|
+
removeRef: (key: keyof Refs) => void;
|
|
17
|
+
hasRef: (key: keyof Refs) => boolean;
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export const refStoreFactory = () =>
|
|
21
|
+
create<RefStore>()(
|
|
22
|
+
subscribeWithSelector((set, get) => ({
|
|
23
|
+
refs: {} as Refs,
|
|
24
|
+
|
|
25
|
+
setRef: <T extends keyof Refs>(key: T, ref: Refs[T]) => {
|
|
26
|
+
set((state) => ({
|
|
27
|
+
refs: {
|
|
28
|
+
...state.refs,
|
|
29
|
+
[key]: ref
|
|
30
|
+
}
|
|
31
|
+
}));
|
|
32
|
+
},
|
|
33
|
+
|
|
34
|
+
getRef: <T extends keyof Refs>(key: T) => {
|
|
35
|
+
return get().refs[key] as Refs[T] | undefined;
|
|
36
|
+
},
|
|
37
|
+
|
|
38
|
+
removeRef: (key: keyof Refs) => {
|
|
39
|
+
set((state) => {
|
|
40
|
+
const { [key]: _, ...rest } = state.refs;
|
|
41
|
+
return { refs: rest as Refs };
|
|
42
|
+
});
|
|
43
|
+
},
|
|
44
|
+
|
|
45
|
+
hasRef: (key: string) => {
|
|
46
|
+
return key in get().refs;
|
|
47
|
+
}
|
|
48
|
+
}))
|
|
49
|
+
);
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Subscribe to changes of a specific ref
|
|
53
|
+
* @param store - The ref store
|
|
54
|
+
* @param key - The key of the ref to watch
|
|
55
|
+
* @param callback - Callback fired when the ref changes
|
|
56
|
+
* @returns Unsubscribe function
|
|
57
|
+
*/
|
|
58
|
+
export function subscribeToRef<T extends keyof Refs>(
|
|
59
|
+
store: StoreApi<RefStore>,
|
|
60
|
+
key: T,
|
|
61
|
+
callback: (ref: Refs[T] | undefined) => void
|
|
62
|
+
) {
|
|
63
|
+
return store.subscribe((state, prevState) => {
|
|
64
|
+
const current = state.refs[key] as Refs[T] | undefined;
|
|
65
|
+
const previous = prevState.refs[key] as Refs[T] | undefined;
|
|
66
|
+
if (current !== previous) {
|
|
67
|
+
return current;
|
|
68
|
+
}
|
|
69
|
+
callback(current);
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Hook to access the current value of a ref from the store
|
|
75
|
+
* @param store - The ref store
|
|
76
|
+
* @param key - The key of the ref
|
|
77
|
+
* @returns The current value of the ref or null
|
|
78
|
+
*/
|
|
79
|
+
export function useRefFromStore<T extends keyof Refs>(
|
|
80
|
+
store: StoreApi<RefStore>,
|
|
81
|
+
key: T
|
|
82
|
+
): Refs[T] | undefined {
|
|
83
|
+
return useStore(store, (state) => state.refs[key] as Refs[T] | undefined);
|
|
84
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { create } from 'zustand';
|
|
2
|
+
import type { INodeRegistry, ValueTypeMetadata } from '../types/NodeMetadata';
|
|
3
|
+
import type { NodeSpecJSON } from '@kiberon-labs/behave-graph';
|
|
4
|
+
|
|
5
|
+
export type RegistryStore = {
|
|
6
|
+
readonly values: Record<string, ValueTypeMetadata>;
|
|
7
|
+
readonly specs: NodeSpecJSON[];
|
|
8
|
+
|
|
9
|
+
getRegistry: () => INodeRegistry;
|
|
10
|
+
updateRegistry: (registry: INodeRegistry) => void;
|
|
11
|
+
updateValues: (values: Record<string, ValueTypeMetadata>) => void;
|
|
12
|
+
updateSpecs: (specs: NodeSpecJSON[]) => void;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export const registryStoreFactory = () =>
|
|
16
|
+
create<RegistryStore>((set, get) => ({
|
|
17
|
+
values: {},
|
|
18
|
+
specs: [],
|
|
19
|
+
|
|
20
|
+
getRegistry: (): INodeRegistry => {
|
|
21
|
+
const state = get();
|
|
22
|
+
return {
|
|
23
|
+
values: state.values,
|
|
24
|
+
specs: state.specs
|
|
25
|
+
};
|
|
26
|
+
},
|
|
27
|
+
|
|
28
|
+
updateRegistry: (registry: INodeRegistry) =>
|
|
29
|
+
set((x) => {
|
|
30
|
+
// Merge specs by type (additive) so layering multiple profiles/plugins
|
|
31
|
+
// (core + image + ai + ...) doesn't clobber previously-registered node
|
|
32
|
+
// types. Later registrations override an existing type. Use updateSpecs
|
|
33
|
+
// for a full replacement.
|
|
34
|
+
const byType = new Map(x.specs.map((spec) => [spec.type, spec]));
|
|
35
|
+
for (const spec of registry.specs) byType.set(spec.type, spec);
|
|
36
|
+
return {
|
|
37
|
+
values: { ...x.values, ...registry.values },
|
|
38
|
+
specs: Array.from(byType.values())
|
|
39
|
+
};
|
|
40
|
+
}),
|
|
41
|
+
|
|
42
|
+
updateValues: (values: Record<string, ValueTypeMetadata>) =>
|
|
43
|
+
set((x) => ({
|
|
44
|
+
values: { ...x.values, ...values }
|
|
45
|
+
})),
|
|
46
|
+
|
|
47
|
+
updateSpecs: (specs: NodeSpecJSON[]) =>
|
|
48
|
+
set(() => ({
|
|
49
|
+
specs
|
|
50
|
+
}))
|
|
51
|
+
}));
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { GraphSession } from '@/system/graphSession';
|
|
2
|
+
import { create } from 'zustand';
|
|
3
|
+
|
|
4
|
+
export type SelectionStore = {
|
|
5
|
+
selectedNodeId: string | null;
|
|
6
|
+
setSelectedNodeId: (nodeId: string | null) => void;
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
export const selectionStoreFactory = (session: GraphSession) => {
|
|
10
|
+
const store = create<SelectionStore>((set) => ({
|
|
11
|
+
selectedNodeId: null,
|
|
12
|
+
setSelectedNodeId: (selectedNodeId: string | null) =>
|
|
13
|
+
set(() => ({ selectedNodeId }))
|
|
14
|
+
}));
|
|
15
|
+
//Track side effect of selected node in the node store
|
|
16
|
+
session.nodeStore.subscribe((state) => {
|
|
17
|
+
const selectedNode = state.nodes.find((n) => n.selected);
|
|
18
|
+
store.getState().setSelectedNodeId(selectedNode?.id ?? null);
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
return store;
|
|
22
|
+
};
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { create } from 'zustand';
|
|
2
|
+
|
|
3
|
+
export const EDGE_TYPE = {
|
|
4
|
+
bezier: 'Bezier',
|
|
5
|
+
smoothStep: 'Smooth step',
|
|
6
|
+
straight: 'Straight',
|
|
7
|
+
simpleBezier: 'Simple Bezier'
|
|
8
|
+
} as const;
|
|
9
|
+
|
|
10
|
+
export type EdgeType = (typeof EDGE_TYPE)[keyof typeof EDGE_TYPE];
|
|
11
|
+
|
|
12
|
+
export type GeneratorLocation = 'inline' | 'panel';
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Single source of truth for editor settings. Each entry's `default` defines the
|
|
16
|
+
* value (and its type); `persist: false` excludes it from the saved settings.
|
|
17
|
+
* The store shape, setters, and the persisted-key list are all derived from this
|
|
18
|
+
* , adding a setting here is the only edit needed (no setter boilerplate, no
|
|
19
|
+
* separate persist allow-list to keep in sync).
|
|
20
|
+
*/
|
|
21
|
+
const SETTINGS = {
|
|
22
|
+
edgeType: { default: EDGE_TYPE.bezier as EdgeType },
|
|
23
|
+
debugMode: { default: false as boolean },
|
|
24
|
+
showMenu: { default: true as boolean },
|
|
25
|
+
showTimings: { default: false as boolean },
|
|
26
|
+
showMinimap: { default: false as boolean },
|
|
27
|
+
showGrid: { default: true as boolean },
|
|
28
|
+
// Transient UI state , not persisted.
|
|
29
|
+
showSearch: { default: false as boolean, persist: false },
|
|
30
|
+
/** Delay applying a node value change until the user commits it. */
|
|
31
|
+
delayedUpdate: { default: false as boolean },
|
|
32
|
+
/** Show value types inline on nodes. */
|
|
33
|
+
inlineTypes: { default: false as boolean },
|
|
34
|
+
/** Show values inline on nodes. */
|
|
35
|
+
inlineValues: { default: false as boolean },
|
|
36
|
+
connectOnClick: { default: true as boolean },
|
|
37
|
+
/**
|
|
38
|
+
* When connecting sockets of different-but-convertible value types,
|
|
39
|
+
* automatically insert a conversion node between them.
|
|
40
|
+
*/
|
|
41
|
+
autoConvert: { default: true as boolean },
|
|
42
|
+
snapGrid: { default: false as boolean },
|
|
43
|
+
gridSize: { default: 15 as number },
|
|
44
|
+
generatorLocation: { default: 'panel' as GeneratorLocation }
|
|
45
|
+
} satisfies Record<string, { default: unknown; persist?: boolean }>;
|
|
46
|
+
|
|
47
|
+
type SettingsSchema = typeof SETTINGS;
|
|
48
|
+
|
|
49
|
+
type SettingsState = {
|
|
50
|
+
[K in keyof SettingsSchema]: SettingsSchema[K]['default'];
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
type SettingsSetters = {
|
|
54
|
+
[K in keyof SettingsSchema as `set${Capitalize<K & string>}`]: (
|
|
55
|
+
value: SettingsSchema[K]['default']
|
|
56
|
+
) => void;
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Generic accessors so plugin-contributed settings (dynamic keys not in the
|
|
61
|
+
* static {@link SETTINGS} schema) live in the same store as the typed built-ins.
|
|
62
|
+
* The auto-generated panel writes every row through {@link SystemSettingsStore.setSetting};
|
|
63
|
+
* the typed per-key setters above remain for existing typed consumers.
|
|
64
|
+
*/
|
|
65
|
+
type SettingsDynamicAccess = {
|
|
66
|
+
/** Dynamic plugin-contributed setting values, keyed by descriptor key. */
|
|
67
|
+
[key: string]: unknown;
|
|
68
|
+
/** Set any setting by key (used by the schema-driven panel + plugins). */
|
|
69
|
+
setSetting: (key: string, value: unknown) => void;
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
export type SystemSettingsStore = SettingsState &
|
|
73
|
+
SettingsSetters &
|
|
74
|
+
SettingsDynamicAccess;
|
|
75
|
+
|
|
76
|
+
const setterName = (key: string): string =>
|
|
77
|
+
`set${key.charAt(0).toUpperCase()}${key.slice(1)}`;
|
|
78
|
+
|
|
79
|
+
/** Settings round-tripped to persisted storage (everything except `persist:false`). */
|
|
80
|
+
export const PERSISTED_SETTING_KEYS = (
|
|
81
|
+
Object.entries(SETTINGS) as [keyof SettingsSchema, { persist?: boolean }][]
|
|
82
|
+
)
|
|
83
|
+
.filter(([, spec]) => spec.persist !== false)
|
|
84
|
+
.map(([key]) => key);
|
|
85
|
+
|
|
86
|
+
export const systemSettingsFactory = () =>
|
|
87
|
+
create<SystemSettingsStore>((set) => {
|
|
88
|
+
const initial: Record<string, unknown> = {};
|
|
89
|
+
for (const [key, spec] of Object.entries(SETTINGS)) {
|
|
90
|
+
initial[key] = spec.default;
|
|
91
|
+
initial[setterName(key)] = (value: unknown) =>
|
|
92
|
+
set({ [key]: value } as Partial<SystemSettingsStore>);
|
|
93
|
+
}
|
|
94
|
+
// Generic setter for dynamic (plugin-contributed) keys and for the
|
|
95
|
+
// schema-driven panel, which writes every row by key.
|
|
96
|
+
initial.setSetting = (key: string, value: unknown) =>
|
|
97
|
+
set({ [key]: value } as Partial<SystemSettingsStore>);
|
|
98
|
+
return initial as SystemSettingsStore;
|
|
99
|
+
});
|
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
import { createStore, type StoreApi } from 'zustand/vanilla';
|
|
2
|
+
import type { FC } from 'react';
|
|
3
|
+
import { EDGE_TYPE } from './settings';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Schema-driven settings.
|
|
7
|
+
*
|
|
8
|
+
* The Settings panel is auto-generated from a registry of {@link SettingDescriptor}s
|
|
9
|
+
* rather than hand-coded JSX. Built-in settings are seeded as {@link DEFAULT_SETTINGS};
|
|
10
|
+
* plugins contribute their own via `system.registerSetting(...)`, and the panel
|
|
11
|
+
* renders them the same way — so a plugin can surface settings without forking
|
|
12
|
+
* the panel.
|
|
13
|
+
*
|
|
14
|
+
* Descriptors are intentionally plain data (everything except `render`/`when` is
|
|
15
|
+
* JSON-serializable), so a future declarative manifest `contributes.configuration`
|
|
16
|
+
* section can feed this same registry.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
export type SettingEnumOption = { value: string; label: string };
|
|
20
|
+
|
|
21
|
+
/** Live values bag passed to a descriptor's {@link SettingDescriptorBase.when}. */
|
|
22
|
+
export type SettingsValues = Record<string, unknown>;
|
|
23
|
+
|
|
24
|
+
/** Props handed to a `type: 'custom'` descriptor's `render` component. */
|
|
25
|
+
export type SettingControlProps = {
|
|
26
|
+
value: unknown;
|
|
27
|
+
setValue: (value: unknown) => void;
|
|
28
|
+
descriptor: SettingDescriptor;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
type SettingDescriptorBase = {
|
|
32
|
+
/**
|
|
33
|
+
* Unique key. Built-ins are flat (`edgeType`) and match the value-store keys
|
|
34
|
+
* 1:1; plugin settings should be namespaced (`graphRunner.autoStart`) to avoid
|
|
35
|
+
* collisions.
|
|
36
|
+
*/
|
|
37
|
+
key: string;
|
|
38
|
+
/** Category heading the row is grouped under, e.g. `"Layout"`. */
|
|
39
|
+
section: string;
|
|
40
|
+
/** Sort order within the section (falls back to registration order). */
|
|
41
|
+
order?: number;
|
|
42
|
+
/** Row label. */
|
|
43
|
+
title?: string;
|
|
44
|
+
/** Secondary description text under the label. */
|
|
45
|
+
description?: string;
|
|
46
|
+
/** Excluded from persisted settings when `false`. Defaults to `true`. */
|
|
47
|
+
persist?: boolean;
|
|
48
|
+
/** Hide the row unless this returns true for the current values. */
|
|
49
|
+
when?: (values: SettingsValues) => boolean;
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
export type SettingDescriptor =
|
|
53
|
+
| (SettingDescriptorBase & { type: 'boolean'; default: boolean })
|
|
54
|
+
| (SettingDescriptorBase & {
|
|
55
|
+
type: 'number';
|
|
56
|
+
default: number;
|
|
57
|
+
min?: number;
|
|
58
|
+
max?: number;
|
|
59
|
+
step?: number;
|
|
60
|
+
})
|
|
61
|
+
| (SettingDescriptorBase & {
|
|
62
|
+
type: 'string';
|
|
63
|
+
default: string;
|
|
64
|
+
placeholder?: string;
|
|
65
|
+
})
|
|
66
|
+
| (SettingDescriptorBase & {
|
|
67
|
+
type: 'enum';
|
|
68
|
+
default: string;
|
|
69
|
+
options: SettingEnumOption[];
|
|
70
|
+
})
|
|
71
|
+
| (SettingDescriptorBase & {
|
|
72
|
+
type: 'custom';
|
|
73
|
+
default?: unknown;
|
|
74
|
+
render: FC<SettingControlProps>;
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
export type SettingsSchemaStore = {
|
|
78
|
+
/** Registered descriptors, in registration order. */
|
|
79
|
+
settings: SettingDescriptor[];
|
|
80
|
+
/** Section names in first-seen order, for stable display grouping. */
|
|
81
|
+
sectionOrder: string[];
|
|
82
|
+
registerSetting: (descriptor: SettingDescriptor) => void;
|
|
83
|
+
registerSettings: (descriptors: SettingDescriptor[]) => void;
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
const toOptions = (values: readonly string[]): SettingEnumOption[] =>
|
|
87
|
+
values.map((value) => ({ value, label: value }));
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Built-in editor settings, mirroring the previously hand-coded panel. Keys
|
|
91
|
+
* match the value-store keys in {@link file://./settings.ts} exactly, so typed
|
|
92
|
+
* consumers (`settings.edgeType`, …) are unaffected.
|
|
93
|
+
*/
|
|
94
|
+
export const DEFAULT_SETTINGS: SettingDescriptor[] = [
|
|
95
|
+
{
|
|
96
|
+
key: 'edgeType',
|
|
97
|
+
section: 'Layout',
|
|
98
|
+
type: 'enum',
|
|
99
|
+
default: EDGE_TYPE.bezier,
|
|
100
|
+
options: toOptions(Object.values(EDGE_TYPE)),
|
|
101
|
+
title: 'Edge Type',
|
|
102
|
+
description: 'Select the type of edge to use in the graph editor.'
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
key: 'inlineTypes',
|
|
106
|
+
section: 'Accessibility',
|
|
107
|
+
type: 'boolean',
|
|
108
|
+
default: false,
|
|
109
|
+
title: 'Show inline types',
|
|
110
|
+
description:
|
|
111
|
+
'Adds additional spans to help differentiate types for colorblind users.'
|
|
112
|
+
},
|
|
113
|
+
{
|
|
114
|
+
key: 'delayedUpdate',
|
|
115
|
+
section: 'Interaction',
|
|
116
|
+
type: 'boolean',
|
|
117
|
+
default: false,
|
|
118
|
+
title: 'Use delayed interaction',
|
|
119
|
+
description: 'Forces a user to click save to update port.'
|
|
120
|
+
},
|
|
121
|
+
{
|
|
122
|
+
key: 'connectOnClick',
|
|
123
|
+
section: 'Interaction',
|
|
124
|
+
type: 'boolean',
|
|
125
|
+
default: true,
|
|
126
|
+
title: 'Click to connect',
|
|
127
|
+
description: 'Allows you to quick connect nodes by clicking on the 2 port.'
|
|
128
|
+
},
|
|
129
|
+
{
|
|
130
|
+
key: 'autoConvert',
|
|
131
|
+
section: 'Interaction',
|
|
132
|
+
type: 'boolean',
|
|
133
|
+
default: true,
|
|
134
|
+
title: 'Auto-convert types',
|
|
135
|
+
description:
|
|
136
|
+
'When connecting different but convertible types, insert a conversion node automatically.'
|
|
137
|
+
},
|
|
138
|
+
{
|
|
139
|
+
key: 'showMinimap',
|
|
140
|
+
section: 'Display',
|
|
141
|
+
type: 'boolean',
|
|
142
|
+
default: false,
|
|
143
|
+
title: 'Show Minimap',
|
|
144
|
+
description: 'Shows the minimap in the graph editing area.'
|
|
145
|
+
},
|
|
146
|
+
{
|
|
147
|
+
key: 'showGrid',
|
|
148
|
+
section: 'Display',
|
|
149
|
+
type: 'boolean',
|
|
150
|
+
default: true,
|
|
151
|
+
title: 'Show Grid',
|
|
152
|
+
description: 'Shows the grid in the graph editing area.'
|
|
153
|
+
},
|
|
154
|
+
{
|
|
155
|
+
key: 'snapGrid',
|
|
156
|
+
section: 'Display',
|
|
157
|
+
type: 'boolean',
|
|
158
|
+
default: false,
|
|
159
|
+
title: 'Snap to Grid',
|
|
160
|
+
description: 'Snaps nodes to the grid while dragging.'
|
|
161
|
+
},
|
|
162
|
+
{
|
|
163
|
+
key: 'showTimings',
|
|
164
|
+
section: 'Performance',
|
|
165
|
+
type: 'boolean',
|
|
166
|
+
default: false,
|
|
167
|
+
title: 'Show execution time',
|
|
168
|
+
description: 'Shows how long it takes for a node to process.'
|
|
169
|
+
}
|
|
170
|
+
];
|
|
171
|
+
|
|
172
|
+
export const settingsSchemaStoreFactory = (
|
|
173
|
+
initial: SettingDescriptor[] = DEFAULT_SETTINGS
|
|
174
|
+
): StoreApi<SettingsSchemaStore> =>
|
|
175
|
+
createStore<SettingsSchemaStore>((set, get) => {
|
|
176
|
+
const registerSetting = (descriptor: SettingDescriptor): void => {
|
|
177
|
+
const { settings, sectionOrder } = get();
|
|
178
|
+
if (settings.some((existing) => existing.key === descriptor.key)) {
|
|
179
|
+
console.warn(
|
|
180
|
+
`Setting "${descriptor.key}" is already registered; ignoring duplicate.`
|
|
181
|
+
);
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
184
|
+
set({
|
|
185
|
+
settings: [...settings, descriptor],
|
|
186
|
+
sectionOrder: sectionOrder.includes(descriptor.section)
|
|
187
|
+
? sectionOrder
|
|
188
|
+
: [...sectionOrder, descriptor.section]
|
|
189
|
+
});
|
|
190
|
+
};
|
|
191
|
+
|
|
192
|
+
// Seed the built-in descriptors as the starting state.
|
|
193
|
+
const settings: SettingDescriptor[] = [];
|
|
194
|
+
const sectionOrder: string[] = [];
|
|
195
|
+
for (const descriptor of initial) {
|
|
196
|
+
if (settings.some((existing) => existing.key === descriptor.key))
|
|
197
|
+
continue;
|
|
198
|
+
settings.push(descriptor);
|
|
199
|
+
if (!sectionOrder.includes(descriptor.section)) {
|
|
200
|
+
sectionOrder.push(descriptor.section);
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
return {
|
|
205
|
+
settings,
|
|
206
|
+
sectionOrder,
|
|
207
|
+
registerSetting,
|
|
208
|
+
registerSettings: (descriptors) => descriptors.forEach(registerSetting)
|
|
209
|
+
};
|
|
210
|
+
});
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import type { IBehaveNode } from '@/types/nodes';
|
|
2
|
+
import type { NodeSpecJSON } from '@kiberon-labs/behave-graph';
|
|
3
|
+
import type { ComponentType } from 'react';
|
|
4
|
+
import { create } from 'zustand';
|
|
5
|
+
|
|
6
|
+
export type SocketGeneratorNode = {
|
|
7
|
+
id: string;
|
|
8
|
+
data: IBehaveNode['data'];
|
|
9
|
+
spec: NodeSpecJSON;
|
|
10
|
+
selected: boolean;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export type SocketGeneratorRenderProps = {
|
|
14
|
+
node: SocketGeneratorNode;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export type SocketGenerator = {
|
|
18
|
+
name: string;
|
|
19
|
+
check: (spec: NodeSpecJSON) => boolean;
|
|
20
|
+
render: ComponentType<SocketGeneratorRenderProps>;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
export type SocketGeneratorStore = {
|
|
24
|
+
generators: SocketGenerator[];
|
|
25
|
+
registerGenerator: (generator: SocketGenerator) => void;
|
|
26
|
+
unregisterGenerator: (name: string) => void;
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
export const socketGeneratorStoreFactory = () =>
|
|
30
|
+
create<SocketGeneratorStore>((set) => ({
|
|
31
|
+
generators: [],
|
|
32
|
+
|
|
33
|
+
registerGenerator: (generator) =>
|
|
34
|
+
set((state) => {
|
|
35
|
+
const existingIndex = state.generators.findIndex(
|
|
36
|
+
(x) => x.name === generator.name
|
|
37
|
+
);
|
|
38
|
+
|
|
39
|
+
if (existingIndex === -1) {
|
|
40
|
+
return {
|
|
41
|
+
generators: [...state.generators, generator]
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const next = state.generators.slice();
|
|
46
|
+
next[existingIndex] = generator;
|
|
47
|
+
return { generators: next };
|
|
48
|
+
}),
|
|
49
|
+
|
|
50
|
+
unregisterGenerator: (name) =>
|
|
51
|
+
set((state) => ({
|
|
52
|
+
generators: state.generators.filter((x) => x.name !== name)
|
|
53
|
+
}))
|
|
54
|
+
}));
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import type { NodeSpecJSON } from '@kiberon-labs/behave-graph';
|
|
2
|
+
import type { ComponentType } from 'react';
|
|
3
|
+
import { create } from 'zustand';
|
|
4
|
+
import { getCustomEventOnTriggeredSpecific } from '@/specifics/CustomEventOnTriggeredSpecific';
|
|
5
|
+
import { getCustomEventTriggerSpecific } from '@/specifics/CustomEventTriggerSpecific';
|
|
6
|
+
import { getVariableGetSpecific } from '@/specifics/VariableGetSpecific';
|
|
7
|
+
import { getVariableSetSpecific } from '@/specifics/VariableSetSpecific';
|
|
8
|
+
import type { IBehaveNode } from '@/types/nodes';
|
|
9
|
+
|
|
10
|
+
export type SpecificNode = {
|
|
11
|
+
id: string;
|
|
12
|
+
data: IBehaveNode['data'];
|
|
13
|
+
spec: NodeSpecJSON;
|
|
14
|
+
selected: boolean;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export type SpecificRenderProps = {
|
|
18
|
+
node: SpecificNode;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export type Specific = {
|
|
22
|
+
name: string;
|
|
23
|
+
check: (spec: NodeSpecJSON) => boolean;
|
|
24
|
+
render: ComponentType<SpecificRenderProps>;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
export type SpecificStore = {
|
|
28
|
+
specifics: Specific[];
|
|
29
|
+
titleBarActions: Record<string, React.ReactElement>;
|
|
30
|
+
registerSpecific: (specific: Specific) => void;
|
|
31
|
+
unregisterSpecific: (name: string) => void;
|
|
32
|
+
registryTitleBarAction: (name: string, action: React.ReactElement) => void;
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
const defaultSpecifics: Specific[] = [
|
|
36
|
+
getCustomEventOnTriggeredSpecific(),
|
|
37
|
+
getCustomEventTriggerSpecific(),
|
|
38
|
+
getVariableGetSpecific(),
|
|
39
|
+
getVariableSetSpecific()
|
|
40
|
+
];
|
|
41
|
+
|
|
42
|
+
export const specificStoreFactory = () =>
|
|
43
|
+
create<SpecificStore>((set) => ({
|
|
44
|
+
specifics: defaultSpecifics,
|
|
45
|
+
|
|
46
|
+
registerSpecific: (specific) =>
|
|
47
|
+
set((state) => {
|
|
48
|
+
const existingIndex = state.specifics.findIndex(
|
|
49
|
+
(x) => x.name === specific.name
|
|
50
|
+
);
|
|
51
|
+
|
|
52
|
+
if (existingIndex === -1) {
|
|
53
|
+
return {
|
|
54
|
+
specifics: [...state.specifics, specific]
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const next = state.specifics.slice();
|
|
59
|
+
next[existingIndex] = specific;
|
|
60
|
+
return { specifics: next };
|
|
61
|
+
}),
|
|
62
|
+
|
|
63
|
+
unregisterSpecific: (name) =>
|
|
64
|
+
set((state) => ({
|
|
65
|
+
specifics: state.specifics.filter((x) => x.name !== name)
|
|
66
|
+
})),
|
|
67
|
+
titleBarActions: {},
|
|
68
|
+
registryTitleBarAction: (name: string, action: React.ReactElement) =>
|
|
69
|
+
set((state) => ({
|
|
70
|
+
titleBarActions: {
|
|
71
|
+
...state.titleBarActions,
|
|
72
|
+
[name]: action
|
|
73
|
+
}
|
|
74
|
+
}))
|
|
75
|
+
}));
|