@kiberon-labs/behave-graph-flow 1.0.0 → 2.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/preview.ts +16 -0
- package/.storybook/styles.css +10 -0
- package/.storybook/vscode.css +814 -0
- package/.turbo/turbo-build.log +7 -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/entry.css +4 -0
- package/dist/index.css +39 -0
- package/dist/index.css.map +1 -0
- package/dist/index.d.ts +2282 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +14873 -0
- package/dist/index.js.map +1 -0
- package/docs/notifications.md +246 -0
- package/docs/protocol.md +679 -0
- package/docs/specifics.md +191 -0
- package/package.json +85 -21
- package/postcss.config.ts +3 -4
- package/src/annotations/index.ts +32 -0
- package/src/components/FloatingToolbar/index.module.css +45 -0
- package/src/components/FloatingToolbar/index.tsx +256 -0
- package/src/components/Flow.tsx +276 -75
- package/src/components/contextMenus/NodePicker.module.css +274 -0
- package/src/components/contextMenus/NodePicker.tsx +481 -0
- package/src/components/contextMenus/edge.tsx +108 -0
- package/src/components/contextMenus/node.tsx +155 -0
- package/src/components/contextMenus/selection.tsx +77 -0
- package/src/components/controls/any/index.tsx +8 -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 +469 -0
- package/src/components/edges/offsetBezier.ts +134 -0
- package/src/components/hotKeys.tsx +20 -0
- package/src/components/layoutController/index.module.css +10 -0
- package/src/components/layoutController/index.tsx +117 -0
- package/src/components/layoutController/utils.ts +205 -0
- package/src/components/menubar/defaults.tsx +480 -0
- package/src/components/menubar/index.tsx +49 -0
- package/src/components/menubar/menuItem.module.css +16 -0
- package/src/components/menubar/menuItem.tsx +32 -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 +87 -0
- package/src/components/nodes/behave/NodeContainer.tsx +46 -0
- package/src/components/nodes/behave/index.tsx +14 -0
- package/src/components/nodes/comment/FormatToolbar.tsx +118 -0
- package/src/components/nodes/comment/comment.tsx +103 -0
- package/src/components/nodes/comment/styles.module.css +150 -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 +113 -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 +20 -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/conversation/index.module.css +151 -0
- package/src/components/panels/conversation/index.tsx +162 -0
- package/src/components/panels/events/CustomEventsEditor.tsx +384 -0
- package/src/components/panels/events/EditEventPanel.tsx +315 -0
- package/src/components/panels/events/ManageEventsPanel.tsx +98 -0
- package/src/components/panels/events/index.tsx +23 -0
- package/src/components/panels/events/styles.module.css +236 -0
- package/src/components/panels/history/index.tsx +92 -0
- package/src/components/panels/history/styles.module.css +106 -0
- package/src/components/panels/keymaps/index.module.css +78 -0
- package/src/components/panels/keymaps/index.tsx +167 -0
- package/src/components/panels/layers/index.tsx +240 -0
- package/src/components/panels/layers/styles.module.css +110 -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 +212 -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 +64 -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 +65 -0
- package/src/components/panels/nodeInputs/SocketGenerators.tsx +32 -0
- package/src/components/panels/nodeInputs/index.module.css +284 -0
- package/src/components/panels/nodeInputs/index.tsx +339 -0
- package/src/components/panels/nodeInputs/useNodeHandlers.ts +76 -0
- package/src/components/panels/nodeInputs/useNodeInputsData.ts +173 -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 +66 -0
- package/src/components/panels/search/index.tsx +215 -0
- package/src/components/panels/systemSettings/index.tsx +206 -0
- package/src/components/panels/systemSettings/styles.module.css +11 -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 +166 -0
- package/src/components/panels/traces/index.tsx +294 -0
- package/src/components/panels/traces/types.ts +48 -0
- package/src/components/panels/traces/useDerivedSpans.ts +212 -0
- package/src/components/panels/traces/utils.ts +25 -0
- package/src/components/panels/variables/CreateVariableScreen.tsx +162 -0
- package/src/components/panels/variables/ManageVariablesScreen.tsx +144 -0
- package/src/components/panels/variables/index.tsx +125 -0
- package/src/components/panels/variables/styles.module.css +236 -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 +76 -0
- package/src/components/sockets/input/styles.module.css +27 -0
- package/src/components/sockets/output/index.tsx +61 -0
- package/src/components/sockets/output/styles.module.css +27 -0
- package/src/css/prosemirror.css +57 -0
- package/src/css/rc-dock.css +112 -0
- package/src/css/rc-menu.css +100 -0
- package/src/css/vars.css +14 -0
- package/src/css/vscode.css +13 -0
- package/src/entry.css +4 -0
- package/src/generators/CustomEventOnTriggeredGenerator.tsx +85 -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/registerDefaultGenerators.ts +34 -0
- package/src/hooks/useBehaveGraphFlow.ts +17 -16
- package/src/hooks/useDetachNodes.ts +39 -0
- package/src/hooks/useFlowHandlers.ts +115 -29
- package/src/hooks/useWasdPan.ts +188 -0
- package/src/index.css +146 -0
- package/src/index.ts +36 -18
- package/src/layout/dagre.tsx +119 -0
- package/src/layout/elk.ts +200 -0
- package/src/plugin/alignment/index.ts +81 -0
- package/src/plugin/docs/index.tsx +299 -0
- package/src/plugin/docs/panel/index.tsx +200 -0
- package/src/plugin/docs/panel/styles.module.css +174 -0
- package/src/plugin/graphrunner/actions.ts +253 -0
- package/src/plugin/graphrunner/buttons.tsx +87 -0
- package/src/plugin/graphrunner/client.ts +704 -0
- package/src/plugin/graphrunner/index.tsx +255 -0
- package/src/plugin/graphrunner/panel.tsx +386 -0
- package/src/plugin/graphrunner/runner.ts +358 -0
- package/src/plugin/graphrunner/session.ts +243 -0
- package/src/plugin/graphrunner/store.ts +206 -0
- package/src/plugin/graphrunner/styles.module.css +211 -0
- package/src/plugin/graphrunner/transport.ts +224 -0
- package/src/plugin/graphrunner/types.ts +672 -0
- package/src/plugin/graphrunner-local/execution-utils.ts +457 -0
- package/src/plugin/graphrunner-local/index.tsx +166 -0
- package/src/plugin/graphrunner-local/panel.tsx +231 -0
- package/src/plugin/graphrunner-local/store.ts +41 -0
- package/src/plugin/graphrunner-local/styles.module.css +101 -0
- package/src/plugin/graphrunner-local/transport.ts +1372 -0
- package/src/plugin/graphrunner-local/types.ts +10 -0
- package/src/plugin/graphrunner-webworker/graph-executor.worker.ts +633 -0
- package/src/plugin/graphrunner-webworker/index.tsx +146 -0
- package/src/plugin/graphrunner-webworker/panel.tsx +173 -0
- package/src/plugin/graphrunner-webworker/store.ts +89 -0
- package/src/plugin/graphrunner-webworker/types.ts +17 -0
- package/src/plugin/graphrunner-webworker/worker-transport.ts +123 -0
- package/src/plugin/realtime/realtimeRunner.ts +570 -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/specifics/registerDefaultSpecifics.ts +5 -0
- package/src/store/actions.tsx +698 -0
- package/src/store/chat.ts +73 -0
- package/src/store/controls.tsx +62 -0
- package/src/store/documentation.tsx +69 -0
- package/src/store/events.tsx +116 -0
- package/src/store/flow.tsx +245 -0
- package/src/store/graphRunnerClient.ts +110 -0
- package/src/store/hotKeys.tsx +323 -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 +43 -0
- package/src/store/selection.ts +22 -0
- package/src/store/settings.ts +99 -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 +278 -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 +134 -0
- package/src/system/index.ts +3 -0
- package/src/system/notifications.ts +98 -0
- package/src/system/plugin.ts +27 -0
- package/src/system/provider.tsx +22 -0
- package/src/system/pubsub.ts +323 -0
- package/src/system/system.ts +223 -0
- package/src/system/tabLoader.tsx +265 -0
- package/src/system/undoRedo.ts +103 -0
- package/src/transformers/Uigraph.ts +60 -0
- package/src/transformers/behaveToFlow.ts +16 -4
- package/src/transformers/flowToBehave.ts +32 -12
- package/src/types/NodeMetadata.ts +27 -0
- package/src/types/graph.ts +49 -0
- package/src/types/nodes.ts +45 -0
- package/src/types.ts +16 -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 +28 -15
- 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/nodes/comment.stories.tsx +106 -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 +167 -0
- package/stories/defaults/systemGenerator.ts +38 -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/flowToBehave.test.ts +26 -4
- package/tests/notifications.test.ts +87 -0
- package/tests/saveLoad.test.ts +372 -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-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/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 +48 -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,134 @@
|
|
|
1
|
+
import type { Viewport } from 'reactflow';
|
|
2
|
+
import type { System } from './system';
|
|
3
|
+
import type { Edge } from 'reactflow';
|
|
4
|
+
import type { UIGraphJSON } from '@/types/graph';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* This is our internal graph representation that we use to perform transformations on
|
|
8
|
+
* It represents the general graph structure, not the underlying behavior graph instance
|
|
9
|
+
*/
|
|
10
|
+
export class Graph {
|
|
11
|
+
public readonly viewports: Viewport[] = [];
|
|
12
|
+
private sys: System;
|
|
13
|
+
|
|
14
|
+
protected annotations: { [key: string]: any } = {};
|
|
15
|
+
|
|
16
|
+
constructor(system: System) {
|
|
17
|
+
this.sys = system;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
setViewport(index: number, viewport: Viewport) {
|
|
21
|
+
this.viewports[index] = viewport;
|
|
22
|
+
this.sys.pubsub.publish('saveViewport', {
|
|
23
|
+
index: index,
|
|
24
|
+
viewport: viewport
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Clears the graph
|
|
30
|
+
*/
|
|
31
|
+
clear() {
|
|
32
|
+
const nodes = this.sys.nodeStore.getState().nodes;
|
|
33
|
+
const edges = this.sys.edgeStore.getState().edges;
|
|
34
|
+
this.sys.undoManager.execute({
|
|
35
|
+
name: 'Clear graph',
|
|
36
|
+
undo: () => {
|
|
37
|
+
this.sys.nodeStore.getState().setNodes(Object.values(nodes));
|
|
38
|
+
this.sys.edgeStore.getState().setEdges(Object.values(edges));
|
|
39
|
+
},
|
|
40
|
+
execute: () => {
|
|
41
|
+
this.sys.nodeStore.getState().setNodes([]);
|
|
42
|
+
this.sys.edgeStore.getState().setEdges([]);
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Return all edges that point into the nodes inputs.
|
|
49
|
+
* O(m) the amount of edges
|
|
50
|
+
*/
|
|
51
|
+
inEdges(nodeId: string, sourceHandle?: string): Edge[] {
|
|
52
|
+
//Get the edges
|
|
53
|
+
const edges = this.sys.edgeStore.getState().edges;
|
|
54
|
+
|
|
55
|
+
return Object.values(edges).filter((x) => {
|
|
56
|
+
if (x.target !== nodeId) {
|
|
57
|
+
return false;
|
|
58
|
+
}
|
|
59
|
+
if (sourceHandle) {
|
|
60
|
+
return x.targetHandle === sourceHandle;
|
|
61
|
+
}
|
|
62
|
+
return true;
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Return all edges that are pointed out by node v.
|
|
68
|
+
* O(m) the amount of edges
|
|
69
|
+
*/
|
|
70
|
+
outEdges(nodeId: string, targetHandle?: string): Edge[] {
|
|
71
|
+
//Get the edges
|
|
72
|
+
const edges = this.sys.edgeStore.getState().edges;
|
|
73
|
+
|
|
74
|
+
return Object.values(edges).filter((x) => {
|
|
75
|
+
if (x.source !== nodeId) {
|
|
76
|
+
return false;
|
|
77
|
+
}
|
|
78
|
+
if (targetHandle) {
|
|
79
|
+
return x.targetHandle === targetHandle;
|
|
80
|
+
}
|
|
81
|
+
return true;
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
serialize(): UIGraphJSON {
|
|
86
|
+
return {
|
|
87
|
+
v: '1.0.0',
|
|
88
|
+
name: 'Untitled Graph',
|
|
89
|
+
user: {
|
|
90
|
+
viewport: this.viewports[0] || { x: 0, y: 0, zoom: 1 }
|
|
91
|
+
},
|
|
92
|
+
annotations: this.annotations,
|
|
93
|
+
data: {
|
|
94
|
+
layers: this.sys.layerStore.getState().serialize()
|
|
95
|
+
},
|
|
96
|
+
flow: {},
|
|
97
|
+
nodes: Object.values(this.sys.nodeStore.getState().nodes),
|
|
98
|
+
edges: Object.values(this.sys.edgeStore.getState().edges)
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
getAnnotations() {
|
|
103
|
+
return { ...this.annotations };
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
setAnnotations(annotations: { [key: string]: any }) {
|
|
107
|
+
this.annotations = {
|
|
108
|
+
...this.annotations,
|
|
109
|
+
...annotations
|
|
110
|
+
};
|
|
111
|
+
this.sys.pubsub.publish('graphAnnotationsChanged', this.getAnnotations());
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
deseralize(data: UIGraphJSON) {
|
|
115
|
+
//Load nodes
|
|
116
|
+
this.sys.nodeStore.getState().setNodes(data.nodes);
|
|
117
|
+
this.sys.edgeStore.getState().setEdges(data.edges);
|
|
118
|
+
this.annotations = data.annotations || {};
|
|
119
|
+
this.sys.layerStore.getState().deserialize(data.data?.layers);
|
|
120
|
+
|
|
121
|
+
// Restore viewport
|
|
122
|
+
if (data.user?.viewport) {
|
|
123
|
+
const reactflow = this.sys.refStore.getState().getRef('reactflow');
|
|
124
|
+
if (reactflow) {
|
|
125
|
+
reactflow.setViewport(data.user.viewport);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// Restore multiple viewports if they exist
|
|
130
|
+
if (data.user?.viewports) {
|
|
131
|
+
this.viewports.splice(0, this.viewports.length, ...data.user.viewports);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import type { System } from '@/system/system';
|
|
2
|
+
import type { Renderable, Toast } from 'react-hot-toast';
|
|
3
|
+
|
|
4
|
+
export type NotificationType = 'info' | 'success' | 'error' | 'loading';
|
|
5
|
+
|
|
6
|
+
export interface NotificationOptions {
|
|
7
|
+
/**
|
|
8
|
+
* Toast ID for programmatic dismissal
|
|
9
|
+
*/
|
|
10
|
+
id?: string;
|
|
11
|
+
/**
|
|
12
|
+
* Duration in milliseconds. Set to Infinity to persist until manually dismissed
|
|
13
|
+
*/
|
|
14
|
+
duration?: number;
|
|
15
|
+
/**
|
|
16
|
+
* Position on screen
|
|
17
|
+
*/
|
|
18
|
+
position?: Toast['position'];
|
|
19
|
+
/**
|
|
20
|
+
* Custom icon
|
|
21
|
+
*/
|
|
22
|
+
icon?: Renderable;
|
|
23
|
+
/**
|
|
24
|
+
* Custom styles
|
|
25
|
+
*/
|
|
26
|
+
style?: React.CSSProperties;
|
|
27
|
+
/**
|
|
28
|
+
* Custom class name
|
|
29
|
+
*/
|
|
30
|
+
className?: string;
|
|
31
|
+
/**
|
|
32
|
+
* Accessible aria-live value
|
|
33
|
+
*/
|
|
34
|
+
ariaLive?: Toast['ariaProps'];
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export class Notifications {
|
|
38
|
+
private readonly system: System;
|
|
39
|
+
constructor(system: System) {
|
|
40
|
+
this.system = system;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Dismiss a specific toast or all toasts
|
|
44
|
+
*/
|
|
45
|
+
dismissNotification(toastId?: string): void {
|
|
46
|
+
this.system.pubsub.publish('notification:dismiss', { toastId });
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Show a notification toast
|
|
51
|
+
*/
|
|
52
|
+
notify(
|
|
53
|
+
message: string,
|
|
54
|
+
type: NotificationType = 'info',
|
|
55
|
+
options?: NotificationOptions
|
|
56
|
+
): void {
|
|
57
|
+
this.system.pubsub.publish('notification', {
|
|
58
|
+
type,
|
|
59
|
+
message,
|
|
60
|
+
options
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Show a success notification
|
|
66
|
+
*/
|
|
67
|
+
success(message: string, options?: NotificationOptions): void {
|
|
68
|
+
this.notify(message, 'success', options);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Show an error notification
|
|
73
|
+
*/
|
|
74
|
+
error(message: string, options?: NotificationOptions): void {
|
|
75
|
+
this.notify(message, 'error', options);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Show a loading notification
|
|
80
|
+
*/
|
|
81
|
+
loading(message: string, options?: NotificationOptions): void {
|
|
82
|
+
this.notify(message, 'loading', options);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Show an info notification
|
|
87
|
+
*/
|
|
88
|
+
info(message: string, options?: NotificationOptions): void {
|
|
89
|
+
this.notify(message, 'info', options);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Dismiss a specific toast or all toasts
|
|
94
|
+
*/
|
|
95
|
+
dismiss(toastId?: string): void {
|
|
96
|
+
this.system.pubsub.publish('notification:dismiss', { toastId });
|
|
97
|
+
}
|
|
98
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { System } from '.';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Plugin initialization function type
|
|
5
|
+
* @template TOptions - Type of options object passed to the plugin
|
|
6
|
+
*/
|
|
7
|
+
export interface Plugin<TOptions = void> {
|
|
8
|
+
(system: System, options: TOptions): void | Promise<void>;
|
|
9
|
+
}
|
|
10
|
+
export type PluginOpts = {
|
|
11
|
+
name: string;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export type LoadablePlugin<TOptions = void> = {
|
|
15
|
+
loader: Plugin<TOptions>;
|
|
16
|
+
opts: PluginOpts;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
export const plugin = <TOptions = void>(
|
|
20
|
+
registerfunc: Plugin<TOptions>,
|
|
21
|
+
opts: PluginOpts
|
|
22
|
+
): LoadablePlugin<TOptions> => {
|
|
23
|
+
return {
|
|
24
|
+
loader: registerfunc,
|
|
25
|
+
opts: opts
|
|
26
|
+
};
|
|
27
|
+
};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import React, { createContext, useContext, type ReactNode } from 'react';
|
|
2
|
+
import type { System } from './system';
|
|
3
|
+
|
|
4
|
+
export const SystemContext = createContext<System | undefined>(undefined);
|
|
5
|
+
|
|
6
|
+
export type SystemProviderProps = {
|
|
7
|
+
children: ReactNode;
|
|
8
|
+
value: System;
|
|
9
|
+
};
|
|
10
|
+
export function SystemProvider({ children, value }: SystemProviderProps) {
|
|
11
|
+
return <SystemContext value={value}>{children}</SystemContext>;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export function useSystem(): System {
|
|
15
|
+
const context = useContext(SystemContext);
|
|
16
|
+
|
|
17
|
+
if (context === undefined) {
|
|
18
|
+
throw new Error('useSystem must be used within a SystemProvider');
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
return context;
|
|
22
|
+
}
|
|
@@ -0,0 +1,323 @@
|
|
|
1
|
+
export interface TopicEvents {
|
|
2
|
+
// This interface is meant to be extended in other parts of the application
|
|
3
|
+
// using module augmentation.
|
|
4
|
+
// Example:
|
|
5
|
+
// declare module './pubsub' {
|
|
6
|
+
// export interface TopicEvents {
|
|
7
|
+
// 'user.created': { id: string; name: string };
|
|
8
|
+
// 'notification': string;
|
|
9
|
+
// }
|
|
10
|
+
// }
|
|
11
|
+
[topic: string]: any;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
type Subscriber<Events extends TopicEvents, K extends keyof Events> = (
|
|
15
|
+
message: K,
|
|
16
|
+
data: Events[K]
|
|
17
|
+
) => void;
|
|
18
|
+
|
|
19
|
+
type AnySubscriber = (message: string, data: any) => void;
|
|
20
|
+
|
|
21
|
+
export class PubSub<Events extends TopicEvents = TopicEvents> {
|
|
22
|
+
private messages: Record<string, Record<string, AnySubscriber>> = {};
|
|
23
|
+
private lastUid = -1;
|
|
24
|
+
private static readonly ALL_SUBSCRIBING_MSG = '*';
|
|
25
|
+
|
|
26
|
+
private hasKeys(obj: object): boolean {
|
|
27
|
+
for (const key in obj) {
|
|
28
|
+
if (Object.prototype.hasOwnProperty.call(obj, key)) {
|
|
29
|
+
return true;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
return false;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
private throwException(ex: Error) {
|
|
36
|
+
return function reThrowException() {
|
|
37
|
+
throw ex;
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
private callSubscriberWithDelayedExceptions(
|
|
42
|
+
subscriber: AnySubscriber,
|
|
43
|
+
message: string,
|
|
44
|
+
data: any
|
|
45
|
+
) {
|
|
46
|
+
try {
|
|
47
|
+
subscriber(message, data);
|
|
48
|
+
} catch (ex: any) {
|
|
49
|
+
setTimeout(this.throwException(ex), 0);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
private callSubscriberWithImmediateExceptions(
|
|
54
|
+
subscriber: AnySubscriber,
|
|
55
|
+
message: string,
|
|
56
|
+
data: any
|
|
57
|
+
) {
|
|
58
|
+
subscriber(message, data);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
private deliverMessage(
|
|
62
|
+
originalMessage: string,
|
|
63
|
+
matchedMessage: string,
|
|
64
|
+
data: any,
|
|
65
|
+
immediateExceptions?: boolean
|
|
66
|
+
) {
|
|
67
|
+
const subscribers = this.messages[matchedMessage];
|
|
68
|
+
const callSubscriber = immediateExceptions
|
|
69
|
+
? this.callSubscriberWithImmediateExceptions
|
|
70
|
+
: this.callSubscriberWithDelayedExceptions;
|
|
71
|
+
|
|
72
|
+
if (!Object.prototype.hasOwnProperty.call(this.messages, matchedMessage)) {
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
for (const s in subscribers) {
|
|
77
|
+
if (Object.prototype.hasOwnProperty.call(subscribers, s)) {
|
|
78
|
+
callSubscriber.call(this, subscribers[s]!, originalMessage, data);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
private createDeliveryFunction<K extends keyof Events & string>(
|
|
84
|
+
message: K,
|
|
85
|
+
data: Events[K],
|
|
86
|
+
immediateExceptions?: boolean
|
|
87
|
+
): () => void {
|
|
88
|
+
return () => {
|
|
89
|
+
const messageString = message as string;
|
|
90
|
+
let topic = messageString;
|
|
91
|
+
let position = topic.lastIndexOf('.');
|
|
92
|
+
|
|
93
|
+
this.deliverMessage(
|
|
94
|
+
messageString,
|
|
95
|
+
messageString,
|
|
96
|
+
data,
|
|
97
|
+
immediateExceptions
|
|
98
|
+
);
|
|
99
|
+
|
|
100
|
+
while (position !== -1) {
|
|
101
|
+
topic = topic.substr(0, position);
|
|
102
|
+
position = topic.lastIndexOf('.');
|
|
103
|
+
this.deliverMessage(messageString, topic, data, immediateExceptions);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
this.deliverMessage(
|
|
107
|
+
messageString,
|
|
108
|
+
PubSub.ALL_SUBSCRIBING_MSG,
|
|
109
|
+
data,
|
|
110
|
+
immediateExceptions
|
|
111
|
+
);
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
private hasDirectSubscribersFor(message: string): boolean {
|
|
116
|
+
const topic = String(message);
|
|
117
|
+
return (
|
|
118
|
+
Object.prototype.hasOwnProperty.call(this.messages, topic) &&
|
|
119
|
+
this.hasKeys(this.messages[topic]!)
|
|
120
|
+
);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
private messageHasSubscribers(message: string): boolean {
|
|
124
|
+
let topic = String(message);
|
|
125
|
+
let found =
|
|
126
|
+
this.hasDirectSubscribersFor(topic) ||
|
|
127
|
+
this.hasDirectSubscribersFor(PubSub.ALL_SUBSCRIBING_MSG);
|
|
128
|
+
let position = topic.lastIndexOf('.');
|
|
129
|
+
|
|
130
|
+
while (!found && position !== -1) {
|
|
131
|
+
topic = topic.substr(0, position);
|
|
132
|
+
position = topic.lastIndexOf('.');
|
|
133
|
+
found = this.hasDirectSubscribersFor(topic);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
return found;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
private internalPublish<K extends keyof Events & string>(
|
|
140
|
+
message: K,
|
|
141
|
+
data: Events[K],
|
|
142
|
+
sync: boolean,
|
|
143
|
+
immediateExceptions: boolean = false
|
|
144
|
+
): boolean {
|
|
145
|
+
const messageString = message as string;
|
|
146
|
+
|
|
147
|
+
const deliver = this.createDeliveryFunction(
|
|
148
|
+
message,
|
|
149
|
+
data,
|
|
150
|
+
immediateExceptions
|
|
151
|
+
);
|
|
152
|
+
const hasSubscribers = this.messageHasSubscribers(messageString);
|
|
153
|
+
|
|
154
|
+
if (!hasSubscribers) {
|
|
155
|
+
return false;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
if (sync) {
|
|
159
|
+
deliver();
|
|
160
|
+
} else {
|
|
161
|
+
setTimeout(deliver, 0);
|
|
162
|
+
}
|
|
163
|
+
return true;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
public publishHook<K extends keyof Events & string>(
|
|
167
|
+
message: K,
|
|
168
|
+
data: Events[K]
|
|
169
|
+
): boolean {
|
|
170
|
+
return this.internalPublish(message, data, false, true);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
public publish<K extends keyof Events & string>(
|
|
174
|
+
message: K,
|
|
175
|
+
data: Events[K]
|
|
176
|
+
): boolean {
|
|
177
|
+
return this.internalPublish(message, data, false);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
public publishSync<K extends keyof Events & string>(
|
|
181
|
+
message: K,
|
|
182
|
+
data: Events[K]
|
|
183
|
+
): boolean {
|
|
184
|
+
return this.internalPublish(message, data, true);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
public subscribe<K extends keyof Events & string>(
|
|
188
|
+
message: K,
|
|
189
|
+
func: Subscriber<Events, K>
|
|
190
|
+
): string | false {
|
|
191
|
+
if (typeof func !== 'function') {
|
|
192
|
+
return false;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
const messageString = message as string;
|
|
196
|
+
|
|
197
|
+
if (!Object.prototype.hasOwnProperty.call(this.messages, messageString)) {
|
|
198
|
+
this.messages[messageString] = {};
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
const token = `uid_${String(++this.lastUid)}`;
|
|
202
|
+
this.messages[messageString]![token] = func as AnySubscriber;
|
|
203
|
+
|
|
204
|
+
return token;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
public subscribeAll(func: AnySubscriber): string | false {
|
|
208
|
+
return this.subscribe(PubSub.ALL_SUBSCRIBING_MSG, func);
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
public subscribeOnce<K extends keyof Events & string>(
|
|
212
|
+
message: K,
|
|
213
|
+
func: Subscriber<Events, K>
|
|
214
|
+
): this {
|
|
215
|
+
const token = this.subscribe(message, (msg, data) => {
|
|
216
|
+
this.unsubscribe(token as string);
|
|
217
|
+
func(msg, data);
|
|
218
|
+
});
|
|
219
|
+
return this;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
public clearAllSubscriptions(): void {
|
|
223
|
+
this.messages = {};
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
public clearSubscriptions(topic: string): void {
|
|
227
|
+
for (const m in this.messages) {
|
|
228
|
+
if (
|
|
229
|
+
Object.prototype.hasOwnProperty.call(this.messages, m) &&
|
|
230
|
+
m.indexOf(topic) === 0
|
|
231
|
+
) {
|
|
232
|
+
delete this.messages[m];
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
public countSubscriptions(topic: string): number {
|
|
238
|
+
let count = 0;
|
|
239
|
+
for (const m in this.messages) {
|
|
240
|
+
if (
|
|
241
|
+
Object.prototype.hasOwnProperty.call(this.messages, m) &&
|
|
242
|
+
m.indexOf(topic) === 0
|
|
243
|
+
) {
|
|
244
|
+
for (const token in this.messages[m]) {
|
|
245
|
+
if (Object.prototype.hasOwnProperty.call(this.messages[m], token)) {
|
|
246
|
+
count++;
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
return count;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
public getSubscriptions(topic: string): string[] {
|
|
255
|
+
const list: string[] = [];
|
|
256
|
+
for (const m in this.messages) {
|
|
257
|
+
if (
|
|
258
|
+
Object.prototype.hasOwnProperty.call(this.messages, m) &&
|
|
259
|
+
m.indexOf(topic) === 0
|
|
260
|
+
) {
|
|
261
|
+
list.push(m);
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
return list;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
private descendantTopicExists(topic: string): boolean {
|
|
268
|
+
for (const m in this.messages) {
|
|
269
|
+
if (
|
|
270
|
+
Object.prototype.hasOwnProperty.call(this.messages, m) &&
|
|
271
|
+
m.indexOf(topic) === 0
|
|
272
|
+
) {
|
|
273
|
+
return true;
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
return false;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
public unsubscribe(value: string | Function): boolean | string {
|
|
280
|
+
const isTopic =
|
|
281
|
+
typeof value === 'string' &&
|
|
282
|
+
(Object.prototype.hasOwnProperty.call(this.messages, value) ||
|
|
283
|
+
this.descendantTopicExists(value));
|
|
284
|
+
const isToken = !isTopic && typeof value === 'string';
|
|
285
|
+
const isFunction = typeof value === 'function';
|
|
286
|
+
let result: boolean | string = false;
|
|
287
|
+
|
|
288
|
+
if (isTopic) {
|
|
289
|
+
this.clearSubscriptions(value as string);
|
|
290
|
+
return true; // Indicate success
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
for (const m in this.messages) {
|
|
294
|
+
if (Object.prototype.hasOwnProperty.call(this.messages, m)) {
|
|
295
|
+
const message = this.messages[m];
|
|
296
|
+
|
|
297
|
+
if (!message) {
|
|
298
|
+
continue;
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
if (isToken && message[value as string]) {
|
|
302
|
+
delete message[value as string];
|
|
303
|
+
result = value;
|
|
304
|
+
break;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
if (isFunction) {
|
|
308
|
+
for (const t in message) {
|
|
309
|
+
if (
|
|
310
|
+
Object.prototype.hasOwnProperty.call(message, t) &&
|
|
311
|
+
message[t] === value
|
|
312
|
+
) {
|
|
313
|
+
delete message[t];
|
|
314
|
+
result = true;
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
return result;
|
|
322
|
+
}
|
|
323
|
+
}
|