@kiberon-labs/behave-graph-flow 1.0.0 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (378) hide show
  1. package/.fallowrc.json +16 -0
  2. package/.storybook/main.ts +32 -0
  3. package/.storybook/manager.ts +6 -0
  4. package/.storybook/preview.ts +64 -0
  5. package/.storybook/styles.css +16 -0
  6. package/.turbo/turbo-build.log +7 -0
  7. package/CHANGELOG.md +368 -0
  8. package/LICENSE +6 -0
  9. package/README.md +2 -2
  10. package/data/Polynomial.json +510 -0
  11. package/data/sequence.json +337 -0
  12. package/data/trigger-event.json +241 -0
  13. package/data/variable-change.json +210 -0
  14. package/dist/AnyControlImpl-Ds-CShIB.js +20 -0
  15. package/dist/AnyControlImpl-Ds-CShIB.js.map +1 -0
  16. package/dist/DocumentationBrowserPanelImpl-deZNzFX8.js +166 -0
  17. package/dist/DocumentationBrowserPanelImpl-deZNzFX8.js.map +1 -0
  18. package/dist/entry.css +4 -0
  19. package/dist/index.css +42 -0
  20. package/dist/index.css.map +1 -0
  21. package/dist/index.d.ts +3597 -0
  22. package/dist/index.d.ts.map +1 -0
  23. package/dist/index.js +18009 -0
  24. package/dist/index.js.map +1 -0
  25. package/dist/noteImpl-KkrrWgJd.js +242 -0
  26. package/dist/noteImpl-KkrrWgJd.js.map +1 -0
  27. package/dist/styles.module-CvmpDkZj.css +3 -0
  28. package/dist/styles.module-CvmpDkZj.css.map +1 -0
  29. package/dist/styles.module-DZxg8aW9.js +271 -0
  30. package/dist/styles.module-DZxg8aW9.js.map +1 -0
  31. package/dist/useChangeNodeData-ChQGK7AI.js +23 -0
  32. package/dist/useChangeNodeData-ChQGK7AI.js.map +1 -0
  33. package/docs/notifications.md +246 -0
  34. package/docs/protocol.md +702 -0
  35. package/docs/specifics.md +191 -0
  36. package/package.json +82 -22
  37. package/postcss.config.ts +3 -4
  38. package/src/annotations/index.ts +32 -0
  39. package/src/components/FloatingToolbar/index.module.css +37 -0
  40. package/src/components/FloatingToolbar/index.tsx +256 -0
  41. package/src/components/Flow.tsx +287 -75
  42. package/src/components/contextMenus/DynamicContextMenu.tsx +85 -0
  43. package/src/components/contextMenus/NodePicker.module.css +274 -0
  44. package/src/components/contextMenus/NodePicker.tsx +481 -0
  45. package/src/components/contextMenus/edge.tsx +22 -0
  46. package/src/components/contextMenus/node.tsx +15 -0
  47. package/src/components/contextMenus/selection.tsx +11 -0
  48. package/src/components/controls/any/AnyControlImpl.tsx +14 -0
  49. package/src/components/controls/any/index.tsx +19 -0
  50. package/src/components/controls/boolean/index.tsx +13 -0
  51. package/src/components/controls/colorPicker/InputPopover.module.css +100 -0
  52. package/src/components/controls/colorPicker/InputPopover.tsx +31 -0
  53. package/src/components/controls/colorPicker/index.module.css +18 -0
  54. package/src/components/controls/colorPicker/index.tsx +61 -0
  55. package/src/components/controls/number/index.tsx +35 -0
  56. package/src/components/controls/string/index.tsx +16 -0
  57. package/src/components/edges/index.tsx +475 -0
  58. package/src/components/edges/offsetBezier.ts +134 -0
  59. package/src/components/hotKeys.tsx +20 -0
  60. package/src/components/layoutController/index.module.css +13 -0
  61. package/src/components/layoutController/index.tsx +140 -0
  62. package/src/components/layoutController/utils.ts +248 -0
  63. package/src/components/menubar/defaults.tsx +516 -0
  64. package/src/components/menubar/index.tsx +49 -0
  65. package/src/components/menubar/menuItem.module.css +31 -0
  66. package/src/components/menubar/menuItem.tsx +65 -0
  67. package/src/components/nodes/behave/Node.module.css +23 -0
  68. package/src/components/nodes/behave/Node.tsx +176 -0
  69. package/src/components/nodes/behave/NodeContainer.module.css +88 -0
  70. package/src/components/nodes/behave/NodeContainer.tsx +46 -0
  71. package/src/components/nodes/behave/index.tsx +14 -0
  72. package/src/components/nodes/group/index.tsx +109 -0
  73. package/src/components/nodes/wrapper/index.tsx +73 -0
  74. package/src/components/nodes/wrapper/styles.module.css +87 -0
  75. package/src/components/notifications/NotificationProvider.tsx +81 -0
  76. package/src/components/notifications/index.ts +2 -0
  77. package/src/components/notifications/utils.ts +71 -0
  78. package/src/components/panels/alignment/index.module.css +10 -0
  79. package/src/components/panels/alignment/index.tsx +244 -0
  80. package/src/components/panels/base/index.tsx +5 -0
  81. package/src/components/panels/base/styles.module.css +12 -0
  82. package/src/components/panels/common/PanelHeader.module.css +24 -0
  83. package/src/components/panels/common/PanelHeader.tsx +22 -0
  84. package/src/components/panels/common/SectionTitle.module.css +13 -0
  85. package/src/components/panels/common/SectionTitle.tsx +10 -0
  86. package/src/components/panels/events/EditEventPanel.tsx +324 -0
  87. package/src/components/panels/events/ManageEventsPanel.tsx +101 -0
  88. package/src/components/panels/events/index.tsx +23 -0
  89. package/src/components/panels/events/styles.module.css +178 -0
  90. package/src/components/panels/graphProperties/index.tsx +125 -0
  91. package/src/components/panels/history/index.tsx +92 -0
  92. package/src/components/panels/history/styles.module.css +97 -0
  93. package/src/components/panels/keymaps/index.module.css +68 -0
  94. package/src/components/panels/keymaps/index.tsx +166 -0
  95. package/src/components/panels/layers/index.tsx +245 -0
  96. package/src/components/panels/layers/styles.module.css +107 -0
  97. package/src/components/panels/legend/index.module.css +6 -0
  98. package/src/components/panels/legend/index.tsx +76 -0
  99. package/src/components/panels/logs/index.module.css +218 -0
  100. package/src/components/panels/logs/index.tsx +288 -0
  101. package/src/components/panels/nodeInputs/InputControl.tsx +63 -0
  102. package/src/components/panels/nodeInputs/InputsGroup.tsx +65 -0
  103. package/src/components/panels/nodeInputs/MultipleNodesView.tsx +37 -0
  104. package/src/components/panels/nodeInputs/NodeSettings.tsx +92 -0
  105. package/src/components/panels/nodeInputs/NodeTitleEditor.tsx +125 -0
  106. package/src/components/panels/nodeInputs/OutputsGroup.tsx +55 -0
  107. package/src/components/panels/nodeInputs/SocketGenerators.tsx +32 -0
  108. package/src/components/panels/nodeInputs/index.module.css +308 -0
  109. package/src/components/panels/nodeInputs/index.tsx +349 -0
  110. package/src/components/panels/nodeInputs/useNodeHandlers.ts +76 -0
  111. package/src/components/panels/nodeInputs/useNodeInputsData.ts +153 -0
  112. package/src/components/panels/nodePicker/index.tsx +115 -0
  113. package/src/components/panels/panel/index.module.css +66 -0
  114. package/src/components/panels/panel/index.tsx +88 -0
  115. package/src/components/panels/search/index.module.css +16 -0
  116. package/src/components/panels/search/index.tsx +215 -0
  117. package/src/components/panels/systemSettings/ConversionsSettings.tsx +203 -0
  118. package/src/components/panels/systemSettings/index.tsx +251 -0
  119. package/src/components/panels/systemSettings/styles.module.css +138 -0
  120. package/src/components/panels/traces/GridLines.tsx +38 -0
  121. package/src/components/panels/traces/TimeGrid.tsx +48 -0
  122. package/src/components/panels/traces/TraceLane.tsx +62 -0
  123. package/src/components/panels/traces/TraceTooltip.tsx +22 -0
  124. package/src/components/panels/traces/TracesHeader.tsx +56 -0
  125. package/src/components/panels/traces/index.module.css +159 -0
  126. package/src/components/panels/traces/index.tsx +298 -0
  127. package/src/components/panels/traces/types.ts +48 -0
  128. package/src/components/panels/traces/useDerivedSpans.ts +307 -0
  129. package/src/components/panels/traces/utils.ts +33 -0
  130. package/src/components/panels/variables/CreateVariableScreen.tsx +162 -0
  131. package/src/components/panels/variables/ManageVariablesScreen.tsx +147 -0
  132. package/src/components/panels/variables/index.tsx +125 -0
  133. package/src/components/panels/variables/styles.module.css +149 -0
  134. package/src/components/primitives/icon.module.css +45 -0
  135. package/src/components/primitives/icon.tsx +38 -0
  136. package/src/components/sockets/input/index.tsx +83 -0
  137. package/src/components/sockets/input/styles.module.css +26 -0
  138. package/src/components/sockets/output/index.tsx +68 -0
  139. package/src/components/sockets/output/styles.module.css +22 -0
  140. package/src/css/notes.css +135 -0
  141. package/src/css/prosemirror.css +57 -0
  142. package/src/css/rc-dock.css +212 -0
  143. package/src/css/rc-menu.css +101 -0
  144. package/src/css/themes/kiberon.css +127 -0
  145. package/src/css/vars.css +198 -0
  146. package/src/css/vscode-elements.css +124 -0
  147. package/src/entry.css +4 -0
  148. package/src/generators/CallSubgraphGenerator.tsx +136 -0
  149. package/src/generators/CustomEventOnTriggeredGenerator.tsx +85 -0
  150. package/src/generators/GraphBoundaryGenerator.module.css +32 -0
  151. package/src/generators/GraphBoundaryGenerator.tsx +193 -0
  152. package/src/generators/SequenceGenerator.tsx +104 -0
  153. package/src/generators/SwitchOnIntegerGenerator.tsx +256 -0
  154. package/src/generators/SwitchOnStringGenerator.tsx +263 -0
  155. package/src/generators/callSubgraphSync.ts +126 -0
  156. package/src/generators/registerDefaultGenerators.ts +55 -0
  157. package/src/generators/registerDefaults.ts +26 -0
  158. package/src/hooks/useBehaveGraphFlow.ts +17 -16
  159. package/src/hooks/useFlowHandlers.ts +154 -30
  160. package/src/hooks/useWasdPan.ts +210 -0
  161. package/src/index.css +134 -0
  162. package/src/index.ts +53 -18
  163. package/src/manifest/contributionRegistry.ts +93 -0
  164. package/src/manifest/index.ts +4 -0
  165. package/src/manifest/loadManifest.ts +82 -0
  166. package/src/manifest/manifestPlugin.ts +29 -0
  167. package/src/manifest/passthroughValueType.ts +40 -0
  168. package/src/plugin/alignment/index.ts +91 -0
  169. package/src/plugin/autosave/controller.ts +366 -0
  170. package/src/plugin/autosave/index.tsx +114 -0
  171. package/src/plugin/autosave/panel/BackupPanel.tsx +141 -0
  172. package/src/plugin/autosave/panel/index.tsx +1 -0
  173. package/src/plugin/autosave/panel/styles.module.css +56 -0
  174. package/src/plugin/autosave/settings.ts +65 -0
  175. package/src/plugin/autosave/storage.ts +147 -0
  176. package/src/plugin/docs/index.tsx +297 -0
  177. package/src/plugin/docs/panel/DocumentationBrowserPanelImpl.tsx +200 -0
  178. package/src/plugin/docs/panel/index.tsx +21 -0
  179. package/src/plugin/docs/panel/styles.module.css +174 -0
  180. package/src/plugin/graphrunner/actions.ts +326 -0
  181. package/src/plugin/graphrunner/buttons.tsx +95 -0
  182. package/src/plugin/graphrunner/client.ts +707 -0
  183. package/src/plugin/graphrunner/index.tsx +184 -0
  184. package/src/plugin/graphrunner/panel.tsx +386 -0
  185. package/src/plugin/graphrunner/runController.ts +283 -0
  186. package/src/plugin/graphrunner/runner.ts +187 -0
  187. package/src/plugin/graphrunner/session.ts +243 -0
  188. package/src/plugin/graphrunner/store.ts +196 -0
  189. package/src/plugin/graphrunner/styles.module.css +171 -0
  190. package/src/plugin/graphrunner/transport.ts +250 -0
  191. package/src/plugin/graphrunner/types.ts +693 -0
  192. package/src/plugin/graphrunner-local/execution-utils.ts +637 -0
  193. package/src/plugin/graphrunner-local/index.tsx +172 -0
  194. package/src/plugin/graphrunner-local/panel.tsx +187 -0
  195. package/src/plugin/graphrunner-local/store.ts +41 -0
  196. package/src/plugin/graphrunner-local/styles.module.css +82 -0
  197. package/src/plugin/graphrunner-local/transport.ts +1339 -0
  198. package/src/plugin/graphrunner-local/types.ts +10 -0
  199. package/src/plugin/graphrunner-webworker/graph-executor.worker.ts +635 -0
  200. package/src/plugin/graphrunner-webworker/index.tsx +140 -0
  201. package/src/plugin/graphrunner-webworker/panel.tsx +173 -0
  202. package/src/plugin/graphrunner-webworker/store.ts +98 -0
  203. package/src/plugin/graphrunner-webworker/worker-transport.ts +123 -0
  204. package/src/plugin/kitchen-sink/index.ts +38 -0
  205. package/src/plugin/layout/dagre.ts +131 -0
  206. package/src/plugin/layout/elk.ts +216 -0
  207. package/src/plugin/layout/index.ts +80 -0
  208. package/src/plugin/notes/FormatToolbar.tsx +200 -0
  209. package/src/plugin/notes/index.tsx +191 -0
  210. package/src/plugin/notes/nodeActions.ts +100 -0
  211. package/src/plugin/notes/note.tsx +20 -0
  212. package/src/plugin/notes/noteImpl.tsx +89 -0
  213. package/src/plugin/realtime/realtimeRunner.ts +624 -0
  214. package/src/specifics/CustomEventOnTriggeredSpecific.tsx +92 -0
  215. package/src/specifics/CustomEventTriggerSpecific.tsx +141 -0
  216. package/src/specifics/VariableGetSpecific.tsx +110 -0
  217. package/src/specifics/VariableSetSpecific.tsx +110 -0
  218. package/src/store/actions.tsx +698 -0
  219. package/src/store/commands.ts +278 -0
  220. package/src/store/contextMenu.ts +192 -0
  221. package/src/store/controls.tsx +62 -0
  222. package/src/store/conversions.ts +47 -0
  223. package/src/store/documentation.tsx +69 -0
  224. package/src/store/events.tsx +116 -0
  225. package/src/store/flow.tsx +230 -0
  226. package/src/store/graphMeta.ts +39 -0
  227. package/src/store/hotKeys.tsx +364 -0
  228. package/src/store/layers.ts +259 -0
  229. package/src/store/legend.tsx +76 -0
  230. package/src/store/logs.ts +28 -0
  231. package/src/store/menubar.ts +41 -0
  232. package/src/store/refs.ts +84 -0
  233. package/src/store/registry.ts +51 -0
  234. package/src/store/selection.ts +22 -0
  235. package/src/store/settings.ts +99 -0
  236. package/src/store/settingsSchema.ts +210 -0
  237. package/src/store/socketGenerator.tsx +54 -0
  238. package/src/store/specific.tsx +75 -0
  239. package/src/store/specs.tsx +35 -0
  240. package/src/store/tabs.ts +282 -0
  241. package/src/store/toolbar.tsx +45 -0
  242. package/src/store/traces.ts +240 -0
  243. package/src/store/variables.ts +37 -0
  244. package/src/system/graph.ts +131 -0
  245. package/src/system/graphSession.ts +172 -0
  246. package/src/system/index.ts +6 -0
  247. package/src/system/notifications.ts +111 -0
  248. package/src/system/persistence.ts +82 -0
  249. package/src/system/plugin.ts +55 -0
  250. package/src/system/provider.tsx +86 -0
  251. package/src/system/pubsub.ts +323 -0
  252. package/src/system/system.ts +653 -0
  253. package/src/system/tabLoader.tsx +303 -0
  254. package/src/system/undoRedo.ts +103 -0
  255. package/src/transformers/Uigraph.ts +61 -0
  256. package/src/transformers/behaveToFlow.ts +16 -4
  257. package/src/transformers/contract.ts +87 -0
  258. package/src/transformers/flowToBehave.ts +40 -12
  259. package/src/types/NodeMetadata.ts +27 -0
  260. package/src/types/graph.ts +49 -0
  261. package/src/types/nodes.ts +50 -0
  262. package/src/types.ts +18 -0
  263. package/src/util/autoConvert.ts +200 -0
  264. package/src/util/colors.ts +1 -29
  265. package/src/util/downloadJson.ts +18 -0
  266. package/src/util/extractNodeMetadata.ts +16 -0
  267. package/src/util/getPickerFilters.ts +1 -1
  268. package/src/util/isBehaveNode.ts +6 -0
  269. package/src/util/isValidConnection.ts +51 -17
  270. package/src/util/mergeSockets.ts +29 -0
  271. package/src/util/serializeVariables.ts +66 -0
  272. package/src/util/sockets.ts +43 -0
  273. package/stories/apex/layoutController/example-graph.worker.ts +39 -0
  274. package/stories/apex/layoutController/index.stories.tsx +48 -0
  275. package/stories/apex/layoutController/webworker.stories.tsx +103 -0
  276. package/stories/apex/menubar/menubar.stories.tsx +19 -0
  277. package/stories/components/colorpicker/index.stories.tsx +20 -0
  278. package/stories/components/contextMenus/edge.stories.tsx +32 -0
  279. package/stories/components/contextMenus/node.stories.tsx +26 -0
  280. package/stories/components/contextMenus/nodePicker.stories.tsx +115 -0
  281. package/stories/components/controls/any/index.stories.tsx +19 -0
  282. package/stories/components/controls/boolean/index.stories.tsx +19 -0
  283. package/stories/components/controls/colorPicker/index.stories.tsx +49 -0
  284. package/stories/components/controls/number/index.stories.tsx +19 -0
  285. package/stories/components/controls/string/index.stories.tsx +19 -0
  286. package/stories/components/nodes/behaveNode.stories.tsx +108 -0
  287. package/stories/components/panels/alignment.stories.tsx +24 -0
  288. package/stories/components/panels/events.stories.tsx +38 -0
  289. package/stories/components/panels/graphRunner.stories.tsx +317 -0
  290. package/stories/components/panels/history.stories.tsx +37 -0
  291. package/stories/components/panels/keymaps.stories.tsx +21 -0
  292. package/stories/components/panels/legend.stories.tsx +37 -0
  293. package/stories/components/panels/logs.stories.tsx +24 -0
  294. package/stories/components/panels/nodeInputs.stories.tsx +21 -0
  295. package/stories/components/panels/nodePicker.stories.tsx +37 -0
  296. package/stories/components/panels/panel.stories.tsx +39 -0
  297. package/stories/components/panels/search.stories.tsx +24 -0
  298. package/stories/components/panels/systemSettings.stories.tsx +26 -0
  299. package/stories/components/panels/traces.stories.tsx +225 -0
  300. package/stories/components/panels/variables.stories.tsx +24 -0
  301. package/stories/defaults/defaultStoryProvider.tsx +170 -0
  302. package/stories/defaults/systemGenerator.ts +43 -0
  303. package/stories/plugins/notes.stories.tsx +100 -0
  304. package/tests/autoConvert.test.ts +329 -0
  305. package/tests/autosavePlugin.test.ts +204 -0
  306. package/tests/callSubgraphSync.test.ts +148 -0
  307. package/tests/commandRegistry.test.ts +137 -0
  308. package/tests/components/edges/offsetBezier.test.ts +51 -0
  309. package/tests/components/layoutController/utils.test.ts +68 -0
  310. package/tests/components/panels/traces/utils.test.ts +52 -0
  311. package/tests/contract.test.ts +51 -0
  312. package/tests/contractSerialize.test.ts +62 -0
  313. package/tests/deriveSpans.test.ts +71 -0
  314. package/tests/flowToBehave.test.ts +27 -4
  315. package/tests/hotkeys.test.ts +79 -0
  316. package/tests/keepAliveLifecycle.test.ts +167 -0
  317. package/tests/loadManifest.test.ts +113 -0
  318. package/tests/noteMarkdown.test.ts +65 -0
  319. package/tests/notesPlugin.test.ts +162 -0
  320. package/tests/notifications.test.ts +87 -0
  321. package/tests/persistence.test.ts +51 -0
  322. package/tests/saveLoad.test.ts +373 -0
  323. package/tests/settings.test.ts +178 -0
  324. package/tests/traceStore.test.ts +46 -0
  325. package/tests/util/calculateNewEdge.test.ts +98 -0
  326. package/tests/util/getSocketsByNodeTypeAndHandleType.test.ts +31 -0
  327. package/tests/util/hasPositionMetaData.test.ts +33 -0
  328. package/tests/util/isBehaveNode.test.ts +22 -0
  329. package/tests/util/isHandleConnected.test.ts +37 -0
  330. package/tests/util/mergeSockets.test.ts +43 -0
  331. package/tests/visual/README.md +64 -0
  332. package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-alignment-chromium-win32.png +0 -0
  333. package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-conversation-chromium-win32.png +0 -0
  334. package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-events-chromium-win32.png +0 -0
  335. package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-history-chromium-win32.png +0 -0
  336. package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-keymaps-chromium-win32.png +0 -0
  337. package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-layers-chromium-win32.png +0 -0
  338. package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-legend-chromium-win32.png +0 -0
  339. package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-localGraphRunner-chromium-win32.png +0 -0
  340. package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-logs-chromium-win32.png +0 -0
  341. package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-nodeInputs-chromium-win32.png +0 -0
  342. package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-nodePicker-chromium-win32.png +0 -0
  343. package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-panel-chromium-win32.png +0 -0
  344. package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-search-chromium-win32.png +0 -0
  345. package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-systemSettings-chromium-win32.png +0 -0
  346. package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-traces-chromium-win32.png +0 -0
  347. package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-variables-chromium-win32.png +0 -0
  348. package/tests/visual/panels.visual.test.tsx +76 -0
  349. package/tests/wasdPan.test.ts +71 -0
  350. package/tsconfig.base.json +39 -0
  351. package/tsconfig.json +18 -59
  352. package/tsconfig.prod.json +23 -0
  353. package/tsdown.config.ts +15 -3
  354. package/typedoc.json +7 -7
  355. package/vite.config.js +7 -0
  356. package/vitest.config.ts +5 -2
  357. package/vitest.visual.config.ts +55 -0
  358. package/src/components/AutoSizeInput.tsx +0 -65
  359. package/src/components/Controls.tsx +0 -87
  360. package/src/components/InputSocket.tsx +0 -142
  361. package/src/components/Node.tsx +0 -68
  362. package/src/components/NodeContainer.tsx +0 -46
  363. package/src/components/NodePicker.tsx +0 -77
  364. package/src/components/OutputSocket.tsx +0 -58
  365. package/src/components/modals/ClearModal.tsx +0 -40
  366. package/src/components/modals/HelpModal.tsx +0 -36
  367. package/src/components/modals/LoadModal.tsx +0 -96
  368. package/src/components/modals/Modal.tsx +0 -64
  369. package/src/components/modals/SaveModal.tsx +0 -60
  370. package/src/hooks/useCustomNodeTypes.tsx +0 -31
  371. package/src/hooks/useGraphRunner.ts +0 -104
  372. package/src/hooks/useMergeMap.ts +0 -14
  373. package/src/hooks/useNodeSpecJson.ts +0 -20
  374. package/src/hooks/useQueriableDefinitions.ts +0 -22
  375. package/src/styles.css +0 -8
  376. package/tailwind.config.ts +0 -19
  377. package/tests/tsconfig.json +0 -10
  378. /package/src/{types.d.ts → types-declarations.d.ts} +0 -0
