@kiberon-labs/behave-graph-flow 2.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/.storybook/manager.ts +6 -0
- package/.storybook/preview.ts +49 -1
- package/.storybook/styles.css +9 -3
- package/.turbo/turbo-build.log +1 -1
- package/CHANGELOG.md +368 -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/index.css +36 -33
- package/dist/index.css.map +1 -1
- package/dist/index.d.ts +1865 -550
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +14357 -11221
- package/dist/index.js.map +1 -1
- 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/protocol.md +43 -20
- package/package.json +5 -9
- package/src/components/FloatingToolbar/index.module.css +5 -13
- package/src/components/FloatingToolbar/index.tsx +9 -9
- package/src/components/Flow.tsx +34 -23
- package/src/components/contextMenus/DynamicContextMenu.tsx +85 -0
- package/src/components/contextMenus/NodePicker.module.css +13 -13
- package/src/components/contextMenus/edge.tsx +9 -95
- package/src/components/contextMenus/node.tsx +9 -149
- package/src/components/contextMenus/selection.tsx +5 -71
- package/src/components/controls/any/AnyControlImpl.tsx +14 -0
- package/src/components/controls/any/index.tsx +13 -2
- package/src/components/edges/index.tsx +75 -69
- package/src/components/layoutController/index.module.css +3 -0
- package/src/components/layoutController/index.tsx +24 -1
- package/src/components/layoutController/utils.ts +46 -3
- package/src/components/menubar/defaults.tsx +55 -19
- package/src/components/menubar/menuItem.module.css +18 -3
- package/src/components/menubar/menuItem.tsx +34 -1
- package/src/components/nodes/behave/NodeContainer.module.css +26 -25
- package/src/components/nodes/group/index.tsx +3 -3
- package/src/components/nodes/wrapper/styles.module.css +6 -32
- package/src/components/panels/alignment/index.module.css +0 -10
- package/src/components/panels/alignment/index.tsx +4 -4
- package/src/components/panels/base/styles.module.css +2 -2
- 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 +14 -5
- package/src/components/panels/events/ManageEventsPanel.tsx +11 -8
- package/src/components/panels/events/styles.module.css +6 -64
- package/src/components/panels/graphProperties/index.tsx +125 -0
- package/src/components/panels/history/index.tsx +2 -2
- package/src/components/panels/history/styles.module.css +0 -9
- package/src/components/panels/keymaps/index.module.css +3 -13
- package/src/components/panels/keymaps/index.tsx +1 -2
- package/src/components/panels/layers/index.tsx +20 -15
- package/src/components/panels/layers/styles.module.css +9 -12
- package/src/components/panels/legend/index.tsx +1 -1
- package/src/components/panels/logs/index.module.css +25 -19
- package/src/components/panels/logs/index.tsx +7 -7
- package/src/components/panels/nodeInputs/InputsGroup.tsx +1 -0
- package/src/components/panels/nodeInputs/NodeSettings.tsx +2 -2
- package/src/components/panels/nodeInputs/NodeTitleEditor.tsx +1 -1
- package/src/components/panels/nodeInputs/OutputsGroup.tsx +2 -12
- package/src/components/panels/nodeInputs/index.module.css +99 -75
- package/src/components/panels/nodeInputs/index.tsx +21 -11
- package/src/components/panels/nodeInputs/useNodeHandlers.ts +2 -2
- package/src/components/panels/nodeInputs/useNodeInputsData.ts +23 -43
- package/src/components/panels/nodePicker/index.tsx +8 -8
- package/src/components/panels/panel/index.module.css +7 -7
- package/src/components/panels/search/index.module.css +0 -50
- package/src/components/panels/search/index.tsx +2 -2
- package/src/components/panels/systemSettings/ConversionsSettings.tsx +203 -0
- package/src/components/panels/systemSettings/index.tsx +221 -176
- package/src/components/panels/systemSettings/styles.module.css +135 -8
- package/src/components/panels/traces/GridLines.tsx +1 -1
- package/src/components/panels/traces/TimeGrid.tsx +3 -3
- package/src/components/panels/traces/TraceLane.tsx +1 -1
- package/src/components/panels/traces/index.module.css +1 -8
- package/src/components/panels/traces/index.tsx +8 -4
- package/src/components/panels/traces/useDerivedSpans.ts +241 -146
- package/src/components/panels/traces/utils.ts +8 -0
- package/src/components/panels/variables/CreateVariableScreen.tsx +3 -3
- package/src/components/panels/variables/ManageVariablesScreen.tsx +12 -9
- package/src/components/panels/variables/index.tsx +2 -2
- package/src/components/panels/variables/styles.module.css +4 -91
- package/src/components/primitives/icon.module.css +4 -4
- package/src/components/sockets/input/index.tsx +9 -2
- package/src/components/sockets/input/styles.module.css +2 -3
- package/src/components/sockets/output/index.tsx +10 -3
- package/src/components/sockets/output/styles.module.css +1 -6
- package/src/css/notes.css +135 -0
- package/src/css/prosemirror.css +3 -3
- package/src/css/rc-dock.css +143 -43
- package/src/css/rc-menu.css +56 -55
- package/src/css/themes/kiberon.css +127 -0
- package/src/css/vars.css +197 -13
- package/src/css/vscode-elements.css +124 -0
- package/src/generators/CallSubgraphGenerator.tsx +136 -0
- package/src/generators/CustomEventOnTriggeredGenerator.tsx +2 -2
- package/src/generators/GraphBoundaryGenerator.module.css +32 -0
- package/src/generators/GraphBoundaryGenerator.tsx +193 -0
- package/src/generators/SequenceGenerator.tsx +2 -2
- package/src/generators/SwitchOnIntegerGenerator.tsx +2 -2
- package/src/generators/SwitchOnStringGenerator.tsx +2 -2
- package/src/generators/callSubgraphSync.ts +126 -0
- package/src/generators/registerDefaultGenerators.ts +21 -0
- package/src/generators/registerDefaults.ts +26 -0
- package/src/hooks/useBehaveGraphFlow.ts +2 -2
- package/src/hooks/useFlowHandlers.ts +47 -9
- package/src/hooks/useWasdPan.ts +26 -4
- package/src/index.css +4 -16
- package/src/index.ts +17 -0
- 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 +22 -12
- 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 +2 -4
- package/src/plugin/docs/panel/DocumentationBrowserPanelImpl.tsx +200 -0
- package/src/plugin/docs/panel/index.tsx +15 -194
- package/src/plugin/docs/panel/styles.module.css +8 -8
- package/src/plugin/graphrunner/actions.ts +258 -185
- package/src/plugin/graphrunner/buttons.tsx +34 -26
- package/src/plugin/graphrunner/client.ts +4 -1
- package/src/plugin/graphrunner/index.tsx +29 -100
- package/src/plugin/graphrunner/panel.tsx +2 -2
- package/src/plugin/graphrunner/runController.ts +283 -0
- package/src/plugin/graphrunner/runner.ts +21 -192
- package/src/plugin/graphrunner/store.ts +14 -24
- package/src/plugin/graphrunner/styles.module.css +17 -57
- package/src/plugin/graphrunner/transport.ts +26 -0
- package/src/plugin/graphrunner/types.ts +21 -0
- package/src/plugin/graphrunner-local/execution-utils.ts +260 -80
- package/src/plugin/graphrunner-local/index.tsx +8 -2
- package/src/plugin/graphrunner-local/panel.tsx +131 -175
- package/src/plugin/graphrunner-local/styles.module.css +57 -76
- package/src/plugin/graphrunner-local/transport.ts +151 -184
- package/src/plugin/graphrunner-webworker/graph-executor.worker.ts +2 -0
- package/src/plugin/graphrunner-webworker/index.tsx +4 -10
- package/src/plugin/graphrunner-webworker/store.ts +9 -0
- package/src/plugin/kitchen-sink/index.ts +38 -0
- package/src/{layout/dagre.tsx → plugin/layout/dagre.ts} +17 -5
- package/src/{layout → plugin/layout}/elk.ts +22 -6
- 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 +58 -4
- package/src/specifics/CustomEventOnTriggeredSpecific.tsx +2 -2
- package/src/specifics/CustomEventTriggerSpecific.tsx +2 -2
- package/src/specifics/VariableGetSpecific.tsx +2 -2
- package/src/specifics/VariableSetSpecific.tsx +2 -2
- package/src/store/actions.tsx +5 -5
- package/src/store/commands.ts +278 -0
- package/src/store/contextMenu.ts +192 -0
- package/src/store/conversions.ts +47 -0
- package/src/store/flow.tsx +23 -38
- package/src/store/graphMeta.ts +39 -0
- package/src/store/hotKeys.tsx +301 -260
- package/src/store/layers.ts +3 -3
- package/src/store/registry.ts +12 -4
- package/src/store/selection.ts +3 -3
- package/src/store/settings.ts +82 -82
- package/src/store/settingsSchema.ts +210 -0
- package/src/store/tabs.ts +5 -1
- package/src/store/traces.ts +3 -3
- package/src/system/graph.ts +11 -14
- package/src/system/graphSession.ts +172 -0
- package/src/system/index.ts +3 -0
- package/src/system/notifications.ts +13 -0
- package/src/system/persistence.ts +82 -0
- package/src/system/plugin.ts +28 -0
- package/src/system/provider.tsx +64 -0
- package/src/system/system.ts +518 -88
- package/src/system/tabLoader.tsx +70 -32
- package/src/system/undoRedo.ts +1 -1
- package/src/transformers/Uigraph.ts +5 -4
- package/src/transformers/contract.ts +87 -0
- package/src/transformers/flowToBehave.ts +13 -5
- package/src/types/nodes.ts +8 -3
- package/src/types.ts +2 -0
- package/src/util/autoConvert.ts +200 -0
- package/src/util/isValidConnection.ts +23 -2
- package/stories/defaults/defaultStoryProvider.tsx +17 -14
- package/stories/defaults/systemGenerator.ts +6 -1
- package/stories/{components/nodes/comment.stories.tsx → plugins/notes.stories.tsx} +24 -30
- 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/contract.test.ts +51 -0
- package/tests/contractSerialize.test.ts +62 -0
- package/tests/deriveSpans.test.ts +71 -0
- package/tests/flowToBehave.test.ts +2 -1
- 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/persistence.test.ts +51 -0
- package/tests/saveLoad.test.ts +7 -6
- package/tests/settings.test.ts +178 -0
- package/tests/traceStore.test.ts +46 -0
- package/tests/visual/README.md +2 -2
- 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-variables-chromium-win32.png +0 -0
- package/tests/visual/panels.visual.test.tsx +3 -3
- package/tests/wasdPan.test.ts +71 -0
- package/vitest.config.ts +1 -1
- package/vitest.visual.config.ts +7 -0
- package/.storybook/vscode.css +0 -814
- package/src/components/nodes/comment/FormatToolbar.tsx +0 -118
- package/src/components/nodes/comment/comment.tsx +0 -103
- package/src/components/nodes/comment/styles.module.css +0 -150
- package/src/components/panels/conversation/index.module.css +0 -151
- package/src/components/panels/conversation/index.tsx +0 -162
- package/src/components/panels/events/CustomEventsEditor.tsx +0 -384
- package/src/css/vscode.css +0 -13
- package/src/hooks/useDetachNodes.ts +0 -39
- package/src/plugin/graphrunner-webworker/types.ts +0 -17
- package/src/specifics/registerDefaultSpecifics.ts +0 -5
- package/src/store/chat.ts +0 -73
- package/src/store/graphRunnerClient.ts +0 -110
package/src/store/settings.ts
CHANGED
|
@@ -9,91 +9,91 @@ export const EDGE_TYPE = {
|
|
|
9
9
|
|
|
10
10
|
export type EdgeType = (typeof EDGE_TYPE)[keyof typeof EDGE_TYPE];
|
|
11
11
|
|
|
12
|
-
export
|
|
13
|
-
dagre: 'Dagre',
|
|
14
|
-
elkForce: 'Elk - Force',
|
|
15
|
-
elkRect: 'Elk - Rect',
|
|
16
|
-
elkLayered: 'Elk - Layered'
|
|
17
|
-
} as const;
|
|
12
|
+
export type GeneratorLocation = 'inline' | 'panel';
|
|
18
13
|
|
|
19
|
-
|
|
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 }>;
|
|
20
46
|
|
|
21
|
-
|
|
47
|
+
type SettingsSchema = typeof SETTINGS;
|
|
48
|
+
|
|
49
|
+
type SettingsState = {
|
|
50
|
+
[K in keyof SettingsSchema]: SettingsSchema[K]['default'];
|
|
51
|
+
};
|
|
22
52
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
showGrid: boolean;
|
|
28
|
-
showSearch: boolean;
|
|
29
|
-
showMenu: boolean;
|
|
30
|
-
edgeType: EdgeType;
|
|
31
|
-
layoutType: LayoutType;
|
|
32
|
-
delayedUpdate: boolean;
|
|
33
|
-
inlineTypes: boolean;
|
|
34
|
-
inlineValues: boolean;
|
|
35
|
-
connectOnClick: boolean;
|
|
36
|
-
snapGrid: boolean;
|
|
37
|
-
gridSize: number;
|
|
38
|
-
generatorLocation: GeneratorLocation;
|
|
39
|
-
setDebugMode: (debugMode: boolean) => void;
|
|
40
|
-
setShowTimings: (showTimings: boolean) => void;
|
|
41
|
-
setShowMinimap: (showMinimap: boolean) => void;
|
|
42
|
-
setShowGrid: (showGrid: boolean) => void;
|
|
43
|
-
setShowSearch: (showSearch: boolean) => void;
|
|
44
|
-
setEdgeType: (edgeType: EdgeType) => void;
|
|
45
|
-
setLayoutType: (layoutType: LayoutType) => void;
|
|
46
|
-
setDelayedUpdate: (delayedUpdate: boolean) => void;
|
|
47
|
-
setInlineTypes: (inlineTypes: boolean) => void;
|
|
48
|
-
setInlineValues: (inlineValues: boolean) => void;
|
|
49
|
-
setConnectOnClick: (connectOnClick: boolean) => void;
|
|
50
|
-
setSnapGrid: (snapGrid: boolean) => void;
|
|
51
|
-
setGridSize: (gridSize: number) => void;
|
|
52
|
-
setGeneratorLocation: (generatorLocation: GeneratorLocation) => void;
|
|
53
|
+
type SettingsSetters = {
|
|
54
|
+
[K in keyof SettingsSchema as `set${Capitalize<K & string>}`]: (
|
|
55
|
+
value: SettingsSchema[K]['default']
|
|
56
|
+
) => void;
|
|
53
57
|
};
|
|
54
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
|
+
|
|
55
86
|
export const systemSettingsFactory = () =>
|
|
56
|
-
create<SystemSettingsStore>((set) =>
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
/**
|
|
70
|
-
* Whether to show the types inline with the nodes
|
|
71
|
-
*/
|
|
72
|
-
inlineTypes: false,
|
|
73
|
-
/**
|
|
74
|
-
* Whether to show the values inline with the nodes
|
|
75
|
-
*/
|
|
76
|
-
inlineValues: false,
|
|
77
|
-
connectOnClick: true,
|
|
78
|
-
snapGrid: false,
|
|
79
|
-
gridSize: 15,
|
|
80
|
-
generatorLocation: 'panel',
|
|
81
|
-
setShowMenu: (showMenu: boolean) => set(() => ({ showMenu })),
|
|
82
|
-
setEdgeType: (edgeType: EdgeType) => set(() => ({ edgeType })),
|
|
83
|
-
setLayoutType: (layoutType: LayoutType) => set(() => ({ layoutType })),
|
|
84
|
-
setDebugMode: (debugMode: boolean) => set(() => ({ debugMode })),
|
|
85
|
-
setShowTimings: (showTimings: boolean) => set(() => ({ showTimings })),
|
|
86
|
-
setShowMinimap: (showMinimap: boolean) => set(() => ({ showMinimap })),
|
|
87
|
-
setShowGrid: (showGrid: boolean) => set(() => ({ showGrid })),
|
|
88
|
-
setShowSearch: (showSearch: boolean) => set(() => ({ showSearch })),
|
|
89
|
-
setDelayedUpdate: (delayedUpdate: boolean) =>
|
|
90
|
-
set(() => ({ delayedUpdate })),
|
|
91
|
-
setInlineTypes: (inlineTypes: boolean) => set(() => ({ inlineTypes })),
|
|
92
|
-
setInlineValues: (inlineValues: boolean) => set(() => ({ inlineValues })),
|
|
93
|
-
setConnectOnClick: (connectOnClick: boolean) =>
|
|
94
|
-
set(() => ({ connectOnClick })),
|
|
95
|
-
setSnapGrid: (snapGrid: boolean) => set(() => ({ snapGrid })),
|
|
96
|
-
setGridSize: (gridSize: number) => set(() => ({ gridSize })),
|
|
97
|
-
setGeneratorLocation: (generatorLocation: GeneratorLocation) =>
|
|
98
|
-
set(() => ({ generatorLocation }))
|
|
99
|
-
}));
|
|
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
|
+
});
|
package/src/store/tabs.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { BoxBase, LayoutBase, PanelBase, TabBase } from 'rc-dock';
|
|
2
2
|
import { create } from 'zustand';
|
|
3
|
+
import { isGraphTabId } from '@/components/layoutController/utils';
|
|
3
4
|
|
|
4
5
|
function isPanelBase(value: BoxBase | PanelBase): value is PanelBase {
|
|
5
6
|
return Array.isArray((value as PanelBase).tabs);
|
|
@@ -120,6 +121,9 @@ const defaultLayout: LayoutBase = {
|
|
|
120
121
|
children: [
|
|
121
122
|
{
|
|
122
123
|
tabs: [
|
|
124
|
+
{
|
|
125
|
+
id: 'graphProperties'
|
|
126
|
+
},
|
|
123
127
|
{
|
|
124
128
|
id: 'variables'
|
|
125
129
|
},
|
|
@@ -226,7 +230,7 @@ export const tabStoreFactory = () =>
|
|
|
226
230
|
|
|
227
231
|
// 2) Otherwise, insert it into a target panel (prefer explicit panelId).
|
|
228
232
|
const targetPanelId =
|
|
229
|
-
options?.panelId ?? (tabId
|
|
233
|
+
options?.panelId ?? (isGraphTabId(tabId) ? 'graphs' : undefined);
|
|
230
234
|
|
|
231
235
|
if (targetPanelId) {
|
|
232
236
|
const res = recurseUpsertTabInPanelId(
|
package/src/store/traces.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { Engine, INode } from '@kiberon-labs/behave-graph';
|
|
2
2
|
import { create } from 'zustand';
|
|
3
|
-
import type {
|
|
3
|
+
import type { GraphSession } from '@/system/graphSession';
|
|
4
4
|
|
|
5
5
|
export type TraceSpan = {
|
|
6
6
|
id: number;
|
|
@@ -74,11 +74,11 @@ export type TraceStore = {
|
|
|
74
74
|
connectEngine: (engine?: Engine) => void;
|
|
75
75
|
recordNodeStart: (node: INode, startTime?: number) => void;
|
|
76
76
|
recordNodeEnd: (node: INode, endTime?: number) => void;
|
|
77
|
-
addSpan: (span: Omit<TraceSpan, 'id'>) => void;
|
|
77
|
+
addSpan: (span: Omit<TraceSpan, 'id' | 'lane'> & { lane?: number }) => void;
|
|
78
78
|
updateSpan: (nodeId: string, updates: Partial<TraceSpan>) => void;
|
|
79
79
|
};
|
|
80
80
|
|
|
81
|
-
export const traceStoreFactory = (_:
|
|
81
|
+
export const traceStoreFactory = (_: GraphSession) => {
|
|
82
82
|
let connectedEngine: Engine | undefined;
|
|
83
83
|
let onStart: ((node: INode) => void) | undefined;
|
|
84
84
|
let onEnd: ((node: INode) => void) | undefined;
|
package/src/system/graph.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Viewport } from 'reactflow';
|
|
2
|
-
import type {
|
|
2
|
+
import type { GraphSession } from './graphSession';
|
|
3
3
|
import type { Edge } from 'reactflow';
|
|
4
4
|
import type { UIGraphJSON } from '@/types/graph';
|
|
5
5
|
|
|
@@ -9,12 +9,10 @@ import type { UIGraphJSON } from '@/types/graph';
|
|
|
9
9
|
*/
|
|
10
10
|
export class Graph {
|
|
11
11
|
public readonly viewports: Viewport[] = [];
|
|
12
|
-
private sys:
|
|
12
|
+
private sys: GraphSession;
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
constructor(system: System) {
|
|
17
|
-
this.sys = system;
|
|
14
|
+
constructor(session: GraphSession) {
|
|
15
|
+
this.sys = session;
|
|
18
16
|
}
|
|
19
17
|
|
|
20
18
|
setViewport(index: number, viewport: Viewport) {
|
|
@@ -83,13 +81,14 @@ export class Graph {
|
|
|
83
81
|
}
|
|
84
82
|
|
|
85
83
|
serialize(): UIGraphJSON {
|
|
84
|
+
const meta = this.sys.metaStore.getState();
|
|
86
85
|
return {
|
|
87
86
|
v: '1.0.0',
|
|
88
|
-
name:
|
|
87
|
+
name: meta.name,
|
|
89
88
|
user: {
|
|
90
89
|
viewport: this.viewports[0] || { x: 0, y: 0, zoom: 1 }
|
|
91
90
|
},
|
|
92
|
-
annotations:
|
|
91
|
+
annotations: { ...meta.metadata },
|
|
93
92
|
data: {
|
|
94
93
|
layers: this.sys.layerStore.getState().serialize()
|
|
95
94
|
},
|
|
@@ -100,14 +99,11 @@ export class Graph {
|
|
|
100
99
|
}
|
|
101
100
|
|
|
102
101
|
getAnnotations() {
|
|
103
|
-
return { ...this.
|
|
102
|
+
return { ...this.sys.metaStore.getState().metadata };
|
|
104
103
|
}
|
|
105
104
|
|
|
106
105
|
setAnnotations(annotations: { [key: string]: any }) {
|
|
107
|
-
this.annotations
|
|
108
|
-
...this.annotations,
|
|
109
|
-
...annotations
|
|
110
|
-
};
|
|
106
|
+
this.sys.metaStore.getState().mergeMetadata(annotations);
|
|
111
107
|
this.sys.pubsub.publish('graphAnnotationsChanged', this.getAnnotations());
|
|
112
108
|
}
|
|
113
109
|
|
|
@@ -115,7 +111,8 @@ export class Graph {
|
|
|
115
111
|
//Load nodes
|
|
116
112
|
this.sys.nodeStore.getState().setNodes(data.nodes);
|
|
117
113
|
this.sys.edgeStore.getState().setEdges(data.edges);
|
|
118
|
-
this.
|
|
114
|
+
this.sys.metaStore.getState().setMetadata(data.annotations || {});
|
|
115
|
+
if (data.name) this.sys.metaStore.getState().setName(data.name);
|
|
119
116
|
this.sys.layerStore.getState().deserialize(data.data?.layers);
|
|
120
117
|
|
|
121
118
|
// Restore viewport
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
import { type StoreApi } from 'zustand';
|
|
2
|
+
import { UndoManager } from './undoRedo';
|
|
3
|
+
import { PubSub } from './pubsub';
|
|
4
|
+
import { Graph } from './graph';
|
|
5
|
+
import type { System, GraphPubSys } from './system';
|
|
6
|
+
import {
|
|
7
|
+
edgeStoreFactory,
|
|
8
|
+
flowStoreFactory,
|
|
9
|
+
nodeStoreFactory,
|
|
10
|
+
type EdgeStore,
|
|
11
|
+
type FlowStore,
|
|
12
|
+
type NodeStore
|
|
13
|
+
} from '@/store/flow';
|
|
14
|
+
import { controlsStoreFactory, type ControlsStore } from '@/store/controls';
|
|
15
|
+
import { variableStoreFactory, type VariableStore } from '@/store/variables';
|
|
16
|
+
import { selectionStoreFactory, type SelectionStore } from '@/store/selection';
|
|
17
|
+
import { refStoreFactory, type RefStore } from '@/store/refs';
|
|
18
|
+
import { actionStoreFactory, type ActionStore } from '@/store/actions';
|
|
19
|
+
import { traceStoreFactory, type TraceStore } from '@/store/traces';
|
|
20
|
+
import { eventsStoreFactory, type EventsStore } from '@/store/events';
|
|
21
|
+
import { layerStoreFactory, type LayerStore } from '@/store/layers';
|
|
22
|
+
import { logStoreFactory, type LogStore } from '@/store/logs';
|
|
23
|
+
import { graphMetaStoreFactory, type GraphMetaStore } from '@/store/graphMeta';
|
|
24
|
+
import type { UIGraphJSON } from '@/types/graph';
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Augmentable surface for per-graph state contributed by plugins. Mirrors
|
|
28
|
+
* {@link ISystem} at the editor level: a plugin adds typed properties to every
|
|
29
|
+
* graph by augmenting this interface and assigning them via
|
|
30
|
+
* {@link GraphSession.decorate} from inside a session extension.
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
* declare module '@/system/graphSession' {
|
|
34
|
+
* interface IGraphSession {
|
|
35
|
+
* myController?: MyController;
|
|
36
|
+
* }
|
|
37
|
+
* }
|
|
38
|
+
*/
|
|
39
|
+
export interface IGraphSession {}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Merge the augmentable surface into the class instance type. Declaration
|
|
43
|
+
* merging (same-named interface + class) makes plugin-added members , set via
|
|
44
|
+
* {@link GraphSession.decorate} , readable as `session.x`, which `implements`
|
|
45
|
+
* alone would NOT provide.
|
|
46
|
+
*/
|
|
47
|
+
// eslint-disable-next-line @typescript-eslint/no-empty-interface
|
|
48
|
+
export interface GraphSession extends IGraphSession {}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* A single open graph. Owns all per-graph state , nodes, edges, variables,
|
|
52
|
+
* selection, traces, layers, logs, undo history and a private pubsub , so that
|
|
53
|
+
* multiple graphs can be open simultaneously in complete isolation.
|
|
54
|
+
*
|
|
55
|
+
* Shared, editor-level resources (registry, specs, settings, notifications, ...)
|
|
56
|
+
* are reached through {@link GraphSession.editor}.
|
|
57
|
+
*
|
|
58
|
+
* Per-graph state contributed by editor plugins is attached on creation via
|
|
59
|
+
* session extensions (`system.registerSessionExtension`), which may register
|
|
60
|
+
* teardown through {@link GraphSession.onDispose}.
|
|
61
|
+
*/
|
|
62
|
+
export class GraphSession {
|
|
63
|
+
public readonly id: string;
|
|
64
|
+
public readonly editor: System;
|
|
65
|
+
/** Reactive graph-level properties (name + metadata). */
|
|
66
|
+
public readonly metaStore: StoreApi<GraphMetaStore>;
|
|
67
|
+
public readonly pubsub = new PubSub<GraphPubSys>();
|
|
68
|
+
public readonly undoManager = new UndoManager();
|
|
69
|
+
|
|
70
|
+
/** Display name, used as the graph tab title. Backed by {@link metaStore}. */
|
|
71
|
+
get name(): string {
|
|
72
|
+
return this.metaStore.getState().name;
|
|
73
|
+
}
|
|
74
|
+
set name(value: string) {
|
|
75
|
+
this.metaStore.getState().setName(value);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
public readonly controlStore: StoreApi<ControlsStore>;
|
|
79
|
+
public readonly variableStore: StoreApi<VariableStore>;
|
|
80
|
+
public readonly refStore: StoreApi<RefStore>;
|
|
81
|
+
public readonly logsStore: StoreApi<LogStore>;
|
|
82
|
+
public readonly eventsStore: StoreApi<EventsStore>;
|
|
83
|
+
public readonly nodeStore: StoreApi<NodeStore>;
|
|
84
|
+
public readonly edgeStore: StoreApi<EdgeStore>;
|
|
85
|
+
public readonly flowStore: StoreApi<FlowStore>;
|
|
86
|
+
public readonly selectionStore: StoreApi<SelectionStore>;
|
|
87
|
+
public readonly actionStore: StoreApi<ActionStore>;
|
|
88
|
+
public readonly layerStore: StoreApi<LayerStore>;
|
|
89
|
+
public readonly traceStore: StoreApi<TraceStore>;
|
|
90
|
+
public readonly graph: Graph;
|
|
91
|
+
|
|
92
|
+
/** Cleanups registered by session extensions, run (LIFO) on {@link dispose}. */
|
|
93
|
+
private readonly disposers: Array<() => void> = [];
|
|
94
|
+
|
|
95
|
+
constructor(editor: System, id = 'graph', name = 'Graph') {
|
|
96
|
+
this.id = id;
|
|
97
|
+
this.editor = editor;
|
|
98
|
+
this.metaStore = graphMetaStoreFactory(name);
|
|
99
|
+
|
|
100
|
+
// Construction order preserves the dependency wiring of the old System ctor.
|
|
101
|
+
this.controlStore = controlsStoreFactory();
|
|
102
|
+
this.variableStore = variableStoreFactory();
|
|
103
|
+
this.refStore = refStoreFactory();
|
|
104
|
+
this.logsStore = logStoreFactory();
|
|
105
|
+
this.eventsStore = eventsStoreFactory();
|
|
106
|
+
this.nodeStore = nodeStoreFactory(this);
|
|
107
|
+
this.edgeStore = edgeStoreFactory(this);
|
|
108
|
+
this.flowStore = flowStoreFactory(this);
|
|
109
|
+
this.selectionStore = selectionStoreFactory(this);
|
|
110
|
+
this.actionStore = actionStoreFactory(this);
|
|
111
|
+
this.layerStore = layerStoreFactory(this);
|
|
112
|
+
this.traceStore = traceStoreFactory(this);
|
|
113
|
+
this.graph = new Graph(this);
|
|
114
|
+
|
|
115
|
+
// Per-session behaviours (alignment, ...) are contributed by opt-in plugins
|
|
116
|
+
// via system.registerSessionExtension(...), not wired here. See the
|
|
117
|
+
// alignment plugin (`@/plugin/alignment`).
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Convenience access to the shared editor notifications service.
|
|
122
|
+
*/
|
|
123
|
+
get notifications() {
|
|
124
|
+
return this.editor.notifications;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Attach a plugin-contributed property to this session. The companion to the
|
|
129
|
+
* {@link IGraphSession} augmentation; mirrors {@link System.decorate}.
|
|
130
|
+
*/
|
|
131
|
+
decorate<K extends keyof IGraphSession>(
|
|
132
|
+
name: K,
|
|
133
|
+
val: IGraphSession[K]
|
|
134
|
+
): void {
|
|
135
|
+
(this as IGraphSession)[name] = val;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Register a cleanup to run when this session is disposed. Session extensions
|
|
140
|
+
* use this (via their returned cleanup) to tear down per-graph state they
|
|
141
|
+
* attached. Cleanups run in reverse registration order.
|
|
142
|
+
*/
|
|
143
|
+
onDispose(cleanup: () => void): void {
|
|
144
|
+
this.disposers.push(cleanup);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
serialize(): UIGraphJSON {
|
|
148
|
+
return this.graph.serialize();
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Tear down this session's reactive wiring. Called when its tab is closed so
|
|
153
|
+
* its pubsub subscriptions and trace flush loop don't leak. Extension-supplied
|
|
154
|
+
* cleanups run first (LIFO), then the built-in teardown.
|
|
155
|
+
*/
|
|
156
|
+
dispose(): void {
|
|
157
|
+
for (let i = this.disposers.length - 1; i >= 0; i--) {
|
|
158
|
+
try {
|
|
159
|
+
this.disposers[i]!();
|
|
160
|
+
} catch (err) {
|
|
161
|
+
console.error('GraphSession disposer failed', err);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
this.disposers.length = 0;
|
|
165
|
+
|
|
166
|
+
// Per-session plugin state (e.g. the graph runner's runController) is torn
|
|
167
|
+
// down by the extension cleanups registered above via onDispose , core no
|
|
168
|
+
// longer reaches into plugin-owned fields here.
|
|
169
|
+
this.traceStore.getState().connectEngine(undefined);
|
|
170
|
+
this.pubsub.clearAllSubscriptions();
|
|
171
|
+
}
|
|
172
|
+
}
|