@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.
Files changed (314) hide show
  1. package/.fallowrc.json +16 -0
  2. package/.storybook/main.ts +32 -0
  3. package/.storybook/preview.ts +16 -0
  4. package/.storybook/styles.css +10 -0
  5. package/.storybook/vscode.css +814 -0
  6. package/.turbo/turbo-build.log +7 -0
  7. package/LICENSE +6 -0
  8. package/README.md +2 -2
  9. package/data/Polynomial.json +510 -0
  10. package/data/sequence.json +337 -0
  11. package/data/trigger-event.json +241 -0
  12. package/data/variable-change.json +210 -0
  13. package/dist/entry.css +4 -0
  14. package/dist/index.css +39 -0
  15. package/dist/index.css.map +1 -0
  16. package/dist/index.d.ts +2282 -0
  17. package/dist/index.d.ts.map +1 -0
  18. package/dist/index.js +14873 -0
  19. package/dist/index.js.map +1 -0
  20. package/docs/notifications.md +246 -0
  21. package/docs/protocol.md +679 -0
  22. package/docs/specifics.md +191 -0
  23. package/package.json +85 -21
  24. package/postcss.config.ts +3 -4
  25. package/src/annotations/index.ts +32 -0
  26. package/src/components/FloatingToolbar/index.module.css +45 -0
  27. package/src/components/FloatingToolbar/index.tsx +256 -0
  28. package/src/components/Flow.tsx +276 -75
  29. package/src/components/contextMenus/NodePicker.module.css +274 -0
  30. package/src/components/contextMenus/NodePicker.tsx +481 -0
  31. package/src/components/contextMenus/edge.tsx +108 -0
  32. package/src/components/contextMenus/node.tsx +155 -0
  33. package/src/components/contextMenus/selection.tsx +77 -0
  34. package/src/components/controls/any/index.tsx +8 -0
  35. package/src/components/controls/boolean/index.tsx +13 -0
  36. package/src/components/controls/colorPicker/InputPopover.module.css +100 -0
  37. package/src/components/controls/colorPicker/InputPopover.tsx +31 -0
  38. package/src/components/controls/colorPicker/index.module.css +18 -0
  39. package/src/components/controls/colorPicker/index.tsx +61 -0
  40. package/src/components/controls/number/index.tsx +35 -0
  41. package/src/components/controls/string/index.tsx +16 -0
  42. package/src/components/edges/index.tsx +469 -0
  43. package/src/components/edges/offsetBezier.ts +134 -0
  44. package/src/components/hotKeys.tsx +20 -0
  45. package/src/components/layoutController/index.module.css +10 -0
  46. package/src/components/layoutController/index.tsx +117 -0
  47. package/src/components/layoutController/utils.ts +205 -0
  48. package/src/components/menubar/defaults.tsx +480 -0
  49. package/src/components/menubar/index.tsx +49 -0
  50. package/src/components/menubar/menuItem.module.css +16 -0
  51. package/src/components/menubar/menuItem.tsx +32 -0
  52. package/src/components/nodes/behave/Node.module.css +23 -0
  53. package/src/components/nodes/behave/Node.tsx +176 -0
  54. package/src/components/nodes/behave/NodeContainer.module.css +87 -0
  55. package/src/components/nodes/behave/NodeContainer.tsx +46 -0
  56. package/src/components/nodes/behave/index.tsx +14 -0
  57. package/src/components/nodes/comment/FormatToolbar.tsx +118 -0
  58. package/src/components/nodes/comment/comment.tsx +103 -0
  59. package/src/components/nodes/comment/styles.module.css +150 -0
  60. package/src/components/nodes/group/index.tsx +109 -0
  61. package/src/components/nodes/wrapper/index.tsx +73 -0
  62. package/src/components/nodes/wrapper/styles.module.css +113 -0
  63. package/src/components/notifications/NotificationProvider.tsx +81 -0
  64. package/src/components/notifications/index.ts +2 -0
  65. package/src/components/notifications/utils.ts +71 -0
  66. package/src/components/panels/alignment/index.module.css +20 -0
  67. package/src/components/panels/alignment/index.tsx +244 -0
  68. package/src/components/panels/base/index.tsx +5 -0
  69. package/src/components/panels/base/styles.module.css +12 -0
  70. package/src/components/panels/conversation/index.module.css +151 -0
  71. package/src/components/panels/conversation/index.tsx +162 -0
  72. package/src/components/panels/events/CustomEventsEditor.tsx +384 -0
  73. package/src/components/panels/events/EditEventPanel.tsx +315 -0
  74. package/src/components/panels/events/ManageEventsPanel.tsx +98 -0
  75. package/src/components/panels/events/index.tsx +23 -0
  76. package/src/components/panels/events/styles.module.css +236 -0
  77. package/src/components/panels/history/index.tsx +92 -0
  78. package/src/components/panels/history/styles.module.css +106 -0
  79. package/src/components/panels/keymaps/index.module.css +78 -0
  80. package/src/components/panels/keymaps/index.tsx +167 -0
  81. package/src/components/panels/layers/index.tsx +240 -0
  82. package/src/components/panels/layers/styles.module.css +110 -0
  83. package/src/components/panels/legend/index.module.css +6 -0
  84. package/src/components/panels/legend/index.tsx +76 -0
  85. package/src/components/panels/logs/index.module.css +212 -0
  86. package/src/components/panels/logs/index.tsx +288 -0
  87. package/src/components/panels/nodeInputs/InputControl.tsx +63 -0
  88. package/src/components/panels/nodeInputs/InputsGroup.tsx +64 -0
  89. package/src/components/panels/nodeInputs/MultipleNodesView.tsx +37 -0
  90. package/src/components/panels/nodeInputs/NodeSettings.tsx +92 -0
  91. package/src/components/panels/nodeInputs/NodeTitleEditor.tsx +125 -0
  92. package/src/components/panels/nodeInputs/OutputsGroup.tsx +65 -0
  93. package/src/components/panels/nodeInputs/SocketGenerators.tsx +32 -0
  94. package/src/components/panels/nodeInputs/index.module.css +284 -0
  95. package/src/components/panels/nodeInputs/index.tsx +339 -0
  96. package/src/components/panels/nodeInputs/useNodeHandlers.ts +76 -0
  97. package/src/components/panels/nodeInputs/useNodeInputsData.ts +173 -0
  98. package/src/components/panels/nodePicker/index.tsx +115 -0
  99. package/src/components/panels/panel/index.module.css +66 -0
  100. package/src/components/panels/panel/index.tsx +88 -0
  101. package/src/components/panels/search/index.module.css +66 -0
  102. package/src/components/panels/search/index.tsx +215 -0
  103. package/src/components/panels/systemSettings/index.tsx +206 -0
  104. package/src/components/panels/systemSettings/styles.module.css +11 -0
  105. package/src/components/panels/traces/GridLines.tsx +38 -0
  106. package/src/components/panels/traces/TimeGrid.tsx +48 -0
  107. package/src/components/panels/traces/TraceLane.tsx +62 -0
  108. package/src/components/panels/traces/TraceTooltip.tsx +22 -0
  109. package/src/components/panels/traces/TracesHeader.tsx +56 -0
  110. package/src/components/panels/traces/index.module.css +166 -0
  111. package/src/components/panels/traces/index.tsx +294 -0
  112. package/src/components/panels/traces/types.ts +48 -0
  113. package/src/components/panels/traces/useDerivedSpans.ts +212 -0
  114. package/src/components/panels/traces/utils.ts +25 -0
  115. package/src/components/panels/variables/CreateVariableScreen.tsx +162 -0
  116. package/src/components/panels/variables/ManageVariablesScreen.tsx +144 -0
  117. package/src/components/panels/variables/index.tsx +125 -0
  118. package/src/components/panels/variables/styles.module.css +236 -0
  119. package/src/components/primitives/icon.module.css +45 -0
  120. package/src/components/primitives/icon.tsx +38 -0
  121. package/src/components/sockets/input/index.tsx +76 -0
  122. package/src/components/sockets/input/styles.module.css +27 -0
  123. package/src/components/sockets/output/index.tsx +61 -0
  124. package/src/components/sockets/output/styles.module.css +27 -0
  125. package/src/css/prosemirror.css +57 -0
  126. package/src/css/rc-dock.css +112 -0
  127. package/src/css/rc-menu.css +100 -0
  128. package/src/css/vars.css +14 -0
  129. package/src/css/vscode.css +13 -0
  130. package/src/entry.css +4 -0
  131. package/src/generators/CustomEventOnTriggeredGenerator.tsx +85 -0
  132. package/src/generators/SequenceGenerator.tsx +104 -0
  133. package/src/generators/SwitchOnIntegerGenerator.tsx +256 -0
  134. package/src/generators/SwitchOnStringGenerator.tsx +263 -0
  135. package/src/generators/registerDefaultGenerators.ts +34 -0
  136. package/src/hooks/useBehaveGraphFlow.ts +17 -16
  137. package/src/hooks/useDetachNodes.ts +39 -0
  138. package/src/hooks/useFlowHandlers.ts +115 -29
  139. package/src/hooks/useWasdPan.ts +188 -0
  140. package/src/index.css +146 -0
  141. package/src/index.ts +36 -18
  142. package/src/layout/dagre.tsx +119 -0
  143. package/src/layout/elk.ts +200 -0
  144. package/src/plugin/alignment/index.ts +81 -0
  145. package/src/plugin/docs/index.tsx +299 -0
  146. package/src/plugin/docs/panel/index.tsx +200 -0
  147. package/src/plugin/docs/panel/styles.module.css +174 -0
  148. package/src/plugin/graphrunner/actions.ts +253 -0
  149. package/src/plugin/graphrunner/buttons.tsx +87 -0
  150. package/src/plugin/graphrunner/client.ts +704 -0
  151. package/src/plugin/graphrunner/index.tsx +255 -0
  152. package/src/plugin/graphrunner/panel.tsx +386 -0
  153. package/src/plugin/graphrunner/runner.ts +358 -0
  154. package/src/plugin/graphrunner/session.ts +243 -0
  155. package/src/plugin/graphrunner/store.ts +206 -0
  156. package/src/plugin/graphrunner/styles.module.css +211 -0
  157. package/src/plugin/graphrunner/transport.ts +224 -0
  158. package/src/plugin/graphrunner/types.ts +672 -0
  159. package/src/plugin/graphrunner-local/execution-utils.ts +457 -0
  160. package/src/plugin/graphrunner-local/index.tsx +166 -0
  161. package/src/plugin/graphrunner-local/panel.tsx +231 -0
  162. package/src/plugin/graphrunner-local/store.ts +41 -0
  163. package/src/plugin/graphrunner-local/styles.module.css +101 -0
  164. package/src/plugin/graphrunner-local/transport.ts +1372 -0
  165. package/src/plugin/graphrunner-local/types.ts +10 -0
  166. package/src/plugin/graphrunner-webworker/graph-executor.worker.ts +633 -0
  167. package/src/plugin/graphrunner-webworker/index.tsx +146 -0
  168. package/src/plugin/graphrunner-webworker/panel.tsx +173 -0
  169. package/src/plugin/graphrunner-webworker/store.ts +89 -0
  170. package/src/plugin/graphrunner-webworker/types.ts +17 -0
  171. package/src/plugin/graphrunner-webworker/worker-transport.ts +123 -0
  172. package/src/plugin/realtime/realtimeRunner.ts +570 -0
  173. package/src/specifics/CustomEventOnTriggeredSpecific.tsx +92 -0
  174. package/src/specifics/CustomEventTriggerSpecific.tsx +141 -0
  175. package/src/specifics/VariableGetSpecific.tsx +110 -0
  176. package/src/specifics/VariableSetSpecific.tsx +110 -0
  177. package/src/specifics/registerDefaultSpecifics.ts +5 -0
  178. package/src/store/actions.tsx +698 -0
  179. package/src/store/chat.ts +73 -0
  180. package/src/store/controls.tsx +62 -0
  181. package/src/store/documentation.tsx +69 -0
  182. package/src/store/events.tsx +116 -0
  183. package/src/store/flow.tsx +245 -0
  184. package/src/store/graphRunnerClient.ts +110 -0
  185. package/src/store/hotKeys.tsx +323 -0
  186. package/src/store/layers.ts +259 -0
  187. package/src/store/legend.tsx +76 -0
  188. package/src/store/logs.ts +28 -0
  189. package/src/store/menubar.ts +41 -0
  190. package/src/store/refs.ts +84 -0
  191. package/src/store/registry.ts +43 -0
  192. package/src/store/selection.ts +22 -0
  193. package/src/store/settings.ts +99 -0
  194. package/src/store/socketGenerator.tsx +54 -0
  195. package/src/store/specific.tsx +75 -0
  196. package/src/store/specs.tsx +35 -0
  197. package/src/store/tabs.ts +278 -0
  198. package/src/store/toolbar.tsx +45 -0
  199. package/src/store/traces.ts +240 -0
  200. package/src/store/variables.ts +37 -0
  201. package/src/system/graph.ts +134 -0
  202. package/src/system/index.ts +3 -0
  203. package/src/system/notifications.ts +98 -0
  204. package/src/system/plugin.ts +27 -0
  205. package/src/system/provider.tsx +22 -0
  206. package/src/system/pubsub.ts +323 -0
  207. package/src/system/system.ts +223 -0
  208. package/src/system/tabLoader.tsx +265 -0
  209. package/src/system/undoRedo.ts +103 -0
  210. package/src/transformers/Uigraph.ts +60 -0
  211. package/src/transformers/behaveToFlow.ts +16 -4
  212. package/src/transformers/flowToBehave.ts +32 -12
  213. package/src/types/NodeMetadata.ts +27 -0
  214. package/src/types/graph.ts +49 -0
  215. package/src/types/nodes.ts +45 -0
  216. package/src/types.ts +16 -0
  217. package/src/util/colors.ts +1 -29
  218. package/src/util/downloadJson.ts +18 -0
  219. package/src/util/extractNodeMetadata.ts +16 -0
  220. package/src/util/getPickerFilters.ts +1 -1
  221. package/src/util/isBehaveNode.ts +6 -0
  222. package/src/util/isValidConnection.ts +28 -15
  223. package/src/util/mergeSockets.ts +29 -0
  224. package/src/util/serializeVariables.ts +66 -0
  225. package/src/util/sockets.ts +43 -0
  226. package/stories/apex/layoutController/example-graph.worker.ts +39 -0
  227. package/stories/apex/layoutController/index.stories.tsx +48 -0
  228. package/stories/apex/layoutController/webworker.stories.tsx +103 -0
  229. package/stories/apex/menubar/menubar.stories.tsx +19 -0
  230. package/stories/components/colorpicker/index.stories.tsx +20 -0
  231. package/stories/components/contextMenus/edge.stories.tsx +32 -0
  232. package/stories/components/contextMenus/node.stories.tsx +26 -0
  233. package/stories/components/contextMenus/nodePicker.stories.tsx +115 -0
  234. package/stories/components/controls/any/index.stories.tsx +19 -0
  235. package/stories/components/controls/boolean/index.stories.tsx +19 -0
  236. package/stories/components/controls/colorPicker/index.stories.tsx +49 -0
  237. package/stories/components/controls/number/index.stories.tsx +19 -0
  238. package/stories/components/controls/string/index.stories.tsx +19 -0
  239. package/stories/components/nodes/behaveNode.stories.tsx +108 -0
  240. package/stories/components/nodes/comment.stories.tsx +106 -0
  241. package/stories/components/panels/alignment.stories.tsx +24 -0
  242. package/stories/components/panels/events.stories.tsx +38 -0
  243. package/stories/components/panels/graphRunner.stories.tsx +317 -0
  244. package/stories/components/panels/history.stories.tsx +37 -0
  245. package/stories/components/panels/keymaps.stories.tsx +21 -0
  246. package/stories/components/panels/legend.stories.tsx +37 -0
  247. package/stories/components/panels/logs.stories.tsx +24 -0
  248. package/stories/components/panels/nodeInputs.stories.tsx +21 -0
  249. package/stories/components/panels/nodePicker.stories.tsx +37 -0
  250. package/stories/components/panels/panel.stories.tsx +39 -0
  251. package/stories/components/panels/search.stories.tsx +24 -0
  252. package/stories/components/panels/systemSettings.stories.tsx +26 -0
  253. package/stories/components/panels/traces.stories.tsx +225 -0
  254. package/stories/components/panels/variables.stories.tsx +24 -0
  255. package/stories/defaults/defaultStoryProvider.tsx +167 -0
  256. package/stories/defaults/systemGenerator.ts +38 -0
  257. package/tests/components/edges/offsetBezier.test.ts +51 -0
  258. package/tests/components/layoutController/utils.test.ts +68 -0
  259. package/tests/components/panels/traces/utils.test.ts +52 -0
  260. package/tests/flowToBehave.test.ts +26 -4
  261. package/tests/notifications.test.ts +87 -0
  262. package/tests/saveLoad.test.ts +372 -0
  263. package/tests/util/calculateNewEdge.test.ts +98 -0
  264. package/tests/util/getSocketsByNodeTypeAndHandleType.test.ts +31 -0
  265. package/tests/util/hasPositionMetaData.test.ts +33 -0
  266. package/tests/util/isBehaveNode.test.ts +22 -0
  267. package/tests/util/isHandleConnected.test.ts +37 -0
  268. package/tests/util/mergeSockets.test.ts +43 -0
  269. package/tests/visual/README.md +64 -0
  270. package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-alignment-chromium-win32.png +0 -0
  271. package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-conversation-chromium-win32.png +0 -0
  272. package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-events-chromium-win32.png +0 -0
  273. package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-history-chromium-win32.png +0 -0
  274. package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-keymaps-chromium-win32.png +0 -0
  275. package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-layers-chromium-win32.png +0 -0
  276. package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-legend-chromium-win32.png +0 -0
  277. package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-logs-chromium-win32.png +0 -0
  278. package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-nodeInputs-chromium-win32.png +0 -0
  279. package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-nodePicker-chromium-win32.png +0 -0
  280. package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-panel-chromium-win32.png +0 -0
  281. package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-search-chromium-win32.png +0 -0
  282. package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-systemSettings-chromium-win32.png +0 -0
  283. package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-traces-chromium-win32.png +0 -0
  284. package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-variables-chromium-win32.png +0 -0
  285. package/tests/visual/panels.visual.test.tsx +76 -0
  286. package/tsconfig.base.json +39 -0
  287. package/tsconfig.json +18 -59
  288. package/tsconfig.prod.json +23 -0
  289. package/tsdown.config.ts +15 -3
  290. package/typedoc.json +7 -7
  291. package/vite.config.js +7 -0
  292. package/vitest.config.ts +5 -2
  293. package/vitest.visual.config.ts +48 -0
  294. package/src/components/AutoSizeInput.tsx +0 -65
  295. package/src/components/Controls.tsx +0 -87
  296. package/src/components/InputSocket.tsx +0 -142
  297. package/src/components/Node.tsx +0 -68
  298. package/src/components/NodeContainer.tsx +0 -46
  299. package/src/components/NodePicker.tsx +0 -77
  300. package/src/components/OutputSocket.tsx +0 -58
  301. package/src/components/modals/ClearModal.tsx +0 -40
  302. package/src/components/modals/HelpModal.tsx +0 -36
  303. package/src/components/modals/LoadModal.tsx +0 -96
  304. package/src/components/modals/Modal.tsx +0 -64
  305. package/src/components/modals/SaveModal.tsx +0 -60
  306. package/src/hooks/useCustomNodeTypes.tsx +0 -31
  307. package/src/hooks/useGraphRunner.ts +0 -104
  308. package/src/hooks/useMergeMap.ts +0 -14
  309. package/src/hooks/useNodeSpecJson.ts +0 -20
  310. package/src/hooks/useQueriableDefinitions.ts +0 -22
  311. package/src/styles.css +0 -8
  312. package/tailwind.config.ts +0 -19
  313. package/tests/tsconfig.json +0 -10
  314. /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,3 @@
1
+ export * from './system';
2
+ export * from './provider';
3
+ export { subscribeToRef, useRefFromStore } from '@/store/refs';
@@ -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
+ }