@foresthubai/workflow-builder 0.4.3 → 0.4.5

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 (414) hide show
  1. package/LICENSE +661 -661
  2. package/NOTICE +16 -16
  3. package/README.md +110 -110
  4. package/dist/BuilderLayout.d.ts.map +1 -1
  5. package/dist/BuilderLayout.js +52 -61
  6. package/dist/BuilderLayout.js.map +1 -1
  7. package/dist/Canvas.d.ts.map +1 -1
  8. package/dist/Canvas.js +10 -3
  9. package/dist/Canvas.js.map +1 -1
  10. package/dist/CanvasEditor.d.ts.map +1 -1
  11. package/dist/CanvasEditor.js.map +1 -1
  12. package/dist/CanvasTabsToolbar.d.ts.map +1 -1
  13. package/dist/CanvasTabsToolbar.js +3 -0
  14. package/dist/CanvasTabsToolbar.js.map +1 -1
  15. package/dist/RightConfigPanel.d.ts.map +1 -1
  16. package/dist/RightConfigPanel.js +3 -0
  17. package/dist/RightConfigPanel.js.map +1 -1
  18. package/dist/WorkflowBuilder.d.ts +7 -13
  19. package/dist/WorkflowBuilder.d.ts.map +1 -1
  20. package/dist/WorkflowBuilder.js +25 -13
  21. package/dist/WorkflowBuilder.js.map +1 -1
  22. package/dist/cn.d.ts.map +1 -1
  23. package/dist/cn.js +3 -0
  24. package/dist/cn.js.map +1 -1
  25. package/dist/components/ui/add-button.d.ts.map +1 -1
  26. package/dist/components/ui/add-button.js +3 -0
  27. package/dist/components/ui/add-button.js.map +1 -1
  28. package/dist/components/ui/alert-dialog.d.ts.map +1 -1
  29. package/dist/components/ui/alert-dialog.js +3 -0
  30. package/dist/components/ui/alert-dialog.js.map +1 -1
  31. package/dist/components/ui/alert.d.ts.map +1 -1
  32. package/dist/components/ui/alert.js +3 -0
  33. package/dist/components/ui/alert.js.map +1 -1
  34. package/dist/components/ui/badge.d.ts.map +1 -1
  35. package/dist/components/ui/badge.js.map +1 -1
  36. package/dist/components/ui/button.d.ts.map +1 -1
  37. package/dist/components/ui/button.js +3 -0
  38. package/dist/components/ui/button.js.map +1 -1
  39. package/dist/components/ui/card.d.ts.map +1 -1
  40. package/dist/components/ui/card.js +3 -0
  41. package/dist/components/ui/card.js.map +1 -1
  42. package/dist/components/ui/checkbox.d.ts.map +1 -1
  43. package/dist/components/ui/checkbox.js +3 -0
  44. package/dist/components/ui/checkbox.js.map +1 -1
  45. package/dist/components/ui/collapsible.d.ts.map +1 -1
  46. package/dist/components/ui/collapsible.js +3 -0
  47. package/dist/components/ui/collapsible.js.map +1 -1
  48. package/dist/components/ui/command.d.ts +2 -2
  49. package/dist/components/ui/command.d.ts.map +1 -1
  50. package/dist/components/ui/command.js +3 -0
  51. package/dist/components/ui/command.js.map +1 -1
  52. package/dist/components/ui/delete-button.d.ts.map +1 -1
  53. package/dist/components/ui/delete-button.js +3 -0
  54. package/dist/components/ui/delete-button.js.map +1 -1
  55. package/dist/components/ui/dialog.d.ts.map +1 -1
  56. package/dist/components/ui/dialog.js +3 -0
  57. package/dist/components/ui/dialog.js.map +1 -1
  58. package/dist/components/ui/dropdown-menu.d.ts.map +1 -1
  59. package/dist/components/ui/dropdown-menu.js +3 -0
  60. package/dist/components/ui/dropdown-menu.js.map +1 -1
  61. package/dist/components/ui/input.d.ts +1 -1
  62. package/dist/components/ui/input.d.ts.map +1 -1
  63. package/dist/components/ui/input.js +3 -0
  64. package/dist/components/ui/input.js.map +1 -1
  65. package/dist/components/ui/label.d.ts.map +1 -1
  66. package/dist/components/ui/label.js +3 -0
  67. package/dist/components/ui/label.js.map +1 -1
  68. package/dist/components/ui/readonly-banner.d.ts.map +1 -1
  69. package/dist/components/ui/readonly-banner.js +3 -0
  70. package/dist/components/ui/readonly-banner.js.map +1 -1
  71. package/dist/components/ui/resizable.d.ts +1 -1
  72. package/dist/components/ui/resizable.d.ts.map +1 -1
  73. package/dist/components/ui/resizable.js +3 -0
  74. package/dist/components/ui/resizable.js.map +1 -1
  75. package/dist/components/ui/scroll-area.d.ts.map +1 -1
  76. package/dist/components/ui/scroll-area.js +3 -0
  77. package/dist/components/ui/scroll-area.js.map +1 -1
  78. package/dist/components/ui/select.d.ts.map +1 -1
  79. package/dist/components/ui/select.js +3 -0
  80. package/dist/components/ui/select.js.map +1 -1
  81. package/dist/components/ui/separator.d.ts.map +1 -1
  82. package/dist/components/ui/separator.js +3 -0
  83. package/dist/components/ui/separator.js.map +1 -1
  84. package/dist/components/ui/switch.d.ts.map +1 -1
  85. package/dist/components/ui/switch.js +3 -0
  86. package/dist/components/ui/switch.js.map +1 -1
  87. package/dist/components/ui/textarea.d.ts +1 -1
  88. package/dist/components/ui/textarea.d.ts.map +1 -1
  89. package/dist/components/ui/textarea.js +3 -0
  90. package/dist/components/ui/textarea.js.map +1 -1
  91. package/dist/components/ui/toast.d.ts.map +1 -1
  92. package/dist/components/ui/toast.js +3 -0
  93. package/dist/components/ui/toast.js.map +1 -1
  94. package/dist/components/ui/toaster.d.ts.map +1 -1
  95. package/dist/components/ui/toaster.js +3 -0
  96. package/dist/components/ui/toaster.js.map +1 -1
  97. package/dist/components/ui/toggle-group.d.ts.map +1 -1
  98. package/dist/components/ui/toggle-group.js +3 -0
  99. package/dist/components/ui/toggle-group.js.map +1 -1
  100. package/dist/components/ui/toggle.d.ts.map +1 -1
  101. package/dist/components/ui/toggle.js +3 -0
  102. package/dist/components/ui/toggle.js.map +1 -1
  103. package/dist/components/ui/tooltip.d.ts.map +1 -1
  104. package/dist/components/ui/tooltip.js +3 -0
  105. package/dist/components/ui/tooltip.js.map +1 -1
  106. package/dist/dialogs/NodePickerDialog.d.ts.map +1 -1
  107. package/dist/dialogs/NodePickerDialog.js +3 -0
  108. package/dist/dialogs/NodePickerDialog.js.map +1 -1
  109. package/dist/dialogs/ValidationDialog.d.ts.map +1 -1
  110. package/dist/dialogs/ValidationDialog.js +3 -0
  111. package/dist/dialogs/ValidationDialog.js.map +1 -1
  112. package/dist/graph/BaseNode.d.ts.map +1 -1
  113. package/dist/graph/BaseNode.js +21 -16
  114. package/dist/graph/BaseNode.js.map +1 -1
  115. package/dist/graph/CustomEdge.d.ts.map +1 -1
  116. package/dist/graph/CustomEdge.js +4 -1
  117. package/dist/graph/CustomEdge.js.map +1 -1
  118. package/dist/graph/CustomNode.d.ts.map +1 -1
  119. package/dist/graph/CustomNode.js +3 -0
  120. package/dist/graph/CustomNode.js.map +1 -1
  121. package/dist/graph/FunctionCallNode.d.ts.map +1 -1
  122. package/dist/graph/FunctionCallNode.js.map +1 -1
  123. package/dist/graph/PortHandle.d.ts.map +1 -1
  124. package/dist/graph/PortHandle.js.map +1 -1
  125. package/dist/graph/reactFlowRegistry.d.ts.map +1 -1
  126. package/dist/graph/reactFlowRegistry.js +3 -0
  127. package/dist/graph/reactFlowRegistry.js.map +1 -1
  128. package/dist/hooks/use-toast.d.ts.map +1 -1
  129. package/dist/hooks/use-toast.js +3 -0
  130. package/dist/hooks/use-toast.js.map +1 -1
  131. package/dist/hooks/useAvailableVariables.d.ts.map +1 -1
  132. package/dist/hooks/useAvailableVariables.js +3 -0
  133. package/dist/hooks/useAvailableVariables.js.map +1 -1
  134. package/dist/hooks/useCanvasHistory.d.ts.map +1 -1
  135. package/dist/hooks/useCanvasHistory.js +3 -0
  136. package/dist/hooks/useCanvasHistory.js.map +1 -1
  137. package/dist/hooks/useCanvasTabs.d.ts.map +1 -1
  138. package/dist/hooks/useCanvasTabs.js +3 -0
  139. package/dist/hooks/useCanvasTabs.js.map +1 -1
  140. package/dist/hooks/useFunctionDiagnosticsSync.d.ts.map +1 -1
  141. package/dist/hooks/useFunctionDiagnosticsSync.js +3 -0
  142. package/dist/hooks/useFunctionDiagnosticsSync.js.map +1 -1
  143. package/dist/hooks/useFunctionRegistry.d.ts.map +1 -1
  144. package/dist/hooks/useFunctionRegistry.js +3 -0
  145. package/dist/hooks/useFunctionRegistry.js.map +1 -1
  146. package/dist/hooks/useFunctions.d.ts.map +1 -1
  147. package/dist/hooks/useFunctions.js +3 -0
  148. package/dist/hooks/useFunctions.js.map +1 -1
  149. package/dist/hooks/useGraph.d.ts.map +1 -1
  150. package/dist/hooks/useGraph.js +3 -0
  151. package/dist/hooks/useGraph.js.map +1 -1
  152. package/dist/hooks/useNodeDefinitions.d.ts.map +1 -1
  153. package/dist/hooks/useNodeDefinitions.js +3 -0
  154. package/dist/hooks/useNodeDefinitions.js.map +1 -1
  155. package/dist/hooks/useParamErrors.d.ts.map +1 -1
  156. package/dist/hooks/useParamErrors.js +3 -0
  157. package/dist/hooks/useParamErrors.js.map +1 -1
  158. package/dist/hooks/useResolvedTheme.d.ts.map +1 -1
  159. package/dist/hooks/useResolvedTheme.js +3 -0
  160. package/dist/hooks/useResolvedTheme.js.map +1 -1
  161. package/dist/hooks/useResourceDiagnosticsSync.d.ts.map +1 -1
  162. package/dist/hooks/useResourceDiagnosticsSync.js +3 -0
  163. package/dist/hooks/useResourceDiagnosticsSync.js.map +1 -1
  164. package/dist/hooks/useSuppressThemeTransition.d.ts.map +1 -1
  165. package/dist/hooks/useSuppressThemeTransition.js +3 -0
  166. package/dist/hooks/useSuppressThemeTransition.js.map +1 -1
  167. package/dist/hooks/useWorkflowSerialization.d.ts.map +1 -1
  168. package/dist/hooks/useWorkflowSerialization.js +3 -0
  169. package/dist/hooks/useWorkflowSerialization.js.map +1 -1
  170. package/dist/i18n/index.d.ts.map +1 -1
  171. package/dist/i18n/index.js +3 -0
  172. package/dist/i18n/index.js.map +1 -1
  173. package/dist/index.d.ts +1 -1
  174. package/dist/index.d.ts.map +1 -1
  175. package/dist/index.js +3 -0
  176. package/dist/index.js.map +1 -1
  177. package/dist/inputs/ExpressionInput.d.ts.map +1 -1
  178. package/dist/inputs/ExpressionInput.js +3 -0
  179. package/dist/inputs/ExpressionInput.js.map +1 -1
  180. package/dist/inputs/ParameterEditor.d.ts.map +1 -1
  181. package/dist/inputs/ParameterEditor.js +3 -0
  182. package/dist/inputs/ParameterEditor.js.map +1 -1
  183. package/dist/inputs/PortSection.d.ts.map +1 -1
  184. package/dist/inputs/PortSection.js.map +1 -1
  185. package/dist/mode.d.ts +11 -0
  186. package/dist/mode.d.ts.map +1 -0
  187. package/dist/mode.js +8 -0
  188. package/dist/mode.js.map +1 -0
  189. package/dist/panels/BuilderSidebar.d.ts.map +1 -1
  190. package/dist/panels/BuilderSidebar.js +3 -0
  191. package/dist/panels/BuilderSidebar.js.map +1 -1
  192. package/dist/panels/ChannelConfigPanel.d.ts.map +1 -1
  193. package/dist/panels/ChannelConfigPanel.js +3 -0
  194. package/dist/panels/ChannelConfigPanel.js.map +1 -1
  195. package/dist/panels/ChannelsPanel.d.ts.map +1 -1
  196. package/dist/panels/ChannelsPanel.js +3 -0
  197. package/dist/panels/ChannelsPanel.js.map +1 -1
  198. package/dist/panels/DebugConsolePanel.d.ts.map +1 -1
  199. package/dist/panels/DebugConsolePanel.js +3 -0
  200. package/dist/panels/DebugConsolePanel.js.map +1 -1
  201. package/dist/panels/DebugContextPanel.d.ts.map +1 -1
  202. package/dist/panels/DebugContextPanel.js +3 -0
  203. package/dist/panels/DebugContextPanel.js.map +1 -1
  204. package/dist/panels/DebugExternalIOPanel.d.ts.map +1 -1
  205. package/dist/panels/DebugExternalIOPanel.js +3 -0
  206. package/dist/panels/DebugExternalIOPanel.js.map +1 -1
  207. package/dist/panels/DiagnosticsPanel.d.ts.map +1 -1
  208. package/dist/panels/DiagnosticsPanel.js +3 -0
  209. package/dist/panels/DiagnosticsPanel.js.map +1 -1
  210. package/dist/panels/EdgeConfigPanel.d.ts.map +1 -1
  211. package/dist/panels/EdgeConfigPanel.js +4 -1
  212. package/dist/panels/EdgeConfigPanel.js.map +1 -1
  213. package/dist/panels/FunctionConfigPanel.d.ts.map +1 -1
  214. package/dist/panels/FunctionConfigPanel.js +4 -1
  215. package/dist/panels/FunctionConfigPanel.js.map +1 -1
  216. package/dist/panels/FunctionListPanel.d.ts.map +1 -1
  217. package/dist/panels/FunctionListPanel.js +3 -0
  218. package/dist/panels/FunctionListPanel.js.map +1 -1
  219. package/dist/panels/MemoryConfigPanel.d.ts.map +1 -1
  220. package/dist/panels/MemoryConfigPanel.js +3 -0
  221. package/dist/panels/MemoryConfigPanel.js.map +1 -1
  222. package/dist/panels/MemoryPanel.d.ts.map +1 -1
  223. package/dist/panels/MemoryPanel.js +3 -0
  224. package/dist/panels/MemoryPanel.js.map +1 -1
  225. package/dist/panels/ModelConfigPanel.d.ts.map +1 -1
  226. package/dist/panels/ModelConfigPanel.js +3 -0
  227. package/dist/panels/ModelConfigPanel.js.map +1 -1
  228. package/dist/panels/ModelsPanel.d.ts.map +1 -1
  229. package/dist/panels/ModelsPanel.js +3 -0
  230. package/dist/panels/ModelsPanel.js.map +1 -1
  231. package/dist/panels/NodeConfigPanel.d.ts.map +1 -1
  232. package/dist/panels/NodeConfigPanel.js +4 -1
  233. package/dist/panels/NodeConfigPanel.js.map +1 -1
  234. package/dist/panels/NodeLibrary.d.ts.map +1 -1
  235. package/dist/panels/NodeLibrary.js +4 -1
  236. package/dist/panels/NodeLibrary.js.map +1 -1
  237. package/dist/panels/ResourceConfigPanel.d.ts.map +1 -1
  238. package/dist/panels/ResourceConfigPanel.js +4 -1
  239. package/dist/panels/ResourceConfigPanel.js.map +1 -1
  240. package/dist/panels/ResourceListPanel.d.ts.map +1 -1
  241. package/dist/panels/ResourceListPanel.js +4 -1
  242. package/dist/panels/ResourceListPanel.js.map +1 -1
  243. package/dist/panels/VariableConfigPanel.d.ts.map +1 -1
  244. package/dist/panels/VariableConfigPanel.js +4 -1
  245. package/dist/panels/VariableConfigPanel.js.map +1 -1
  246. package/dist/panels/VariablesPanel.d.ts.map +1 -1
  247. package/dist/panels/VariablesPanel.js +4 -1
  248. package/dist/panels/VariablesPanel.js.map +1 -1
  249. package/dist/stores/canvasStore.d.ts.map +1 -1
  250. package/dist/stores/canvasStore.js +3 -0
  251. package/dist/stores/canvasStore.js.map +1 -1
  252. package/dist/stores/debugStore.d.ts.map +1 -1
  253. package/dist/stores/debugStore.js +3 -0
  254. package/dist/stores/debugStore.js.map +1 -1
  255. package/dist/stores/diagnosticsStore.d.ts.map +1 -1
  256. package/dist/stores/diagnosticsStore.js +3 -0
  257. package/dist/stores/diagnosticsStore.js.map +1 -1
  258. package/dist/stores/editorStore.d.ts +1 -1
  259. package/dist/stores/editorStore.d.ts.map +1 -1
  260. package/dist/stores/editorStore.js +3 -0
  261. package/dist/stores/editorStore.js.map +1 -1
  262. package/dist/utils/categoryConstants.d.ts.map +1 -1
  263. package/dist/utils/categoryConstants.js +3 -0
  264. package/dist/utils/categoryConstants.js.map +1 -1
  265. package/dist/utils/channelOperations.d.ts.map +1 -1
  266. package/dist/utils/channelOperations.js +3 -0
  267. package/dist/utils/channelOperations.js.map +1 -1
  268. package/dist/utils/connectionRules.d.ts +3 -1
  269. package/dist/utils/connectionRules.d.ts.map +1 -1
  270. package/dist/utils/connectionRules.js +11 -16
  271. package/dist/utils/connectionRules.js.map +1 -1
  272. package/dist/utils/functionOperations.d.ts.map +1 -1
  273. package/dist/utils/functionOperations.js +3 -0
  274. package/dist/utils/functionOperations.js.map +1 -1
  275. package/dist/utils/graphOperations.d.ts.map +1 -1
  276. package/dist/utils/graphOperations.js +3 -0
  277. package/dist/utils/graphOperations.js.map +1 -1
  278. package/dist/utils/history.d.ts.map +1 -1
  279. package/dist/utils/history.js +4 -1
  280. package/dist/utils/history.js.map +1 -1
  281. package/dist/utils/memoryOperations.d.ts.map +1 -1
  282. package/dist/utils/memoryOperations.js +3 -0
  283. package/dist/utils/memoryOperations.js.map +1 -1
  284. package/dist/utils/migrateFunctionNodes.d.ts.map +1 -1
  285. package/dist/utils/migrateFunctionNodes.js +3 -0
  286. package/dist/utils/migrateFunctionNodes.js.map +1 -1
  287. package/dist/utils/modelOperations.d.ts.map +1 -1
  288. package/dist/utils/modelOperations.js +3 -0
  289. package/dist/utils/modelOperations.js.map +1 -1
  290. package/dist/utils/paramDisplay.d.ts.map +1 -1
  291. package/dist/utils/paramDisplay.js +3 -0
  292. package/dist/utils/paramDisplay.js.map +1 -1
  293. package/dist/utils/resourceHelpers.d.ts.map +1 -1
  294. package/dist/utils/resourceHelpers.js +3 -0
  295. package/dist/utils/resourceHelpers.js.map +1 -1
  296. package/dist/utils/translation.d.ts.map +1 -1
  297. package/dist/utils/translation.js +3 -0
  298. package/dist/utils/translation.js.map +1 -1
  299. package/dist/utils/variableOperations.d.ts.map +1 -1
  300. package/dist/utils/variableOperations.js +3 -0
  301. package/dist/utils/variableOperations.js.map +1 -1
  302. package/package.json +2 -2
  303. package/src/BuilderLayout.tsx +338 -345
  304. package/src/Canvas.tsx +270 -261
  305. package/src/CanvasEditor.tsx +146 -142
  306. package/src/CanvasTabsToolbar.tsx +180 -176
  307. package/src/RightConfigPanel.tsx +270 -266
  308. package/src/WorkflowBuilder.tsx +423 -408
  309. package/src/cn.ts +10 -6
  310. package/src/components/ui/add-button.tsx +43 -39
  311. package/src/components/ui/alert-dialog.tsx +145 -141
  312. package/src/components/ui/alert.tsx +63 -59
  313. package/src/components/ui/badge.tsx +40 -36
  314. package/src/components/ui/button.tsx +89 -85
  315. package/src/components/ui/card.tsx +83 -79
  316. package/src/components/ui/checkbox.tsx +32 -28
  317. package/src/components/ui/collapsible.tsx +13 -9
  318. package/src/components/ui/command.tsx +157 -153
  319. package/src/components/ui/delete-button.tsx +27 -23
  320. package/src/components/ui/dialog.tsx +129 -125
  321. package/src/components/ui/dropdown-menu.tsx +202 -198
  322. package/src/components/ui/input.tsx +59 -55
  323. package/src/components/ui/label.tsx +28 -24
  324. package/src/components/ui/readonly-banner.tsx +19 -15
  325. package/src/components/ui/resizable.tsx +47 -43
  326. package/src/components/ui/scroll-area.tsx +106 -102
  327. package/src/components/ui/select.tsx +164 -160
  328. package/src/components/ui/separator.tsx +33 -29
  329. package/src/components/ui/switch.tsx +31 -27
  330. package/src/components/ui/textarea.tsx +55 -51
  331. package/src/components/ui/toast.tsx +131 -127
  332. package/src/components/ui/toaster.tsx +37 -33
  333. package/src/components/ui/toggle-group.tsx +63 -59
  334. package/src/components/ui/toggle.tsx +47 -43
  335. package/src/components/ui/tooltip.tsx +36 -32
  336. package/src/dialogs/NodePickerDialog.tsx +88 -84
  337. package/src/dialogs/ValidationDialog.tsx +188 -184
  338. package/src/graph/BaseNode.tsx +563 -557
  339. package/src/graph/CustomEdge.tsx +189 -185
  340. package/src/graph/CustomNode.tsx +20 -16
  341. package/src/graph/FunctionCallNode.tsx +34 -30
  342. package/src/graph/PortHandle.tsx +193 -189
  343. package/src/graph/reactFlowRegistry.ts +30 -26
  344. package/src/hooks/use-toast.ts +129 -125
  345. package/src/hooks/useAvailableVariables.ts +24 -20
  346. package/src/hooks/useCanvasHistory.ts +26 -22
  347. package/src/hooks/useCanvasTabs.ts +172 -168
  348. package/src/hooks/useFunctionDiagnosticsSync.ts +44 -40
  349. package/src/hooks/useFunctionRegistry.ts +30 -26
  350. package/src/hooks/useFunctions.ts +48 -44
  351. package/src/hooks/useGraph.ts +165 -161
  352. package/src/hooks/useNodeDefinitions.ts +86 -82
  353. package/src/hooks/useParamErrors.ts +30 -26
  354. package/src/hooks/useResolvedTheme.ts +34 -30
  355. package/src/hooks/useResourceDiagnosticsSync.ts +62 -58
  356. package/src/hooks/useSuppressThemeTransition.ts +83 -79
  357. package/src/hooks/useWorkflowSerialization.ts +145 -141
  358. package/src/i18n/index.ts +57 -53
  359. package/src/i18n/locales/de.json +501 -501
  360. package/src/i18n/locales/en.json +557 -557
  361. package/src/index.ts +31 -27
  362. package/src/inputs/ExpressionInput.tsx +301 -297
  363. package/src/inputs/ParameterEditor.tsx +519 -515
  364. package/src/inputs/PortSection.tsx +148 -144
  365. package/src/mode.ts +15 -0
  366. package/src/panels/BuilderSidebar.tsx +305 -301
  367. package/src/panels/ChannelConfigPanel.tsx +53 -49
  368. package/src/panels/ChannelsPanel.tsx +32 -28
  369. package/src/panels/DebugConsolePanel.tsx +77 -73
  370. package/src/panels/DebugContextPanel.tsx +81 -77
  371. package/src/panels/DebugExternalIOPanel.tsx +184 -180
  372. package/src/panels/DiagnosticsPanel.tsx +174 -170
  373. package/src/panels/EdgeConfigPanel.tsx +108 -104
  374. package/src/panels/FunctionConfigPanel.tsx +183 -179
  375. package/src/panels/FunctionListPanel.tsx +49 -45
  376. package/src/panels/MemoryConfigPanel.tsx +59 -55
  377. package/src/panels/MemoryPanel.tsx +44 -40
  378. package/src/panels/ModelConfigPanel.tsx +45 -41
  379. package/src/panels/ModelsPanel.tsx +40 -36
  380. package/src/panels/NodeConfigPanel.tsx +634 -630
  381. package/src/panels/NodeLibrary.tsx +292 -288
  382. package/src/panels/ResourceConfigPanel.tsx +136 -132
  383. package/src/panels/ResourceListPanel.tsx +117 -113
  384. package/src/panels/VariableConfigPanel.tsx +165 -161
  385. package/src/panels/VariablesPanel.tsx +149 -145
  386. package/src/stores/canvasStore.test.ts +48 -44
  387. package/src/stores/canvasStore.ts +249 -245
  388. package/src/stores/debugStore.ts +78 -74
  389. package/src/stores/diagnosticsStore.ts +134 -130
  390. package/src/stores/editorStore.ts +194 -190
  391. package/src/styles/index.css +526 -526
  392. package/src/utils/categoryConstants.ts +30 -26
  393. package/src/utils/channelOperations.ts +90 -86
  394. package/src/utils/connectionRules.ts +140 -137
  395. package/src/utils/functionOperations.ts +183 -179
  396. package/src/utils/graphOperations.ts +554 -550
  397. package/src/utils/history.test.ts +92 -0
  398. package/src/utils/history.ts +211 -207
  399. package/src/utils/memoryOperations.ts +61 -57
  400. package/src/utils/migrateFunctionNodes.ts +111 -107
  401. package/src/utils/modelOperations.ts +59 -55
  402. package/src/utils/paramDisplay.ts +75 -71
  403. package/src/utils/resourceHelpers.ts +36 -32
  404. package/src/utils/translation.ts +32 -28
  405. package/src/utils/variableOperations.ts +79 -75
  406. package/tailwind-preset.ts +170 -166
  407. package/dist/lib/utils.d.ts +0 -3
  408. package/dist/lib/utils.d.ts.map +0 -1
  409. package/dist/lib/utils.js +0 -6
  410. package/dist/lib/utils.js.map +0 -1
  411. package/dist/toolbars/CanvasTabsToolbar.d.ts +0 -11
  412. package/dist/toolbars/CanvasTabsToolbar.d.ts.map +0 -1
  413. package/dist/toolbars/CanvasTabsToolbar.js +0 -101
  414. package/dist/toolbars/CanvasTabsToolbar.js.map +0 -1
