@octaviaflow/core 3.0.18-beta.0 → 3.0.18-beta.10

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