@octaviaflow/core 3.0.17-beta.0 → 3.0.18-beta.1

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 (464) hide show
  1. package/dist/chunk-2RD5OERK.js +2553 -0
  2. package/dist/chunk-2RD5OERK.js.map +1 -0
  3. package/dist/chunk-CGWNV2HS.js +2549 -0
  4. package/dist/chunk-CGWNV2HS.js.map +1 -0
  5. package/dist/chunk-CS7JWNQD.js +2552 -0
  6. package/dist/chunk-CS7JWNQD.js.map +1 -0
  7. package/dist/chunk-D6CFZILB.js +2550 -0
  8. package/dist/chunk-D6CFZILB.js.map +1 -0
  9. package/dist/chunk-ECOTUJWJ.js +2548 -0
  10. package/dist/chunk-ECOTUJWJ.js.map +1 -0
  11. package/dist/chunk-F3ZHEDDP.js +2548 -0
  12. package/dist/chunk-F3ZHEDDP.js.map +1 -0
  13. package/dist/chunk-QWICIDGH.js +2547 -0
  14. package/dist/chunk-QWICIDGH.js.map +1 -0
  15. package/dist/chunk-TTKIDRN7.js +2551 -0
  16. package/dist/chunk-TTKIDRN7.js.map +1 -0
  17. package/dist/chunk-UFGAO5OY.js +2546 -0
  18. package/dist/chunk-UFGAO5OY.js.map +1 -0
  19. package/dist/components/Accordion/Accordion.d.ts +45 -0
  20. package/dist/components/Accordion/Accordion.d.ts.map +1 -0
  21. package/dist/components/Accordion/index.d.ts +2 -0
  22. package/dist/components/Accordion/index.d.ts.map +1 -0
  23. package/dist/components/ActionsDrawer/ActionsDrawer.d.ts +6 -0
  24. package/dist/components/ActionsDrawer/ActionsDrawer.d.ts.map +1 -1
  25. package/dist/components/AgentCard/AgentCard.d.ts +53 -7
  26. package/dist/components/AgentCard/AgentCard.d.ts.map +1 -1
  27. package/dist/components/AlertCard/AlertCard.d.ts +76 -0
  28. package/dist/components/AlertCard/AlertCard.d.ts.map +1 -0
  29. package/dist/components/AlertCard/index.d.ts +2 -0
  30. package/dist/components/AlertCard/index.d.ts.map +1 -0
  31. package/dist/components/AuthCard/AuthCard.d.ts +29 -42
  32. package/dist/components/AuthCard/AuthCard.d.ts.map +1 -1
  33. package/dist/components/Avatar/Avatar.d.ts +48 -11
  34. package/dist/components/Avatar/Avatar.d.ts.map +1 -1
  35. package/dist/components/Avatar/index.d.ts +1 -1
  36. package/dist/components/Avatar/index.d.ts.map +1 -1
  37. package/dist/components/Badge/Badge.d.ts +46 -8
  38. package/dist/components/Badge/Badge.d.ts.map +1 -1
  39. package/dist/components/Badge/index.d.ts +1 -1
  40. package/dist/components/Badge/index.d.ts.map +1 -1
  41. package/dist/components/Banner/Banner.d.ts +53 -6
  42. package/dist/components/Banner/Banner.d.ts.map +1 -1
  43. package/dist/components/Banner/index.d.ts +1 -1
  44. package/dist/components/Banner/index.d.ts.map +1 -1
  45. package/dist/components/BarChart/BarChart.d.ts +62 -5
  46. package/dist/components/BarChart/BarChart.d.ts.map +1 -1
  47. package/dist/components/BarChart/index.d.ts +1 -1
  48. package/dist/components/BarChart/index.d.ts.map +1 -1
  49. package/dist/components/BlogCard/BlogCard.d.ts +39 -4
  50. package/dist/components/BlogCard/BlogCard.d.ts.map +1 -1
  51. package/dist/components/Button/Button.d.ts +23 -5
  52. package/dist/components/Button/Button.d.ts.map +1 -1
  53. package/dist/components/Calendar/Calendar.d.ts +53 -4
  54. package/dist/components/Calendar/Calendar.d.ts.map +1 -1
  55. package/dist/components/CalendarHeatmap/CalendarHeatmap.d.ts +47 -0
  56. package/dist/components/CalendarHeatmap/CalendarHeatmap.d.ts.map +1 -0
  57. package/dist/components/CalendarHeatmap/index.d.ts +2 -0
  58. package/dist/components/CalendarHeatmap/index.d.ts.map +1 -0
  59. package/dist/components/Callout/Callout.d.ts +33 -7
  60. package/dist/components/Callout/Callout.d.ts.map +1 -1
  61. package/dist/components/Callout/index.d.ts +1 -1
  62. package/dist/components/Callout/index.d.ts.map +1 -1
  63. package/dist/components/Card/Card.d.ts +49 -8
  64. package/dist/components/Card/Card.d.ts.map +1 -1
  65. package/dist/components/Card/index.d.ts +1 -1
  66. package/dist/components/Card/index.d.ts.map +1 -1
  67. package/dist/components/ChatBubble/ChatBubble.d.ts +32 -7
  68. package/dist/components/ChatBubble/ChatBubble.d.ts.map +1 -1
  69. package/dist/components/ChatBubble/index.d.ts +1 -1
  70. package/dist/components/ChatBubble/index.d.ts.map +1 -1
  71. package/dist/components/Checkbox/Checkbox.d.ts +16 -3
  72. package/dist/components/Checkbox/Checkbox.d.ts.map +1 -1
  73. package/dist/components/Checkbox/index.d.ts +1 -1
  74. package/dist/components/Checkbox/index.d.ts.map +1 -1
  75. package/dist/components/Chip/Chip.d.ts +28 -9
  76. package/dist/components/Chip/Chip.d.ts.map +1 -1
  77. package/dist/components/Chip/index.d.ts +1 -1
  78. package/dist/components/Chip/index.d.ts.map +1 -1
  79. package/dist/components/ChoiceCard/ChoiceCard.d.ts +44 -6
  80. package/dist/components/ChoiceCard/ChoiceCard.d.ts.map +1 -1
  81. package/dist/components/ChoiceCard/index.d.ts +1 -1
  82. package/dist/components/ChoiceCard/index.d.ts.map +1 -1
  83. package/dist/components/Coachmark/Coachmark.d.ts +52 -0
  84. package/dist/components/Coachmark/Coachmark.d.ts.map +1 -0
  85. package/dist/components/Coachmark/index.d.ts +2 -0
  86. package/dist/components/Coachmark/index.d.ts.map +1 -0
  87. package/dist/components/CodeEditor/CodeEditor.d.ts +10 -1
  88. package/dist/components/CodeEditor/CodeEditor.d.ts.map +1 -1
  89. package/dist/components/ColorPicker/ColorPicker.d.ts +25 -6
  90. package/dist/components/ColorPicker/ColorPicker.d.ts.map +1 -1
  91. package/dist/components/ColorPicker/index.d.ts +1 -1
  92. package/dist/components/ColorPicker/index.d.ts.map +1 -1
  93. package/dist/components/CommandPalette/CommandPalette.d.ts +64 -0
  94. package/dist/components/CommandPalette/CommandPalette.d.ts.map +1 -0
  95. package/dist/components/CommandPalette/index.d.ts +2 -0
  96. package/dist/components/CommandPalette/index.d.ts.map +1 -0
  97. package/dist/components/ConditionBuilder/ConditionBuilder.d.ts +24 -4
  98. package/dist/components/ConditionBuilder/ConditionBuilder.d.ts.map +1 -1
  99. package/dist/components/ConfigPanel/ConfigPanel.d.ts +29 -4
  100. package/dist/components/ConfigPanel/ConfigPanel.d.ts.map +1 -1
  101. package/dist/components/ConfigPanel/index.d.ts +1 -1
  102. package/dist/components/ConfigPanel/index.d.ts.map +1 -1
  103. package/dist/components/ConfirmDialog/ConfirmDialog.d.ts +47 -0
  104. package/dist/components/ConfirmDialog/ConfirmDialog.d.ts.map +1 -0
  105. package/dist/components/ConfirmDialog/index.d.ts +2 -0
  106. package/dist/components/ConfirmDialog/index.d.ts.map +1 -0
  107. package/dist/components/ConnectorCard/ConnectorCard.d.ts +49 -0
  108. package/dist/components/ConnectorCard/ConnectorCard.d.ts.map +1 -0
  109. package/dist/components/ConnectorCard/index.d.ts +2 -0
  110. package/dist/components/ConnectorCard/index.d.ts.map +1 -0
  111. package/dist/components/ContextMenu/ContextMenu.d.ts +46 -0
  112. package/dist/components/ContextMenu/ContextMenu.d.ts.map +1 -0
  113. package/dist/components/ContextMenu/index.d.ts +2 -0
  114. package/dist/components/ContextMenu/index.d.ts.map +1 -0
  115. package/dist/components/CountUp/CountUp.d.ts +35 -0
  116. package/dist/components/CountUp/CountUp.d.ts.map +1 -0
  117. package/dist/components/CountUp/index.d.ts +2 -0
  118. package/dist/components/CountUp/index.d.ts.map +1 -0
  119. package/dist/components/DataMapper/DataMapper.d.ts +3 -3
  120. package/dist/components/DataMapper/DataMapper.d.ts.map +1 -1
  121. package/dist/components/DataTable/DataTable.d.ts +35 -3
  122. package/dist/components/DataTable/DataTable.d.ts.map +1 -1
  123. package/dist/components/DatasetCard/DatasetCard.d.ts +55 -0
  124. package/dist/components/DatasetCard/DatasetCard.d.ts.map +1 -0
  125. package/dist/components/DatasetCard/index.d.ts +2 -0
  126. package/dist/components/DatasetCard/index.d.ts.map +1 -0
  127. package/dist/components/DatePicker/DatePicker.d.ts +18 -5
  128. package/dist/components/DatePicker/DatePicker.d.ts.map +1 -1
  129. package/dist/components/DatePicker/index.d.ts +1 -1
  130. package/dist/components/DatePicker/index.d.ts.map +1 -1
  131. package/dist/components/DescriptionList/DescriptionList.d.ts +10 -6
  132. package/dist/components/DescriptionList/DescriptionList.d.ts.map +1 -1
  133. package/dist/components/DescriptionList/index.d.ts +1 -1
  134. package/dist/components/DescriptionList/index.d.ts.map +1 -1
  135. package/dist/components/Dialog/Dialog.d.ts +13 -5
  136. package/dist/components/Dialog/Dialog.d.ts.map +1 -1
  137. package/dist/components/Dialog/index.d.ts +1 -1
  138. package/dist/components/Dialog/index.d.ts.map +1 -1
  139. package/dist/components/Divider/Divider.d.ts +24 -0
  140. package/dist/components/Divider/Divider.d.ts.map +1 -0
  141. package/dist/components/Divider/index.d.ts +2 -0
  142. package/dist/components/Divider/index.d.ts.map +1 -0
  143. package/dist/components/DonutChart/DonutChart.d.ts +32 -4
  144. package/dist/components/DonutChart/DonutChart.d.ts.map +1 -1
  145. package/dist/components/Drawer/Drawer.d.ts +12 -5
  146. package/dist/components/Drawer/Drawer.d.ts.map +1 -1
  147. package/dist/components/Drawer/index.d.ts +1 -1
  148. package/dist/components/Drawer/index.d.ts.map +1 -1
  149. package/dist/components/EmptyState/EmptyState.d.ts +16 -6
  150. package/dist/components/EmptyState/EmptyState.d.ts.map +1 -1
  151. package/dist/components/EmptyState/index.d.ts +1 -1
  152. package/dist/components/EmptyState/index.d.ts.map +1 -1
  153. package/dist/components/ExecutionConsole/ExecutionConsole.d.ts +18 -2
  154. package/dist/components/ExecutionConsole/ExecutionConsole.d.ts.map +1 -1
  155. package/dist/components/FeatureCard/FeatureCard.d.ts +29 -10
  156. package/dist/components/FeatureCard/FeatureCard.d.ts.map +1 -1
  157. package/dist/components/FileDropzone/FileDropzone.d.ts +3 -3
  158. package/dist/components/FileDropzone/FileDropzone.d.ts.map +1 -1
  159. package/dist/components/FlowMinimap/FlowMinimap.d.ts +27 -2
  160. package/dist/components/FlowMinimap/FlowMinimap.d.ts.map +1 -1
  161. package/dist/components/FlowToolbar/FlowToolbar.d.ts +91 -1
  162. package/dist/components/FlowToolbar/FlowToolbar.d.ts.map +1 -1
  163. package/dist/components/FlowToolbar/index.d.ts +1 -1
  164. package/dist/components/FlowToolbar/index.d.ts.map +1 -1
  165. package/dist/components/Gauge/Gauge.d.ts +46 -0
  166. package/dist/components/Gauge/Gauge.d.ts.map +1 -0
  167. package/dist/components/Gauge/index.d.ts +2 -0
  168. package/dist/components/Gauge/index.d.ts.map +1 -0
  169. package/dist/components/Grid/Grid.d.ts +46 -0
  170. package/dist/components/Grid/Grid.d.ts.map +1 -0
  171. package/dist/components/Grid/index.d.ts +2 -0
  172. package/dist/components/Grid/index.d.ts.map +1 -0
  173. package/dist/components/Heatmap/Heatmap.d.ts +54 -0
  174. package/dist/components/Heatmap/Heatmap.d.ts.map +1 -0
  175. package/dist/components/Heatmap/index.d.ts +2 -0
  176. package/dist/components/Heatmap/index.d.ts.map +1 -0
  177. package/dist/components/IconCard/IconCard.d.ts +24 -6
  178. package/dist/components/IconCard/IconCard.d.ts.map +1 -1
  179. package/dist/components/IconCard/index.d.ts +1 -1
  180. package/dist/components/IconCard/index.d.ts.map +1 -1
  181. package/dist/components/InlineMessage/InlineMessage.d.ts +24 -0
  182. package/dist/components/InlineMessage/InlineMessage.d.ts.map +1 -0
  183. package/dist/components/InlineMessage/index.d.ts +2 -0
  184. package/dist/components/InlineMessage/index.d.ts.map +1 -0
  185. package/dist/components/Input/Input.d.ts.map +1 -1
  186. package/dist/components/IntegrationCard/IntegrationCard.d.ts +69 -0
  187. package/dist/components/IntegrationCard/IntegrationCard.d.ts.map +1 -0
  188. package/dist/components/IntegrationCard/index.d.ts +2 -0
  189. package/dist/components/IntegrationCard/index.d.ts.map +1 -0
  190. package/dist/components/JsonViewer/JsonViewer.d.ts +10 -4
  191. package/dist/components/JsonViewer/JsonViewer.d.ts.map +1 -1
  192. package/dist/components/KanbanCard/KanbanCard.d.ts +40 -7
  193. package/dist/components/KanbanCard/KanbanCard.d.ts.map +1 -1
  194. package/dist/components/Kbd/Kbd.d.ts +8 -9
  195. package/dist/components/Kbd/Kbd.d.ts.map +1 -1
  196. package/dist/components/Kbd/index.d.ts +1 -1
  197. package/dist/components/Kbd/index.d.ts.map +1 -1
  198. package/dist/components/LineChart/LineChart.d.ts +42 -4
  199. package/dist/components/LineChart/LineChart.d.ts.map +1 -1
  200. package/dist/components/LineChart/index.d.ts +1 -1
  201. package/dist/components/LineChart/index.d.ts.map +1 -1
  202. package/dist/components/LinkButton/LinkButton.d.ts +16 -4
  203. package/dist/components/LinkButton/LinkButton.d.ts.map +1 -1
  204. package/dist/components/LinkButton/index.d.ts +1 -1
  205. package/dist/components/LinkButton/index.d.ts.map +1 -1
  206. package/dist/components/MetricCard/MetricCard.d.ts +71 -0
  207. package/dist/components/MetricCard/MetricCard.d.ts.map +1 -0
  208. package/dist/components/MetricCard/index.d.ts +2 -0
  209. package/dist/components/MetricCard/index.d.ts.map +1 -0
  210. package/dist/components/MonacoEditor/MonacoDiffEditor.d.ts +22 -5
  211. package/dist/components/MonacoEditor/MonacoDiffEditor.d.ts.map +1 -1
  212. package/dist/components/MonacoEditor/MonacoEditor.d.ts +28 -7
  213. package/dist/components/MonacoEditor/MonacoEditor.d.ts.map +1 -1
  214. package/dist/components/MonacoEditor/index.d.ts +2 -2
  215. package/dist/components/MonacoEditor/index.d.ts.map +1 -1
  216. package/dist/components/MultiSelect/MultiSelect.d.ts +23 -7
  217. package/dist/components/MultiSelect/MultiSelect.d.ts.map +1 -1
  218. package/dist/components/MultiSelect/index.d.ts +1 -1
  219. package/dist/components/MultiSelect/index.d.ts.map +1 -1
  220. package/dist/components/NumberInput/NumberInput.d.ts +13 -7
  221. package/dist/components/NumberInput/NumberInput.d.ts.map +1 -1
  222. package/dist/components/NumberInput/index.d.ts +1 -1
  223. package/dist/components/NumberInput/index.d.ts.map +1 -1
  224. package/dist/components/OTPInput/OTPInput.d.ts +27 -4
  225. package/dist/components/OTPInput/OTPInput.d.ts.map +1 -1
  226. package/dist/components/OTPInput/index.d.ts +1 -1
  227. package/dist/components/OTPInput/index.d.ts.map +1 -1
  228. package/dist/components/Pagination/Pagination.d.ts +50 -0
  229. package/dist/components/Pagination/Pagination.d.ts.map +1 -0
  230. package/dist/components/Pagination/index.d.ts +2 -0
  231. package/dist/components/Pagination/index.d.ts.map +1 -0
  232. package/dist/components/PasswordInput/PasswordInput.d.ts +22 -7
  233. package/dist/components/PasswordInput/PasswordInput.d.ts.map +1 -1
  234. package/dist/components/PasswordInput/index.d.ts +1 -1
  235. package/dist/components/PasswordInput/index.d.ts.map +1 -1
  236. package/dist/components/PhoneInput/PhoneInput.d.ts +19 -6
  237. package/dist/components/PhoneInput/PhoneInput.d.ts.map +1 -1
  238. package/dist/components/PhoneInput/countries.d.ts +15 -0
  239. package/dist/components/PhoneInput/countries.d.ts.map +1 -0
  240. package/dist/components/PhoneInput/index.d.ts +2 -1
  241. package/dist/components/PhoneInput/index.d.ts.map +1 -1
  242. package/dist/components/PipelineCard/PipelineCard.d.ts +100 -0
  243. package/dist/components/PipelineCard/PipelineCard.d.ts.map +1 -0
  244. package/dist/components/PipelineCard/index.d.ts +2 -0
  245. package/dist/components/PipelineCard/index.d.ts.map +1 -0
  246. package/dist/components/Popover/Popover.d.ts +5 -1
  247. package/dist/components/Popover/Popover.d.ts.map +1 -1
  248. package/dist/components/PricingCard/PricingCard.d.ts +28 -5
  249. package/dist/components/PricingCard/PricingCard.d.ts.map +1 -1
  250. package/dist/components/ProductCard/ProductCard.d.ts +35 -4
  251. package/dist/components/ProductCard/ProductCard.d.ts.map +1 -1
  252. package/dist/components/ProgressBar/ProgressBar.d.ts +28 -0
  253. package/dist/components/ProgressBar/ProgressBar.d.ts.map +1 -0
  254. package/dist/components/ProgressBar/index.d.ts +2 -0
  255. package/dist/components/ProgressBar/index.d.ts.map +1 -0
  256. package/dist/components/ProgressRing/ProgressRing.d.ts +22 -5
  257. package/dist/components/ProgressRing/ProgressRing.d.ts.map +1 -1
  258. package/dist/components/ProgressRing/index.d.ts +1 -1
  259. package/dist/components/ProgressRing/index.d.ts.map +1 -1
  260. package/dist/components/PromptInput/PromptInput.d.ts +59 -16
  261. package/dist/components/PromptInput/PromptInput.d.ts.map +1 -1
  262. package/dist/components/PromptInput/index.d.ts +1 -1
  263. package/dist/components/PromptInput/index.d.ts.map +1 -1
  264. package/dist/components/Quote/Quote.d.ts +20 -6
  265. package/dist/components/Quote/Quote.d.ts.map +1 -1
  266. package/dist/components/Quote/index.d.ts +1 -1
  267. package/dist/components/Quote/index.d.ts.map +1 -1
  268. package/dist/components/Radio/Radio.d.ts +12 -5
  269. package/dist/components/Radio/Radio.d.ts.map +1 -1
  270. package/dist/components/Radio/RadioGroup.d.ts +16 -15
  271. package/dist/components/Radio/RadioGroup.d.ts.map +1 -1
  272. package/dist/components/Radio/index.d.ts +2 -2
  273. package/dist/components/Radio/index.d.ts.map +1 -1
  274. package/dist/components/RangeSlider/RangeSlider.d.ts +18 -5
  275. package/dist/components/RangeSlider/RangeSlider.d.ts.map +1 -1
  276. package/dist/components/RangeSlider/index.d.ts +1 -1
  277. package/dist/components/RangeSlider/index.d.ts.map +1 -1
  278. package/dist/components/Rating/BinaryRating.d.ts +40 -0
  279. package/dist/components/Rating/BinaryRating.d.ts.map +1 -0
  280. package/dist/components/Rating/Rating.d.ts +21 -6
  281. package/dist/components/Rating/Rating.d.ts.map +1 -1
  282. package/dist/components/Rating/index.d.ts +2 -1
  283. package/dist/components/Rating/index.d.ts.map +1 -1
  284. package/dist/components/Resizable/Resizable.d.ts +32 -36
  285. package/dist/components/Resizable/Resizable.d.ts.map +1 -1
  286. package/dist/components/Resizable/index.d.ts +1 -1
  287. package/dist/components/Resizable/index.d.ts.map +1 -1
  288. package/dist/components/Ribbon/Ribbon.d.ts +12 -6
  289. package/dist/components/Ribbon/Ribbon.d.ts.map +1 -1
  290. package/dist/components/Ribbon/index.d.ts +1 -1
  291. package/dist/components/Ribbon/index.d.ts.map +1 -1
  292. package/dist/components/Sankey/Sankey.d.ts +53 -0
  293. package/dist/components/Sankey/Sankey.d.ts.map +1 -0
  294. package/dist/components/Sankey/index.d.ts +2 -0
  295. package/dist/components/Sankey/index.d.ts.map +1 -0
  296. package/dist/components/ScrollArea/ScrollArea.d.ts +33 -0
  297. package/dist/components/ScrollArea/ScrollArea.d.ts.map +1 -0
  298. package/dist/components/ScrollArea/index.d.ts +2 -0
  299. package/dist/components/ScrollArea/index.d.ts.map +1 -0
  300. package/dist/components/SegmentedControl/SegmentedControl.d.ts +38 -0
  301. package/dist/components/SegmentedControl/SegmentedControl.d.ts.map +1 -0
  302. package/dist/components/SegmentedControl/index.d.ts +2 -0
  303. package/dist/components/SegmentedControl/index.d.ts.map +1 -0
  304. package/dist/components/Select/Select.d.ts +19 -1
  305. package/dist/components/Select/Select.d.ts.map +1 -1
  306. package/dist/components/Sheet/Sheet.d.ts.map +1 -1
  307. package/dist/components/Show/Show.d.ts +35 -0
  308. package/dist/components/Show/Show.d.ts.map +1 -0
  309. package/dist/components/Show/index.d.ts +2 -0
  310. package/dist/components/Show/index.d.ts.map +1 -0
  311. package/dist/components/Sidebar/Sidebar.d.ts +7 -8
  312. package/dist/components/Sidebar/Sidebar.d.ts.map +1 -1
  313. package/dist/components/Skeleton/Skeleton.d.ts +43 -5
  314. package/dist/components/Skeleton/Skeleton.d.ts.map +1 -1
  315. package/dist/components/Skeleton/index.d.ts +1 -1
  316. package/dist/components/Skeleton/index.d.ts.map +1 -1
  317. package/dist/components/Slider/Slider.d.ts +26 -7
  318. package/dist/components/Slider/Slider.d.ts.map +1 -1
  319. package/dist/components/Slider/index.d.ts +1 -1
  320. package/dist/components/Slider/index.d.ts.map +1 -1
  321. package/dist/components/SocialButton/SocialButton.d.ts +23 -5
  322. package/dist/components/SocialButton/SocialButton.d.ts.map +1 -1
  323. package/dist/components/SocialButton/index.d.ts +1 -1
  324. package/dist/components/SocialButton/index.d.ts.map +1 -1
  325. package/dist/components/Sortable/Sortable.d.ts +14 -6
  326. package/dist/components/Sortable/Sortable.d.ts.map +1 -1
  327. package/dist/components/Sparkline/Sparkline.d.ts +38 -3
  328. package/dist/components/Sparkline/Sparkline.d.ts.map +1 -1
  329. package/dist/components/Sparkline/index.d.ts +1 -1
  330. package/dist/components/Sparkline/index.d.ts.map +1 -1
  331. package/dist/components/Spinner/Spinner.d.ts +14 -5
  332. package/dist/components/Spinner/Spinner.d.ts.map +1 -1
  333. package/dist/components/Spinner/index.d.ts +1 -1
  334. package/dist/components/Spinner/index.d.ts.map +1 -1
  335. package/dist/components/Spotlight/Spotlight.d.ts +37 -0
  336. package/dist/components/Spotlight/Spotlight.d.ts.map +1 -0
  337. package/dist/components/Spotlight/index.d.ts +2 -0
  338. package/dist/components/Spotlight/index.d.ts.map +1 -0
  339. package/dist/components/Stack/Stack.d.ts +41 -0
  340. package/dist/components/Stack/Stack.d.ts.map +1 -0
  341. package/dist/components/Stack/index.d.ts +2 -0
  342. package/dist/components/Stack/index.d.ts.map +1 -0
  343. package/dist/components/Stat/Stat.d.ts +15 -6
  344. package/dist/components/Stat/Stat.d.ts.map +1 -1
  345. package/dist/components/Stat/index.d.ts +1 -1
  346. package/dist/components/Stat/index.d.ts.map +1 -1
  347. package/dist/components/StatusTiles/StatusTiles.d.ts +39 -0
  348. package/dist/components/StatusTiles/StatusTiles.d.ts.map +1 -0
  349. package/dist/components/StatusTiles/index.d.ts +2 -0
  350. package/dist/components/StatusTiles/index.d.ts.map +1 -0
  351. package/dist/components/Stepper/Stepper.d.ts +53 -0
  352. package/dist/components/Stepper/Stepper.d.ts.map +1 -0
  353. package/dist/components/Stepper/index.d.ts +2 -0
  354. package/dist/components/Stepper/index.d.ts.map +1 -0
  355. package/dist/components/Switch/Switch.d.ts +11 -6
  356. package/dist/components/Switch/Switch.d.ts.map +1 -1
  357. package/dist/components/Switch/index.d.ts +1 -1
  358. package/dist/components/Switch/index.d.ts.map +1 -1
  359. package/dist/components/Table/Table.d.ts +11 -5
  360. package/dist/components/Table/Table.d.ts.map +1 -1
  361. package/dist/components/Tabs/Tabs.d.ts.map +1 -1
  362. package/dist/components/TagsInput/TagsInput.d.ts +10 -5
  363. package/dist/components/TagsInput/TagsInput.d.ts.map +1 -1
  364. package/dist/components/TagsInput/index.d.ts +1 -1
  365. package/dist/components/TagsInput/index.d.ts.map +1 -1
  366. package/dist/components/TemplateCard/TemplateCard.d.ts +120 -0
  367. package/dist/components/TemplateCard/TemplateCard.d.ts.map +1 -0
  368. package/dist/components/TemplateCard/index.d.ts +2 -0
  369. package/dist/components/TemplateCard/index.d.ts.map +1 -0
  370. package/dist/components/TestimonialCard/TestimonialCard.d.ts +30 -5
  371. package/dist/components/TestimonialCard/TestimonialCard.d.ts.map +1 -1
  372. package/dist/components/Textarea/Textarea.d.ts +81 -7
  373. package/dist/components/Textarea/Textarea.d.ts.map +1 -1
  374. package/dist/components/Textarea/index.d.ts +1 -1
  375. package/dist/components/Textarea/index.d.ts.map +1 -1
  376. package/dist/components/TimePicker/TimePicker.d.ts +7 -5
  377. package/dist/components/TimePicker/TimePicker.d.ts.map +1 -1
  378. package/dist/components/TimePicker/index.d.ts +1 -1
  379. package/dist/components/TimePicker/index.d.ts.map +1 -1
  380. package/dist/components/Timeline/Timeline.d.ts +14 -5
  381. package/dist/components/Timeline/Timeline.d.ts.map +1 -1
  382. package/dist/components/Timeline/index.d.ts +1 -1
  383. package/dist/components/Timeline/index.d.ts.map +1 -1
  384. package/dist/components/TimezonePicker/TimezonePicker.d.ts +8 -5
  385. package/dist/components/TimezonePicker/TimezonePicker.d.ts.map +1 -1
  386. package/dist/components/TimezonePicker/index.d.ts +1 -1
  387. package/dist/components/TimezonePicker/index.d.ts.map +1 -1
  388. package/dist/components/Toast/Toast.d.ts +15 -0
  389. package/dist/components/Toast/Toast.d.ts.map +1 -1
  390. package/dist/components/Toggle/Toggle.d.ts +16 -6
  391. package/dist/components/Toggle/Toggle.d.ts.map +1 -1
  392. package/dist/components/Toggle/index.d.ts +1 -1
  393. package/dist/components/Toggle/index.d.ts.map +1 -1
  394. package/dist/components/ToolCard/ToolCard.d.ts +12 -10
  395. package/dist/components/ToolCard/ToolCard.d.ts.map +1 -1
  396. package/dist/components/Tooltip/Tooltip.d.ts +13 -2
  397. package/dist/components/Tooltip/Tooltip.d.ts.map +1 -1
  398. package/dist/components/Tooltip/index.d.ts +1 -1
  399. package/dist/components/Tooltip/index.d.ts.map +1 -1
  400. package/dist/components/TraceStep/TraceStep.d.ts +37 -8
  401. package/dist/components/TraceStep/TraceStep.d.ts.map +1 -1
  402. package/dist/components/TreeView/TreeView.d.ts +54 -0
  403. package/dist/components/TreeView/TreeView.d.ts.map +1 -0
  404. package/dist/components/TreeView/index.d.ts +2 -0
  405. package/dist/components/TreeView/index.d.ts.map +1 -0
  406. package/dist/components/UserCard/UserCard.d.ts +38 -5
  407. package/dist/components/UserCard/UserCard.d.ts.map +1 -1
  408. package/dist/components/XmlViewer/XmlViewer.d.ts +11 -6
  409. package/dist/components/XmlViewer/XmlViewer.d.ts.map +1 -1
  410. package/dist/components/YamlViewer/YamlViewer.d.ts +13 -6
  411. package/dist/components/YamlViewer/YamlViewer.d.ts.map +1 -1
  412. package/dist/hooks/useBanner.d.ts +27 -0
  413. package/dist/hooks/useBanner.d.ts.map +1 -0
  414. package/dist/hooks/useBreakpoint.d.ts +29 -0
  415. package/dist/hooks/useBreakpoint.d.ts.map +1 -0
  416. package/dist/hooks/useCallout.d.ts +32 -0
  417. package/dist/hooks/useCallout.d.ts.map +1 -0
  418. package/dist/hooks/useMediaQuery.d.ts +15 -0
  419. package/dist/hooks/useMediaQuery.d.ts.map +1 -0
  420. package/dist/hooks/usePasswordStrength.d.ts +37 -0
  421. package/dist/hooks/usePasswordStrength.d.ts.map +1 -0
  422. package/dist/hooks/useRating.d.ts +51 -0
  423. package/dist/hooks/useRating.d.ts.map +1 -0
  424. package/dist/hooks/useTextareaCommands.d.ts +55 -0
  425. package/dist/hooks/useTextareaCommands.d.ts.map +1 -0
  426. package/dist/hooks/useTextareaSelection.d.ts +34 -0
  427. package/dist/hooks/useTextareaSelection.d.ts.map +1 -0
  428. package/dist/hooks/useTextareaTools.d.ts +88 -0
  429. package/dist/hooks/useTextareaTools.d.ts.map +1 -0
  430. package/dist/hooks/useTimeline.d.ts +31 -0
  431. package/dist/hooks/useTimeline.d.ts.map +1 -0
  432. package/dist/hooks/useTraceTimeline.d.ts +54 -0
  433. package/dist/hooks/useTraceTimeline.d.ts.map +1 -0
  434. package/dist/index.cjs +25553 -12329
  435. package/dist/index.cjs.map +1 -1
  436. package/dist/index.d.ts +92 -49
  437. package/dist/index.d.ts.map +1 -1
  438. package/dist/index.js +25703 -12011
  439. package/dist/index.js.map +1 -1
  440. package/dist/monaco.cjs +359 -488
  441. package/dist/monaco.cjs.map +1 -1
  442. package/dist/monaco.d.ts +1 -1
  443. package/dist/monaco.d.ts.map +1 -1
  444. package/dist/monaco.js +381 -489
  445. package/dist/monaco.js.map +1 -1
  446. package/dist/stories/_shared/TestPage.d.ts +12 -0
  447. package/dist/stories/_shared/TestPage.d.ts.map +1 -0
  448. package/dist/styles.css +1 -1
  449. package/dist/utils/Slot.d.ts +7 -0
  450. package/dist/utils/Slot.d.ts.map +1 -0
  451. package/dist/utils/composeRefs.d.ts +7 -0
  452. package/dist/utils/composeRefs.d.ts.map +1 -0
  453. package/dist/utils/gradients.d.ts +77 -0
  454. package/dist/utils/gradients.d.ts.map +1 -0
  455. package/dist/utils/zIndex.d.ts +53 -0
  456. package/dist/utils/zIndex.d.ts.map +1 -0
  457. package/dist/workflow/components/kinds/BaseNode.d.ts +7 -1
  458. package/dist/workflow/components/kinds/BaseNode.d.ts.map +1 -1
  459. package/dist/workflow/components/kinds/index.d.ts +6 -0
  460. package/dist/workflow/components/kinds/index.d.ts.map +1 -1
  461. package/dist/workflow.cjs +9 -2
  462. package/dist/workflow.cjs.map +1 -1
  463. package/dist/workflow.js +1 -1
  464. package/package.json +5 -5
