@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,124 @@
1
+ /*
2
+ * @vscode-elements adapter.
3
+ *
4
+ * The editor uses @vscode-elements/react-elements (VscodeButton, VscodeTextfield,
5
+ * VscodeCheckbox, VscodeBadge, VscodeSingleSelect, …). Those web components style
6
+ * themselves from `--vscode-*` custom properties — they don't know about our
7
+ * `--ds-*` tokens. This file feeds them: it expresses our design tokens in the
8
+ * `--vscode-*` vocabulary the components understand, so they follow the active
9
+ * theme (default or an alternate like Kiberon) instead of falling back to their
10
+ * built-in VS Code blue.
11
+ *
12
+ * IMPORTANT — why the selector lists every theme scope:
13
+ * A custom property whose value is `var(--ds-x)` is substituted at the element
14
+ * it's declared on, then that *resolved* value inherits. Declaring the bridge
15
+ * only at `:root` would bake in the default `--ds-*` values and ignore a scoped
16
+ * theme. So the bridge is declared on `:root` AND on each theme container (where
17
+ * `--ds-*` is re-declared), so it re-resolves to that scope's tokens. When you
18
+ * add a new theme under css/themes/, add its scope selector here too.
19
+ *
20
+ * In the real VS Code extension this is inert: VS Code injects `--vscode-*` as
21
+ * inline styles on <html>, which win over these :root rules — so vscode-elements
22
+ * track the user's actual VS Code theme there, as intended.
23
+ */
24
+ :root,
25
+ [data-flow-theme="kiberon"],
26
+ .flow-theme-kiberon {
27
+ /* Type */
28
+ --vscode-font-family: var(--ds-font-ui);
29
+
30
+ /* Foreground / focus / chrome */
31
+ --vscode-foreground: var(--ds-fg);
32
+ --vscode-disabledForeground: var(--ds-fg-muted);
33
+ --vscode-descriptionForeground: var(--ds-fg-muted);
34
+ --vscode-icon-foreground: var(--ds-icon-fg);
35
+ --vscode-focusBorder: var(--ds-focus-border);
36
+ --vscode-widget-border: var(--ds-border);
37
+ --vscode-contrastBorder: var(--ds-border);
38
+
39
+ /* Buttons */
40
+ --vscode-button-background: var(--ds-button-bg);
41
+ --vscode-button-foreground: var(--ds-button-fg);
42
+ --vscode-button-hoverBackground: var(--ds-button-hover-bg);
43
+ --vscode-button-border: var(--ds-button-border);
44
+ --vscode-button-secondaryBackground: var(--ds-button-secondary-bg);
45
+ --vscode-button-secondaryForeground: var(--ds-fg);
46
+ --vscode-button-secondaryHoverBackground: var(--ds-list-hover-bg);
47
+
48
+ /* Text inputs / textarea */
49
+ --vscode-input-background: var(--ds-input-bg);
50
+ --vscode-input-foreground: var(--ds-input-fg);
51
+ --vscode-input-border: var(--ds-input-border);
52
+ --vscode-input-placeholderForeground: var(--ds-fg-muted);
53
+ --vscode-settings-textInputBackground: var(--ds-input-bg);
54
+ --vscode-settings-textInputForeground: var(--ds-input-fg);
55
+ --vscode-settings-textInputBorder: var(--ds-input-border);
56
+
57
+ /* Checkbox */
58
+ --vscode-checkbox-background: var(--ds-input-bg);
59
+ --vscode-checkbox-foreground: var(--ds-fg);
60
+ --vscode-checkbox-border: var(--ds-input-border);
61
+ --vscode-checkbox-selectBackground: var(--ds-button-bg);
62
+ --vscode-checkbox-selectBorder: var(--ds-button-bg);
63
+ --vscode-settings-checkboxBackground: var(--ds-input-bg);
64
+ --vscode-settings-checkboxForeground: var(--ds-fg);
65
+ --vscode-settings-checkboxBorder: var(--ds-input-border);
66
+
67
+ /* Dropdown / single-select */
68
+ --vscode-dropdown-background: var(--ds-widget-bg);
69
+ --vscode-dropdown-foreground: var(--ds-fg);
70
+ --vscode-dropdown-border: var(--ds-input-border);
71
+ --vscode-dropdown-listBackground: var(--ds-widget-bg);
72
+ --vscode-settings-dropdownBackground: var(--ds-widget-bg);
73
+ --vscode-settings-dropdownForeground: var(--ds-fg);
74
+ --vscode-settings-dropdownBorder: var(--ds-input-border);
75
+
76
+ /* Badge */
77
+ --vscode-badge-background: var(--ds-badge-bg);
78
+ --vscode-badge-foreground: var(--ds-badge-fg);
79
+
80
+ /* Lists / trees */
81
+ --vscode-list-activeSelectionBackground: var(--ds-list-active-bg);
82
+ --vscode-list-activeSelectionForeground: var(--ds-list-active-fg);
83
+ --vscode-list-inactiveSelectionBackground: var(--ds-list-hover-bg);
84
+ --vscode-list-hoverBackground: var(--ds-list-hover-bg);
85
+ --vscode-list-hoverForeground: var(--ds-fg);
86
+ --vscode-list-focusBackground: var(--ds-list-active-bg);
87
+ --vscode-list-focusOutline: var(--ds-focus-border);
88
+
89
+ /* Toolbar */
90
+ --vscode-toolbar-hoverBackground: var(--ds-toolbar-hover-bg);
91
+ --vscode-toolbar-activeBackground: var(--ds-toolbar-active-bg);
92
+
93
+ /* Surfaces — collapsible headers, tables, dividers, panels */
94
+ --vscode-editorWidget-background: var(--ds-widget-bg);
95
+ --vscode-editorWidget-foreground: var(--ds-widget-fg);
96
+ --vscode-editorWidget-border: var(--ds-border-subtle);
97
+ --vscode-panel-border: var(--ds-panel-border);
98
+ --vscode-sideBar-background: var(--ds-sidebar-bg);
99
+ --vscode-sideBarSectionHeader-background: var(--ds-section-header-bg);
100
+ --vscode-sideBarSectionHeader-foreground: var(--ds-section-header-fg);
101
+ --vscode-sideBarSectionHeader-border: var(--ds-section-header-border);
102
+ --vscode-settings-headerForeground: var(--ds-fg);
103
+ }
104
+
105
+ /*
106
+ * Native form controls (checkbox / range / radio) tint from `accent-color`,
107
+ * which is a normal property — it re-resolves `var(--ds-*)` per element, so it
108
+ * follows a scoped theme without extra selectors.
109
+ */
110
+ input[type="checkbox"],
111
+ input[type="radio"],
112
+ input[type="range"] {
113
+ accent-color: var(--ds-button-bg);
114
+ }
115
+
116
+ /*
117
+ * Safety: vscode-elements form controls carry an intrinsic default width that can
118
+ * exceed a narrow panel and force horizontal overflow. Cap them to their container.
119
+ */
120
+ vscode-textfield,
121
+ vscode-textarea,
122
+ vscode-single-select {
123
+ max-width: 100%;
124
+ }
package/src/entry.css ADDED
@@ -0,0 +1,4 @@
1
+ @import "reactflow/dist/style.css";
2
+ @import 'rc-menu/assets/index.css';
3
+ @import "rc-dock/dist/rc-dock-dark.css";
4
+ @import "./index.css";
@@ -0,0 +1,136 @@
1
+ import React, { useCallback, useEffect, useMemo } from 'react';
2
+ import { useStore } from 'zustand';
3
+ import {
4
+ VscodeOption,
5
+ VscodeSingleSelect
6
+ } from '@vscode-elements/react-elements';
7
+ import { useGraph } from '@/system/provider';
8
+ import type { SocketGeneratorRenderProps } from '@/store/socketGenerator';
9
+ import type { Socket } from '@/types';
10
+ import type { IBehaveNode } from '@/types/nodes.js';
11
+ import type { NodeSpecJSON } from '@kiberon-labs/behave-graph/Graphs/IO/NodeSpecJSON';
12
+ import {
13
+ CALL_SUBGRAPH_TYPE,
14
+ contractToParams,
15
+ deriveContract,
16
+ paramsToSockets,
17
+ type ContractParam
18
+ } from '@/transformers/contract';
19
+
20
+ export function getCallSubgraphGenerator() {
21
+ return {
22
+ name: `${CALL_SUBGRAPH_TYPE}.socketGenerator`,
23
+ check: (spec: NodeSpecJSON) => spec?.type === CALL_SUBGRAPH_TYPE,
24
+ render: CallSubgraphGenerator
25
+ };
26
+ }
27
+
28
+ const toSockets = (params: ContractParam[] | undefined): Socket[] =>
29
+ paramsToSockets(params ?? []);
30
+
31
+ /**
32
+ * Properties-panel editor for a Call Subgraph node: pick which open graph to
33
+ * call. Selecting one copies that graph's contract into the node configuration
34
+ * and mirrors it onto the node's dynamic input/output ports. The `flow` input
35
+ * and the `started` / `completed` flow outputs are static on the core node.
36
+ */
37
+ const CallSubgraphGenerator: React.FC<SocketGeneratorRenderProps> = ({
38
+ node
39
+ }) => {
40
+ const session = useGraph();
41
+ const sessions = useStore(session.editor.activeGraph, (s) => s.sessions);
42
+
43
+ const options = useMemo(
44
+ () =>
45
+ Object.values(sessions)
46
+ .filter((s) => s.id !== session.id)
47
+ .map((s) => ({ id: s.id, name: s.name })),
48
+ [sessions, session.id]
49
+ );
50
+
51
+ const config = node.data.configuration as
52
+ | {
53
+ subgraphId?: string;
54
+ inputs?: ContractParam[];
55
+ outputs?: ContractParam[];
56
+ }
57
+ | undefined;
58
+ const subgraphId = String(config?.subgraphId ?? '');
59
+ const portsKey = JSON.stringify({
60
+ inputs: config?.inputs ?? [],
61
+ outputs: config?.outputs ?? []
62
+ });
63
+
64
+ // Mirror the copied contract onto dynamic ports.
65
+ useEffect(() => {
66
+ const inputs = toSockets(config?.inputs);
67
+ const outputs = toSockets(config?.outputs);
68
+ session.nodeStore.getState().setNodes((prev) =>
69
+ prev.map((n) => {
70
+ if (n.id !== node.id) return n;
71
+ return {
72
+ ...n,
73
+ data: {
74
+ ...n.data,
75
+ dynamicPorts: { ...n.data?.dynamicPorts, inputs, outputs }
76
+ }
77
+ } as IBehaveNode;
78
+ })
79
+ );
80
+ // eslint-disable-next-line react-hooks/exhaustive-deps
81
+ }, [portsKey, node.id, session.nodeStore]);
82
+
83
+ const select = useCallback(
84
+ (nextId: string) => {
85
+ const target = sessions[nextId];
86
+ const contract = target
87
+ ? deriveContract(target.nodeStore.getState().nodes)
88
+ : { graphInputs: [], graphOutputs: [] };
89
+ const inputs = contractToParams(contract.graphInputs);
90
+ const outputs = contractToParams(contract.graphOutputs);
91
+
92
+ session.nodeStore.getState().setNodes((prev) =>
93
+ prev.map((n) => {
94
+ if (n.id !== node.id) return n;
95
+ return {
96
+ ...n,
97
+ data: {
98
+ ...n.data,
99
+ configuration: {
100
+ ...n.data?.configuration,
101
+ subgraphId: nextId,
102
+ inputs,
103
+ outputs
104
+ }
105
+ }
106
+ } as IBehaveNode;
107
+ })
108
+ );
109
+ },
110
+ [node.id, session, sessions]
111
+ );
112
+
113
+ return (
114
+ <div style={{ display: 'flex', flexDirection: 'column', gap: 4 }}>
115
+ <div style={{ fontSize: 12, opacity: 0.9 }}>Subgraph</div>
116
+ <VscodeSingleSelect
117
+ value={subgraphId}
118
+ onChange={(e: any) => select(String(e?.target?.value ?? ''))}
119
+ disabled={options.length === 0}
120
+ >
121
+ {options.length === 0 ? (
122
+ <VscodeOption value="">No other graphs open</VscodeOption>
123
+ ) : (
124
+ <>
125
+ <VscodeOption value="">Select a graph...</VscodeOption>
126
+ {options.map((opt) => (
127
+ <VscodeOption key={opt.id} value={opt.id}>
128
+ {opt.name || opt.id}
129
+ </VscodeOption>
130
+ ))}
131
+ </>
132
+ )}
133
+ </VscodeSingleSelect>
134
+ </div>
135
+ );
136
+ };
@@ -0,0 +1,85 @@
1
+ import React, { useEffect } from 'react';
2
+ import { useStore } from 'zustand';
3
+ import { useGraph } from '@/system/provider';
4
+ import type { SocketGeneratorRenderProps } from '@/store/socketGenerator';
5
+ import type { Socket } from '@/types';
6
+ import type { IBehaveNode } from '@/types/nodes.js';
7
+ import type { NodeSpecJSON } from '@kiberon-labs/behave-graph/Graphs/IO/NodeSpecJSON';
8
+
9
+ const NAME = 'customEvent/onTriggered.socketGenerator';
10
+
11
+ export function getCustomEventOnTriggeredGenerator() {
12
+ return {
13
+ name: NAME,
14
+ check: (spec: NodeSpecJSON) => spec?.type === 'customEvent/onTriggered',
15
+ render: CustomEventOnTriggeredGenerator
16
+ };
17
+ }
18
+
19
+ const CustomEventOnTriggeredGenerator: React.FC<SocketGeneratorRenderProps> = ({
20
+ node
21
+ }) => {
22
+ const system = useGraph();
23
+ const customEvents = useStore(system.eventsStore, (s) => s.customEvents);
24
+
25
+ const customEventId = node.data.configuration?.customEventId;
26
+
27
+ useEffect(() => {
28
+ // Find the selected custom event
29
+ const event = customEvents[customEventId];
30
+
31
+ if (!event) {
32
+ // No event selected or event not found - clear parameter outputs
33
+ system.nodeStore.getState().setNodes((prev) =>
34
+ prev.map((n) => {
35
+ if (n.id !== node.id) return n;
36
+ return {
37
+ ...n,
38
+ data: {
39
+ ...n.data,
40
+ dynamicPorts: {
41
+ ...n.data?.dynamicPorts,
42
+ outputs: []
43
+ }
44
+ }
45
+ };
46
+ })
47
+ );
48
+ return;
49
+ }
50
+
51
+ // Generate output sockets based on event parameters (not including flow)
52
+ const outputs: Socket[] = [];
53
+
54
+ // Add output for each parameter
55
+ if (event.parameters && Array.isArray(event.parameters)) {
56
+ event.parameters.forEach((param: any) => {
57
+ outputs.push({
58
+ name: param.name || 'param',
59
+ key: param.name || 'param',
60
+ valueType: param.valueTypeName || 'string'
61
+ });
62
+ });
63
+ }
64
+
65
+ // Update node ports
66
+ system.nodeStore.getState().setNodes((prev) =>
67
+ prev.map((n) => {
68
+ if (n.id !== node.id) return n;
69
+ return {
70
+ ...n,
71
+ data: {
72
+ ...n.data,
73
+ dynamicPorts: {
74
+ ...n.data?.dynamicPorts,
75
+ outputs
76
+ }
77
+ }
78
+ } as IBehaveNode;
79
+ })
80
+ );
81
+ }, [customEventId, customEvents, node.id, system.nodeStore]);
82
+
83
+ // This generator doesn't render any UI
84
+ return null;
85
+ };
@@ -0,0 +1,32 @@
1
+ .list {
2
+ display: flex;
3
+ flex-direction: column;
4
+ gap: 0.4rem;
5
+ }
6
+
7
+ /* One card per boundary param so the name field gets its own full-width line
8
+ instead of collapsing next to the type select. */
9
+ .param {
10
+ display: flex;
11
+ flex-direction: column;
12
+ gap: 0.3rem;
13
+ padding: 0.4rem;
14
+ border: 1px solid var(--ds-border-subtle, #454545);
15
+ border-radius: var(--component-radii-sm, 4px);
16
+ background: var(--ds-widget-bg, #202020);
17
+ }
18
+
19
+ .topRow {
20
+ display: flex;
21
+ align-items: center;
22
+ gap: 0.3rem;
23
+ }
24
+
25
+ .name {
26
+ flex: 1;
27
+ min-width: 0;
28
+ }
29
+
30
+ .type {
31
+ width: 100%;
32
+ }
@@ -0,0 +1,193 @@
1
+ import React, { useCallback, useEffect, useMemo } from 'react';
2
+ import { useStore } from 'zustand';
3
+ import {
4
+ VscodeButton,
5
+ VscodeOption,
6
+ VscodeSingleSelect,
7
+ VscodeTextfield
8
+ } from '@vscode-elements/react-elements';
9
+ import { Trash } from 'iconoir-react';
10
+ import { useGraph } from '@/system/provider';
11
+ import type { SocketGeneratorRenderProps } from '@/store/socketGenerator';
12
+ import type { Socket } from '@/types';
13
+ import type { IBehaveNode } from '@/types/nodes.js';
14
+ import type { NodeSpecJSON } from '@kiberon-labs/behave-graph/Graphs/IO/NodeSpecJSON';
15
+ import { v4 as uuidv4 } from 'uuid';
16
+ import {
17
+ GRAPH_INPUT_TYPE,
18
+ GRAPH_OUTPUT_TYPE,
19
+ paramId,
20
+ type ContractParam
21
+ } from '@/transformers/contract';
22
+ import styles from './GraphBoundaryGenerator.module.css';
23
+
24
+ type BoundaryKind = 'input' | 'output';
25
+
26
+ export function getGraphInputGenerator() {
27
+ return {
28
+ name: `${GRAPH_INPUT_TYPE}.socketGenerator`,
29
+ check: (spec: NodeSpecJSON) => spec?.type === GRAPH_INPUT_TYPE,
30
+ render: (props: SocketGeneratorRenderProps) => (
31
+ <GraphBoundaryGenerator {...props} kind="input" />
32
+ )
33
+ };
34
+ }
35
+
36
+ export function getGraphOutputGenerator() {
37
+ return {
38
+ name: `${GRAPH_OUTPUT_TYPE}.socketGenerator`,
39
+ check: (spec: NodeSpecJSON) => spec?.type === GRAPH_OUTPUT_TYPE,
40
+ render: (props: SocketGeneratorRenderProps) => (
41
+ <GraphBoundaryGenerator {...props} kind="output" />
42
+ )
43
+ };
44
+ }
45
+
46
+ /**
47
+ * Properties-panel editor for a subgraph boundary node's contract: add / name /
48
+ * type the inputs (`graph/input`) or outputs (`graph/output`). The configured
49
+ * params are mirrored onto the node's dynamic ports , `graph/input` exposes them
50
+ * as outputs, `graph/output` as inputs (the `flow` socket is static on the core
51
+ * node).
52
+ */
53
+ const GraphBoundaryGenerator: React.FC<
54
+ SocketGeneratorRenderProps & { kind: BoundaryKind }
55
+ > = ({ node, kind }) => {
56
+ const session = useGraph();
57
+ // Select the stable `values` object then derive , a freshly built array inside
58
+ // the selector would change identity every render and loop.
59
+ const values = useStore(session.editor.registry, (s) => s.values);
60
+ const valueTypes = useMemo(
61
+ () => Object.keys(values).filter((t) => t !== 'flow'),
62
+ [values]
63
+ );
64
+
65
+ const params: ContractParam[] = useMemo(
66
+ () =>
67
+ Array.isArray(node.data.configuration?.parameters)
68
+ ? (node.data.configuration!.parameters as ContractParam[])
69
+ : [],
70
+ [node.data]
71
+ );
72
+ const paramsKey = JSON.stringify(params);
73
+
74
+ // Mirror params onto dynamic ports. The socket identity (name/key/handle id)
75
+ // is the stable param id; the display label is the editable name.
76
+ useEffect(() => {
77
+ const sockets: Socket[] = params.map((param) => {
78
+ const id = paramId(param);
79
+ return {
80
+ name: id,
81
+ key: id,
82
+ label: param.name || id,
83
+ valueType: param.valueTypeName || 'string'
84
+ };
85
+ });
86
+ session.nodeStore.getState().setNodes((prev) =>
87
+ prev.map((n) => {
88
+ if (n.id !== node.id) return n;
89
+ return {
90
+ ...n,
91
+ data: {
92
+ ...n.data,
93
+ dynamicPorts: {
94
+ ...n.data?.dynamicPorts,
95
+ ...(kind === 'input' ? { outputs: sockets } : { inputs: sockets })
96
+ }
97
+ }
98
+ } as IBehaveNode;
99
+ })
100
+ );
101
+ // eslint-disable-next-line react-hooks/exhaustive-deps
102
+ }, [paramsKey, kind, node.id, session.nodeStore]);
103
+
104
+ const update = useCallback(
105
+ (next: ContractParam[]) => {
106
+ session.nodeStore.getState().setNodes((prev) =>
107
+ prev.map((n) => {
108
+ if (n.id !== node.id) return n;
109
+ return {
110
+ ...n,
111
+ data: {
112
+ ...n.data,
113
+ configuration: { ...n.data?.configuration, parameters: next }
114
+ }
115
+ } as IBehaveNode;
116
+ })
117
+ );
118
+ },
119
+ [node.id, session]
120
+ );
121
+
122
+ const addParam = useCallback(() => {
123
+ const base = kind === 'input' ? 'in' : 'out';
124
+ const existing = new Set(params.map((p) => p.name));
125
+ let i = params.length + 1;
126
+ let name = `${base}${i}`;
127
+ while (existing.has(name)) name = `${base}${++i}`;
128
+ update([
129
+ ...params,
130
+ { id: uuidv4(), name, valueTypeName: valueTypes[0] ?? 'string' }
131
+ ]);
132
+ }, [kind, params, update, valueTypes]);
133
+
134
+ const setName = useCallback(
135
+ (index: number, name: string) =>
136
+ update(params.map((p, i) => (i === index ? { ...p, name } : p))),
137
+ [params, update]
138
+ );
139
+
140
+ const setType = useCallback(
141
+ (index: number, valueTypeName: string) =>
142
+ update(params.map((p, i) => (i === index ? { ...p, valueTypeName } : p))),
143
+ [params, update]
144
+ );
145
+
146
+ const remove = useCallback(
147
+ (index: number) => update(params.filter((_, i) => i !== index)),
148
+ [params, update]
149
+ );
150
+
151
+ return (
152
+ <div className={styles.list}>
153
+ {params.map((param, index) => (
154
+ <div key={param.id ?? index} className={styles.param}>
155
+ <div className={styles.topRow}>
156
+ <VscodeTextfield
157
+ className={styles.name}
158
+ value={param.name}
159
+ placeholder={`${kind} name`}
160
+ onChange={(e: any) =>
161
+ setName(index, String(e?.target?.value ?? ''))
162
+ }
163
+ />
164
+ <VscodeButton
165
+ secondary
166
+ iconOnly
167
+ title={`Remove ${kind}`}
168
+ onClick={() => remove(index)}
169
+ >
170
+ <Trash />
171
+ </VscodeButton>
172
+ </div>
173
+ <VscodeSingleSelect
174
+ className={styles.type}
175
+ value={param.valueTypeName}
176
+ onChange={(e: any) =>
177
+ setType(index, String(e?.target?.value ?? 'string'))
178
+ }
179
+ >
180
+ {valueTypes.map((t) => (
181
+ <VscodeOption key={t} value={t}>
182
+ {t}
183
+ </VscodeOption>
184
+ ))}
185
+ </VscodeSingleSelect>
186
+ </div>
187
+ ))}
188
+ <VscodeButton secondary onClick={addParam}>
189
+ + Add {kind}
190
+ </VscodeButton>
191
+ </div>
192
+ );
193
+ };
@@ -0,0 +1,104 @@
1
+ import React, { useCallback } from 'react';
2
+ import { VscodeButton } from '@vscode-elements/react-elements';
3
+ import { Plus, Minus } from 'iconoir-react';
4
+
5
+ import { useGraph } from '@/system/provider';
6
+ import type { SocketGeneratorRenderProps } from '@/store/socketGenerator';
7
+ import type { NodeSpecJSON } from '@kiberon-labs/behave-graph/Graphs/IO/NodeSpecJSON';
8
+
9
+ const NAME = 'flow/sequence.socketGenerator';
10
+
11
+ export function getSequenceGenerator() {
12
+ return {
13
+ name: NAME,
14
+ check: (spec: NodeSpecJSON) =>
15
+ (spec as { type?: string })?.type === 'flow/sequence',
16
+ render: SequenceGenerator
17
+ };
18
+ }
19
+
20
+ const SequenceGenerator: React.FC<SocketGeneratorRenderProps> = ({ node }) => {
21
+ const system = useGraph();
22
+
23
+ const numOutputs = node.data.configuration?.numOutputs ?? 0;
24
+
25
+ const updateNumOutputs = useCallback(
26
+ (newNumOutputs: number) => {
27
+ if (newNumOutputs < 1) return;
28
+
29
+ const outputs: { name: string; key: string; valueType: string }[] = [];
30
+ for (let i = 1; i <= newNumOutputs; i++) {
31
+ outputs.push({
32
+ name: `${i}`,
33
+ key: `${i}`,
34
+ valueType: 'flow'
35
+ });
36
+ }
37
+
38
+ system.nodeStore.getState().setNodes((prev) =>
39
+ prev.map((n) => {
40
+ if (n.id !== node.id) return n;
41
+ return {
42
+ ...n,
43
+ data: {
44
+ ...n.data,
45
+ configuration: {
46
+ ...n.data.configuration,
47
+ numOutputs: newNumOutputs
48
+ },
49
+ dynamicPorts: {
50
+ ...n.data.dynamicPorts,
51
+ outputs
52
+ }
53
+ }
54
+ };
55
+ })
56
+ );
57
+ },
58
+ [node.id, system]
59
+ );
60
+
61
+ const addOutput = useCallback(() => {
62
+ updateNumOutputs(numOutputs + 1);
63
+ }, [numOutputs, updateNumOutputs]);
64
+
65
+ const removeOutput = useCallback(() => {
66
+ updateNumOutputs(Math.max(1, numOutputs - 1));
67
+ }, [numOutputs, updateNumOutputs]);
68
+
69
+ return (
70
+ <div
71
+ style={{
72
+ display: 'flex',
73
+ flexDirection: 'column',
74
+ gap: 8
75
+ }}
76
+ >
77
+ <div
78
+ style={{
79
+ display: 'flex',
80
+ alignItems: 'center',
81
+ justifyContent: 'space-between',
82
+ marginBottom: 4
83
+ }}
84
+ >
85
+ <div style={{ fontSize: 12, opacity: 0.9 }}>Outputs: {numOutputs}</div>
86
+ </div>
87
+
88
+ <div style={{ display: 'flex', gap: 4, marginTop: 4 }}>
89
+ <VscodeButton onClick={addOutput} title="Add Output" iconOnly>
90
+ <Plus />
91
+ </VscodeButton>
92
+ <VscodeButton
93
+ onClick={removeOutput}
94
+ secondary
95
+ iconOnly
96
+ title="Remove Output"
97
+ disabled={numOutputs === 1}
98
+ >
99
+ <Minus />
100
+ </VscodeButton>
101
+ </div>
102
+ </div>
103
+ );
104
+ };