@@ -0,0 +1,131 @@
1
+ import type { Viewport } from 'reactflow';
2
+ import type { GraphSession } from './graphSession';
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: GraphSession;
13
+
14
+ constructor(session: GraphSession) {
15
+ this.sys = session;
16
+ }
17
+
18
+ setViewport(index: number, viewport: Viewport) {
19
+ this.viewports[index] = viewport;
20
+ this.sys.pubsub.publish('saveViewport', {
21
+ index: index,
22
+ viewport: viewport
23
+ });
24
+ }
25
+
26
+ /**
27
+ * Clears the graph
28
+ */
29
+ clear() {
30
+ const nodes = this.sys.nodeStore.getState().nodes;
31
+ const edges = this.sys.edgeStore.getState().edges;
32
+ this.sys.undoManager.execute({
33
+ name: 'Clear graph',
34
+ undo: () => {
35
+ this.sys.nodeStore.getState().setNodes(Object.values(nodes));
36
+ this.sys.edgeStore.getState().setEdges(Object.values(edges));
37
+ },
38
+ execute: () => {
39
+ this.sys.nodeStore.getState().setNodes([]);
40
+ this.sys.edgeStore.getState().setEdges([]);
41
+ }
42
+ });
43
+ }
44
+
45
+ /**
46
+ * Return all edges that point into the nodes inputs.
47
+ * O(m) the amount of edges
48
+ */
49
+ inEdges(nodeId: string, sourceHandle?: string): Edge[] {
50
+ //Get the edges
51
+ const edges = this.sys.edgeStore.getState().edges;
52
+
53
+ return Object.values(edges).filter((x) => {
54
+ if (x.target !== nodeId) {
55
+ return false;
56
+ }
57
+ if (sourceHandle) {
58
+ return x.targetHandle === sourceHandle;
59
+ }
60
+ return true;
61
+ });
62
+ }
63
+
64
+ /**
65
+ * Return all edges that are pointed out by node v.
66
+ * O(m) the amount of edges
67
+ */
68
+ outEdges(nodeId: string, targetHandle?: string): Edge[] {
69
+ //Get the edges
70
+ const edges = this.sys.edgeStore.getState().edges;
71
+
72
+ return Object.values(edges).filter((x) => {
73
+ if (x.source !== nodeId) {
74
+ return false;
75
+ }
76
+ if (targetHandle) {
77
+ return x.targetHandle === targetHandle;
78
+ }
79
+ return true;
80
+ });
81
+ }
82
+
83
+ serialize(): UIGraphJSON {
84
+ const meta = this.sys.metaStore.getState();
85
+ return {
86
+ v: '1.0.0',
87
+ name: meta.name,
88
+ user: {
89
+ viewport: this.viewports[0] || { x: 0, y: 0, zoom: 1 }
90
+ },
91
+ annotations: { ...meta.metadata },
92
+ data: {
93
+ layers: this.sys.layerStore.getState().serialize()
94
+ },
95
+ flow: {},
96
+ nodes: Object.values(this.sys.nodeStore.getState().nodes),
97
+ edges: Object.values(this.sys.edgeStore.getState().edges)
98
+ };
99
+ }
100
+
101
+ getAnnotations() {
102
+ return { ...this.sys.metaStore.getState().metadata };
103
+ }
104
+
105
+ setAnnotations(annotations: { [key: string]: any }) {
106
+ this.sys.metaStore.getState().mergeMetadata(annotations);
107
+ this.sys.pubsub.publish('graphAnnotationsChanged', this.getAnnotations());
108
+ }
109
+
110
+ deseralize(data: UIGraphJSON) {
111
+ //Load nodes
112
+ this.sys.nodeStore.getState().setNodes(data.nodes);
113
+ this.sys.edgeStore.getState().setEdges(data.edges);
114
+ this.sys.metaStore.getState().setMetadata(data.annotations || {});
115
+ if (data.name) this.sys.metaStore.getState().setName(data.name);
116
+ this.sys.layerStore.getState().deserialize(data.data?.layers);
117
+
118
+ // Restore viewport
119
+ if (data.user?.viewport) {
120
+ const reactflow = this.sys.refStore.getState().getRef('reactflow');
121
+ if (reactflow) {
122
+ reactflow.setViewport(data.user.viewport);
123
+ }
124
+ }
125
+
126
+ // Restore multiple viewports if they exist
127
+ if (data.user?.viewports) {
128
+ this.viewports.splice(0, this.viewports.length, ...data.user.viewports);
129
+ }
130
+ }
131
+ }
@@ -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
+ }
@@ -0,0 +1,6 @@
1
+ export * from './system';
2
+ export * from './persistence';
3
+ export * from './graphSession';
4
+ export * from './provider';
5
+ export * from './plugin';
6
+ export { subscribeToRef, useRefFromStore } from '@/store/refs';
@@ -0,0 +1,111 @@
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 NotificationData {
7
+ type: NotificationType;
8
+ message: string;
9
+ options?: {
10
+ id?: string;
11
+ duration?: number;
12
+ position?: any;
13
+ icon?: Renderable;
14
+ style?: React.CSSProperties;
15
+ className?: string;
16
+ ariaLive?: any;
17
+ };
18
+ }
19
+ export interface NotificationOptions {
20
+ /**
21
+ * Toast ID for programmatic dismissal
22
+ */
23
+ id?: string;
24
+ /**
25
+ * Duration in milliseconds. Set to Infinity to persist until manually dismissed
26
+ */
27
+ duration?: number;
28
+ /**
29
+ * Position on screen
30
+ */
31
+ position?: Toast['position'];
32
+ /**
33
+ * Custom icon
34
+ */
35
+ icon?: Renderable;
36
+ /**
37
+ * Custom styles
38
+ */
39
+ style?: React.CSSProperties;
40
+ /**
41
+ * Custom class name
42
+ */
43
+ className?: string;
44
+ /**
45
+ * Accessible aria-live value
46
+ */
47
+ ariaLive?: Toast['ariaProps'];
48
+ }
49
+
50
+ export class Notifications {
51
+ private readonly system: System;
52
+ constructor(system: System) {
53
+ this.system = system;
54
+ }
55
+ /**
56
+ * Dismiss a specific toast or all toasts
57
+ */
58
+ dismissNotification(toastId?: string): void {
59
+ this.system.pubsub.publish('notification:dismiss', { toastId });
60
+ }
61
+
62
+ /**
63
+ * Show a notification toast
64
+ */
65
+ notify(
66
+ message: string,
67
+ type: NotificationType = 'info',
68
+ options?: NotificationOptions
69
+ ): void {
70
+ this.system.pubsub.publish('notification', {
71
+ type,
72
+ message,
73
+ options
74
+ });
75
+ }
76
+
77
+ /**
78
+ * Show a success notification
79
+ */
80
+ success(message: string, options?: NotificationOptions): void {
81
+ this.notify(message, 'success', options);
82
+ }
83
+
84
+ /**
85
+ * Show an error notification
86
+ */
87
+ error(message: string, options?: NotificationOptions): void {
88
+ this.notify(message, 'error', options);
89
+ }
90
+
91
+ /**
92
+ * Show a loading notification
93
+ */
94
+ loading(message: string, options?: NotificationOptions): void {
95
+ this.notify(message, 'loading', options);
96
+ }
97
+
98
+ /**
99
+ * Show an info notification
100
+ */
101
+ info(message: string, options?: NotificationOptions): void {
102
+ this.notify(message, 'info', options);
103
+ }
104
+
105
+ /**
106
+ * Dismiss a specific toast or all toasts
107
+ */
108
+ dismiss(toastId?: string): void {
109
+ this.system.pubsub.publish('notification:dismiss', { toastId });
110
+ }
111
+ }
@@ -0,0 +1,82 @@
1
+ import type { LayoutBase } from 'rc-dock';
2
+ import type { GraphJSON } from '@kiberon-labs/behave-graph';
3
+ import type { UIGraphJSON } from '@/types/graph';
4
+ import { downloadJson } from '@/util/downloadJson';
5
+ import type { System } from './system';
6
+
7
+ /**
8
+ * Sinks invoked when the editor emits its save events. Each entry maps one
9
+ * editor-level pubsub topic to the side effect that persists it (write the JSON
10
+ * somewhere). Override any subset to redirect where saved data goes; sinks left
11
+ * unspecified keep the built-in file-download behaviour.
12
+ *
13
+ * Loading is not represented here: the menubar's "Load" items already read a
14
+ * file from disk and deserialize it into the focused graph by default, so there
15
+ * is nothing host-specific to wire for the common case.
16
+ */
17
+ export interface PersistenceAdapter {
18
+ /** Persist a full UI graph save (`graph:saved`). */
19
+ saveGraph: (graph: UIGraphJSON) => void;
20
+ /** Persist a raw inner behave-graph save (`graph:inner:saved`). */
21
+ saveInnerGraph: (graph: GraphJSON) => void;
22
+ /** Persist a dock layout save (`layout:saved`). */
23
+ saveLayout: (layout: LayoutBase) => void;
24
+ }
25
+
26
+ /**
27
+ * Whether the file-download default can run. Guards the built-in sinks so that
28
+ * constructing a `System` in a non-DOM context (tests, SSR, the compiler) never
29
+ * throws , the subscriptions are harmless, only the download body is skipped.
30
+ */
31
+ const canDownload = (): boolean =>
32
+ typeof document !== 'undefined' && typeof URL !== 'undefined';
33
+
34
+ /**
35
+ * The built-in persistence: saving triggers a browser download of the
36
+ * corresponding JSON file. This is the default so a freshly constructed editor
37
+ * has working Save actions without any per-host or per-story wiring.
38
+ */
39
+ export const defaultPersistenceAdapter: PersistenceAdapter = {
40
+ saveGraph: (graph) => {
41
+ if (canDownload()) downloadJson('graph.json', graph);
42
+ },
43
+ saveInnerGraph: (graph) => {
44
+ if (canDownload()) downloadJson('graph.behave.json', graph);
45
+ },
46
+ saveLayout: (layout) => {
47
+ if (canDownload()) downloadJson('layout.json', layout);
48
+ }
49
+ };
50
+
51
+ /**
52
+ * Subscribe the given (or default) persistence sinks to the editor's save
53
+ * topics. Any sink not provided falls back to {@link defaultPersistenceAdapter}.
54
+ * Returns a disposer that removes every subscription it added.
55
+ */
56
+ export function installPersistence(
57
+ system: System,
58
+ adapter: Partial<PersistenceAdapter> = {}
59
+ ): () => void {
60
+ const resolved: PersistenceAdapter = {
61
+ ...defaultPersistenceAdapter,
62
+ ...adapter
63
+ };
64
+
65
+ const tokens = [
66
+ system.pubsub.subscribe('graph:saved', (_, graph) =>
67
+ resolved.saveGraph(graph)
68
+ ),
69
+ system.pubsub.subscribe('graph:inner:saved', (_, graph) =>
70
+ resolved.saveInnerGraph(graph)
71
+ ),
72
+ system.pubsub.subscribe('layout:saved', (_, layout) =>
73
+ resolved.saveLayout(layout)
74
+ )
75
+ ];
76
+
77
+ return () => {
78
+ for (const token of tokens) {
79
+ if (typeof token === 'string') system.pubsub.unsubscribe(token);
80
+ }
81
+ };
82
+ }
@@ -0,0 +1,55 @@
1
+ import type { System } from '.';
2
+ import type { GraphSession } from './graphSession';
3
+
4
+ /**
5
+ * Plugin initialization function type
6
+ * @template TOptions - Type of options object passed to the plugin
7
+ */
8
+ export interface Plugin<TOptions = void> {
9
+ (system: System, options: TOptions): void | Promise<void>;
10
+ }
11
+
12
+ /**
13
+ * Cleanup returned by a {@link SessionExtension}. Run when the session it was
14
+ * applied to is disposed (its tab closed).
15
+ */
16
+ export type SessionExtensionCleanup = () => void;
17
+
18
+ /**
19
+ * Extends a single {@link GraphSession}. Registered at the editor level via
20
+ * `system.registerSessionExtension(...)`, it runs against every graph , those
21
+ * already open at registration time and any created afterwards , so an editor
22
+ * plugin can attach per-graph state (extra stores, controllers, pubsub
23
+ * subscriptions) to each new graph instance.
24
+ *
25
+ * Return a cleanup to tear that per-graph state down when the session is
26
+ * disposed.
27
+ *
28
+ * @example
29
+ * system.registerSessionExtension((session) => {
30
+ * const controller = new MyController(session);
31
+ * session.decorate('myController', controller);
32
+ * return () => controller.dispose();
33
+ * });
34
+ */
35
+ export interface SessionExtension {
36
+ (session: GraphSession): void | SessionExtensionCleanup;
37
+ }
38
+ export type PluginOpts = {
39
+ name: string;
40
+ };
41
+
42
+ export type LoadablePlugin<TOptions = void> = {
43
+ loader: Plugin<TOptions>;
44
+ opts: PluginOpts;
45
+ };
46
+
47
+ export const plugin = <TOptions = void>(
48
+ registerfunc: Plugin<TOptions>,
49
+ opts: PluginOpts
50
+ ): LoadablePlugin<TOptions> => {
51
+ return {
52
+ loader: registerfunc,
53
+ opts: opts
54
+ };
55
+ };
@@ -0,0 +1,86 @@
1
+ import React, { createContext, useContext, type ReactNode } from 'react';
2
+ import { useStore } from 'zustand';
3
+ import type { System } from './system';
4
+ import type { GraphSession } from './graphSession';
5
+
6
+ // ---------------------------------------------------------------------------
7
+ // Editor system context
8
+ // ---------------------------------------------------------------------------
9
+
10
+ export const SystemContext = createContext<System | undefined>(undefined);
11
+
12
+ export type SystemProviderProps = {
13
+ children: ReactNode;
14
+ value: System;
15
+ };
16
+
17
+ /**
18
+ * Provides the editor-level {@link System} to the React tree.
19
+ */
20
+ export function SystemProvider({ children, value }: SystemProviderProps) {
21
+ return <SystemContext value={value}>{children}</SystemContext>;
22
+ }
23
+
24
+ /** Alias for {@link SystemProvider} expressing its editor-level role. */
25
+ export const EditorProvider = SystemProvider;
26
+
27
+ /**
28
+ * Access the editor-level {@link System}.
29
+ */
30
+ export function useSystem(): System {
31
+ const context = useContext(SystemContext);
32
+
33
+ if (context === undefined) {
34
+ throw new Error('useSystem must be used within a SystemProvider');
35
+ }
36
+
37
+ return context;
38
+ }
39
+
40
+ /** Alias for {@link useSystem}. */
41
+ export const useEditor = useSystem;
42
+
43
+ // ---------------------------------------------------------------------------
44
+ // Per-graph session context
45
+ // ---------------------------------------------------------------------------
46
+
47
+ const GraphContext = createContext<GraphSession | undefined>(undefined);
48
+
49
+ export type GraphProviderProps = {
50
+ children: ReactNode;
51
+ value: GraphSession;
52
+ };
53
+
54
+ /**
55
+ * Provides a single {@link GraphSession} to the subtree rendered inside a graph
56
+ * tab. Components within use {@link useGraph} to read per-graph state bound to
57
+ * their own tab, regardless of which tab is currently focused.
58
+ */
59
+ export function GraphProvider({ children, value }: GraphProviderProps) {
60
+ return <GraphContext value={value}>{children}</GraphContext>;
61
+ }
62
+
63
+ /**
64
+ * Access the {@link GraphSession} of the surrounding graph tab.
65
+ */
66
+ export function useGraph(): GraphSession {
67
+ const context = useContext(GraphContext);
68
+
69
+ if (context === undefined) {
70
+ throw new Error('useGraph must be used within a GraphProvider');
71
+ }
72
+
73
+ return context;
74
+ }
75
+
76
+ /**
77
+ * Access the currently focused {@link GraphSession}, or undefined when no graph
78
+ * is open. Subscribes to the editor's active-graph store, so panels rendered
79
+ * outside of a graph tab re-render when the focused graph changes.
80
+ */
81
+ export function useActiveGraph(): GraphSession | undefined {
82
+ const editor = useSystem();
83
+ return useStore(editor.activeGraph, (s) =>
84
+ s.activeGraphId ? s.sessions[s.activeGraphId] : undefined
85
+ );
86
+ }