@@ -0,0 +1,2553 @@
1
+ import {
2
+ cn
3
+ } from "./chunk-ZAUUGK2Y.js";
4
+
5
+ // src/workflow/utils/paths.ts
6
+ function buildEdgePath(routing, start, startSide, end, endSide, options = {}) {
7
+ switch (routing) {
8
+ case "step":
9
+ return stepPath(start, startSide, end, endSide);
10
+ case "smoothstep":
11
+ return smoothStepPath(start, startSide, end, endSide, options.borderRadius ?? 8);
12
+ case "straight":
13
+ return straightPath(start, end);
14
+ default:
15
+ return bezierPath(start, startSide, end, endSide, options.curvature ?? 0.25);
16
+ }
17
+ }
18
+ function bezierPath(start, startSide, end, endSide, curvature = 0.25) {
19
+ const sourceOffset = calcControlOffset(start, startSide, end, curvature);
20
+ const targetOffset = calcControlOffset(end, endSide, start, curvature);
21
+ const c1 = offsetAlongSide(start, startSide, sourceOffset);
22
+ const c2 = offsetAlongSide(end, endSide, targetOffset);
23
+ const d = `M ${start.x},${start.y} C ${c1.x},${c1.y} ${c2.x},${c2.y} ${end.x},${end.y}`;
24
+ const midX = 0.125 * start.x + 0.375 * c1.x + 0.375 * c2.x + 0.125 * end.x;
25
+ const midY = 0.125 * start.y + 0.375 * c1.y + 0.375 * c2.y + 0.125 * end.y;
26
+ const tx = 3 * ((1 - 0.5) ** 2 * (c1.x - start.x) + 2 * (1 - 0.5) * 0.5 * (c2.x - c1.x) + 0.5 ** 2 * (end.x - c2.x));
27
+ const ty = 3 * ((1 - 0.5) ** 2 * (c1.y - start.y) + 2 * (1 - 0.5) * 0.5 * (c2.y - c1.y) + 0.5 ** 2 * (end.y - c2.y));
28
+ const midAngle = Math.atan2(ty, tx);
29
+ return { d, midX, midY, midAngle };
30
+ }
31
+ function axisDistance(from, side, to) {
32
+ switch (side) {
33
+ case "top":
34
+ return from.y - to.y;
35
+ case "bottom":
36
+ return to.y - from.y;
37
+ case "left":
38
+ return from.x - to.x;
39
+ case "right":
40
+ return to.x - from.x;
41
+ }
42
+ }
43
+ function calcControlOffset(from, side, to, curvature) {
44
+ const distance2 = axisDistance(from, side, to);
45
+ if (distance2 >= 0) {
46
+ return distance2 * 0.5 * (1 + curvature);
47
+ }
48
+ return curvature * 25 * Math.sqrt(-distance2);
49
+ }
50
+ function offsetAlongSide(p, side, magnitude) {
51
+ switch (side) {
52
+ case "top":
53
+ return { x: p.x, y: p.y - magnitude };
54
+ case "bottom":
55
+ return { x: p.x, y: p.y + magnitude };
56
+ case "left":
57
+ return { x: p.x - magnitude, y: p.y };
58
+ case "right":
59
+ return { x: p.x + magnitude, y: p.y };
60
+ }
61
+ }
62
+ function stepPath(start, startSide, end, endSide) {
63
+ const corners = computeStepCorners(start, startSide, end, endSide);
64
+ const pts = [start, ...corners, end];
65
+ const d = pts.map((p, i) => `${i === 0 ? "M" : "L"} ${p.x},${p.y}`).join(" ");
66
+ const { midX, midY, midAngle } = midpointOnPolyline(pts);
67
+ return { d, midX, midY, midAngle };
68
+ }
69
+ function smoothStepPath(start, startSide, end, endSide, borderRadius = 8) {
70
+ const corners = computeStepCorners(start, startSide, end, endSide);
71
+ const pts = [start, ...corners, end];
72
+ if (corners.length === 0) {
73
+ return straightPath(start, end);
74
+ }
75
+ const segments = [`M ${pts[0].x},${pts[0].y}`];
76
+ for (let i = 1; i < pts.length - 1; i++) {
77
+ const prev = pts[i - 1];
78
+ const here = pts[i];
79
+ const next = pts[i + 1];
80
+ const r = Math.min(borderRadius, distance(prev, here) / 2, distance(here, next) / 2);
81
+ const enter = pointTowards(here, prev, r);
82
+ const exit = pointTowards(here, next, r);
83
+ segments.push(`L ${enter.x},${enter.y}`);
84
+ segments.push(`Q ${here.x},${here.y} ${exit.x},${exit.y}`);
85
+ }
86
+ const last = pts[pts.length - 1];
87
+ segments.push(`L ${last.x},${last.y}`);
88
+ const d = segments.join(" ");
89
+ const { midX, midY, midAngle } = midpointOnPolyline(pts);
90
+ return { d, midX, midY, midAngle };
91
+ }
92
+ function straightPath(start, end) {
93
+ const d = `M ${start.x},${start.y} L ${end.x},${end.y}`;
94
+ return {
95
+ d,
96
+ midX: (start.x + end.x) / 2,
97
+ midY: (start.y + end.y) / 2,
98
+ midAngle: Math.atan2(end.y - start.y, end.x - start.x)
99
+ };
100
+ }
101
+ function computeStepCorners(start, startSide, end, endSide) {
102
+ const sourceVertical = startSide === "top" || startSide === "bottom";
103
+ const targetVertical = endSide === "top" || endSide === "bottom";
104
+ if (sourceVertical && targetVertical) {
105
+ const midY = (start.y + end.y) / 2;
106
+ return [
107
+ { x: start.x, y: midY },
108
+ { x: end.x, y: midY }
109
+ ];
110
+ }
111
+ if (!sourceVertical && !targetVertical) {
112
+ const midX = (start.x + end.x) / 2;
113
+ return [
114
+ { x: midX, y: start.y },
115
+ { x: midX, y: end.y }
116
+ ];
117
+ }
118
+ if (sourceVertical) {
119
+ return [{ x: end.x, y: start.y }];
120
+ }
121
+ return [{ x: start.x, y: end.y }];
122
+ }
123
+ function midpointOnPolyline(pts) {
124
+ if (pts.length === 2) {
125
+ return {
126
+ midX: (pts[0].x + pts[1].x) / 2,
127
+ midY: (pts[0].y + pts[1].y) / 2,
128
+ midAngle: Math.atan2(pts[1].y - pts[0].y, pts[1].x - pts[0].x)
129
+ };
130
+ }
131
+ let totalLen = 0;
132
+ const lens = [];
133
+ for (let i = 0; i < pts.length - 1; i++) {
134
+ const l = distance(pts[i], pts[i + 1]);
135
+ lens.push(l);
136
+ totalLen += l;
137
+ }
138
+ const half = totalLen / 2;
139
+ let acc = 0;
140
+ for (let i = 0; i < lens.length; i++) {
141
+ if (acc + lens[i] >= half) {
142
+ const seg = lens[i];
143
+ const remaining = half - acc;
144
+ const t = seg === 0 ? 0 : remaining / seg;
145
+ const a = pts[i];
146
+ const b = pts[i + 1];
147
+ return {
148
+ midX: a.x + (b.x - a.x) * t,
149
+ midY: a.y + (b.y - a.y) * t,
150
+ midAngle: Math.atan2(b.y - a.y, b.x - a.x)
151
+ };
152
+ }
153
+ acc += lens[i];
154
+ }
155
+ return { midX: pts[0].x, midY: pts[0].y, midAngle: 0 };
156
+ }
157
+ function distance(a, b) {
158
+ return Math.hypot(b.x - a.x, b.y - a.y);
159
+ }
160
+ function pointTowards(from, to, dist) {
161
+ const d = distance(from, to);
162
+ if (d === 0) return from;
163
+ const t = dist / d;
164
+ return { x: from.x + (to.x - from.x) * t, y: from.y + (to.y - from.y) * t };
165
+ }
166
+
167
+ // src/workflow/hooks/useFlow.ts
168
+ import { createContext, useContext } from "react";
169
+ var FlowInstanceContext = createContext(null);
170
+ function useFlow() {
171
+ const instance = useContext(FlowInstanceContext);
172
+ if (!instance) {
173
+ throw new Error("[@octaviaflow/core/workflow] useFlow() must be called inside <FlowCanvas>.");
174
+ }
175
+ return instance;
176
+ }
177
+
178
+ // src/workflow/store/changes.ts
179
+ function applyNodeChanges(nodes, changes) {
180
+ if (changes.length === 0) return nodes;
181
+ const byId = /* @__PURE__ */ new Map();
182
+ const adds = [];
183
+ const removes = /* @__PURE__ */ new Set();
184
+ let touched = false;
185
+ for (const change2 of changes) {
186
+ switch (change2.type) {
187
+ case "add":
188
+ adds.push(change2.item);
189
+ touched = true;
190
+ break;
191
+ case "remove":
192
+ removes.add(change2.id);
193
+ touched = true;
194
+ break;
195
+ default: {
196
+ const id = change2.id;
197
+ const arr = byId.get(id);
198
+ if (arr) arr.push(change2);
199
+ else byId.set(id, [change2]);
200
+ touched = true;
201
+ break;
202
+ }
203
+ }
204
+ }
205
+ if (!touched) return nodes;
206
+ const next = [];
207
+ for (const node of nodes) {
208
+ if (removes.has(node.id)) continue;
209
+ const patches = byId.get(node.id);
210
+ if (!patches) {
211
+ next.push(node);
212
+ continue;
213
+ }
214
+ let n = node;
215
+ for (const patch of patches) {
216
+ switch (patch.type) {
217
+ case "position":
218
+ n = {
219
+ ...n,
220
+ position: patch.position,
221
+ dragging: patch.dragging
222
+ };
223
+ break;
224
+ case "dimensions":
225
+ n = {
226
+ ...n,
227
+ width: patch.dimensions.width,
228
+ height: patch.dimensions.height
229
+ };
230
+ break;
231
+ case "select":
232
+ if (n.selected === patch.selected) break;
233
+ n = { ...n, selected: patch.selected };
234
+ break;
235
+ case "replace":
236
+ n = patch.item;
237
+ break;
238
+ }
239
+ }
240
+ next.push(n);
241
+ }
242
+ for (const add of adds) next.push(add);
243
+ return next;
244
+ }
245
+ function applyEdgeChanges(edges, changes) {
246
+ if (changes.length === 0) return edges;
247
+ const byId = /* @__PURE__ */ new Map();
248
+ const adds = [];
249
+ const removes = /* @__PURE__ */ new Set();
250
+ let touched = false;
251
+ for (const change2 of changes) {
252
+ switch (change2.type) {
253
+ case "add":
254
+ adds.push(change2.item);
255
+ touched = true;
256
+ break;
257
+ case "remove":
258
+ removes.add(change2.id);
259
+ touched = true;
260
+ break;
261
+ default: {
262
+ const arr = byId.get(change2.id);
263
+ if (arr) arr.push(change2);
264
+ else byId.set(change2.id, [change2]);
265
+ touched = true;
266
+ break;
267
+ }
268
+ }
269
+ }
270
+ if (!touched) return edges;
271
+ const next = [];
272
+ for (const edge of edges) {
273
+ if (removes.has(edge.id)) continue;
274
+ const patches = byId.get(edge.id);
275
+ if (!patches) {
276
+ next.push(edge);
277
+ continue;
278
+ }
279
+ let e = edge;
280
+ for (const patch of patches) {
281
+ switch (patch.type) {
282
+ case "select":
283
+ if (e.selected === patch.selected) break;
284
+ e = { ...e, selected: patch.selected };
285
+ break;
286
+ case "replace":
287
+ e = patch.item;
288
+ break;
289
+ }
290
+ }
291
+ next.push(e);
292
+ }
293
+ for (const add of adds) next.push(add);
294
+ return next;
295
+ }
296
+ var change = {
297
+ node: {
298
+ add(item) {
299
+ return { type: "add", item };
300
+ },
301
+ remove(id) {
302
+ return { type: "remove", id };
303
+ },
304
+ position(id, position, dragging) {
305
+ return { type: "position", id, position, dragging };
306
+ },
307
+ dimensions(id, dimensions) {
308
+ return { type: "dimensions", id, dimensions };
309
+ },
310
+ select(id, selected) {
311
+ return { type: "select", id, selected };
312
+ },
313
+ replace(id, item) {
314
+ return { type: "replace", id, item };
315
+ }
316
+ },
317
+ edge: {
318
+ add(item) {
319
+ return { type: "add", item };
320
+ },
321
+ remove(id) {
322
+ return { type: "remove", id };
323
+ },
324
+ select(id, selected) {
325
+ return { type: "select", id, selected };
326
+ },
327
+ replace(id, item) {
328
+ return { type: "replace", id, item };
329
+ }
330
+ }
331
+ };
332
+
333
+ // src/workflow/utils/geometry.ts
334
+ var DEFAULT_NODE_WIDTH = 368;
335
+ var DEFAULT_NODE_HEIGHT = 96;
336
+ var COLLAPSED_GROUP_HEIGHT = 36;
337
+ var COLLAPSED_FOREACH_HEIGHT = 40;
338
+ function effectiveHeight(node) {
339
+ const data = node.data;
340
+ if (data?.collapsed) {
341
+ if (node.type === "group") return COLLAPSED_GROUP_HEIGHT;
342
+ if (node.type === "forEach") return COLLAPSED_FOREACH_HEIGHT;
343
+ }
344
+ return node.height ?? DEFAULT_NODE_HEIGHT;
345
+ }
346
+ function handleCentre(node, side, index, total) {
347
+ const w = node.width ?? DEFAULT_NODE_WIDTH;
348
+ const h = effectiveHeight(node);
349
+ const x0 = node.position.x;
350
+ const y0 = node.position.y;
351
+ const denom = total + 1;
352
+ const ratio = (index + 1) / denom;
353
+ switch (side) {
354
+ case "top":
355
+ return { x: x0 + w * ratio, y: y0 };
356
+ case "bottom":
357
+ return { x: x0 + w * ratio, y: y0 + h };
358
+ case "left":
359
+ return { x: x0, y: y0 + h * ratio };
360
+ case "right":
361
+ return { x: x0 + w, y: y0 + h * ratio };
362
+ }
363
+ }
364
+ function bezierPath2(start, startSide, end, endSide) {
365
+ const distance2 = Math.hypot(end.x - start.x, end.y - start.y);
366
+ const magnitude = Math.max(40, Math.min(160, distance2 * 0.45));
367
+ const c1 = offsetBySide(start, startSide, magnitude);
368
+ const c2 = offsetBySide(end, endSide, magnitude);
369
+ const d = `M ${start.x},${start.y} C ${c1.x},${c1.y} ${c2.x},${c2.y} ${end.x},${end.y}`;
370
+ const midX = 0.125 * start.x + 0.375 * c1.x + 0.375 * c2.x + 0.125 * end.x;
371
+ const midY = 0.125 * start.y + 0.375 * c1.y + 0.375 * c2.y + 0.125 * end.y;
372
+ return { d, midX, midY };
373
+ }
374
+ function offsetBySide(p, side, m) {
375
+ switch (side) {
376
+ case "top":
377
+ return { x: p.x, y: p.y - m };
378
+ case "bottom":
379
+ return { x: p.x, y: p.y + m };
380
+ case "left":
381
+ return { x: p.x - m, y: p.y };
382
+ case "right":
383
+ return { x: p.x + m, y: p.y };
384
+ }
385
+ }
386
+ function screenToFlow(p, vp) {
387
+ return {
388
+ x: (p.x - vp.x) / vp.zoom,
389
+ y: (p.y - vp.y) / vp.zoom
390
+ };
391
+ }
392
+ function flowToScreen(p, vp) {
393
+ return {
394
+ x: p.x * vp.zoom + vp.x,
395
+ y: p.y * vp.zoom + vp.y
396
+ };
397
+ }
398
+
399
+ // src/workflow/utils/parenting.ts
400
+ function descendantsOf(nodeId, nodes) {
401
+ const childrenByParent = /* @__PURE__ */ new Map();
402
+ for (const n of nodes) {
403
+ if (!n.parentId) continue;
404
+ const arr = childrenByParent.get(n.parentId);
405
+ if (arr) arr.push(n);
406
+ else childrenByParent.set(n.parentId, [n]);
407
+ }
408
+ const out = [];
409
+ const stack = [nodeId];
410
+ const visited = /* @__PURE__ */ new Set([nodeId]);
411
+ while (stack.length) {
412
+ const cur = stack.pop();
413
+ if (cur === void 0) break;
414
+ const list = childrenByParent.get(cur);
415
+ if (!list) continue;
416
+ for (const c of list) {
417
+ if (visited.has(c.id)) continue;
418
+ visited.add(c.id);
419
+ out.push(c);
420
+ stack.push(c.id);
421
+ }
422
+ }
423
+ return out;
424
+ }
425
+ function findAncestor(node, nodes, predicate) {
426
+ let cursor = node;
427
+ const seen = /* @__PURE__ */ new Set();
428
+ while (cursor?.parentId) {
429
+ if (seen.has(cursor.parentId)) return void 0;
430
+ seen.add(cursor.parentId);
431
+ const parent = nodes.find((n) => n.id === cursor.parentId);
432
+ if (!parent) return void 0;
433
+ if (predicate(parent)) return parent;
434
+ cursor = parent;
435
+ }
436
+ return void 0;
437
+ }
438
+ function clampToParentExtent(node, proposed, nodes) {
439
+ if (node.extent !== "parent" || !node.parentId) return proposed;
440
+ const parent = nodes.find((n) => n.id === node.parentId);
441
+ if (!parent) return proposed;
442
+ const pw = parent.width ?? DEFAULT_NODE_WIDTH;
443
+ const ph = effectiveHeight(parent);
444
+ const w = node.width ?? DEFAULT_NODE_WIDTH;
445
+ const h = effectiveHeight(node);
446
+ const minX = parent.position.x;
447
+ const minY = parent.position.y;
448
+ const maxX = parent.position.x + pw - w;
449
+ const maxY = parent.position.y + ph - h;
450
+ return {
451
+ x: Math.max(minX, Math.min(maxX, proposed.x)),
452
+ y: Math.max(minY, Math.min(maxY, proposed.y))
453
+ };
454
+ }
455
+ function findContainingGroup(point, nodes, exclude = []) {
456
+ for (let i = nodes.length - 1; i >= 0; i--) {
457
+ const n = nodes[i];
458
+ if (exclude.includes(n.id)) continue;
459
+ if (n.type !== "group") continue;
460
+ if (n.data && typeof n.data === "object" && n.data.collapsed) {
461
+ continue;
462
+ }
463
+ const w = n.width ?? DEFAULT_NODE_WIDTH;
464
+ const h = effectiveHeight(n);
465
+ if (point.x >= n.position.x && point.y >= n.position.y && point.x <= n.position.x + w && point.y <= n.position.y + h) {
466
+ return n;
467
+ }
468
+ }
469
+ return void 0;
470
+ }
471
+
472
+ // src/workflow/components/FlowEdge/FlowEdge.tsx
473
+ import {
474
+ memo,
475
+ useEffect,
476
+ useId,
477
+ useRef,
478
+ useState
479
+ } from "react";
480
+
481
+ // src/workflow/components/Handle/handleRegistry.ts
482
+ import { createContext as createContext2, useContext as useContext2 } from "react";
483
+ var HandleRegistryContext = createContext2(null);
484
+ function useHandleRegistry() {
485
+ const r = useContext2(HandleRegistryContext);
486
+ if (!r) {
487
+ throw new Error("[@octaviaflow/core/workflow] Handle must be used inside <FlowCanvas>.");
488
+ }
489
+ return r;
490
+ }
491
+ function createHandleRegistry() {
492
+ const map = /* @__PURE__ */ new Map();
493
+ const key = (n, t, h) => `${n}::${t}::${h}`;
494
+ const listeners = /* @__PURE__ */ new Set();
495
+ const notify = () => {
496
+ for (const l of listeners) l();
497
+ };
498
+ return {
499
+ register(d) {
500
+ map.set(key(d.nodeId, d.type, d.handleId), d);
501
+ notify();
502
+ return () => {
503
+ const k = key(d.nodeId, d.type, d.handleId);
504
+ if (map.get(k) === d) {
505
+ map.delete(k);
506
+ notify();
507
+ }
508
+ };
509
+ },
510
+ resolve(nodeId, type, handleId) {
511
+ return map.get(key(nodeId, type, handleId));
512
+ },
513
+ subscribe(listener) {
514
+ listeners.add(listener);
515
+ return () => {
516
+ listeners.delete(listener);
517
+ };
518
+ }
519
+ };
520
+ }
521
+
522
+ // src/workflow/components/FlowEdge/FlowEdge.tsx
523
+ import { jsx, jsxs } from "react/jsx-runtime";
524
+ function FlowEdgeImpl({
525
+ edge,
526
+ nodes,
527
+ onSelect,
528
+ onDelete,
529
+ onLabelChange,
530
+ showDelete = true,
531
+ curvature = 0.25,
532
+ borderRadius = 8
533
+ }) {
534
+ const uid = useId();
535
+ const markerId = `ods-flow-edge-arrow-${uid.replace(/:/g, "")}`;
536
+ const registry = useHandleRegistry();
537
+ const [hovered, setHovered] = useState(false);
538
+ const [editing, setEditing] = useState(false);
539
+ const [draftLabel, setDraftLabel] = useState(edge.label ?? "");
540
+ const inputRef = useRef(null);
541
+ useEffect(() => {
542
+ if (!editing) setDraftLabel(edge.label ?? "");
543
+ }, [edge.label, editing]);
544
+ const sourceNode = nodes.find((n) => n.id === edge.source);
545
+ const targetNode = nodes.find((n) => n.id === edge.target);
546
+ if (!sourceNode || !targetNode) return null;
547
+ const sourceHandleId = edge.sourceHandle ?? "default";
548
+ const targetHandleId = edge.targetHandle ?? "default";
549
+ const sourceDesc = registry.resolve(sourceNode.id, "source", sourceHandleId);
550
+ const targetDesc = registry.resolve(targetNode.id, "target", targetHandleId);
551
+ const sourceSide = sourceDesc?.side ?? sourceNode.sourcePosition ?? "bottom";
552
+ const targetSide = targetDesc?.side ?? targetNode.targetPosition ?? "top";
553
+ const sourceIndex = sourceDesc?.index ?? 0;
554
+ const sourceTotal = sourceDesc?.total ?? 1;
555
+ const targetIndex = targetDesc?.index ?? 0;
556
+ const targetTotal = targetDesc?.total ?? 1;
557
+ const rawStart = handleCentre(sourceNode, sourceSide, sourceIndex, sourceTotal);
558
+ const rawEnd = handleCentre(targetNode, targetSide, targetIndex, targetTotal);
559
+ const HANDLE_GAP = 8;
560
+ const start = offsetAlongSide2(rawStart, sourceSide, HANDLE_GAP);
561
+ const end = offsetAlongSide2(rawEnd, targetSide, HANDLE_GAP);
562
+ const routing = edge.routing ?? "bezier";
563
+ const { d, midX, midY } = buildEdgePath(routing, start, sourceSide, end, targetSide, {
564
+ curvature,
565
+ borderRadius
566
+ });
567
+ const { d: hitD } = buildEdgePath(routing, rawStart, sourceSide, rawEnd, targetSide, {
568
+ curvature,
569
+ borderRadius
570
+ });
571
+ const type = edge.type ?? "default";
572
+ const isHot = hovered || edge.selected;
573
+ const stroke = type === "error" ? "var(--ods-status-failed, #dc2626)" : isHot ? "var(--ods-accent, #4f46e5)" : "var(--ods-border-strong, #6b7280)";
574
+ const typeDash = type === "conditional" ? "6 4" : type === "loop" ? "4 4" : void 0;
575
+ const dash = edge.style?.strokeDasharray ?? typeDash;
576
+ const strokeWidth = edge.style?.strokeWidth ?? (isHot ? 2 : 1.4);
577
+ const animateDash = edge.animated === true;
578
+ const label = edge.label;
579
+ const hasDelete = showDelete && (isHot || edge.selected) && !!onDelete;
580
+ const showChrome = !!label || editing || hasDelete;
581
+ const commitLabel = (next) => {
582
+ setEditing(false);
583
+ if (next !== edge.label) onLabelChange?.(edge.id, next);
584
+ };
585
+ const onLabelKey = (e) => {
586
+ if (e.key === "Enter") {
587
+ e.preventDefault();
588
+ commitLabel(draftLabel);
589
+ } else if (e.key === "Escape") {
590
+ e.preventDefault();
591
+ setEditing(false);
592
+ setDraftLabel(edge.label ?? "");
593
+ }
594
+ };
595
+ return /* @__PURE__ */ jsxs(
596
+ "g",
597
+ {
598
+ className: cn(
599
+ "ods-flow-edge-v2",
600
+ `ods-flow-edge-v2--${type}`,
601
+ `ods-flow-edge-v2--routing-${routing}`,
602
+ edge.selected && "ods-flow-edge-v2--selected",
603
+ hovered && "ods-flow-edge-v2--hovered",
604
+ edge.className
605
+ ),
606
+ "data-edge-id": edge.id,
607
+ "data-edge-routing": routing,
608
+ onMouseEnter: () => setHovered(true),
609
+ onMouseLeave: () => setHovered(false),
610
+ onClick: (e) => {
611
+ e.stopPropagation();
612
+ onSelect?.(edge.id);
613
+ },
614
+ children: [
615
+ /* @__PURE__ */ jsx("defs", { children: /* @__PURE__ */ jsx(
616
+ "marker",
617
+ {
618
+ id: markerId,
619
+ viewBox: "0 0 10 10",
620
+ refX: "9",
621
+ refY: "5",
622
+ markerWidth: "7",
623
+ markerHeight: "7",
624
+ orient: "auto-start-reverse",
625
+ children: /* @__PURE__ */ jsx("path", { d: "M0 0L10 5L0 10z", fill: stroke })
626
+ }
627
+ ) }),
628
+ /* @__PURE__ */ jsx("path", { d: hitD, stroke: "transparent", strokeWidth: 20, fill: "none" }),
629
+ /* @__PURE__ */ jsx(
630
+ "path",
631
+ {
632
+ d,
633
+ stroke,
634
+ strokeWidth,
635
+ strokeDasharray: dash,
636
+ fill: "none",
637
+ markerEnd: `url(#${markerId})`,
638
+ style: animateDash ? {
639
+ strokeDasharray: dash ?? "6 4",
640
+ animation: "ods-flow-edge-flow 0.6s linear infinite"
641
+ } : void 0
642
+ }
643
+ ),
644
+ showChrome && /* @__PURE__ */ jsx(
645
+ "foreignObject",
646
+ {
647
+ x: midX - 140,
648
+ y: midY - 16,
649
+ width: 280,
650
+ height: 32,
651
+ style: { overflow: "visible", pointerEvents: "none" },
652
+ children: /* @__PURE__ */ jsxs("div", { className: "ods-flow-edge-v2__chrome", children: [
653
+ (label || editing) && (editing ? /* @__PURE__ */ jsx(
654
+ "input",
655
+ {
656
+ ref: inputRef,
657
+ className: "ods-flow-edge-v2__label-input",
658
+ value: draftLabel,
659
+ autoFocus: true,
660
+ onChange: (e) => setDraftLabel(e.target.value),
661
+ onBlur: () => commitLabel(draftLabel),
662
+ onKeyDown: onLabelKey,
663
+ onClick: (e) => e.stopPropagation(),
664
+ onMouseDown: (e) => e.stopPropagation(),
665
+ "aria-label": "Edit edge label"
666
+ }
667
+ ) : /* @__PURE__ */ jsx(
668
+ "button",
669
+ {
670
+ type: "button",
671
+ className: "ods-flow-edge-v2__label-chip",
672
+ onDoubleClick: (e) => {
673
+ if (!onLabelChange) return;
674
+ e.stopPropagation();
675
+ setDraftLabel(edge.label ?? "");
676
+ setEditing(true);
677
+ },
678
+ onClick: (e) => {
679
+ e.stopPropagation();
680
+ onSelect?.(edge.id);
681
+ },
682
+ title: onLabelChange ? "Double-click to edit" : void 0,
683
+ tabIndex: onLabelChange ? 0 : -1,
684
+ children: /* @__PURE__ */ jsx("span", { children: label })
685
+ }
686
+ )),
687
+ hasDelete && /* @__PURE__ */ jsx(
688
+ "button",
689
+ {
690
+ type: "button",
691
+ className: "ods-flow-edge-v2__delete-btn",
692
+ onClick: (e) => {
693
+ e.stopPropagation();
694
+ onDelete?.(edge.id);
695
+ },
696
+ "aria-label": "Delete edge",
697
+ children: /* @__PURE__ */ jsx("svg", { width: "10", height: "10", viewBox: "0 0 10 10", "aria-hidden": "true", children: /* @__PURE__ */ jsx(
698
+ "path",
699
+ {
700
+ d: "M2 2l6 6M8 2l-6 6",
701
+ stroke: "currentColor",
702
+ strokeWidth: 1.5,
703
+ strokeLinecap: "round"
704
+ }
705
+ ) })
706
+ }
707
+ )
708
+ ] })
709
+ }
710
+ )
711
+ ]
712
+ }
713
+ );
714
+ }
715
+ function offsetAlongSide2(p, side, gap) {
716
+ switch (side) {
717
+ case "top":
718
+ return { x: p.x, y: p.y - gap };
719
+ case "bottom":
720
+ return { x: p.x, y: p.y + gap };
721
+ case "left":
722
+ return { x: p.x - gap, y: p.y };
723
+ case "right":
724
+ return { x: p.x + gap, y: p.y };
725
+ }
726
+ }
727
+ var FlowEdge = memo(FlowEdgeImpl, (prev, next) => {
728
+ if (prev.edge !== next.edge) return false;
729
+ if (prev.onSelect !== next.onSelect || prev.onDelete !== next.onDelete) return false;
730
+ if (prev.onLabelChange !== next.onLabelChange) return false;
731
+ if (prev.showDelete !== next.showDelete) return false;
732
+ if (prev.curvature !== next.curvature || prev.borderRadius !== next.borderRadius) return false;
733
+ if (prev.handleVersion !== next.handleVersion) return false;
734
+ const ps = prev.nodes.find((n) => n.id === prev.edge.source);
735
+ const pt = prev.nodes.find((n) => n.id === prev.edge.target);
736
+ const ns = next.nodes.find((n) => n.id === next.edge.source);
737
+ const nt = next.nodes.find((n) => n.id === next.edge.target);
738
+ if (ps !== ns || pt !== nt) return false;
739
+ return true;
740
+ });
741
+
742
+ // src/workflow/components/FlowNode/FlowNodeContext.tsx
743
+ import { createContext as createContext3, useContext as useContext3 } from "react";
744
+ var FlowNodeContext = createContext3(null);
745
+ function useFlowNodeContext() {
746
+ const v = useContext3(FlowNodeContext);
747
+ if (!v) {
748
+ throw new Error(
749
+ "[@octaviaflow/core/workflow] Handle / NodeToolbar must be inside a node renderer."
750
+ );
751
+ }
752
+ return v;
753
+ }
754
+
755
+ // src/workflow/components/FlowNode/FlowNode.tsx
756
+ import { useEffect as useEffect2, useMemo, useRef as useRef2 } from "react";
757
+
758
+ // src/workflow/components/FlowCanvas/FlowCanvasContext.tsx
759
+ import { createContext as createContext4, useContext as useContext4 } from "react";
760
+ var FlowDispatchContext = createContext4(null);
761
+ function useFlowDispatch() {
762
+ const dispatch = useContext4(FlowDispatchContext);
763
+ if (!dispatch) {
764
+ throw new Error(
765
+ "[@octaviaflow/core/workflow] useFlowDispatch must be called inside <FlowCanvas>."
766
+ );
767
+ }
768
+ return dispatch;
769
+ }
770
+ var FlowNodeBridgeContext = createContext4(null);
771
+ function useFlowNodeBridge() {
772
+ const b = useContext4(FlowNodeBridgeContext);
773
+ if (!b) {
774
+ throw new Error("[@octaviaflow/core/workflow] FlowNode must be a child of <FlowCanvas>.");
775
+ }
776
+ return b;
777
+ }
778
+
779
+ // src/workflow/components/FlowNode/FlowNode.tsx
780
+ import { jsx as jsx2 } from "react/jsx-runtime";
781
+ function FlowNode({
782
+ node,
783
+ selected,
784
+ dragging,
785
+ isConnecting,
786
+ Kind,
787
+ // Match the BaseNode body's fixed 368 px width so the wrapper bbox and
788
+ // the rendered card line up on the first paint — before the
789
+ // ResizeObserver has had a chance to write back the measured size.
790
+ // Container kinds (group / forEach) opt out by setting `node.width`.
791
+ defaultWidth = 368
792
+ }) {
793
+ const bridge = useFlowNodeBridge();
794
+ const wrapperRef = useRef2(null);
795
+ useEffect2(() => {
796
+ const el = wrapperRef.current;
797
+ if (!el || typeof ResizeObserver === "undefined") return;
798
+ if (node.type === "group" || node.type === "forEach") return;
799
+ const ro = new ResizeObserver(() => {
800
+ bridge.reportDimensions(node.id, el.offsetWidth, el.offsetHeight);
801
+ });
802
+ ro.observe(el);
803
+ return () => ro.disconnect();
804
+ }, [bridge, node.id, node.type]);
805
+ const ctx = useMemo(
806
+ () => ({ id: node.id, node, selected }),
807
+ [node, selected]
808
+ );
809
+ const downPosRef = useRef2(null);
810
+ const draggedRef = useRef2(false);
811
+ const CLICK_VS_DRAG_PX = 5;
812
+ const handlePointerDown = (e) => {
813
+ if (e.target.closest("[data-handle-id]")) return;
814
+ if (e.target.closest("[data-flow-no-drag='true']")) return;
815
+ e.stopPropagation();
816
+ downPosRef.current = { x: e.clientX, y: e.clientY };
817
+ draggedRef.current = false;
818
+ bridge.beginNodeDrag(node.id, e.pointerId, e.clientX, e.clientY, e.altKey);
819
+ };
820
+ const handlePointerMove = (e) => {
821
+ const start = downPosRef.current;
822
+ if (!start || draggedRef.current) return;
823
+ if (Math.abs(e.clientX - start.x) > CLICK_VS_DRAG_PX || Math.abs(e.clientY - start.y) > CLICK_VS_DRAG_PX) {
824
+ draggedRef.current = true;
825
+ }
826
+ };
827
+ const handleClick = (e) => {
828
+ if (e.target.closest("[data-handle-id]")) return;
829
+ e.stopPropagation();
830
+ if (draggedRef.current) {
831
+ draggedRef.current = false;
832
+ downPosRef.current = null;
833
+ return;
834
+ }
835
+ downPosRef.current = null;
836
+ bridge.selectNode(node.id, e.metaKey || e.ctrlKey || e.shiftKey);
837
+ bridge.notifyNodeClick(node.id);
838
+ };
839
+ return /* @__PURE__ */ jsx2(
840
+ "div",
841
+ {
842
+ ref: wrapperRef,
843
+ "data-node-id": node.id,
844
+ "data-node-type": node.type,
845
+ "data-node-selected": selected ? "true" : "false",
846
+ className: cn(
847
+ "ods-flow-node-v2",
848
+ `ods-flow-node-v2--kind-${node.type}`,
849
+ selected && "ods-flow-node-v2--selected",
850
+ dragging && "ods-flow-node-v2--dragging",
851
+ isConnecting && "ods-flow-node-v2--connecting",
852
+ node.className
853
+ ),
854
+ style: {
855
+ position: "absolute",
856
+ left: node.position.x,
857
+ top: node.position.y,
858
+ width: node.width ?? defaultWidth,
859
+ // Z-stack (per architecture doc): groups (20) sit below normal
860
+ // nodes (30) so children render visually on top of their parent
861
+ // frame. Selection raises by 10. Consumer override wins.
862
+ zIndex: node.zIndex ?? (selected ? node.type === "group" ? 35 : 40 : node.type === "group" ? 20 : 30),
863
+ ...node.style
864
+ },
865
+ onPointerDown: handlePointerDown,
866
+ onPointerMove: handlePointerMove,
867
+ onClick: handleClick,
868
+ children: /* @__PURE__ */ jsx2(FlowNodeContext.Provider, { value: ctx, children: /* @__PURE__ */ jsx2(Kind, { node, selected, dragging, isConnecting }) })
869
+ }
870
+ );
871
+ }
872
+
873
+ // src/workflow/components/FlowNode/nodeKinds.ts
874
+ function buildNodeKindRegistry(defaults, overrides) {
875
+ return Object.freeze({ ...defaults, ...overrides ?? {} });
876
+ }
877
+
878
+ // src/workflow/components/Handle/Handle.tsx
879
+ import { useEffect as useEffect3, useRef as useRef3 } from "react";
880
+ import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
881
+ var DEFAULT_HANDLE_ID = "default";
882
+ function Handle({
883
+ type,
884
+ position,
885
+ id = DEFAULT_HANDLE_ID,
886
+ isConnectable = true,
887
+ isConnectableStart,
888
+ isConnectableEnd,
889
+ index = 0,
890
+ total = 1,
891
+ label,
892
+ className,
893
+ style
894
+ }) {
895
+ const registry = useHandleRegistry();
896
+ const node = useFlowNodeContext();
897
+ const dispatch = useFlowDispatch();
898
+ const ref = useRef3(null);
899
+ const canStart = isConnectableStart ?? isConnectable;
900
+ const canEnd = isConnectableEnd ?? isConnectable;
901
+ useEffect3(() => {
902
+ const dispose = registry.register({
903
+ nodeId: node.id,
904
+ handleId: id,
905
+ type,
906
+ side: position,
907
+ index,
908
+ total
909
+ });
910
+ return dispose;
911
+ }, [registry, node.id, id, type, position, index, total]);
912
+ const handlePointerDown = (e) => {
913
+ if (!canStart) return;
914
+ e.stopPropagation();
915
+ e.preventDefault();
916
+ dispatch({
917
+ type: "connection/start",
918
+ nodeId: node.id,
919
+ handleId: id,
920
+ handleType: type,
921
+ pointerId: e.pointerId,
922
+ clientX: e.clientX,
923
+ clientY: e.clientY
924
+ });
925
+ };
926
+ return /* @__PURE__ */ jsxs2(
927
+ "div",
928
+ {
929
+ ref,
930
+ "data-handle-id": id,
931
+ "data-handle-node-id": node.id,
932
+ "data-handle-type": type,
933
+ "data-handle-side": position,
934
+ "data-handle-connectable-end": canEnd ? "true" : "false",
935
+ className: cn(
936
+ "ods-flow-handle",
937
+ `ods-flow-handle--${type}`,
938
+ `ods-flow-handle--side-${position}`,
939
+ !isConnectable && "ods-flow-handle--disabled",
940
+ className
941
+ ),
942
+ style: {
943
+ ...handleSideStyle(position, index, total),
944
+ ...style
945
+ },
946
+ onPointerDown: handlePointerDown,
947
+ children: [
948
+ /* @__PURE__ */ jsx3("div", { className: "ods-flow-handle__dot" }),
949
+ label && /* @__PURE__ */ jsx3("span", { className: "ods-flow-handle__label", children: label })
950
+ ]
951
+ }
952
+ );
953
+ }
954
+ function handleSideStyle(side, index, total) {
955
+ const ratio = (index + 1) / (total + 1) * 100;
956
+ switch (side) {
957
+ case "top":
958
+ return { position: "absolute", top: -6, left: `${ratio}%`, transform: "translateX(-50%)" };
959
+ case "bottom":
960
+ return { position: "absolute", bottom: -6, left: `${ratio}%`, transform: "translateX(-50%)" };
961
+ case "left":
962
+ return { position: "absolute", left: -6, top: `${ratio}%`, transform: "translateY(-50%)" };
963
+ case "right":
964
+ return { position: "absolute", right: -6, top: `${ratio}%`, transform: "translateY(-50%)" };
965
+ }
966
+ }
967
+
968
+ // src/workflow/components/kinds/BaseNode.tsx
969
+ import { TrashCanIcon } from "@octaviaflow/icons";
970
+ import { useContext as useContext5 } from "react";
971
+ import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
972
+ function BaseNode({
973
+ kind,
974
+ kindIcon,
975
+ icon,
976
+ title,
977
+ chip,
978
+ description,
979
+ valueChip,
980
+ accent = "green",
981
+ status,
982
+ onDelete,
983
+ footer,
984
+ className,
985
+ children
986
+ }) {
987
+ const ctx = useContext5(FlowNodeContext);
988
+ const bridge = useContext5(FlowNodeBridgeContext);
989
+ const deleteHandler = onDelete === false ? void 0 : onDelete ?? (ctx && bridge ? () => bridge.deleteNode(ctx.id) : void 0);
990
+ return /* @__PURE__ */ jsxs3(
991
+ "div",
992
+ {
993
+ className: cn(
994
+ "ods-flow-base-node",
995
+ `ods-flow-base-node--accent-${accent}`,
996
+ status && `ods-flow-base-node--status-${status}`,
997
+ className
998
+ ),
999
+ children: [
1000
+ /* @__PURE__ */ jsxs3("div", { className: "ods-flow-base-node__pill", children: [
1001
+ kindIcon && /* @__PURE__ */ jsx4("span", { className: "ods-flow-base-node__pill-icon", "aria-hidden": "true", children: kindIcon }),
1002
+ /* @__PURE__ */ jsx4("span", { className: "ods-flow-base-node__pill-label", children: kind })
1003
+ ] }),
1004
+ status && status !== "idle" && /* @__PURE__ */ jsx4(
1005
+ "span",
1006
+ {
1007
+ className: cn("ods-flow-base-node__status", `ods-flow-base-node__status--${status}`),
1008
+ "aria-hidden": "true"
1009
+ }
1010
+ ),
1011
+ /* @__PURE__ */ jsxs3("div", { className: "ods-flow-base-node__body", children: [
1012
+ /* @__PURE__ */ jsxs3("div", { className: "ods-flow-base-node__content", children: [
1013
+ /* @__PURE__ */ jsx4("div", { className: "ods-flow-base-node__bubble", "aria-hidden": "true", children: icon }),
1014
+ /* @__PURE__ */ jsxs3("div", { className: "ods-flow-base-node__content-text", children: [
1015
+ /* @__PURE__ */ jsx4("div", { className: "ods-flow-base-node__content-title", children: title }),
1016
+ (chip !== void 0 || description !== void 0 || valueChip !== void 0) && /* @__PURE__ */ jsxs3("div", { className: "ods-flow-base-node__content-info", children: [
1017
+ chip !== void 0 && /* @__PURE__ */ jsx4("span", { className: "ods-flow-base-node__chip", children: chip }),
1018
+ description !== void 0 && /* @__PURE__ */ jsx4("span", { className: "ods-flow-base-node__description", children: description }),
1019
+ valueChip !== void 0 && /* @__PURE__ */ jsx4("span", { className: "ods-flow-base-node__value-chip", children: valueChip })
1020
+ ] })
1021
+ ] })
1022
+ ] }),
1023
+ footer && /* @__PURE__ */ jsx4("div", { className: "ods-flow-base-node__footer", children: footer }),
1024
+ deleteHandler && /* @__PURE__ */ jsx4(
1025
+ "button",
1026
+ {
1027
+ type: "button",
1028
+ className: "ods-flow-base-node__delete",
1029
+ onClick: (e) => {
1030
+ e.stopPropagation();
1031
+ deleteHandler();
1032
+ },
1033
+ "aria-label": "Delete node",
1034
+ "data-flow-no-drag": "true",
1035
+ title: "Delete node",
1036
+ children: /* @__PURE__ */ jsx4(TrashCanIcon, { size: 16, "aria-hidden": true })
1037
+ }
1038
+ )
1039
+ ] }),
1040
+ children
1041
+ ]
1042
+ }
1043
+ );
1044
+ }
1045
+
1046
+ // src/workflow/components/kinds/index.tsx
1047
+ import { Fragment, jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
1048
+ var ActionNode = ({
1049
+ node
1050
+ }) => {
1051
+ const d = node.data ?? {};
1052
+ return /* @__PURE__ */ jsxs4(
1053
+ BaseNode,
1054
+ {
1055
+ kind: d.kind ?? "ACTION",
1056
+ icon: d.icon,
1057
+ title: d.title ?? "Action",
1058
+ chip: d.chip ?? d.badge,
1059
+ description: d.description ?? d.subtitle,
1060
+ valueChip: d.valueChip,
1061
+ status: d.status,
1062
+ accent: "green",
1063
+ children: [
1064
+ /* @__PURE__ */ jsx5(Handle, { type: "target", position: "top" }),
1065
+ /* @__PURE__ */ jsx5(Handle, { type: "source", position: "bottom" })
1066
+ ]
1067
+ }
1068
+ );
1069
+ };
1070
+ var TriggerNode = ({
1071
+ node
1072
+ }) => {
1073
+ const d = node.data ?? {};
1074
+ return /* @__PURE__ */ jsx5(
1075
+ BaseNode,
1076
+ {
1077
+ kind: d.kind ?? "TRIGGER",
1078
+ icon: d.icon,
1079
+ title: d.title ?? "Trigger",
1080
+ chip: d.chip,
1081
+ description: d.description ?? "Manually triggered",
1082
+ valueChip: d.valueChip,
1083
+ status: d.status,
1084
+ accent: "green",
1085
+ children: /* @__PURE__ */ jsx5(Handle, { type: "source", position: "bottom" })
1086
+ }
1087
+ );
1088
+ };
1089
+ var ConditionNode = ({
1090
+ node
1091
+ }) => {
1092
+ const d = node.data ?? {};
1093
+ const branches = d.branches ?? [
1094
+ { id: "true", label: "true" },
1095
+ { id: "false", label: "false" }
1096
+ ];
1097
+ return /* @__PURE__ */ jsxs4(
1098
+ BaseNode,
1099
+ {
1100
+ kind: d.kind ?? "CONDITION",
1101
+ icon: d.icon,
1102
+ title: d.title ?? "Condition",
1103
+ chip: d.chip ?? d.badge,
1104
+ description: d.description ?? d.subtitle,
1105
+ valueChip: d.valueChip,
1106
+ status: d.status,
1107
+ accent: "amber",
1108
+ children: [
1109
+ /* @__PURE__ */ jsx5(Handle, { type: "target", position: "top" }),
1110
+ branches.map((b, i) => /* @__PURE__ */ jsx5(
1111
+ Handle,
1112
+ {
1113
+ type: "source",
1114
+ position: "bottom",
1115
+ id: b.id,
1116
+ index: i,
1117
+ total: branches.length,
1118
+ label: b.label
1119
+ },
1120
+ b.id
1121
+ ))
1122
+ ]
1123
+ }
1124
+ );
1125
+ };
1126
+ var GroupNode = ({
1127
+ node
1128
+ }) => {
1129
+ const d = node.data ?? {};
1130
+ const collapsed = !!d.collapsed;
1131
+ const hiddenCount = d.hiddenCount;
1132
+ const bridge = useFlowNodeBridge();
1133
+ const onChevronClick = (e) => {
1134
+ e.stopPropagation();
1135
+ bridge.toggleNodeCollapse(node.id);
1136
+ };
1137
+ return /* @__PURE__ */ jsxs4(
1138
+ "div",
1139
+ {
1140
+ className: "ods-flow-group",
1141
+ "data-collapsed": collapsed ? "true" : "false",
1142
+ style: {
1143
+ width: node.width ?? 360,
1144
+ height: collapsed ? 36 : node.height ?? 200
1145
+ },
1146
+ children: [
1147
+ /* @__PURE__ */ jsxs4("div", { className: "ods-flow-group__header", "data-flow-no-drag": "false", children: [
1148
+ /* @__PURE__ */ jsx5(
1149
+ "button",
1150
+ {
1151
+ type: "button",
1152
+ className: "ods-flow-group__chevron",
1153
+ "data-flow-no-drag": "true",
1154
+ "aria-label": collapsed ? "Expand group" : "Collapse group",
1155
+ "aria-expanded": !collapsed,
1156
+ onClick: onChevronClick,
1157
+ onPointerDown: (e) => e.stopPropagation(),
1158
+ children: collapsed ? "\u25B8" : "\u25BE"
1159
+ }
1160
+ ),
1161
+ /* @__PURE__ */ jsx5("span", { className: "ods-flow-group__title", children: d.title ?? "Group" }),
1162
+ d.subtitle && /* @__PURE__ */ jsx5("span", { className: "ods-flow-group__subtitle", children: d.subtitle }),
1163
+ collapsed && hiddenCount !== void 0 && hiddenCount > 0 && /* @__PURE__ */ jsxs4("span", { className: "ods-flow-group__count", "aria-label": `${hiddenCount} hidden steps`, children: [
1164
+ hiddenCount,
1165
+ " steps"
1166
+ ] })
1167
+ ] }),
1168
+ /* @__PURE__ */ jsx5(Handle, { type: "target", position: "top", id: "__group_in" }),
1169
+ /* @__PURE__ */ jsx5(Handle, { type: "source", position: "bottom", id: "__group_out" })
1170
+ ]
1171
+ }
1172
+ );
1173
+ };
1174
+ var ForEachNode = ({
1175
+ node
1176
+ }) => {
1177
+ const d = node.data ?? {};
1178
+ const iteratorExpr = d.iterator ?? d.description ?? "items[]";
1179
+ const collapsed = !!d.collapsed;
1180
+ const hiddenCount = d.hiddenCount;
1181
+ const bridge = useFlowNodeBridge();
1182
+ const onChevronClick = (e) => {
1183
+ e.stopPropagation();
1184
+ bridge.toggleNodeCollapse(node.id);
1185
+ };
1186
+ return /* @__PURE__ */ jsxs4(
1187
+ "div",
1188
+ {
1189
+ className: "ods-flow-foreach",
1190
+ "data-collapsed": collapsed ? "true" : "false",
1191
+ style: {
1192
+ width: node.width ?? 420,
1193
+ height: collapsed ? 40 : node.height ?? 260
1194
+ },
1195
+ children: [
1196
+ /* @__PURE__ */ jsxs4("div", { className: "ods-flow-foreach__header", children: [
1197
+ /* @__PURE__ */ jsx5(
1198
+ "button",
1199
+ {
1200
+ type: "button",
1201
+ className: "ods-flow-foreach__chevron",
1202
+ "data-flow-no-drag": "true",
1203
+ "aria-label": collapsed ? "Expand iterator" : "Collapse iterator",
1204
+ "aria-expanded": !collapsed,
1205
+ onClick: onChevronClick,
1206
+ onPointerDown: (e) => e.stopPropagation(),
1207
+ children: collapsed ? "\u25B8" : "\u25BE"
1208
+ }
1209
+ ),
1210
+ /* @__PURE__ */ jsx5("span", { className: "ods-flow-foreach__icon", "aria-hidden": "true", children: "\u21BB" }),
1211
+ /* @__PURE__ */ jsx5("span", { className: "ods-flow-foreach__title", children: d.title ?? "For each" }),
1212
+ /* @__PURE__ */ jsx5("code", { className: "ods-flow-foreach__iterator", children: iteratorExpr }),
1213
+ collapsed && hiddenCount !== void 0 && hiddenCount > 0 && /* @__PURE__ */ jsxs4("span", { className: "ods-flow-foreach__count", "aria-label": `${hiddenCount} hidden steps`, children: [
1214
+ hiddenCount,
1215
+ " steps"
1216
+ ] })
1217
+ ] }),
1218
+ /* @__PURE__ */ jsx5(Handle, { type: "target", position: "top", id: "__group_in" }),
1219
+ /* @__PURE__ */ jsx5(Handle, { type: "source", position: "bottom", id: "__group_out" }),
1220
+ !collapsed && // Expanded mode — full 3-handle iterator surface (in / item / done).
1221
+ // `in` shares the top edge with `__group_in`; consumers wiring an
1222
+ // explicit `targetHandle: "in"` get the labelled, visible variant.
1223
+ /* @__PURE__ */ jsxs4(Fragment, { children: [
1224
+ /* @__PURE__ */ jsx5(Handle, { type: "target", position: "top", id: "in", label: "in" }),
1225
+ /* @__PURE__ */ jsx5(Handle, { type: "source", position: "right", id: "item", label: "item" }),
1226
+ /* @__PURE__ */ jsx5(Handle, { type: "source", position: "bottom", id: "done", label: "done" })
1227
+ ] })
1228
+ ]
1229
+ }
1230
+ );
1231
+ };
1232
+ var OutputNode = ({
1233
+ node
1234
+ }) => {
1235
+ const d = node.data ?? {};
1236
+ return /* @__PURE__ */ jsx5(
1237
+ BaseNode,
1238
+ {
1239
+ kind: d.kind ?? "OUTPUT",
1240
+ icon: d.icon,
1241
+ title: d.title ?? "Output",
1242
+ chip: d.chip ?? d.badge,
1243
+ description: d.description ?? d.subtitle,
1244
+ status: d.status,
1245
+ accent: "green",
1246
+ children: /* @__PURE__ */ jsx5(Handle, { type: "target", position: "top" })
1247
+ }
1248
+ );
1249
+ };
1250
+ var ErrorNode = ({
1251
+ node
1252
+ }) => {
1253
+ const d = node.data ?? {};
1254
+ return /* @__PURE__ */ jsxs4(
1255
+ BaseNode,
1256
+ {
1257
+ kind: d.kind ?? "ERROR",
1258
+ icon: d.icon,
1259
+ title: d.title ?? "On error",
1260
+ chip: d.chip ?? d.badge,
1261
+ description: d.description ?? d.subtitle,
1262
+ status: d.status ?? "error",
1263
+ accent: "red",
1264
+ children: [
1265
+ /* @__PURE__ */ jsx5(Handle, { type: "target", position: "top" }),
1266
+ /* @__PURE__ */ jsx5(Handle, { type: "source", position: "bottom" })
1267
+ ]
1268
+ }
1269
+ );
1270
+ };
1271
+ var WaitNode = ({
1272
+ node
1273
+ }) => {
1274
+ const d = node.data ?? {};
1275
+ const waitMs = d.waitMs;
1276
+ const durationChip = waitMs ? `${Math.round(waitMs / 100) / 10}s` : void 0;
1277
+ return /* @__PURE__ */ jsxs4(
1278
+ BaseNode,
1279
+ {
1280
+ kind: d.kind ?? "WAIT",
1281
+ icon: d.icon,
1282
+ title: d.title ?? "Wait",
1283
+ chip: d.chip ?? durationChip,
1284
+ description: d.description ?? (durationChip ? "Pause execution" : void 0),
1285
+ status: d.status,
1286
+ accent: "violet",
1287
+ children: [
1288
+ /* @__PURE__ */ jsx5(Handle, { type: "target", position: "top" }),
1289
+ /* @__PURE__ */ jsx5(Handle, { type: "source", position: "bottom" })
1290
+ ]
1291
+ }
1292
+ );
1293
+ };
1294
+ var ParallelNode = ({
1295
+ node
1296
+ }) => {
1297
+ const d = node.data ?? {};
1298
+ const branches = d.branches ?? [
1299
+ { id: "a", label: "a" },
1300
+ { id: "b", label: "b" }
1301
+ ];
1302
+ return /* @__PURE__ */ jsxs4(
1303
+ BaseNode,
1304
+ {
1305
+ kind: d.kind ?? "PARALLEL",
1306
+ icon: d.icon,
1307
+ title: d.title ?? "Parallel",
1308
+ chip: d.chip ?? `${branches.length}\xD7`,
1309
+ description: d.description ?? "Fan-out branches",
1310
+ status: d.status,
1311
+ accent: "blue",
1312
+ children: [
1313
+ /* @__PURE__ */ jsx5(Handle, { type: "target", position: "top" }),
1314
+ branches.map((b, i) => /* @__PURE__ */ jsx5(
1315
+ Handle,
1316
+ {
1317
+ type: "source",
1318
+ position: "bottom",
1319
+ id: b.id,
1320
+ index: i,
1321
+ total: branches.length,
1322
+ label: b.label
1323
+ },
1324
+ b.id
1325
+ ))
1326
+ ]
1327
+ }
1328
+ );
1329
+ };
1330
+ var StickyNode = ({
1331
+ node
1332
+ }) => {
1333
+ const d = node.data ?? {};
1334
+ return /* @__PURE__ */ jsxs4(
1335
+ "div",
1336
+ {
1337
+ className: "ods-flow-sticky",
1338
+ style: {
1339
+ width: node.width ?? 240,
1340
+ minHeight: node.height ?? 120
1341
+ },
1342
+ children: [
1343
+ d.title && /* @__PURE__ */ jsx5("div", { className: "ods-flow-sticky__title", children: d.title }),
1344
+ d.description && /* @__PURE__ */ jsx5("div", { className: "ods-flow-sticky__body", children: d.description })
1345
+ ]
1346
+ }
1347
+ );
1348
+ };
1349
+ var WebhookNode = ({
1350
+ node
1351
+ }) => {
1352
+ const d = node.data ?? {};
1353
+ return /* @__PURE__ */ jsx5(
1354
+ BaseNode,
1355
+ {
1356
+ kind: d.kind ?? "WEBHOOK",
1357
+ icon: d.icon,
1358
+ title: d.title ?? "Webhook",
1359
+ chip: d.chip ?? d.method ?? "POST",
1360
+ description: d.description ?? d.path ?? "/hooks/incoming",
1361
+ valueChip: d.valueChip,
1362
+ status: d.status,
1363
+ accent: "blue",
1364
+ children: /* @__PURE__ */ jsx5(Handle, { type: "source", position: "bottom" })
1365
+ }
1366
+ );
1367
+ };
1368
+ var HttpRequestNode = ({
1369
+ node
1370
+ }) => {
1371
+ const d = node.data ?? {};
1372
+ return /* @__PURE__ */ jsxs4(
1373
+ BaseNode,
1374
+ {
1375
+ kind: d.kind ?? "HTTP",
1376
+ icon: d.icon,
1377
+ title: d.title ?? "HTTP Request",
1378
+ chip: d.chip ?? d.method ?? "GET",
1379
+ description: d.description ?? d.url ?? "Call an API",
1380
+ valueChip: d.valueChip,
1381
+ status: d.status,
1382
+ accent: "blue",
1383
+ children: [
1384
+ /* @__PURE__ */ jsx5(Handle, { type: "target", position: "top" }),
1385
+ /* @__PURE__ */ jsx5(Handle, { type: "source", position: "bottom" })
1386
+ ]
1387
+ }
1388
+ );
1389
+ };
1390
+ var DEFAULT_NODE_KINDS = {
1391
+ action: ActionNode,
1392
+ trigger: TriggerNode,
1393
+ condition: ConditionNode,
1394
+ group: GroupNode,
1395
+ forEach: ForEachNode,
1396
+ output: OutputNode,
1397
+ error: ErrorNode,
1398
+ wait: WaitNode,
1399
+ parallel: ParallelNode,
1400
+ sticky: StickyNode,
1401
+ webhook: WebhookNode,
1402
+ httpRequest: HttpRequestNode
1403
+ };
1404
+
1405
+ // src/workflow/components/FlowCanvas/FlowCanvas.tsx
1406
+ import {
1407
+ memo as memo2,
1408
+ useCallback,
1409
+ useEffect as useEffect4,
1410
+ useMemo as useMemo2,
1411
+ useRef as useRef4,
1412
+ useState as useState2
1413
+ } from "react";
1414
+
1415
+ // src/workflow/store/context.ts
1416
+ import { createContext as createContext5, useContext as useContext6 } from "react";
1417
+ var FlowStoreContext = createContext5(null);
1418
+ function useFlowStore() {
1419
+ const store = useContext6(FlowStoreContext);
1420
+ if (!store) {
1421
+ throw new Error(
1422
+ "[@octaviaflow/core/workflow] useFlowStore must be called inside a <FlowCanvas>."
1423
+ );
1424
+ }
1425
+ return store;
1426
+ }
1427
+
1428
+ // src/workflow/store/createFlowStore.ts
1429
+ var DEFAULT_VIEWPORT = { x: 0, y: 0, zoom: 1 };
1430
+ function createFlowStore({
1431
+ initialNodes = [],
1432
+ initialEdges = [],
1433
+ initialViewport = DEFAULT_VIEWPORT
1434
+ } = {}) {
1435
+ let snapshot = {
1436
+ nodes: initialNodes,
1437
+ edges: initialEdges,
1438
+ viewport: initialViewport,
1439
+ selectedNodeIds: EMPTY_SET,
1440
+ selectedEdgeIds: EMPTY_SET,
1441
+ connection: null
1442
+ };
1443
+ const listeners = /* @__PURE__ */ new Set();
1444
+ const emit = () => {
1445
+ for (const l of listeners) l();
1446
+ };
1447
+ const subscribe = (listener) => {
1448
+ listeners.add(listener);
1449
+ return () => {
1450
+ listeners.delete(listener);
1451
+ };
1452
+ };
1453
+ const replace = (patch) => {
1454
+ snapshot = { ...snapshot, ...patch };
1455
+ emit();
1456
+ };
1457
+ return {
1458
+ subscribe,
1459
+ getSnapshot: () => snapshot,
1460
+ setNodes(nodes) {
1461
+ if (nodes === snapshot.nodes) return;
1462
+ replace({ nodes });
1463
+ },
1464
+ setEdges(edges) {
1465
+ if (edges === snapshot.edges) return;
1466
+ replace({ edges });
1467
+ },
1468
+ setViewport(viewport) {
1469
+ if (viewport.x === snapshot.viewport.x && viewport.y === snapshot.viewport.y && viewport.zoom === snapshot.viewport.zoom) {
1470
+ return;
1471
+ }
1472
+ replace({ viewport });
1473
+ },
1474
+ setSelection(selectedNodeIds, selectedEdgeIds) {
1475
+ replace({ selectedNodeIds, selectedEdgeIds });
1476
+ },
1477
+ setConnection(connection) {
1478
+ if (connection === snapshot.connection) return;
1479
+ replace({ connection });
1480
+ }
1481
+ };
1482
+ }
1483
+ var EMPTY_SET = /* @__PURE__ */ new Set();
1484
+
1485
+ // src/workflow/utils/collision.ts
1486
+ function resolveNodeCollisions(node, proposed, others, opts) {
1487
+ const { gap, maxIterations = 8, exclude, scopeToSiblings = true } = opts;
1488
+ if (gap < 0 || others.length === 0) return proposed;
1489
+ const w = node.width ?? DEFAULT_NODE_WIDTH;
1490
+ const h = effectiveHeight(node);
1491
+ const parentId = node.parentId;
1492
+ const candidates = others.filter((o) => {
1493
+ if (o.id === node.id) return false;
1494
+ if (o.hidden) return false;
1495
+ if (exclude?.has(o.id)) return false;
1496
+ if (scopeToSiblings && (o.parentId ?? void 0) !== (parentId ?? void 0)) {
1497
+ return false;
1498
+ }
1499
+ return true;
1500
+ });
1501
+ if (candidates.length === 0) return proposed;
1502
+ let cur = proposed;
1503
+ for (let iter = 0; iter < maxIterations; iter++) {
1504
+ let bestOverlap = Number.POSITIVE_INFINITY;
1505
+ let bestPushX = 0;
1506
+ let bestPushY = 0;
1507
+ let hit = false;
1508
+ const aLeft = cur.x - gap;
1509
+ const aRight = cur.x + w + gap;
1510
+ const aTop = cur.y - gap;
1511
+ const aBottom = cur.y + h + gap;
1512
+ for (const o of candidates) {
1513
+ const ow = o.width ?? DEFAULT_NODE_WIDTH;
1514
+ const oh = effectiveHeight(o);
1515
+ const bLeft = o.position.x;
1516
+ const bRight = o.position.x + ow;
1517
+ const bTop = o.position.y;
1518
+ const bBottom = o.position.y + oh;
1519
+ const overlapX = Math.min(aRight, bRight) - Math.max(aLeft, bLeft);
1520
+ const overlapY = Math.min(aBottom, bBottom) - Math.max(aTop, bTop);
1521
+ if (overlapX <= 0 || overlapY <= 0) continue;
1522
+ let pushX = 0;
1523
+ let pushY = 0;
1524
+ let overlap;
1525
+ if (overlapX < overlapY) {
1526
+ const aCx = cur.x + w / 2;
1527
+ const bCx = o.position.x + ow / 2;
1528
+ pushX = aCx < bCx ? -overlapX : overlapX;
1529
+ overlap = overlapX;
1530
+ } else {
1531
+ const aCy = cur.y + h / 2;
1532
+ const bCy = o.position.y + oh / 2;
1533
+ pushY = aCy < bCy ? -overlapY : overlapY;
1534
+ overlap = overlapY;
1535
+ }
1536
+ if (overlap < bestOverlap) {
1537
+ bestOverlap = overlap;
1538
+ bestPushX = pushX;
1539
+ bestPushY = pushY;
1540
+ hit = true;
1541
+ }
1542
+ }
1543
+ if (!hit) break;
1544
+ cur = { x: cur.x + bestPushX, y: cur.y + bestPushY };
1545
+ }
1546
+ return cur;
1547
+ }
1548
+
1549
+ // src/workflow/components/FlowCanvas/FlowCanvas.tsx
1550
+ import { jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
1551
+ var DEFAULT_VIEWPORT2 = { x: 0, y: 0, zoom: 1 };
1552
+ function FlowCanvas({
1553
+ nodes,
1554
+ edges,
1555
+ onNodesChange,
1556
+ onEdgesChange,
1557
+ viewport: controlledViewport,
1558
+ defaultViewport = DEFAULT_VIEWPORT2,
1559
+ onViewportChange,
1560
+ minZoom = 0.25,
1561
+ maxZoom = 2,
1562
+ nodeKinds,
1563
+ onConnect,
1564
+ onConnectStart,
1565
+ onConnectEnd,
1566
+ isValidConnection,
1567
+ onSelectionChange,
1568
+ onPaneClick,
1569
+ onNodeClick,
1570
+ onEdgeClick,
1571
+ onEdgeLabelChange,
1572
+ onInit,
1573
+ onBeforeDelete,
1574
+ onNodeContextMenu,
1575
+ onEdgeContextMenu,
1576
+ onPaneContextMenu,
1577
+ nodesDraggable = true,
1578
+ nodesConnectable = true,
1579
+ panOnDrag: panOnDragProp,
1580
+ zoomOnScroll: zoomOnScrollProp,
1581
+ preset = "mouse",
1582
+ paneClickDistance = 4,
1583
+ paneClickClearsSelection = true,
1584
+ background = "dots",
1585
+ gridSize = 20,
1586
+ snapToGrid = false,
1587
+ nodeCollisionGap = -1,
1588
+ subflowCollisionGap,
1589
+ height = "100%",
1590
+ width = "100%",
1591
+ className,
1592
+ style,
1593
+ children,
1594
+ emptyState
1595
+ }) {
1596
+ const presetDefaults = {
1597
+ mouse: { panOnDrag: true, zoomOnScroll: true },
1598
+ trackpad: { panOnDrag: true, zoomOnScroll: true },
1599
+ touch: { panOnDrag: false, zoomOnScroll: true }
1600
+ };
1601
+ const panOnDrag = panOnDragProp ?? presetDefaults[preset].panOnDrag;
1602
+ const zoomOnScroll = zoomOnScrollProp ?? presetDefaults[preset].zoomOnScroll;
1603
+ const store = useState2(
1604
+ () => createFlowStore({
1605
+ initialNodes: nodes,
1606
+ initialEdges: edges,
1607
+ initialViewport: controlledViewport ?? defaultViewport
1608
+ })
1609
+ )[0];
1610
+ const handleRegistry = useState2(() => createHandleRegistry())[0];
1611
+ const [handleVersion, setHandleVersion] = useState2(0);
1612
+ useEffect4(() => {
1613
+ const unsub = handleRegistry.subscribe(() => {
1614
+ setHandleVersion((v) => v + 1);
1615
+ });
1616
+ return unsub;
1617
+ }, [handleRegistry]);
1618
+ const kinds = useMemo2(() => buildNodeKindRegistry(DEFAULT_NODE_KINDS, nodeKinds), [nodeKinds]);
1619
+ const containerRef = useRef4(null);
1620
+ useEffect4(() => store.setNodes(nodes), [store, nodes]);
1621
+ useEffect4(() => store.setEdges(edges), [store, edges]);
1622
+ const [uncontrolledVp, setUncontrolledVp] = useState2(controlledViewport ?? defaultViewport);
1623
+ const viewport = controlledViewport ?? uncontrolledVp;
1624
+ useEffect4(() => store.setViewport(viewport), [store, viewport]);
1625
+ const setViewport = useCallback(
1626
+ (next) => {
1627
+ if (controlledViewport === void 0) setUncontrolledVp(next);
1628
+ onViewportChange?.(next);
1629
+ },
1630
+ [controlledViewport, onViewportChange]
1631
+ );
1632
+ const selectedNodeIds = useMemo2(() => {
1633
+ const s = /* @__PURE__ */ new Set();
1634
+ for (const n of nodes) if (n.selected) s.add(n.id);
1635
+ return s;
1636
+ }, [nodes]);
1637
+ const selectedEdgeIds = useMemo2(() => {
1638
+ const s = /* @__PURE__ */ new Set();
1639
+ for (const e of edges) if (e.selected) s.add(e.id);
1640
+ return s;
1641
+ }, [edges]);
1642
+ useEffect4(() => {
1643
+ store.setSelection(selectedNodeIds, selectedEdgeIds);
1644
+ if (onSelectionChange) {
1645
+ onSelectionChange({
1646
+ nodes: nodes.filter((n) => selectedNodeIds.has(n.id)),
1647
+ edges: edges.filter((e) => selectedEdgeIds.has(e.id))
1648
+ });
1649
+ }
1650
+ }, [store, selectedNodeIds, selectedEdgeIds, nodes, edges, onSelectionChange]);
1651
+ const selectNode = useCallback(
1652
+ (id, additive) => {
1653
+ const next = [];
1654
+ const nextEdges = [];
1655
+ if (!additive) {
1656
+ for (const n of nodes) {
1657
+ if (n.selected && n.id !== id) next.push(change.node.select(n.id, false));
1658
+ }
1659
+ for (const e of edges) {
1660
+ if (e.selected) nextEdges.push(change.edge.select(e.id, false));
1661
+ }
1662
+ }
1663
+ const isSelected = selectedNodeIds.has(id);
1664
+ if (additive && isSelected) {
1665
+ next.push(change.node.select(id, false));
1666
+ } else if (!isSelected) {
1667
+ next.push(change.node.select(id, true));
1668
+ }
1669
+ if (next.length) onNodesChange?.(next);
1670
+ if (nextEdges.length) onEdgesChange?.(nextEdges);
1671
+ },
1672
+ [nodes, edges, selectedNodeIds, onNodesChange, onEdgesChange]
1673
+ );
1674
+ const notifyNodeClick = useCallback(
1675
+ (id) => {
1676
+ const node = nodes.find((n) => n.id === id);
1677
+ if (node) onNodeClick?.(node);
1678
+ },
1679
+ [nodes, onNodeClick]
1680
+ );
1681
+ const selectEdge = useCallback(
1682
+ (id, additive) => {
1683
+ const next = [];
1684
+ const nextNodes = [];
1685
+ if (!additive) {
1686
+ for (const e of edges) {
1687
+ if (e.selected && e.id !== id) next.push(change.edge.select(e.id, false));
1688
+ }
1689
+ for (const n of nodes) {
1690
+ if (n.selected) nextNodes.push(change.node.select(n.id, false));
1691
+ }
1692
+ }
1693
+ const isSelected = selectedEdgeIds.has(id);
1694
+ if (additive && isSelected) {
1695
+ next.push(change.edge.select(id, false));
1696
+ } else if (!isSelected) {
1697
+ next.push(change.edge.select(id, true));
1698
+ }
1699
+ if (next.length) onEdgesChange?.(next);
1700
+ if (nextNodes.length) onNodesChange?.(nextNodes);
1701
+ const edge = edges.find((e) => e.id === id);
1702
+ if (edge) onEdgeClick?.(edge);
1703
+ },
1704
+ [nodes, edges, selectedEdgeIds, onEdgesChange, onNodesChange, onEdgeClick]
1705
+ );
1706
+ const clearSelection = useCallback(() => {
1707
+ const ns = [];
1708
+ const es = [];
1709
+ for (const n of nodes) if (n.selected) ns.push(change.node.select(n.id, false));
1710
+ for (const e of edges) if (e.selected) es.push(change.edge.select(e.id, false));
1711
+ if (ns.length) onNodesChange?.(ns);
1712
+ if (es.length) onEdgesChange?.(es);
1713
+ }, [nodes, edges, onNodesChange, onEdgesChange]);
1714
+ const dragRef = useRef4(null);
1715
+ const [draggingId, setDraggingId] = useState2(null);
1716
+ const beginNodeDrag = useCallback(
1717
+ (nodeId, pointerId, clientX, clientY, altKey = false) => {
1718
+ if (!nodesDraggable) return;
1719
+ const node = nodes.find((n) => n.id === nodeId);
1720
+ if (!node) return;
1721
+ const kids = descendantsOf(nodeId, nodes).map((d) => ({
1722
+ id: d.id,
1723
+ startPosition: d.position
1724
+ }));
1725
+ dragRef.current = {
1726
+ pointerId,
1727
+ nodeId,
1728
+ startClientX: clientX,
1729
+ startClientY: clientY,
1730
+ startPosition: node.position,
1731
+ descendants: kids,
1732
+ altDetach: altKey && !!node.parentId,
1733
+ rafScheduled: false,
1734
+ nextDelta: null
1735
+ };
1736
+ setDraggingId(nodeId);
1737
+ selectNode(nodeId, false);
1738
+ },
1739
+ [nodes, nodesDraggable, selectNode]
1740
+ );
1741
+ const [conn, setConn] = useState2(null);
1742
+ const connRef = useRef4(null);
1743
+ useEffect4(() => {
1744
+ connRef.current = conn;
1745
+ }, [conn]);
1746
+ const beginConnection = useCallback(
1747
+ (nodeId, handleId, handleType, pointerId, clientX, clientY) => {
1748
+ if (!nodesConnectable) return;
1749
+ const node = nodes.find((n) => n.id === nodeId);
1750
+ if (!node) return;
1751
+ const desc = handleRegistry.resolve(nodeId, handleType, handleId);
1752
+ const side = desc?.side ?? (handleType === "source" ? "bottom" : "top");
1753
+ const index = desc?.index ?? 0;
1754
+ const total = desc?.total ?? 1;
1755
+ const ratio = (index + 1) / (total + 1);
1756
+ const w = node.width ?? 368;
1757
+ const h = effectiveHeight(node);
1758
+ const start = (() => {
1759
+ switch (side) {
1760
+ case "top":
1761
+ return { x: node.position.x + w * ratio, y: node.position.y };
1762
+ case "bottom":
1763
+ return { x: node.position.x + w * ratio, y: node.position.y + h };
1764
+ case "left":
1765
+ return { x: node.position.x, y: node.position.y + h * ratio };
1766
+ case "right":
1767
+ return { x: node.position.x + w, y: node.position.y + h * ratio };
1768
+ }
1769
+ })();
1770
+ const from = { nodeId, handleId, handleType };
1771
+ const rect = containerRef.current?.getBoundingClientRect();
1772
+ const end = rect ? screenToFlow({ x: clientX - rect.left, y: clientY - rect.top }, viewport) : start;
1773
+ setConn({ pointerId, from, start, end });
1774
+ store.setConnection(from);
1775
+ onConnectStart?.({ clientX, clientY, pointerId }, from);
1776
+ },
1777
+ [nodes, nodesConnectable, handleRegistry, viewport, store, onConnectStart]
1778
+ );
1779
+ const viewportRef = useRef4(viewport);
1780
+ const nodesRef = useRef4(nodes);
1781
+ const edgesRef = useRef4(edges);
1782
+ const onNodesChangeRefForInstance = useRef4(onNodesChange);
1783
+ const onEdgesChangeRefForInstance = useRef4(onEdgesChange);
1784
+ const onBeforeDeleteRef = useRef4(onBeforeDelete);
1785
+ const snapToGridRef = useRef4(snapToGrid);
1786
+ const gridSizeRef = useRef4(gridSize);
1787
+ const nodeCollisionGapRef = useRef4(nodeCollisionGap);
1788
+ const subflowCollisionGapRef = useRef4(subflowCollisionGap ?? nodeCollisionGap);
1789
+ useEffect4(() => {
1790
+ edgesRef.current = edges;
1791
+ }, [edges]);
1792
+ useEffect4(() => {
1793
+ onNodesChangeRefForInstance.current = onNodesChange;
1794
+ }, [onNodesChange]);
1795
+ useEffect4(() => {
1796
+ onEdgesChangeRefForInstance.current = onEdgesChange;
1797
+ }, [onEdgesChange]);
1798
+ useEffect4(() => {
1799
+ onBeforeDeleteRef.current = onBeforeDelete;
1800
+ }, [onBeforeDelete]);
1801
+ useEffect4(() => {
1802
+ snapToGridRef.current = snapToGrid;
1803
+ }, [snapToGrid]);
1804
+ useEffect4(() => {
1805
+ gridSizeRef.current = gridSize;
1806
+ }, [gridSize]);
1807
+ useEffect4(() => {
1808
+ nodeCollisionGapRef.current = nodeCollisionGap;
1809
+ }, [nodeCollisionGap]);
1810
+ useEffect4(() => {
1811
+ subflowCollisionGapRef.current = subflowCollisionGap ?? nodeCollisionGap;
1812
+ }, [subflowCollisionGap, nodeCollisionGap]);
1813
+ const onNodesChangeRef = useRef4(onNodesChange);
1814
+ const onConnectRef = useRef4(onConnect);
1815
+ const onConnectEndRef = useRef4(onConnectEnd);
1816
+ const isValidConnectionRef = useRef4(isValidConnection);
1817
+ useEffect4(() => {
1818
+ viewportRef.current = viewport;
1819
+ }, [viewport]);
1820
+ useEffect4(() => {
1821
+ nodesRef.current = nodes;
1822
+ }, [nodes]);
1823
+ useEffect4(() => {
1824
+ onNodesChangeRef.current = onNodesChange;
1825
+ }, [onNodesChange]);
1826
+ useEffect4(() => {
1827
+ onConnectRef.current = onConnect;
1828
+ }, [onConnect]);
1829
+ useEffect4(() => {
1830
+ onConnectEndRef.current = onConnectEnd;
1831
+ }, [onConnectEnd]);
1832
+ useEffect4(() => {
1833
+ isValidConnectionRef.current = isValidConnection;
1834
+ }, [isValidConnection]);
1835
+ useEffect4(() => {
1836
+ const onPointerMove = (e) => {
1837
+ const vp = viewportRef.current;
1838
+ const drag = dragRef.current;
1839
+ if (drag && drag.pointerId === e.pointerId) {
1840
+ const dx = (e.clientX - drag.startClientX) / vp.zoom;
1841
+ const dy = (e.clientY - drag.startClientY) / vp.zoom;
1842
+ drag.nextDelta = { dx, dy };
1843
+ if (!drag.rafScheduled) {
1844
+ drag.rafScheduled = true;
1845
+ requestAnimationFrame(() => {
1846
+ const d = dragRef.current;
1847
+ if (!d) return;
1848
+ d.rafScheduled = false;
1849
+ const delta = d.nextDelta;
1850
+ if (!delta) return;
1851
+ const dragNode = nodesRef.current.find((n) => n.id === d.nodeId);
1852
+ if (!dragNode) return;
1853
+ const proposed = {
1854
+ x: d.startPosition.x + delta.dx,
1855
+ y: d.startPosition.y + delta.dy
1856
+ };
1857
+ const clamped = d.altDetach ? proposed : clampToParentExtent(dragNode, proposed, nodesRef.current);
1858
+ const isContainer = dragNode.type === "group" || dragNode.type === "forEach";
1859
+ const gap = isContainer ? subflowCollisionGapRef.current : nodeCollisionGapRef.current;
1860
+ const excludeIds = /* @__PURE__ */ new Set([d.nodeId, ...d.descendants.map((kid) => kid.id)]);
1861
+ const finalPos = resolveNodeCollisions(dragNode, clamped, nodesRef.current, {
1862
+ gap,
1863
+ exclude: excludeIds
1864
+ });
1865
+ const realDx = finalPos.x - d.startPosition.x;
1866
+ const realDy = finalPos.y - d.startPosition.y;
1867
+ const changes = [change.node.position(d.nodeId, finalPos, true)];
1868
+ for (const kid of d.descendants) {
1869
+ changes.push(
1870
+ change.node.position(
1871
+ kid.id,
1872
+ { x: kid.startPosition.x + realDx, y: kid.startPosition.y + realDy },
1873
+ true
1874
+ )
1875
+ );
1876
+ }
1877
+ onNodesChangeRef.current?.(changes);
1878
+ });
1879
+ }
1880
+ }
1881
+ const c = connRef.current;
1882
+ if (c && c.pointerId === e.pointerId) {
1883
+ const rect = containerRef.current?.getBoundingClientRect();
1884
+ if (rect) {
1885
+ const end = screenToFlow({ x: e.clientX - rect.left, y: e.clientY - rect.top }, vp);
1886
+ setConn({ ...c, end });
1887
+ }
1888
+ }
1889
+ };
1890
+ const onPointerUp = (e) => {
1891
+ const vp = viewportRef.current;
1892
+ const drag = dragRef.current;
1893
+ if (drag && drag.pointerId === e.pointerId) {
1894
+ const dx = (e.clientX - drag.startClientX) / vp.zoom;
1895
+ const dy = (e.clientY - drag.startClientY) / vp.zoom;
1896
+ const dragNode = nodesRef.current.find((n) => n.id === drag.nodeId);
1897
+ if (dragNode) {
1898
+ let proposed = {
1899
+ x: drag.startPosition.x + dx,
1900
+ y: drag.startPosition.y + dy
1901
+ };
1902
+ if (snapToGridRef.current) {
1903
+ const g = gridSizeRef.current;
1904
+ proposed = {
1905
+ x: Math.round(proposed.x / g) * g,
1906
+ y: Math.round(proposed.y / g) * g
1907
+ };
1908
+ }
1909
+ const clamped = drag.altDetach ? proposed : clampToParentExtent(dragNode, proposed, nodesRef.current);
1910
+ const isContainer = dragNode.type === "group" || dragNode.type === "forEach";
1911
+ const gap = isContainer ? subflowCollisionGapRef.current : nodeCollisionGapRef.current;
1912
+ const excludeIds = /* @__PURE__ */ new Set([
1913
+ drag.nodeId,
1914
+ ...drag.descendants.map((kid) => kid.id)
1915
+ ]);
1916
+ const finalPos = resolveNodeCollisions(dragNode, clamped, nodesRef.current, {
1917
+ gap,
1918
+ exclude: excludeIds
1919
+ });
1920
+ const realDx = finalPos.x - drag.startPosition.x;
1921
+ const realDy = finalPos.y - drag.startPosition.y;
1922
+ const changes = [change.node.position(drag.nodeId, finalPos, false)];
1923
+ for (const kid of drag.descendants) {
1924
+ changes.push(
1925
+ change.node.position(
1926
+ kid.id,
1927
+ { x: kid.startPosition.x + realDx, y: kid.startPosition.y + realDy },
1928
+ false
1929
+ )
1930
+ );
1931
+ }
1932
+ if (drag.altDetach && dragNode.parentId) {
1933
+ const targetGroup = findContainingGroup(
1934
+ {
1935
+ x: finalPos.x + (dragNode.width ?? 0) / 2,
1936
+ y: finalPos.y + (dragNode.height ?? 0) / 2
1937
+ },
1938
+ nodesRef.current,
1939
+ [drag.nodeId, ...drag.descendants.map((d) => d.id)]
1940
+ );
1941
+ const nextParentId = targetGroup?.id;
1942
+ const updated = {
1943
+ ...dragNode,
1944
+ position: finalPos,
1945
+ parentId: nextParentId,
1946
+ // Preserve extent only when staying in a group.
1947
+ extent: nextParentId ? dragNode.extent : void 0
1948
+ };
1949
+ changes.push(change.node.replace(drag.nodeId, updated));
1950
+ }
1951
+ onNodesChangeRef.current?.(changes);
1952
+ }
1953
+ dragRef.current = null;
1954
+ setDraggingId(null);
1955
+ }
1956
+ const c = connRef.current;
1957
+ if (c && c.pointerId === e.pointerId) {
1958
+ const target = e.target;
1959
+ const handleEl = target?.closest("[data-handle-id]");
1960
+ let connection = null;
1961
+ let connectedTo;
1962
+ if (handleEl) {
1963
+ const targetNodeId = handleEl.dataset.handleNodeId;
1964
+ const targetHandleId = handleEl.dataset.handleId;
1965
+ const targetType = handleEl.dataset.handleType;
1966
+ const connectableEnd = handleEl.dataset.handleConnectableEnd === "true";
1967
+ if (connectableEnd && (targetNodeId !== c.from.nodeId || targetHandleId !== c.from.handleId) && targetType !== c.from.handleType) {
1968
+ const source = c.from.handleType === "source" ? c.from : { nodeId: targetNodeId, handleId: targetHandleId, handleType: "source" };
1969
+ const target2 = c.from.handleType === "target" ? c.from : { nodeId: targetNodeId, handleId: targetHandleId, handleType: "target" };
1970
+ connection = {
1971
+ source: source.nodeId,
1972
+ sourceHandle: source.handleId,
1973
+ target: target2.nodeId,
1974
+ targetHandle: target2.handleId
1975
+ };
1976
+ connectedTo = {
1977
+ nodeId: targetNodeId,
1978
+ handleId: targetHandleId,
1979
+ handleType: targetType
1980
+ };
1981
+ const validator = isValidConnectionRef.current;
1982
+ if (validator && !validator(connection)) {
1983
+ connection = null;
1984
+ connectedTo = void 0;
1985
+ }
1986
+ }
1987
+ }
1988
+ const rect = containerRef.current?.getBoundingClientRect();
1989
+ const flowPos = rect ? screenToFlow({ x: e.clientX - rect.left, y: e.clientY - rect.top }, vp) : { x: 0, y: 0 };
1990
+ const endState = {
1991
+ cancelled: !connection,
1992
+ position: { x: e.clientX, y: e.clientY },
1993
+ flowPosition: flowPos,
1994
+ from: c.from,
1995
+ to: connectedTo
1996
+ };
1997
+ if (connection) onConnectRef.current?.(connection);
1998
+ onConnectEndRef.current?.(e, endState);
1999
+ setConn(null);
2000
+ store.setConnection(null);
2001
+ }
2002
+ };
2003
+ const onPointerCancel = () => {
2004
+ if (dragRef.current) {
2005
+ dragRef.current = null;
2006
+ setDraggingId(null);
2007
+ }
2008
+ if (connRef.current) {
2009
+ setConn(null);
2010
+ store.setConnection(null);
2011
+ }
2012
+ };
2013
+ window.addEventListener("pointermove", onPointerMove);
2014
+ window.addEventListener("pointerup", onPointerUp);
2015
+ window.addEventListener("pointercancel", onPointerCancel);
2016
+ return () => {
2017
+ window.removeEventListener("pointermove", onPointerMove);
2018
+ window.removeEventListener("pointerup", onPointerUp);
2019
+ window.removeEventListener("pointercancel", onPointerCancel);
2020
+ };
2021
+ }, [store]);
2022
+ const panRef = useRef4(null);
2023
+ const onCanvasPointerDown = (e) => {
2024
+ if (e.button !== 0) return;
2025
+ const t = e.target;
2026
+ if (t.closest("[data-node-id]") || t.closest("[data-edge-id]") || t.closest("[data-handle-id]")) {
2027
+ return;
2028
+ }
2029
+ if (!panOnDrag) {
2030
+ panRef.current = {
2031
+ pointerId: e.pointerId,
2032
+ startClientX: e.clientX,
2033
+ startClientY: e.clientY,
2034
+ startVp: viewport,
2035
+ moved: false
2036
+ };
2037
+ return;
2038
+ }
2039
+ panRef.current = {
2040
+ pointerId: e.pointerId,
2041
+ startClientX: e.clientX,
2042
+ startClientY: e.clientY,
2043
+ startVp: viewport,
2044
+ moved: false
2045
+ };
2046
+ };
2047
+ useEffect4(() => {
2048
+ const onMove = (e) => {
2049
+ const pan = panRef.current;
2050
+ if (!pan || pan.pointerId !== e.pointerId) return;
2051
+ const dx = e.clientX - pan.startClientX;
2052
+ const dy = e.clientY - pan.startClientY;
2053
+ if (Math.abs(dx) > paneClickDistance || Math.abs(dy) > paneClickDistance) {
2054
+ if (!pan.moved) setPanGesture(true);
2055
+ pan.moved = true;
2056
+ }
2057
+ if (pan.moved && panOnDrag) {
2058
+ setViewport({ ...pan.startVp, x: pan.startVp.x + dx, y: pan.startVp.y + dy });
2059
+ }
2060
+ };
2061
+ const onUp = () => {
2062
+ const pan = panRef.current;
2063
+ if (!pan) return;
2064
+ if (!pan.moved) {
2065
+ onPaneClick?.();
2066
+ if (paneClickClearsSelection) clearSelection();
2067
+ }
2068
+ panRef.current = null;
2069
+ setPanGesture(false);
2070
+ };
2071
+ window.addEventListener("pointermove", onMove);
2072
+ window.addEventListener("pointerup", onUp);
2073
+ window.addEventListener("pointercancel", onUp);
2074
+ return () => {
2075
+ window.removeEventListener("pointermove", onMove);
2076
+ window.removeEventListener("pointerup", onUp);
2077
+ window.removeEventListener("pointercancel", onUp);
2078
+ };
2079
+ }, [
2080
+ setViewport,
2081
+ paneClickDistance,
2082
+ panOnDrag,
2083
+ onPaneClick,
2084
+ clearSelection,
2085
+ paneClickClearsSelection
2086
+ ]);
2087
+ const handleWheel = (e) => {
2088
+ if (!zoomOnScroll) return;
2089
+ e.preventDefault();
2090
+ const rect = containerRef.current?.getBoundingClientRect();
2091
+ if (!rect) return;
2092
+ const px = e.clientX - rect.left;
2093
+ const py = e.clientY - rect.top;
2094
+ const factor = Math.exp(-e.deltaY * 1e-3);
2095
+ const nextZoom = Math.max(minZoom, Math.min(maxZoom, viewport.zoom * factor));
2096
+ const k = nextZoom / viewport.zoom;
2097
+ setViewport({
2098
+ zoom: nextZoom,
2099
+ x: px - (px - viewport.x) * k,
2100
+ y: py - (py - viewport.y) * k
2101
+ });
2102
+ };
2103
+ const dispatch = useCallback(
2104
+ (a) => {
2105
+ if (a.type === "connection/start") {
2106
+ beginConnection(a.nodeId, a.handleId, a.handleType, a.pointerId, a.clientX, a.clientY);
2107
+ }
2108
+ },
2109
+ [beginConnection]
2110
+ );
2111
+ const reportDimensions = useCallback(
2112
+ (nodeId, width2, height2) => {
2113
+ const node = nodes.find((n) => n.id === nodeId);
2114
+ if (!node) return;
2115
+ if (node.width === width2 && node.height === height2) return;
2116
+ onNodesChange?.([change.node.dimensions(nodeId, { width: width2, height: height2 })]);
2117
+ },
2118
+ [nodes, onNodesChange]
2119
+ );
2120
+ const toggleNodeCollapseImpl = useCallback(
2121
+ (nodeId) => {
2122
+ const node = nodes.find((n) => n.id === nodeId);
2123
+ if (!node) return;
2124
+ const prevData = node.data ?? {};
2125
+ const nextNode = {
2126
+ ...node,
2127
+ data: { ...prevData, collapsed: !prevData.collapsed }
2128
+ };
2129
+ onNodesChange?.([change.node.replace(nodeId, nextNode)]);
2130
+ },
2131
+ [nodes, onNodesChange]
2132
+ );
2133
+ const deleteNodeImpl = useCallback(
2134
+ (nodeId) => {
2135
+ const incidentEdgeIds = edgesRef.current.filter((e) => e.source === nodeId || e.target === nodeId).map((e) => e.id);
2136
+ if (incidentEdgeIds.length > 0) {
2137
+ onEdgesChange?.(incidentEdgeIds.map((id) => change.edge.remove(id)));
2138
+ }
2139
+ onNodesChange?.([change.node.remove(nodeId)]);
2140
+ },
2141
+ [onNodesChange, onEdgesChange]
2142
+ );
2143
+ const instance = useMemo2(
2144
+ () => ({
2145
+ // viewport
2146
+ getViewport: () => viewportRef.current,
2147
+ setViewport: (vp) => setViewport(vp),
2148
+ setCenter: (x, y, opts) => {
2149
+ const z = opts?.zoom ?? viewportRef.current.zoom;
2150
+ const rect = containerRef.current?.getBoundingClientRect();
2151
+ if (!rect) return;
2152
+ setViewport({
2153
+ zoom: z,
2154
+ x: rect.width / 2 - x * z,
2155
+ y: rect.height / 2 - y * z
2156
+ });
2157
+ },
2158
+ fitView: async (opts) => {
2159
+ const rect = containerRef.current?.getBoundingClientRect();
2160
+ if (!rect) return false;
2161
+ const padding = opts?.padding ?? 80;
2162
+ const targetNodes = opts?.nodes ? nodesRef.current.filter((n) => opts.nodes.some((x) => x.id === n.id)) : nodesRef.current.filter((n) => !n.hidden);
2163
+ if (targetNodes.length === 0) return false;
2164
+ let minX = Number.POSITIVE_INFINITY;
2165
+ let minY = Number.POSITIVE_INFINITY;
2166
+ let maxX = Number.NEGATIVE_INFINITY;
2167
+ let maxY = Number.NEGATIVE_INFINITY;
2168
+ for (const n of targetNodes) {
2169
+ const w = n.width ?? DEFAULT_NODE_WIDTH;
2170
+ const h = effectiveHeight(n);
2171
+ if (n.position.x < minX) minX = n.position.x;
2172
+ if (n.position.y < minY) minY = n.position.y;
2173
+ if (n.position.x + w > maxX) maxX = n.position.x + w;
2174
+ if (n.position.y + h > maxY) maxY = n.position.y + h;
2175
+ }
2176
+ const cw = maxX - minX;
2177
+ const ch = maxY - minY;
2178
+ const zx = (rect.width - padding * 2) / cw;
2179
+ const zy = (rect.height - padding * 2) / ch;
2180
+ const zoom = Math.max(
2181
+ opts?.minZoom ?? 0.25,
2182
+ Math.min(opts?.maxZoom ?? 1.5, Math.min(zx, zy))
2183
+ );
2184
+ setViewport({
2185
+ zoom,
2186
+ x: rect.width / 2 - (minX + maxX) / 2 * zoom,
2187
+ y: rect.height / 2 - (minY + maxY) / 2 * zoom
2188
+ });
2189
+ return true;
2190
+ },
2191
+ zoomIn: (opts) => {
2192
+ const step = opts?.step ?? 0.2;
2193
+ const next = Math.min(maxZoom, viewportRef.current.zoom * (1 + step));
2194
+ setViewport({ ...viewportRef.current, zoom: next });
2195
+ },
2196
+ zoomOut: (opts) => {
2197
+ const step = opts?.step ?? 0.2;
2198
+ const next = Math.max(minZoom, viewportRef.current.zoom / (1 + step));
2199
+ setViewport({ ...viewportRef.current, zoom: next });
2200
+ },
2201
+ zoomTo: (level) => {
2202
+ setViewport({
2203
+ ...viewportRef.current,
2204
+ zoom: Math.max(minZoom, Math.min(maxZoom, level))
2205
+ });
2206
+ },
2207
+ // transforms
2208
+ screenToFlowPosition: (p) => screenToFlow(p, viewportRef.current),
2209
+ flowToScreenPosition: (p) => flowToScreen(p, viewportRef.current),
2210
+ // reads
2211
+ getNodes: () => nodesRef.current.slice(),
2212
+ getEdges: () => edgesRef.current.slice(),
2213
+ getNode: (id) => nodesRef.current.find((n) => n.id === id),
2214
+ getEdge: (id) => edgesRef.current.find((e) => e.id === id),
2215
+ getNodesBounds: (subset) => {
2216
+ const pool = subset ? nodesRef.current.filter((n) => subset.some((x) => x.id === n.id)) : nodesRef.current.filter((n) => !n.hidden);
2217
+ if (pool.length === 0) return { x: 0, y: 0, width: 0, height: 0 };
2218
+ let minX = Number.POSITIVE_INFINITY;
2219
+ let minY = Number.POSITIVE_INFINITY;
2220
+ let maxX = Number.NEGATIVE_INFINITY;
2221
+ let maxY = Number.NEGATIVE_INFINITY;
2222
+ for (const n of pool) {
2223
+ const w = n.width ?? DEFAULT_NODE_WIDTH;
2224
+ const h = effectiveHeight(n);
2225
+ minX = Math.min(minX, n.position.x);
2226
+ minY = Math.min(minY, n.position.y);
2227
+ maxX = Math.max(maxX, n.position.x + w);
2228
+ maxY = Math.max(maxY, n.position.y + h);
2229
+ }
2230
+ return { x: minX, y: minY, width: maxX - minX, height: maxY - minY };
2231
+ },
2232
+ getIntersectingNodes: (area, partially = true) => {
2233
+ return nodesRef.current.filter((n) => {
2234
+ if (n.hidden) return false;
2235
+ const w = n.width ?? DEFAULT_NODE_WIDTH;
2236
+ const h = effectiveHeight(n);
2237
+ if (partially) {
2238
+ return n.position.x < area.x + area.width && n.position.x + w > area.x && n.position.y < area.y + area.height && n.position.y + h > area.y;
2239
+ }
2240
+ return n.position.x >= area.x && n.position.y >= area.y && n.position.x + w <= area.x + area.width && n.position.y + h <= area.y + area.height;
2241
+ });
2242
+ },
2243
+ // mutations
2244
+ addNodes: (nodes2) => {
2245
+ const arr = Array.isArray(nodes2) ? nodes2 : [nodes2];
2246
+ onNodesChangeRefForInstance.current?.(arr.map((item) => change.node.add(item)));
2247
+ },
2248
+ addEdges: (edges2) => {
2249
+ const arr = Array.isArray(edges2) ? edges2 : [edges2];
2250
+ onEdgesChangeRefForInstance.current?.(arr.map((item) => change.edge.add(item)));
2251
+ },
2252
+ updateNodeData: (id, partial) => {
2253
+ const cur = nodesRef.current.find((n) => n.id === id);
2254
+ if (!cur) return;
2255
+ const nextData = { ...cur.data ?? {}, ...partial };
2256
+ onNodesChangeRefForInstance.current?.([
2257
+ change.node.replace(id, { ...cur, data: nextData })
2258
+ ]);
2259
+ },
2260
+ updateNode: (id, partial) => {
2261
+ const cur = nodesRef.current.find((n) => n.id === id);
2262
+ if (!cur) return;
2263
+ onNodesChangeRefForInstance.current?.([change.node.replace(id, { ...cur, ...partial })]);
2264
+ },
2265
+ deleteElements: async ({ nodes: ns, edges: es }) => {
2266
+ const nodesToDelete = (ns ?? []).map((x) => nodesRef.current.find((n) => n.id === x.id)).filter((n) => !!n);
2267
+ const edgesToDelete = (es ?? []).map((x) => edgesRef.current.find((e) => e.id === x.id)).filter((e) => !!e);
2268
+ const before = onBeforeDeleteRef.current;
2269
+ if (before) {
2270
+ const ok = await before({ nodes: nodesToDelete, edges: edgesToDelete });
2271
+ if (!ok) return false;
2272
+ }
2273
+ if (nodesToDelete.length > 0) {
2274
+ onNodesChangeRefForInstance.current?.(nodesToDelete.map((n) => change.node.remove(n.id)));
2275
+ }
2276
+ if (edgesToDelete.length > 0) {
2277
+ onEdgesChangeRefForInstance.current?.(edgesToDelete.map((e) => change.edge.remove(e.id)));
2278
+ }
2279
+ return true;
2280
+ }
2281
+ }),
2282
+ [setViewport, minZoom, maxZoom]
2283
+ );
2284
+ const initFiredRef = useRef4(false);
2285
+ useEffect4(() => {
2286
+ if (initFiredRef.current) return;
2287
+ initFiredRef.current = true;
2288
+ onInit?.(instance);
2289
+ }, [instance, onInit]);
2290
+ useEffect4(() => {
2291
+ const onKey = (e) => {
2292
+ if (e.key !== "Backspace" && e.key !== "Delete") return;
2293
+ const target = e.target;
2294
+ if (target && (target.tagName === "INPUT" || target.tagName === "TEXTAREA" || target.tagName === "SELECT" || target.isContentEditable)) {
2295
+ return;
2296
+ }
2297
+ if (!containerRef.current?.contains(target) && document.activeElement !== document.body) {
2298
+ return;
2299
+ }
2300
+ const sel = store.getSnapshot();
2301
+ if (sel.selectedNodeIds.size === 0 && sel.selectedEdgeIds.size === 0) return;
2302
+ e.preventDefault();
2303
+ void instance.deleteElements({
2304
+ nodes: Array.from(sel.selectedNodeIds, (id) => ({ id })),
2305
+ edges: Array.from(sel.selectedEdgeIds, (id) => ({ id }))
2306
+ });
2307
+ };
2308
+ window.addEventListener("keydown", onKey);
2309
+ return () => window.removeEventListener("keydown", onKey);
2310
+ }, [instance, store]);
2311
+ const bridge = useMemo2(
2312
+ () => ({
2313
+ beginNodeDrag,
2314
+ selectNode,
2315
+ notifyNodeClick,
2316
+ selectEdge,
2317
+ reportDimensions,
2318
+ deleteNode: deleteNodeImpl,
2319
+ toggleNodeCollapse: toggleNodeCollapseImpl
2320
+ }),
2321
+ [
2322
+ beginNodeDrag,
2323
+ selectNode,
2324
+ notifyNodeClick,
2325
+ selectEdge,
2326
+ reportDimensions,
2327
+ deleteNodeImpl,
2328
+ toggleNodeCollapseImpl
2329
+ ]
2330
+ );
2331
+ const [panGesture, setPanGesture] = useState2(false);
2332
+ const isEmpty = nodes.length === 0 && edges.length === 0;
2333
+ const isConnecting = conn !== null;
2334
+ const visibleNodes = useMemo2(() => nodes.filter((n) => !n.hidden), [nodes]);
2335
+ const visibleEdges = useMemo2(() => {
2336
+ if (visibleNodes.length === nodes.length) return edges;
2337
+ const visibleIds = new Set(visibleNodes.map((n) => n.id));
2338
+ return edges.filter((e) => visibleIds.has(e.source) && visibleIds.has(e.target));
2339
+ }, [edges, nodes, visibleNodes]);
2340
+ const orderedNodes = useMemo2(() => {
2341
+ const isContainer = (n) => n.type === "group" || n.type === "forEach";
2342
+ const depth = (n) => {
2343
+ let d = 0;
2344
+ let cursor = n.parentId;
2345
+ const seen = /* @__PURE__ */ new Set();
2346
+ while (cursor) {
2347
+ if (seen.has(cursor)) return Number.POSITIVE_INFINITY;
2348
+ seen.add(cursor);
2349
+ d++;
2350
+ cursor = visibleNodes.find((x) => x.id === cursor)?.parentId;
2351
+ }
2352
+ return d;
2353
+ };
2354
+ const containers = visibleNodes.filter(isContainer);
2355
+ const others = visibleNodes.filter((n) => !isContainer(n));
2356
+ containers.sort((a, b) => depth(a) - depth(b));
2357
+ return [...containers, ...others];
2358
+ }, [visibleNodes]);
2359
+ return /* @__PURE__ */ jsx6(FlowStoreContext.Provider, { value: store, children: /* @__PURE__ */ jsx6(FlowInstanceContext.Provider, { value: instance, children: /* @__PURE__ */ jsx6(HandleRegistryContext.Provider, { value: handleRegistry, children: /* @__PURE__ */ jsx6(FlowDispatchContext.Provider, { value: dispatch, children: /* @__PURE__ */ jsx6(FlowNodeBridgeContext.Provider, { value: bridge, children: /* @__PURE__ */ jsxs5(
2360
+ "div",
2361
+ {
2362
+ ref: containerRef,
2363
+ className: cn(
2364
+ "ods-flow-canvas-v2",
2365
+ panGesture && "ods-flow-canvas-v2--panning",
2366
+ isConnecting && "ods-flow-canvas-v2--connecting",
2367
+ draggingId && "ods-flow-canvas-v2--dragging",
2368
+ className
2369
+ ),
2370
+ style: {
2371
+ position: "relative",
2372
+ width,
2373
+ height,
2374
+ overflow: "hidden",
2375
+ userSelect: "none",
2376
+ touchAction: "none",
2377
+ // Cursor: state-driven so it flips instantly with the
2378
+ // gesture. CSS `:active` would lag behind pointer-capture.
2379
+ cursor: panGesture ? "grabbing" : isConnecting ? "crosshair" : panOnDrag ? "grab" : "default",
2380
+ ...style
2381
+ },
2382
+ onPointerDown: onCanvasPointerDown,
2383
+ onWheel: handleWheel,
2384
+ onContextMenu: (e) => {
2385
+ const t = e.target;
2386
+ const nodeEl = t.closest("[data-node-id]");
2387
+ if (nodeEl && onNodeContextMenu) {
2388
+ const id = nodeEl.dataset.nodeId;
2389
+ const node = nodes.find((n) => n.id === id);
2390
+ if (node) onNodeContextMenu(e, node);
2391
+ return;
2392
+ }
2393
+ const edgeEl = t.closest("[data-edge-id]");
2394
+ if (edgeEl && onEdgeContextMenu) {
2395
+ const id = edgeEl.dataset.edgeId;
2396
+ const edge = edges.find((x) => x.id === id);
2397
+ if (edge) onEdgeContextMenu(e, edge);
2398
+ return;
2399
+ }
2400
+ onPaneContextMenu?.(e);
2401
+ },
2402
+ "data-empty": isEmpty ? "true" : void 0,
2403
+ children: [
2404
+ background !== "none" && /* @__PURE__ */ jsx6(
2405
+ "div",
2406
+ {
2407
+ className: cn(
2408
+ "ods-flow-canvas-v2__grid",
2409
+ `ods-flow-canvas-v2__grid--${background}`
2410
+ ),
2411
+ style: {
2412
+ // Custom property drives the four variants' SCSS.
2413
+ "--ods-flow-grid-size": `${gridSize * viewport.zoom}px`,
2414
+ backgroundPosition: `${viewport.x}px ${viewport.y}px`
2415
+ }
2416
+ }
2417
+ ),
2418
+ /* @__PURE__ */ jsxs5(
2419
+ "div",
2420
+ {
2421
+ className: "ods-flow-canvas-v2__viewport",
2422
+ style: {
2423
+ position: "absolute",
2424
+ inset: 0,
2425
+ transform: `translate(${viewport.x}px, ${viewport.y}px) scale(${viewport.zoom})`,
2426
+ transformOrigin: "0 0"
2427
+ },
2428
+ children: [
2429
+ /* @__PURE__ */ jsx6(
2430
+ EdgesLayer,
2431
+ {
2432
+ edges: visibleEdges,
2433
+ nodes: visibleNodes,
2434
+ onSelect: (id) => bridge.selectEdge(id, false),
2435
+ onDelete: (id) => onEdgesChangeRef(id, onEdgesChange),
2436
+ onLabelChange: onEdgeLabelChange,
2437
+ ghost: conn ? { start: conn.start, end: conn.end } : null,
2438
+ handleVersion
2439
+ }
2440
+ ),
2441
+ orderedNodes.map((node) => {
2442
+ const Kind = kinds[node.type] ?? kinds.action;
2443
+ if (!Kind) return null;
2444
+ return /* @__PURE__ */ jsx6(
2445
+ FlowNode,
2446
+ {
2447
+ node,
2448
+ selected: selectedNodeIds.has(node.id),
2449
+ dragging: draggingId === node.id,
2450
+ isConnecting,
2451
+ Kind
2452
+ },
2453
+ node.id
2454
+ );
2455
+ })
2456
+ ]
2457
+ }
2458
+ ),
2459
+ isEmpty && emptyState && /* @__PURE__ */ jsx6("div", { className: "ods-flow-canvas-v2__empty", children: emptyState }),
2460
+ children
2461
+ ]
2462
+ }
2463
+ ) }) }) }) }) });
2464
+ }
2465
+ function onEdgesChangeRef(id, cb) {
2466
+ cb?.([change.edge.remove(id)]);
2467
+ }
2468
+ var EdgesLayer = memo2(function EdgesLayer2({
2469
+ edges,
2470
+ nodes,
2471
+ onSelect,
2472
+ onDelete,
2473
+ onLabelChange,
2474
+ ghost,
2475
+ handleVersion: _handleVersion
2476
+ }) {
2477
+ return /* @__PURE__ */ jsxs5(
2478
+ "svg",
2479
+ {
2480
+ className: "ods-flow-canvas-v2__edges",
2481
+ style: { position: "absolute", inset: 0, overflow: "visible", pointerEvents: "none" },
2482
+ width: "100%",
2483
+ height: "100%",
2484
+ children: [
2485
+ /* @__PURE__ */ jsx6("g", { style: { pointerEvents: "auto" }, children: edges.map((edge) => /* @__PURE__ */ jsx6(
2486
+ FlowEdge,
2487
+ {
2488
+ edge,
2489
+ nodes,
2490
+ onSelect,
2491
+ onDelete,
2492
+ onLabelChange,
2493
+ handleVersion: _handleVersion
2494
+ },
2495
+ edge.id
2496
+ )) }),
2497
+ ghost && /* @__PURE__ */ jsx6(
2498
+ "path",
2499
+ {
2500
+ d: `M ${ghost.start.x} ${ghost.start.y} L ${ghost.end.x} ${ghost.end.y}`,
2501
+ stroke: "var(--ods-accent, #4f46e5)",
2502
+ strokeWidth: 1.5,
2503
+ strokeDasharray: "4 4",
2504
+ fill: "none"
2505
+ }
2506
+ )
2507
+ ]
2508
+ }
2509
+ );
2510
+ });
2511
+
2512
+ export {
2513
+ buildEdgePath,
2514
+ bezierPath,
2515
+ stepPath,
2516
+ smoothStepPath,
2517
+ straightPath,
2518
+ useFlow,
2519
+ applyNodeChanges,
2520
+ applyEdgeChanges,
2521
+ change,
2522
+ useFlowStore,
2523
+ DEFAULT_NODE_WIDTH,
2524
+ DEFAULT_NODE_HEIGHT,
2525
+ handleCentre,
2526
+ bezierPath2,
2527
+ screenToFlow,
2528
+ flowToScreen,
2529
+ descendantsOf,
2530
+ findAncestor,
2531
+ clampToParentExtent,
2532
+ findContainingGroup,
2533
+ FlowEdge,
2534
+ useFlowNodeContext,
2535
+ FlowNode,
2536
+ buildNodeKindRegistry,
2537
+ Handle,
2538
+ ActionNode,
2539
+ TriggerNode,
2540
+ ConditionNode,
2541
+ GroupNode,
2542
+ ForEachNode,
2543
+ OutputNode,
2544
+ ErrorNode,
2545
+ WaitNode,
2546
+ ParallelNode,
2547
+ StickyNode,
2548
+ WebhookNode,
2549
+ HttpRequestNode,
2550
+ DEFAULT_NODE_KINDS,
2551
+ FlowCanvas
2552
+ };
2553
+ //# sourceMappingURL=chunk-2RD5OERK.js.map