@@ -1,168 +1,172 @@
1
- import { useState, useCallback, useEffect } from "react";
2
- import { MAIN_CANVAS_ID } from "../stores/canvasStore";
3
- import { useEditorStore } from "../stores/editorStore";
4
-
5
- // Holds info for a canvas tab. id is identical to canvasId.
6
- export interface CanvasTab {
7
- id: string;
8
- label: string;
9
- }
10
-
11
- /**
12
- * Hook for managing canvas tabs UI.
13
- * Tab switching directly updates the UI store's activeCanvasId.
14
- */
15
- export const useCanvasTabs = () => {
16
- const [tabs, setTabs] = useState<CanvasTab[]>([{ id: MAIN_CANVAS_ID, label: "Main" }]);
17
-
18
- // Get active canvas ID and setter from editor store
19
- const activeCanvasId = useEditorStore((state) => state.activeCanvasId);
20
- const setActiveCanvas = useEditorStore((state) => state.setActiveCanvas);
21
- const selectFunction = useEditorStore((state) => state.selectFunction);
22
-
23
- // Tabs are a projection of the function declarations: a deleted function drops its
24
- // tab (falling back to Main if it was active), a renamed one relabels. Open/close
25
- // of an existing function's tab is still explicit (openTab/closeTab) this only
26
- // reconciles against the source of truth so the strip can't show a stale function.
27
- const functions = useEditorStore((state) => state.functions);
28
- useEffect(() => {
29
- setTabs((prev) => {
30
- let changed = false;
31
- const next = prev.flatMap<CanvasTab>((t) => {
32
- if (t.id === MAIN_CANVAS_ID) return [t];
33
- const fn = functions[t.id];
34
- if (!fn) {
35
- changed = true;
36
- return [];
37
- }
38
- if (fn.name !== t.label) {
39
- changed = true;
40
- return [{ ...t, label: fn.name }];
41
- }
42
- return [t];
43
- });
44
- return changed ? next : prev;
45
- });
46
- if (activeCanvasId !== MAIN_CANVAS_ID && !functions[activeCanvasId]) {
47
- setActiveCanvas(MAIN_CANVAS_ID);
48
- }
49
- }, [functions, activeCanvasId, setActiveCanvas]);
50
-
51
- // Switch to a tab's canvas. A function tab focuses its declaration (selectFunction
52
- // switches the canvas AND selects the function so its config panel opens) — matching
53
- // the dropdown/sidebar open path; any other tab just switches the canvas.
54
- const setActiveTabId = useCallback(
55
- (tabId: string) => {
56
- if (tabId !== MAIN_CANVAS_ID && functions[tabId]) {
57
- selectFunction(tabId);
58
- } else {
59
- setActiveCanvas(tabId);
60
- }
61
- },
62
- [functions, selectFunction, setActiveCanvas],
63
- );
64
-
65
- // Open a tab for a function (add if not exists, switch to it)
66
- const openTab = useCallback(
67
- (id: string, label: string) => {
68
- setTabs((prev) => {
69
- const existing = prev.find((t) => t.id === id);
70
- if (existing) {
71
- return prev; // Already exists
72
- }
73
- return [...prev, { id, label }];
74
- });
75
- setActiveCanvas(id);
76
- return id;
77
- },
78
- [setActiveCanvas],
79
- );
80
-
81
- // Close a tab (just removes from visible tabs, does NOT delete canvas data)
82
- const closeTab = useCallback(
83
- (tabId: string) => {
84
- // Cannot close main tab
85
- if (tabId === MAIN_CANVAS_ID) return;
86
-
87
- setTabs((prev) => {
88
- const filtered = prev.filter((t) => t.id !== tabId);
89
- // If closing active tab, switch to main
90
- if (tabId === activeCanvasId) {
91
- setActiveCanvas(MAIN_CANVAS_ID);
92
- }
93
- return filtered;
94
- });
95
- },
96
- [activeCanvasId, setActiveCanvas],
97
- );
98
-
99
- // Remove a tab completely (called when function is deleted)
100
- const removeTab = useCallback(
101
- (tabId: string) => {
102
- if (tabId === MAIN_CANVAS_ID) return;
103
-
104
- setTabs((prev) => {
105
- const filtered = prev.filter((t) => t.id !== tabId);
106
- // Switch to main canvas if removing active tab
107
- if (tabId === activeCanvasId) {
108
- setActiveCanvas(MAIN_CANVAS_ID);
109
- }
110
- return filtered;
111
- });
112
- },
113
- [activeCanvasId, setActiveCanvas],
114
- );
115
-
116
- const renameTab = useCallback((tabId: string, newLabel: string) => {
117
- setTabs((prev) => prev.map((t) => (t.id === tabId ? { ...t, label: newLabel } : t)));
118
- }, []);
119
-
120
- const reorderTabs = useCallback((fromIndex: number, toIndex: number) => {
121
- if (fromIndex === 0 || toIndex === 0) return;
122
- setTabs((prev) => {
123
- const updated = [...prev];
124
- const [moved] = updated.splice(fromIndex, 1);
125
- if (!moved) return prev;
126
- updated.splice(toIndex, 0, moved);
127
- return updated;
128
- });
129
- }, []);
130
-
131
- // Reset to main canvas only (closes all function tabs)
132
- const resetToMain = useCallback(() => {
133
- setTabs([{ id: MAIN_CANVAS_ID, label: "Main" }]);
134
- setActiveCanvas(MAIN_CANVAS_ID);
135
- }, [setActiveCanvas]);
136
-
137
- // Restore a previously saved tab state
138
- const restoreTabState = useCallback(
139
- (savedTabs: CanvasTab[], savedActiveId: string) => {
140
- setTabs(savedTabs);
141
- setActiveCanvas(savedActiveId);
142
- },
143
- [setActiveCanvas],
144
- );
145
-
146
- // Get label for a tab
147
- const getTabLabel = useCallback(
148
- (tabId: string) => {
149
- return tabs.find((t) => t.id === tabId)?.label || "Unknown";
150
- },
151
- [tabs],
152
- );
153
-
154
- return {
155
- tabs,
156
- activeTabId: activeCanvasId,
157
- setActiveTabId,
158
- openTab,
159
- closeTab,
160
- removeTab,
161
- renameTab,
162
- reorderTabs,
163
- resetToMain,
164
- restoreTabState,
165
- getTabLabel,
166
- isMainCanvas: activeCanvasId === MAIN_CANVAS_ID,
167
- };
168
- };
1
+ // SPDX-License-Identifier: AGPL-3.0-only
2
+ // Copyright (c) 2026 ForestHub. All rights reserved.
3
+ // For commercial licensing, contact root@foresthub.ai
4
+
5
+ import { useState, useCallback, useEffect } from "react";
6
+ import { MAIN_CANVAS_ID } from "../stores/canvasStore";
7
+ import { useEditorStore } from "../stores/editorStore";
8
+
9
+ // Holds info for a canvas tab. id is identical to canvasId.
10
+ export interface CanvasTab {
11
+ id: string;
12
+ label: string;
13
+ }
14
+
15
+ /**
16
+ * Hook for managing canvas tabs UI.
17
+ * Tab switching directly updates the UI store's activeCanvasId.
18
+ */
19
+ export const useCanvasTabs = () => {
20
+ const [tabs, setTabs] = useState<CanvasTab[]>([{ id: MAIN_CANVAS_ID, label: "Main" }]);
21
+
22
+ // Get active canvas ID and setter from editor store
23
+ const activeCanvasId = useEditorStore((state) => state.activeCanvasId);
24
+ const setActiveCanvas = useEditorStore((state) => state.setActiveCanvas);
25
+ const selectFunction = useEditorStore((state) => state.selectFunction);
26
+
27
+ // Tabs are a projection of the function declarations: a deleted function drops its
28
+ // tab (falling back to Main if it was active), a renamed one relabels. Open/close
29
+ // of an existing function's tab is still explicit (openTab/closeTab) this only
30
+ // reconciles against the source of truth so the strip can't show a stale function.
31
+ const functions = useEditorStore((state) => state.functions);
32
+ useEffect(() => {
33
+ setTabs((prev) => {
34
+ let changed = false;
35
+ const next = prev.flatMap<CanvasTab>((t) => {
36
+ if (t.id === MAIN_CANVAS_ID) return [t];
37
+ const fn = functions[t.id];
38
+ if (!fn) {
39
+ changed = true;
40
+ return [];
41
+ }
42
+ if (fn.name !== t.label) {
43
+ changed = true;
44
+ return [{ ...t, label: fn.name }];
45
+ }
46
+ return [t];
47
+ });
48
+ return changed ? next : prev;
49
+ });
50
+ if (activeCanvasId !== MAIN_CANVAS_ID && !functions[activeCanvasId]) {
51
+ setActiveCanvas(MAIN_CANVAS_ID);
52
+ }
53
+ }, [functions, activeCanvasId, setActiveCanvas]);
54
+
55
+ // Switch to a tab's canvas. A function tab focuses its declaration (selectFunction
56
+ // switches the canvas AND selects the function so its config panel opens) — matching
57
+ // the dropdown/sidebar open path; any other tab just switches the canvas.
58
+ const setActiveTabId = useCallback(
59
+ (tabId: string) => {
60
+ if (tabId !== MAIN_CANVAS_ID && functions[tabId]) {
61
+ selectFunction(tabId);
62
+ } else {
63
+ setActiveCanvas(tabId);
64
+ }
65
+ },
66
+ [functions, selectFunction, setActiveCanvas],
67
+ );
68
+
69
+ // Open a tab for a function (add if not exists, switch to it)
70
+ const openTab = useCallback(
71
+ (id: string, label: string) => {
72
+ setTabs((prev) => {
73
+ const existing = prev.find((t) => t.id === id);
74
+ if (existing) {
75
+ return prev; // Already exists
76
+ }
77
+ return [...prev, { id, label }];
78
+ });
79
+ setActiveCanvas(id);
80
+ return id;
81
+ },
82
+ [setActiveCanvas],
83
+ );
84
+
85
+ // Close a tab (just removes from visible tabs, does NOT delete canvas data)
86
+ const closeTab = useCallback(
87
+ (tabId: string) => {
88
+ // Cannot close main tab
89
+ if (tabId === MAIN_CANVAS_ID) return;
90
+
91
+ setTabs((prev) => {
92
+ const filtered = prev.filter((t) => t.id !== tabId);
93
+ // If closing active tab, switch to main
94
+ if (tabId === activeCanvasId) {
95
+ setActiveCanvas(MAIN_CANVAS_ID);
96
+ }
97
+ return filtered;
98
+ });
99
+ },
100
+ [activeCanvasId, setActiveCanvas],
101
+ );
102
+
103
+ // Remove a tab completely (called when function is deleted)
104
+ const removeTab = useCallback(
105
+ (tabId: string) => {
106
+ if (tabId === MAIN_CANVAS_ID) return;
107
+
108
+ setTabs((prev) => {
109
+ const filtered = prev.filter((t) => t.id !== tabId);
110
+ // Switch to main canvas if removing active tab
111
+ if (tabId === activeCanvasId) {
112
+ setActiveCanvas(MAIN_CANVAS_ID);
113
+ }
114
+ return filtered;
115
+ });
116
+ },
117
+ [activeCanvasId, setActiveCanvas],
118
+ );
119
+
120
+ const renameTab = useCallback((tabId: string, newLabel: string) => {
121
+ setTabs((prev) => prev.map((t) => (t.id === tabId ? { ...t, label: newLabel } : t)));
122
+ }, []);
123
+
124
+ const reorderTabs = useCallback((fromIndex: number, toIndex: number) => {
125
+ if (fromIndex === 0 || toIndex === 0) return;
126
+ setTabs((prev) => {
127
+ const updated = [...prev];
128
+ const [moved] = updated.splice(fromIndex, 1);
129
+ if (!moved) return prev;
130
+ updated.splice(toIndex, 0, moved);
131
+ return updated;
132
+ });
133
+ }, []);
134
+
135
+ // Reset to main canvas only (closes all function tabs)
136
+ const resetToMain = useCallback(() => {
137
+ setTabs([{ id: MAIN_CANVAS_ID, label: "Main" }]);
138
+ setActiveCanvas(MAIN_CANVAS_ID);
139
+ }, [setActiveCanvas]);
140
+
141
+ // Restore a previously saved tab state
142
+ const restoreTabState = useCallback(
143
+ (savedTabs: CanvasTab[], savedActiveId: string) => {
144
+ setTabs(savedTabs);
145
+ setActiveCanvas(savedActiveId);
146
+ },
147
+ [setActiveCanvas],
148
+ );
149
+
150
+ // Get label for a tab
151
+ const getTabLabel = useCallback(
152
+ (tabId: string) => {
153
+ return tabs.find((t) => t.id === tabId)?.label || "Unknown";
154
+ },
155
+ [tabs],
156
+ );
157
+
158
+ return {
159
+ tabs,
160
+ activeTabId: activeCanvasId,
161
+ setActiveTabId,
162
+ openTab,
163
+ closeTab,
164
+ removeTab,
165
+ renameTab,
166
+ reorderTabs,
167
+ resetToMain,
168
+ restoreTabState,
169
+ getTabLabel,
170
+ isMainCanvas: activeCanvasId === MAIN_CANVAS_ID,
171
+ };
172
+ };
@@ -1,40 +1,44 @@
1
- import { useEffect } from "react";
2
- import { validateFunction } from "@foresthubai/workflow-core/diagnostics";
3
- import { computeAvailableVariables } from "@foresthubai/workflow-core/variable";
4
- import { useEditorStore } from "../stores/editorStore";
5
- import { useDiagnosticsStore } from "../stores/diagnosticsStore";
6
- import { getCanvasStore } from "../stores/canvasStore";
7
-
8
- /**
9
- * Keeps the `byFunctionId` diagnostics slot in sync with the function declarations —
10
- * the single source for the sidebar tab badge, the function list ring, AND the config
11
- * panel's per-output rings (they all read this slot). Mounted once at the
12
- * workflow-builder root so it survives tab open/close.
13
- *
14
- * Scope-aware: each function is validated against its own body canvas's variables, so
15
- * invalid/typed return expressions surface here too not just missing ones. (Reacts
16
- * to declaration/expression edits via `functions`; a body-only edit that changes the
17
- * available variables without touching a declaration refreshes on the next
18
- * declaration change or a full `validate`.)
19
- */
20
- export function useFunctionDiagnosticsSync(): void {
21
- const functions = useEditorStore((s) => s.functions);
22
-
23
- useEffect(() => {
24
- const ds = useDiagnosticsStore.getState();
25
-
26
- const seen = new Set<string>();
27
- for (const [id, def] of Object.entries(functions)) {
28
- seen.add(id);
29
- const store = getCanvasStore(id);
30
- const lookup = store
31
- ? computeAvailableVariables(store.getState().variables, store.getState().edges).lookup
32
- : undefined;
33
- ds.setFunctionDiagnostics(id, validateFunction(def, lookup));
34
- }
35
-
36
- for (const id of Object.keys(ds.byFunctionId)) {
37
- if (!seen.has(id)) ds.clearFunctionDiagnostics(id);
38
- }
39
- }, [functions]);
40
- }
1
+ // SPDX-License-Identifier: AGPL-3.0-only
2
+ // Copyright (c) 2026 ForestHub. All rights reserved.
3
+ // For commercial licensing, contact root@foresthub.ai
4
+
5
+ import { useEffect } from "react";
6
+ import { validateFunction } from "@foresthubai/workflow-core/diagnostics";
7
+ import { computeAvailableVariables } from "@foresthubai/workflow-core/variable";
8
+ import { useEditorStore } from "../stores/editorStore";
9
+ import { useDiagnosticsStore } from "../stores/diagnosticsStore";
10
+ import { getCanvasStore } from "../stores/canvasStore";
11
+
12
+ /**
13
+ * Keeps the `byFunctionId` diagnostics slot in sync with the function declarations —
14
+ * the single source for the sidebar tab badge, the function list ring, AND the config
15
+ * panel's per-output rings (they all read this slot). Mounted once at the
16
+ * workflow-builder root so it survives tab open/close.
17
+ *
18
+ * Scope-aware: each function is validated against its own body canvas's variables, so
19
+ * invalid/typed return expressions surface here too — not just missing ones. (Reacts
20
+ * to declaration/expression edits via `functions`; a body-only edit that changes the
21
+ * available variables without touching a declaration refreshes on the next
22
+ * declaration change or a full `validate`.)
23
+ */
24
+ export function useFunctionDiagnosticsSync(): void {
25
+ const functions = useEditorStore((s) => s.functions);
26
+
27
+ useEffect(() => {
28
+ const ds = useDiagnosticsStore.getState();
29
+
30
+ const seen = new Set<string>();
31
+ for (const [id, def] of Object.entries(functions)) {
32
+ seen.add(id);
33
+ const store = getCanvasStore(id);
34
+ const lookup = store
35
+ ? computeAvailableVariables(store.getState().variables, store.getState().edges).lookup
36
+ : undefined;
37
+ ds.setFunctionDiagnostics(id, validateFunction(def, lookup));
38
+ }
39
+
40
+ for (const id of Object.keys(ds.byFunctionId)) {
41
+ if (!seen.has(id)) ds.clearFunctionDiagnostics(id);
42
+ }
43
+ }, [functions]);
44
+ }
@@ -1,26 +1,30 @@
1
- import { useCallback, useMemo } from "react";
2
- import { useEditorStore } from "../stores/editorStore";
3
- import type { FunctionDeclaration } from "@foresthubai/workflow-core/function";
4
-
5
- // Functions are a project-scoped resource: the registry IS editorStore.functions —
6
- // the domain FunctionDeclaration, no conversion. (Crossing to the flat api FunctionInfo
7
- // is done only when stamping a call-site snapshot; see useNodeDefinitions/migration.)
8
-
9
- /**
10
- * Access to all function declarations by id. Reactive over editorStore.functions.
11
- * - functions: Record of FunctionDeclaration by id
12
- * - functionsList: array of FunctionDeclaration
13
- * - getFunction(id): one declaration by id
14
- */
15
- export function useFunctionRegistry() {
16
- const functions = useEditorStore((s) => s.functions);
17
- const functionsList = useMemo(() => Object.values(functions), [functions]);
18
- const getFunction = useCallback((id: string): FunctionDeclaration | undefined => functions[id], [functions]);
19
-
20
- return { functions, functionsList, getFunction };
21
- }
22
-
23
- /** All function declarations without React subscription (for non-component code). */
24
- export function getAllFunctions(): Record<string, FunctionDeclaration> {
25
- return useEditorStore.getState().functions;
26
- }
1
+ // SPDX-License-Identifier: AGPL-3.0-only
2
+ // Copyright (c) 2026 ForestHub. All rights reserved.
3
+ // For commercial licensing, contact root@foresthub.ai
4
+
5
+ import { useCallback, useMemo } from "react";
6
+ import { useEditorStore } from "../stores/editorStore";
7
+ import type { FunctionDeclaration } from "@foresthubai/workflow-core/function";
8
+
9
+ // Functions are a project-scoped resource: the registry IS editorStore.functions —
10
+ // the domain FunctionDeclaration, no conversion. (Crossing to the flat api FunctionInfo
11
+ // is done only when stamping a call-site snapshot; see useNodeDefinitions/migration.)
12
+
13
+ /**
14
+ * Access to all function declarations by id. Reactive over editorStore.functions.
15
+ * - functions: Record of FunctionDeclaration by id
16
+ * - functionsList: array of FunctionDeclaration
17
+ * - getFunction(id): one declaration by id
18
+ */
19
+ export function useFunctionRegistry() {
20
+ const functions = useEditorStore((s) => s.functions);
21
+ const functionsList = useMemo(() => Object.values(functions), [functions]);
22
+ const getFunction = useCallback((id: string): FunctionDeclaration | undefined => functions[id], [functions]);
23
+
24
+ return { functions, functionsList, getFunction };
25
+ }
26
+
27
+ /** All function declarations without React subscription (for non-component code). */
28
+ export function getAllFunctions(): Record<string, FunctionDeclaration> {
29
+ return useEditorStore.getState().functions;
30
+ }
@@ -1,44 +1,48 @@
1
- import { useCallback } from "react";
2
- import { useEditorStore } from "../stores/editorStore";
3
- import { getOrCreateCanvasStore } from "../stores/canvasStore";
4
- import { useFunctionRegistry } from "./useFunctionRegistry";
5
- import { addFunction } from "../utils/functionOperations";
6
-
7
- export interface UseFunctionsOptions {
8
- /** Open (or focus) a tab for a function canvas. */
9
- onOpenTab: (id: string, label: string) => void;
10
- }
11
-
12
- /**
13
- * Coordinates the canvas-tab UI with function declarations (editorStore). The
14
- * declarations themselves are CRUD'd in utils/functionOperations; this hook only
15
- * handles the open/create flows that must also touch the tab strip and selection.
16
- */
17
- export const useFunctions = ({ onOpenTab }: UseFunctionsOptions) => {
18
- const { functionsList: functions, getFunction } = useFunctionRegistry();
19
- const selectFunction = useEditorStore((s) => s.selectFunction);
20
-
21
- // Open an existing function: ensure its body canvas exists, open its tab, and
22
- // select it so the right panel shows its definition. onOpenTab switches the active
23
- // canvas first; selectFunction sets the selection last so it isn't cleared.
24
- const openFunction = useCallback(
25
- (functionId: string) => {
26
- const fn = getFunction(functionId);
27
- if (!fn) return;
28
- getOrCreateCanvasStore(functionId);
29
- onOpenTab(functionId, fn.name);
30
- selectFunction(functionId);
31
- },
32
- [getFunction, onOpenTab, selectFunction],
33
- );
34
-
35
- // Create a new function and open it (the canvas body is created by addFunction).
36
- const createFunction = useCallback(() => {
37
- const fn = addFunction();
38
- onOpenTab(fn.id, fn.name);
39
- selectFunction(fn.id);
40
- return fn.id;
41
- }, [onOpenTab, selectFunction]);
42
-
43
- return { functions, openFunction, createFunction };
44
- };
1
+ // SPDX-License-Identifier: AGPL-3.0-only
2
+ // Copyright (c) 2026 ForestHub. All rights reserved.
3
+ // For commercial licensing, contact root@foresthub.ai
4
+
5
+ import { useCallback } from "react";
6
+ import { useEditorStore } from "../stores/editorStore";
7
+ import { getOrCreateCanvasStore } from "../stores/canvasStore";
8
+ import { useFunctionRegistry } from "./useFunctionRegistry";
9
+ import { addFunction } from "../utils/functionOperations";
10
+
11
+ export interface UseFunctionsOptions {
12
+ /** Open (or focus) a tab for a function canvas. */
13
+ onOpenTab: (id: string, label: string) => void;
14
+ }
15
+
16
+ /**
17
+ * Coordinates the canvas-tab UI with function declarations (editorStore). The
18
+ * declarations themselves are CRUD'd in utils/functionOperations; this hook only
19
+ * handles the open/create flows that must also touch the tab strip and selection.
20
+ */
21
+ export const useFunctions = ({ onOpenTab }: UseFunctionsOptions) => {
22
+ const { functionsList: functions, getFunction } = useFunctionRegistry();
23
+ const selectFunction = useEditorStore((s) => s.selectFunction);
24
+
25
+ // Open an existing function: ensure its body canvas exists, open its tab, and
26
+ // select it so the right panel shows its definition. onOpenTab switches the active
27
+ // canvas first; selectFunction sets the selection last so it isn't cleared.
28
+ const openFunction = useCallback(
29
+ (functionId: string) => {
30
+ const fn = getFunction(functionId);
31
+ if (!fn) return;
32
+ getOrCreateCanvasStore(functionId);
33
+ onOpenTab(functionId, fn.name);
34
+ selectFunction(functionId);
35
+ },
36
+ [getFunction, onOpenTab, selectFunction],
37
+ );
38
+
39
+ // Create a new function and open it (the canvas body is created by addFunction).
40
+ const createFunction = useCallback(() => {
41
+ const fn = addFunction();
42
+ onOpenTab(fn.id, fn.name);
43
+ selectFunction(fn.id);
44
+ return fn.id;
45
+ }, [onOpenTab, selectFunction]);
46
+
47
+ return { functions, openFunction, createFunction };
48
+ };