@mindlogic-ai/logician-ui 3.1.0-alpha.9 → 3.2.0-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (396) hide show
  1. package/dist/components/Icon/_constants/iconList.d.ts +1 -1
  2. package/dist/components/Icon/_constants/iconList.d.ts.map +1 -1
  3. package/dist/components/Icon/_constants/iconList.js +18 -0
  4. package/dist/components/Icon/_constants/iconList.js.map +1 -1
  5. package/dist/components/Icon/_constants/iconList.mjs +20 -2
  6. package/dist/components/Icon/_constants/iconList.mjs.map +1 -1
  7. package/dist/components/Icon/index.d.ts +2 -1
  8. package/dist/components/Icon/index.d.ts.map +1 -1
  9. package/dist/components/Icon/index.js +20 -1
  10. package/dist/components/Icon/index.js.map +1 -1
  11. package/dist/components/Icon/index.mjs +4 -2
  12. package/dist/components/Icon/index.mjs.map +1 -1
  13. package/dist/components/SegmentedControl/SegmentedControl.d.ts.map +1 -1
  14. package/dist/components/SegmentedControl/SegmentedControl.js +20 -4
  15. package/dist/components/SegmentedControl/SegmentedControl.js.map +1 -1
  16. package/dist/components/SegmentedControl/SegmentedControl.mjs +20 -4
  17. package/dist/components/SegmentedControl/SegmentedControl.mjs.map +1 -1
  18. package/dist/components/Workflow/Workflow.d.ts +3 -0
  19. package/dist/components/Workflow/Workflow.d.ts.map +1 -0
  20. package/dist/components/Workflow/Workflow.js +109 -0
  21. package/dist/components/Workflow/Workflow.js.map +1 -0
  22. package/dist/components/Workflow/Workflow.mjs +107 -0
  23. package/dist/components/Workflow/Workflow.mjs.map +1 -0
  24. package/dist/components/Workflow/Workflow.translations.json.js +164 -0
  25. package/dist/components/Workflow/Workflow.translations.json.js.map +1 -0
  26. package/dist/components/Workflow/Workflow.translations.json.mjs +138 -0
  27. package/dist/components/Workflow/Workflow.translations.json.mjs.map +1 -0
  28. package/dist/components/Workflow/Workflow.types.d.ts +435 -0
  29. package/dist/components/Workflow/Workflow.types.d.ts.map +1 -0
  30. package/dist/components/Workflow/Workflow.types.js +19 -0
  31. package/dist/components/Workflow/Workflow.types.js.map +1 -0
  32. package/dist/components/Workflow/Workflow.types.mjs +16 -0
  33. package/dist/components/Workflow/Workflow.types.mjs.map +1 -0
  34. package/dist/components/Workflow/WorkflowContext/WorkflowContext.d.ts +10 -0
  35. package/dist/components/Workflow/WorkflowContext/WorkflowContext.d.ts.map +1 -0
  36. package/dist/components/Workflow/WorkflowContext/WorkflowContext.js +163 -0
  37. package/dist/components/Workflow/WorkflowContext/WorkflowContext.js.map +1 -0
  38. package/dist/components/Workflow/WorkflowContext/WorkflowContext.mjs +159 -0
  39. package/dist/components/Workflow/WorkflowContext/WorkflowContext.mjs.map +1 -0
  40. package/dist/components/Workflow/WorkflowContext/WorkflowContext.types.d.ts +117 -0
  41. package/dist/components/Workflow/WorkflowContext/WorkflowContext.types.d.ts.map +1 -0
  42. package/dist/components/Workflow/WorkflowContext/index.d.ts +3 -0
  43. package/dist/components/Workflow/WorkflowContext/index.d.ts.map +1 -0
  44. package/dist/components/Workflow/canvas/Canvas/BranchLabelBadge.d.ts +19 -0
  45. package/dist/components/Workflow/canvas/Canvas/BranchLabelBadge.d.ts.map +1 -0
  46. package/dist/components/Workflow/canvas/Canvas/BranchLabelBadge.js +44 -0
  47. package/dist/components/Workflow/canvas/Canvas/BranchLabelBadge.js.map +1 -0
  48. package/dist/components/Workflow/canvas/Canvas/BranchLabelBadge.mjs +42 -0
  49. package/dist/components/Workflow/canvas/Canvas/BranchLabelBadge.mjs.map +1 -0
  50. package/dist/components/Workflow/canvas/Canvas/Canvas.d.ts +10 -0
  51. package/dist/components/Workflow/canvas/Canvas/Canvas.d.ts.map +1 -0
  52. package/dist/components/Workflow/canvas/Canvas/Canvas.js +531 -0
  53. package/dist/components/Workflow/canvas/Canvas/Canvas.js.map +1 -0
  54. package/dist/components/Workflow/canvas/Canvas/Canvas.mjs +529 -0
  55. package/dist/components/Workflow/canvas/Canvas/Canvas.mjs.map +1 -0
  56. package/dist/components/Workflow/canvas/Canvas/Canvas.styles.d.ts +53 -0
  57. package/dist/components/Workflow/canvas/Canvas/Canvas.styles.d.ts.map +1 -0
  58. package/dist/components/Workflow/canvas/Canvas/Canvas.styles.js +96 -0
  59. package/dist/components/Workflow/canvas/Canvas/Canvas.styles.js.map +1 -0
  60. package/dist/components/Workflow/canvas/Canvas/Canvas.styles.mjs +93 -0
  61. package/dist/components/Workflow/canvas/Canvas/Canvas.styles.mjs.map +1 -0
  62. package/dist/components/Workflow/canvas/Canvas/CanvasControls.d.ts +27 -0
  63. package/dist/components/Workflow/canvas/Canvas/CanvasControls.d.ts.map +1 -0
  64. package/dist/components/Workflow/canvas/Canvas/CanvasControls.js +70 -0
  65. package/dist/components/Workflow/canvas/Canvas/CanvasControls.js.map +1 -0
  66. package/dist/components/Workflow/canvas/Canvas/CanvasControls.mjs +68 -0
  67. package/dist/components/Workflow/canvas/Canvas/CanvasControls.mjs.map +1 -0
  68. package/dist/components/Workflow/canvas/Canvas/LabeledEdge.d.ts +10 -0
  69. package/dist/components/Workflow/canvas/Canvas/LabeledEdge.d.ts.map +1 -0
  70. package/dist/components/Workflow/canvas/Canvas/LabeledEdge.js +106 -0
  71. package/dist/components/Workflow/canvas/Canvas/LabeledEdge.js.map +1 -0
  72. package/dist/components/Workflow/canvas/Canvas/LabeledEdge.mjs +104 -0
  73. package/dist/components/Workflow/canvas/Canvas/LabeledEdge.mjs.map +1 -0
  74. package/dist/components/Workflow/canvas/Canvas/edgeLabelVariant.d.ts +13 -0
  75. package/dist/components/Workflow/canvas/Canvas/edgeLabelVariant.d.ts.map +1 -0
  76. package/dist/components/Workflow/canvas/Canvas/edgeLabelVariant.js +18 -0
  77. package/dist/components/Workflow/canvas/Canvas/edgeLabelVariant.js.map +1 -0
  78. package/dist/components/Workflow/canvas/Canvas/edgeLabelVariant.mjs +16 -0
  79. package/dist/components/Workflow/canvas/Canvas/edgeLabelVariant.mjs.map +1 -0
  80. package/dist/components/Workflow/canvas/Canvas/index.d.ts +2 -0
  81. package/dist/components/Workflow/canvas/Canvas/index.d.ts.map +1 -0
  82. package/dist/components/Workflow/canvas/CollapsibleSection/CollapsibleSection.d.ts +30 -0
  83. package/dist/components/Workflow/canvas/CollapsibleSection/CollapsibleSection.d.ts.map +1 -0
  84. package/dist/components/Workflow/canvas/CollapsibleSection/CollapsibleSection.js +34 -0
  85. package/dist/components/Workflow/canvas/CollapsibleSection/CollapsibleSection.js.map +1 -0
  86. package/dist/components/Workflow/canvas/CollapsibleSection/CollapsibleSection.mjs +32 -0
  87. package/dist/components/Workflow/canvas/CollapsibleSection/CollapsibleSection.mjs.map +1 -0
  88. package/dist/components/Workflow/canvas/CollapsibleSection/index.d.ts +2 -0
  89. package/dist/components/Workflow/canvas/CollapsibleSection/index.d.ts.map +1 -0
  90. package/dist/components/Workflow/canvas/DrawerShell/DrawerHeader.d.ts +37 -0
  91. package/dist/components/Workflow/canvas/DrawerShell/DrawerHeader.d.ts.map +1 -0
  92. package/dist/components/Workflow/canvas/DrawerShell/DrawerHeader.js +33 -0
  93. package/dist/components/Workflow/canvas/DrawerShell/DrawerHeader.js.map +1 -0
  94. package/dist/components/Workflow/canvas/DrawerShell/DrawerHeader.mjs +31 -0
  95. package/dist/components/Workflow/canvas/DrawerShell/DrawerHeader.mjs.map +1 -0
  96. package/dist/components/Workflow/canvas/DrawerShell/DrawerIssues.d.ts +16 -0
  97. package/dist/components/Workflow/canvas/DrawerShell/DrawerIssues.d.ts.map +1 -0
  98. package/dist/components/Workflow/canvas/DrawerShell/DrawerIssues.js +54 -0
  99. package/dist/components/Workflow/canvas/DrawerShell/DrawerIssues.js.map +1 -0
  100. package/dist/components/Workflow/canvas/DrawerShell/DrawerIssues.mjs +52 -0
  101. package/dist/components/Workflow/canvas/DrawerShell/DrawerIssues.mjs.map +1 -0
  102. package/dist/components/Workflow/canvas/DrawerShell/DrawerShell.d.ts +27 -0
  103. package/dist/components/Workflow/canvas/DrawerShell/DrawerShell.d.ts.map +1 -0
  104. package/dist/components/Workflow/canvas/DrawerShell/DrawerShell.js +178 -0
  105. package/dist/components/Workflow/canvas/DrawerShell/DrawerShell.js.map +1 -0
  106. package/dist/components/Workflow/canvas/DrawerShell/DrawerShell.mjs +176 -0
  107. package/dist/components/Workflow/canvas/DrawerShell/DrawerShell.mjs.map +1 -0
  108. package/dist/components/Workflow/canvas/DrawerShell/index.d.ts +3 -0
  109. package/dist/components/Workflow/canvas/DrawerShell/index.d.ts.map +1 -0
  110. package/dist/components/Workflow/canvas/EdgeInspector/BuiltInEdgeInspector.d.ts +12 -0
  111. package/dist/components/Workflow/canvas/EdgeInspector/BuiltInEdgeInspector.d.ts.map +1 -0
  112. package/dist/components/Workflow/canvas/EdgeInspector/BuiltInEdgeInspector.js +68 -0
  113. package/dist/components/Workflow/canvas/EdgeInspector/BuiltInEdgeInspector.js.map +1 -0
  114. package/dist/components/Workflow/canvas/EdgeInspector/BuiltInEdgeInspector.mjs +66 -0
  115. package/dist/components/Workflow/canvas/EdgeInspector/BuiltInEdgeInspector.mjs.map +1 -0
  116. package/dist/components/Workflow/canvas/EdgeInspector/endpointTitle.d.ts +19 -0
  117. package/dist/components/Workflow/canvas/EdgeInspector/endpointTitle.d.ts.map +1 -0
  118. package/dist/components/Workflow/canvas/EdgeInspector/endpointTitle.js +35 -0
  119. package/dist/components/Workflow/canvas/EdgeInspector/endpointTitle.js.map +1 -0
  120. package/dist/components/Workflow/canvas/EdgeInspector/endpointTitle.mjs +32 -0
  121. package/dist/components/Workflow/canvas/EdgeInspector/endpointTitle.mjs.map +1 -0
  122. package/dist/components/Workflow/canvas/EdgeInspector/index.d.ts +3 -0
  123. package/dist/components/Workflow/canvas/EdgeInspector/index.d.ts.map +1 -0
  124. package/dist/components/Workflow/canvas/FieldWrapper/FieldWrapper.d.ts +54 -0
  125. package/dist/components/Workflow/canvas/FieldWrapper/FieldWrapper.d.ts.map +1 -0
  126. package/dist/components/Workflow/canvas/FieldWrapper/FieldWrapper.js +56 -0
  127. package/dist/components/Workflow/canvas/FieldWrapper/FieldWrapper.js.map +1 -0
  128. package/dist/components/Workflow/canvas/FieldWrapper/FieldWrapper.mjs +54 -0
  129. package/dist/components/Workflow/canvas/FieldWrapper/FieldWrapper.mjs.map +1 -0
  130. package/dist/components/Workflow/canvas/FieldWrapper/index.d.ts +3 -0
  131. package/dist/components/Workflow/canvas/FieldWrapper/index.d.ts.map +1 -0
  132. package/dist/components/Workflow/canvas/FloatingCard/FloatingCard.d.ts +16 -0
  133. package/dist/components/Workflow/canvas/FloatingCard/FloatingCard.d.ts.map +1 -0
  134. package/dist/components/Workflow/canvas/FloatingCard/FloatingCard.js +25 -0
  135. package/dist/components/Workflow/canvas/FloatingCard/FloatingCard.js.map +1 -0
  136. package/dist/components/Workflow/canvas/FloatingCard/FloatingCard.mjs +22 -0
  137. package/dist/components/Workflow/canvas/FloatingCard/FloatingCard.mjs.map +1 -0
  138. package/dist/components/Workflow/canvas/FloatingCard/index.d.ts +2 -0
  139. package/dist/components/Workflow/canvas/FloatingCard/index.d.ts.map +1 -0
  140. package/dist/components/Workflow/canvas/GenericNode/GenericNode.d.ts +14 -0
  141. package/dist/components/Workflow/canvas/GenericNode/GenericNode.d.ts.map +1 -0
  142. package/dist/components/Workflow/canvas/GenericNode/GenericNode.js +61 -0
  143. package/dist/components/Workflow/canvas/GenericNode/GenericNode.js.map +1 -0
  144. package/dist/components/Workflow/canvas/GenericNode/GenericNode.mjs +59 -0
  145. package/dist/components/Workflow/canvas/GenericNode/GenericNode.mjs.map +1 -0
  146. package/dist/components/Workflow/canvas/GenericNode/GenericNode.types.d.ts +11 -0
  147. package/dist/components/Workflow/canvas/GenericNode/GenericNode.types.d.ts.map +1 -0
  148. package/dist/components/Workflow/canvas/GenericNode/index.d.ts +3 -0
  149. package/dist/components/Workflow/canvas/GenericNode/index.d.ts.map +1 -0
  150. package/dist/components/Workflow/canvas/GraphErrorBanner/GraphErrorBanner.d.ts +15 -0
  151. package/dist/components/Workflow/canvas/GraphErrorBanner/GraphErrorBanner.d.ts.map +1 -0
  152. package/dist/components/Workflow/canvas/GraphErrorBanner/GraphErrorBanner.js +145 -0
  153. package/dist/components/Workflow/canvas/GraphErrorBanner/GraphErrorBanner.js.map +1 -0
  154. package/dist/components/Workflow/canvas/GraphErrorBanner/GraphErrorBanner.mjs +143 -0
  155. package/dist/components/Workflow/canvas/GraphErrorBanner/GraphErrorBanner.mjs.map +1 -0
  156. package/dist/components/Workflow/canvas/GraphErrorBanner/index.d.ts +2 -0
  157. package/dist/components/Workflow/canvas/GraphErrorBanner/index.d.ts.map +1 -0
  158. package/dist/components/Workflow/canvas/IconTile/IconTile.d.ts +10 -0
  159. package/dist/components/Workflow/canvas/IconTile/IconTile.d.ts.map +1 -0
  160. package/dist/components/Workflow/canvas/IconTile/IconTile.js +21 -0
  161. package/dist/components/Workflow/canvas/IconTile/IconTile.js.map +1 -0
  162. package/dist/components/Workflow/canvas/IconTile/IconTile.mjs +19 -0
  163. package/dist/components/Workflow/canvas/IconTile/IconTile.mjs.map +1 -0
  164. package/dist/components/Workflow/canvas/IconTile/IconTile.styles.d.ts +18 -0
  165. package/dist/components/Workflow/canvas/IconTile/IconTile.styles.d.ts.map +1 -0
  166. package/dist/components/Workflow/canvas/IconTile/IconTile.styles.js +40 -0
  167. package/dist/components/Workflow/canvas/IconTile/IconTile.styles.js.map +1 -0
  168. package/dist/components/Workflow/canvas/IconTile/IconTile.styles.mjs +37 -0
  169. package/dist/components/Workflow/canvas/IconTile/IconTile.styles.mjs.map +1 -0
  170. package/dist/components/Workflow/canvas/IconTile/IconTile.types.d.ts +15 -0
  171. package/dist/components/Workflow/canvas/IconTile/IconTile.types.d.ts.map +1 -0
  172. package/dist/components/Workflow/canvas/IconTile/index.d.ts +4 -0
  173. package/dist/components/Workflow/canvas/IconTile/index.d.ts.map +1 -0
  174. package/dist/components/Workflow/canvas/IssueList/IssueList.d.ts +24 -0
  175. package/dist/components/Workflow/canvas/IssueList/IssueList.d.ts.map +1 -0
  176. package/dist/components/Workflow/canvas/IssueList/IssueList.js +34 -0
  177. package/dist/components/Workflow/canvas/IssueList/IssueList.js.map +1 -0
  178. package/dist/components/Workflow/canvas/IssueList/IssueList.mjs +32 -0
  179. package/dist/components/Workflow/canvas/IssueList/IssueList.mjs.map +1 -0
  180. package/dist/components/Workflow/canvas/IssueList/index.d.ts +2 -0
  181. package/dist/components/Workflow/canvas/IssueList/index.d.ts.map +1 -0
  182. package/dist/components/Workflow/canvas/NodePalette/NodePalette.d.ts +9 -0
  183. package/dist/components/Workflow/canvas/NodePalette/NodePalette.d.ts.map +1 -0
  184. package/dist/components/Workflow/canvas/NodePalette/NodePalette.js +94 -0
  185. package/dist/components/Workflow/canvas/NodePalette/NodePalette.js.map +1 -0
  186. package/dist/components/Workflow/canvas/NodePalette/NodePalette.mjs +92 -0
  187. package/dist/components/Workflow/canvas/NodePalette/NodePalette.mjs.map +1 -0
  188. package/dist/components/Workflow/canvas/NodePalette/NodePalette.styles.d.ts +7 -0
  189. package/dist/components/Workflow/canvas/NodePalette/NodePalette.styles.d.ts.map +1 -0
  190. package/dist/components/Workflow/canvas/NodePalette/NodePalette.styles.js +13 -0
  191. package/dist/components/Workflow/canvas/NodePalette/NodePalette.styles.js.map +1 -0
  192. package/dist/components/Workflow/canvas/NodePalette/NodePalette.styles.mjs +10 -0
  193. package/dist/components/Workflow/canvas/NodePalette/NodePalette.styles.mjs.map +1 -0
  194. package/dist/components/Workflow/canvas/NodePalette/NodePaletteToggle.d.ts +10 -0
  195. package/dist/components/Workflow/canvas/NodePalette/NodePaletteToggle.d.ts.map +1 -0
  196. package/dist/components/Workflow/canvas/NodePalette/NodePaletteToggle.js +28 -0
  197. package/dist/components/Workflow/canvas/NodePalette/NodePaletteToggle.js.map +1 -0
  198. package/dist/components/Workflow/canvas/NodePalette/NodePaletteToggle.mjs +26 -0
  199. package/dist/components/Workflow/canvas/NodePalette/NodePaletteToggle.mjs.map +1 -0
  200. package/dist/components/Workflow/canvas/NodePalette/index.d.ts +4 -0
  201. package/dist/components/Workflow/canvas/NodePalette/index.d.ts.map +1 -0
  202. package/dist/components/Workflow/canvas/NodeShell/NodeShell.d.ts +3 -0
  203. package/dist/components/Workflow/canvas/NodeShell/NodeShell.d.ts.map +1 -0
  204. package/dist/components/Workflow/canvas/NodeShell/NodeShell.js +137 -0
  205. package/dist/components/Workflow/canvas/NodeShell/NodeShell.js.map +1 -0
  206. package/dist/components/Workflow/canvas/NodeShell/NodeShell.mjs +135 -0
  207. package/dist/components/Workflow/canvas/NodeShell/NodeShell.mjs.map +1 -0
  208. package/dist/components/Workflow/canvas/NodeShell/NodeShell.styles.d.ts +66 -0
  209. package/dist/components/Workflow/canvas/NodeShell/NodeShell.styles.d.ts.map +1 -0
  210. package/dist/components/Workflow/canvas/NodeShell/NodeShell.styles.js +87 -0
  211. package/dist/components/Workflow/canvas/NodeShell/NodeShell.styles.js.map +1 -0
  212. package/dist/components/Workflow/canvas/NodeShell/NodeShell.styles.mjs +77 -0
  213. package/dist/components/Workflow/canvas/NodeShell/NodeShell.styles.mjs.map +1 -0
  214. package/dist/components/Workflow/canvas/NodeShell/NodeShell.types.d.ts +35 -0
  215. package/dist/components/Workflow/canvas/NodeShell/NodeShell.types.d.ts.map +1 -0
  216. package/dist/components/Workflow/canvas/NodeShell/index.d.ts +4 -0
  217. package/dist/components/Workflow/canvas/NodeShell/index.d.ts.map +1 -0
  218. package/dist/components/Workflow/canvas/SeverityDot/SeverityDot.d.ts +15 -0
  219. package/dist/components/Workflow/canvas/SeverityDot/SeverityDot.d.ts.map +1 -0
  220. package/dist/components/Workflow/canvas/SeverityDot/SeverityDot.js +14 -0
  221. package/dist/components/Workflow/canvas/SeverityDot/SeverityDot.js.map +1 -0
  222. package/dist/components/Workflow/canvas/SeverityDot/SeverityDot.mjs +12 -0
  223. package/dist/components/Workflow/canvas/SeverityDot/SeverityDot.mjs.map +1 -0
  224. package/dist/components/Workflow/canvas/SeverityDot/index.d.ts +2 -0
  225. package/dist/components/Workflow/canvas/SeverityDot/index.d.ts.map +1 -0
  226. package/dist/components/Workflow/canvas/issueSeverity.d.ts +23 -0
  227. package/dist/components/Workflow/canvas/issueSeverity.d.ts.map +1 -0
  228. package/dist/components/Workflow/canvas/issueSeverity.js +51 -0
  229. package/dist/components/Workflow/canvas/issueSeverity.js.map +1 -0
  230. package/dist/components/Workflow/canvas/issueSeverity.mjs +47 -0
  231. package/dist/components/Workflow/canvas/issueSeverity.mjs.map +1 -0
  232. package/dist/components/Workflow/canvas/useFieldFocusRequest.d.ts +14 -0
  233. package/dist/components/Workflow/canvas/useFieldFocusRequest.d.ts.map +1 -0
  234. package/dist/components/Workflow/canvas/useFieldFocusRequest.js +48 -0
  235. package/dist/components/Workflow/canvas/useFieldFocusRequest.js.map +1 -0
  236. package/dist/components/Workflow/canvas/useFieldFocusRequest.mjs +46 -0
  237. package/dist/components/Workflow/canvas/useFieldFocusRequest.mjs.map +1 -0
  238. package/dist/components/Workflow/canvas/workflowLabelProps.d.ts +12 -0
  239. package/dist/components/Workflow/canvas/workflowLabelProps.d.ts.map +1 -0
  240. package/dist/components/Workflow/canvas/workflowLabelProps.js +17 -0
  241. package/dist/components/Workflow/canvas/workflowLabelProps.js.map +1 -0
  242. package/dist/components/Workflow/canvas/workflowLabelProps.mjs +15 -0
  243. package/dist/components/Workflow/canvas/workflowLabelProps.mjs.map +1 -0
  244. package/dist/components/Workflow/connectionRules.d.ts +59 -0
  245. package/dist/components/Workflow/connectionRules.d.ts.map +1 -0
  246. package/dist/components/Workflow/connectionRules.js +150 -0
  247. package/dist/components/Workflow/connectionRules.js.map +1 -0
  248. package/dist/components/Workflow/connectionRules.mjs +145 -0
  249. package/dist/components/Workflow/connectionRules.mjs.map +1 -0
  250. package/dist/components/Workflow/createNode.d.ts +27 -0
  251. package/dist/components/Workflow/createNode.d.ts.map +1 -0
  252. package/dist/components/Workflow/createNode.js +66 -0
  253. package/dist/components/Workflow/createNode.js.map +1 -0
  254. package/dist/components/Workflow/createNode.mjs +62 -0
  255. package/dist/components/Workflow/createNode.mjs.map +1 -0
  256. package/dist/components/Workflow/graphHistory.d.ts +23 -0
  257. package/dist/components/Workflow/graphHistory.d.ts.map +1 -0
  258. package/dist/components/Workflow/graphHistory.js +73 -0
  259. package/dist/components/Workflow/graphHistory.js.map +1 -0
  260. package/dist/components/Workflow/graphHistory.mjs +70 -0
  261. package/dist/components/Workflow/graphHistory.mjs.map +1 -0
  262. package/dist/components/Workflow/graphObserver.d.ts +13 -0
  263. package/dist/components/Workflow/graphObserver.d.ts.map +1 -0
  264. package/dist/components/Workflow/graphObserver.js +11 -0
  265. package/dist/components/Workflow/graphObserver.js.map +1 -0
  266. package/dist/components/Workflow/graphObserver.mjs +8 -0
  267. package/dist/components/Workflow/graphObserver.mjs.map +1 -0
  268. package/dist/components/Workflow/graphReducer.d.ts +75 -0
  269. package/dist/components/Workflow/graphReducer.d.ts.map +1 -0
  270. package/dist/components/Workflow/graphReducer.js +122 -0
  271. package/dist/components/Workflow/graphReducer.js.map +1 -0
  272. package/dist/components/Workflow/graphReducer.mjs +119 -0
  273. package/dist/components/Workflow/graphReducer.mjs.map +1 -0
  274. package/dist/components/Workflow/index.d.ts +22 -0
  275. package/dist/components/Workflow/index.d.ts.map +1 -0
  276. package/dist/components/Workflow/layout/autoLayout.d.ts +49 -0
  277. package/dist/components/Workflow/layout/autoLayout.d.ts.map +1 -0
  278. package/dist/components/Workflow/layout/autoLayout.js +149 -0
  279. package/dist/components/Workflow/layout/autoLayout.js.map +1 -0
  280. package/dist/components/Workflow/layout/autoLayout.mjs +146 -0
  281. package/dist/components/Workflow/layout/autoLayout.mjs.map +1 -0
  282. package/dist/components/Workflow/stories/toyNodeTypes.d.ts +40 -0
  283. package/dist/components/Workflow/stories/toyNodeTypes.d.ts.map +1 -0
  284. package/dist/components/Workflow/useWorkflowIssueMessage.d.ts +15 -0
  285. package/dist/components/Workflow/useWorkflowIssueMessage.d.ts.map +1 -0
  286. package/dist/components/Workflow/useWorkflowIssueMessage.js +45 -0
  287. package/dist/components/Workflow/useWorkflowIssueMessage.js.map +1 -0
  288. package/dist/components/Workflow/useWorkflowIssueMessage.mjs +43 -0
  289. package/dist/components/Workflow/useWorkflowIssueMessage.mjs.map +1 -0
  290. package/dist/components/Workflow/useWorkflowKeyboard.d.ts +10 -0
  291. package/dist/components/Workflow/useWorkflowKeyboard.d.ts.map +1 -0
  292. package/dist/components/Workflow/useWorkflowKeyboard.js +116 -0
  293. package/dist/components/Workflow/useWorkflowKeyboard.js.map +1 -0
  294. package/dist/components/Workflow/useWorkflowKeyboard.mjs +114 -0
  295. package/dist/components/Workflow/useWorkflowKeyboard.mjs.map +1 -0
  296. package/dist/icons.js +17 -0
  297. package/dist/icons.js.map +1 -1
  298. package/dist/icons.mjs +1 -1
  299. package/dist/index.d.ts +1 -0
  300. package/dist/index.d.ts.map +1 -1
  301. package/dist/index.js +38 -0
  302. package/dist/index.js.map +1 -1
  303. package/dist/index.mjs +14 -0
  304. package/dist/index.mjs.map +1 -1
  305. package/dist/test-support/setup.d.ts +5 -0
  306. package/dist/test-support/setup.d.ts.map +1 -0
  307. package/dist/theme/colors.d.ts +196 -44
  308. package/dist/theme/colors.d.ts.map +1 -1
  309. package/dist/theme/colors.js +184 -22
  310. package/dist/theme/colors.js.map +1 -1
  311. package/dist/theme/colors.mjs +184 -22
  312. package/dist/theme/colors.mjs.map +1 -1
  313. package/dist/theme/global.d.ts.map +1 -1
  314. package/dist/theme/global.js +30 -2
  315. package/dist/theme/global.js.map +1 -1
  316. package/dist/theme/global.mjs +30 -2
  317. package/dist/theme/global.mjs.map +1 -1
  318. package/package.json +10 -2
  319. package/src/components/Icon/_constants/iconList.ts +35 -0
  320. package/src/components/Icon/index.tsx +20 -0
  321. package/src/components/SegmentedControl/SegmentedControl.tsx +21 -4
  322. package/src/components/Workflow/README.md +362 -0
  323. package/src/components/Workflow/Workflow.translations.json +112 -0
  324. package/src/components/Workflow/Workflow.tsx +189 -0
  325. package/src/components/Workflow/Workflow.types.ts +496 -0
  326. package/src/components/Workflow/WorkflowContext/WorkflowContext.tsx +215 -0
  327. package/src/components/Workflow/WorkflowContext/WorkflowContext.types.ts +122 -0
  328. package/src/components/Workflow/WorkflowContext/index.ts +10 -0
  329. package/src/components/Workflow/WorkflowContext/workflowSelection.test.tsx +93 -0
  330. package/src/components/Workflow/canvas/Canvas/BranchLabelBadge.tsx +69 -0
  331. package/src/components/Workflow/canvas/Canvas/Canvas.styles.ts +91 -0
  332. package/src/components/Workflow/canvas/Canvas/Canvas.tsx +773 -0
  333. package/src/components/Workflow/canvas/Canvas/CanvasControls.tsx +178 -0
  334. package/src/components/Workflow/canvas/Canvas/LabeledEdge.tsx +198 -0
  335. package/src/components/Workflow/canvas/Canvas/edgeLabelVariant.test.ts +26 -0
  336. package/src/components/Workflow/canvas/Canvas/edgeLabelVariant.ts +23 -0
  337. package/src/components/Workflow/canvas/Canvas/index.ts +1 -0
  338. package/src/components/Workflow/canvas/CollapsibleSection/CollapsibleSection.tsx +96 -0
  339. package/src/components/Workflow/canvas/CollapsibleSection/index.ts +4 -0
  340. package/src/components/Workflow/canvas/DrawerShell/DrawerHeader.tsx +104 -0
  341. package/src/components/Workflow/canvas/DrawerShell/DrawerIssues.tsx +115 -0
  342. package/src/components/Workflow/canvas/DrawerShell/DrawerShell.tsx +408 -0
  343. package/src/components/Workflow/canvas/DrawerShell/index.ts +2 -0
  344. package/src/components/Workflow/canvas/EdgeInspector/BuiltInEdgeInspector.tsx +135 -0
  345. package/src/components/Workflow/canvas/EdgeInspector/endpointTitle.ts +38 -0
  346. package/src/components/Workflow/canvas/EdgeInspector/index.ts +2 -0
  347. package/src/components/Workflow/canvas/FieldWrapper/FieldWrapper.tsx +118 -0
  348. package/src/components/Workflow/canvas/FieldWrapper/index.ts +6 -0
  349. package/src/components/Workflow/canvas/FloatingCard/FloatingCard.tsx +37 -0
  350. package/src/components/Workflow/canvas/FloatingCard/index.ts +1 -0
  351. package/src/components/Workflow/canvas/GenericNode/GenericNode.tsx +114 -0
  352. package/src/components/Workflow/canvas/GenericNode/GenericNode.types.ts +10 -0
  353. package/src/components/Workflow/canvas/GenericNode/index.ts +5 -0
  354. package/src/components/Workflow/canvas/GraphErrorBanner/GraphErrorBanner.tsx +284 -0
  355. package/src/components/Workflow/canvas/GraphErrorBanner/index.ts +1 -0
  356. package/src/components/Workflow/canvas/IconTile/IconTile.styles.ts +40 -0
  357. package/src/components/Workflow/canvas/IconTile/IconTile.tsx +36 -0
  358. package/src/components/Workflow/canvas/IconTile/IconTile.types.ts +13 -0
  359. package/src/components/Workflow/canvas/IconTile/index.ts +7 -0
  360. package/src/components/Workflow/canvas/IssueList/IssueList.tsx +84 -0
  361. package/src/components/Workflow/canvas/IssueList/index.ts +1 -0
  362. package/src/components/Workflow/canvas/NodePalette/NodePalette.styles.ts +7 -0
  363. package/src/components/Workflow/canvas/NodePalette/NodePalette.tsx +180 -0
  364. package/src/components/Workflow/canvas/NodePalette/NodePaletteToggle.tsx +39 -0
  365. package/src/components/Workflow/canvas/NodePalette/index.ts +3 -0
  366. package/src/components/Workflow/canvas/NodeShell/NodeShell.styles.ts +84 -0
  367. package/src/components/Workflow/canvas/NodeShell/NodeShell.tsx +321 -0
  368. package/src/components/Workflow/canvas/NodeShell/NodeShell.types.ts +45 -0
  369. package/src/components/Workflow/canvas/NodeShell/index.ts +8 -0
  370. package/src/components/Workflow/canvas/SeverityDot/SeverityDot.tsx +33 -0
  371. package/src/components/Workflow/canvas/SeverityDot/index.ts +1 -0
  372. package/src/components/Workflow/canvas/issueSeverity.ts +48 -0
  373. package/src/components/Workflow/canvas/useFieldFocusRequest.ts +54 -0
  374. package/src/components/Workflow/canvas/workflowLabelProps.ts +11 -0
  375. package/src/components/Workflow/connectionRules.test.ts +326 -0
  376. package/src/components/Workflow/connectionRules.ts +190 -0
  377. package/src/components/Workflow/createNode.test.ts +61 -0
  378. package/src/components/Workflow/createNode.ts +67 -0
  379. package/src/components/Workflow/graphHistory.test.ts +178 -0
  380. package/src/components/Workflow/graphHistory.ts +91 -0
  381. package/src/components/Workflow/graphObserver.ts +21 -0
  382. package/src/components/Workflow/graphReducer.test.ts +314 -0
  383. package/src/components/Workflow/graphReducer.ts +196 -0
  384. package/src/components/Workflow/index.ts +74 -0
  385. package/src/components/Workflow/layout/autoLayout.test.ts +170 -0
  386. package/src/components/Workflow/layout/autoLayout.ts +200 -0
  387. package/src/components/Workflow/stories/Workflow.stories.tsx +111 -0
  388. package/src/components/Workflow/stories/toyNodeTypes.tsx +146 -0
  389. package/src/components/Workflow/useWorkflowIssueMessage.test.ts +101 -0
  390. package/src/components/Workflow/useWorkflowIssueMessage.ts +49 -0
  391. package/src/components/Workflow/useWorkflowKeyboard.ts +126 -0
  392. package/src/index.ts +1 -0
  393. package/src/test-support/setup.ts +11 -0
  394. package/src/theme/SemanticTokens.mdx +61 -7
  395. package/src/theme/colors.ts +216 -26
  396. package/src/theme/global.ts +31 -2
@@ -0,0 +1,773 @@
1
+ 'use client';
2
+
3
+ import {
4
+ DragEvent,
5
+ type ReactNode,
6
+ useCallback,
7
+ useEffect,
8
+ useRef,
9
+ useState,
10
+ } from 'react';
11
+ import { Box } from '@chakra-ui/react';
12
+ import type { OnConnectEnd, OnConnectStart, OnReconnect } from '@xyflow/react';
13
+ import {
14
+ applyEdgeChanges,
15
+ applyNodeChanges,
16
+ Background,
17
+ Connection,
18
+ ConnectionLineType,
19
+ Edge,
20
+ EdgeChange,
21
+ IsValidConnection,
22
+ MiniMap,
23
+ NodeChange,
24
+ NodeTypes,
25
+ ReactFlow,
26
+ ReactFlowProvider,
27
+ useReactFlow,
28
+ } from '@xyflow/react';
29
+
30
+ import '@xyflow/react/dist/style.css';
31
+
32
+ import {
33
+ existingEdgeFromHandle,
34
+ isValidConnection as isValidWorkflowConnection,
35
+ soleEdgeToHandle,
36
+ } from '../../connectionRules';
37
+ import { genId } from '../../createNode';
38
+ import {
39
+ autoLayout,
40
+ estimateLabelOverhang,
41
+ type NodeDimensions,
42
+ } from '../../layout/autoLayout';
43
+ import { useWorkflowKeyboard } from '../../useWorkflowKeyboard';
44
+ import type {
45
+ Graph,
46
+ GraphEdge,
47
+ GraphNode,
48
+ Position,
49
+ } from '../../Workflow.types';
50
+ import { resolveDefaultConfig } from '../../Workflow.types';
51
+ import { useWorkflow, useWorkflowTranslate } from '../../WorkflowContext';
52
+ import type { WorkflowReactFlowNode } from '../GenericNode';
53
+ import { GenericNode } from '../GenericNode';
54
+ import { GraphErrorBanner } from '../GraphErrorBanner';
55
+ import { DRAG_MIME, NodePalette, NodePaletteToggle } from '../NodePalette';
56
+ import { canvasSelectionCss, defaultEdgeOptions } from './Canvas.styles';
57
+ import { CanvasControls } from './CanvasControls';
58
+ import { LabeledEdge } from './LabeledEdge';
59
+
60
+ // React Flow's `nodeTypes` prop — distinct from our domain "node type registry".
61
+ // We use a unique key here ('workflow') rather than 'default' to avoid React
62
+ // Flow's built-in default-node CSS (.react-flow__node-default: padding +
63
+ // border + 150px width) rendering as a black box behind our NodeShell.
64
+ const rfNodeTypes: NodeTypes = { workflow: GenericNode };
65
+
66
+ // React Flow edge type registry — `labeled` swaps the SVG `labelStyle`
67
+ // path for a Chakra `Subtext` so the label inherits semantic typography.
68
+ const rfEdgeTypes = { labeled: LabeledEdge };
69
+
70
+ // Cap zoom so a tiny graph doesn't balloon, and pad so nodes don't touch the
71
+ // edges. Shared between the initial `fitView` prop, the read-only re-fit, and
72
+ // the post-auto-arrange re-fit so every framing settles the same way.
73
+ const FIT_VIEW_OPTIONS = { maxZoom: 1.2, padding: 0.15 };
74
+
75
+ // User-triggered re-fits (the fit-view button, the post-arrange reframe) glide
76
+ // instead of teleporting, matching the error-banner jump's duration. The
77
+ // initial mount and the read-only layout-settling re-fits stay instant — there
78
+ // the viewport has no meaningful prior position to animate from.
79
+ const ANIMATED_FIT_VIEW_OPTIONS = { ...FIT_VIEW_OPTIONS, duration: 400 };
80
+
81
+ function graphToReactFlow(
82
+ graph: Graph,
83
+ isPinned: (kind: string) => boolean,
84
+ readOnly: boolean,
85
+ selection: { nodeId: string | null; edgeId: string | null }
86
+ ): { nodes: WorkflowReactFlowNode[]; edges: Edge[] } {
87
+ return {
88
+ nodes: graph.nodes.map<WorkflowReactFlowNode>((n) => ({
89
+ id: n.id,
90
+ type: 'workflow',
91
+ position: n.position,
92
+ data: { nodeId: n.id },
93
+ selected: n.id === selection.nodeId,
94
+ deletable: !readOnly && !isPinned(n.kind),
95
+ })),
96
+ edges: graph.edges.map((e) => ({
97
+ id: e.id,
98
+ source: e.source,
99
+ target: e.target,
100
+ sourceHandle: e.sourceHandle,
101
+ targetHandle: e.targetHandle,
102
+ label: e.label,
103
+ animated: false,
104
+ selected: e.id === selection.edgeId,
105
+ deletable: !readOnly,
106
+ })),
107
+ };
108
+ }
109
+
110
+ function CanvasInner({
111
+ showPalette,
112
+ onNodeClick: onNodeClickHost,
113
+ onEdgeClick: onEdgeClickHost,
114
+ children,
115
+ }: {
116
+ showPalette: boolean;
117
+ onNodeClick?: (node: GraphNode) => void;
118
+ onEdgeClick?: (edge: GraphEdge) => void;
119
+ children?: ReactNode;
120
+ }) {
121
+ const {
122
+ graph,
123
+ dispatch,
124
+ editor: { selectedNodeId, selectedEdgeId, runStates, drawerTarget },
125
+ setSelectedNodeId,
126
+ setSelectedEdgeId,
127
+ setDrawerTarget,
128
+ revealInspector,
129
+ getNodeType,
130
+ onArrange,
131
+ readOnly,
132
+ issues,
133
+ hostBridge,
134
+ } = useWorkflow();
135
+ const wrapperRef = useRef<HTMLDivElement | null>(null);
136
+ // When a drag starts from an already-connected entry (input) handle, we grab
137
+ // that edge and re-route its source instead of laying down a duplicate. The
138
+ // ref carries the grabbed edge id from `onConnectStart` to `onConnect`.
139
+ const grabbedEntryEdgeRef = useRef<string | null>(null);
140
+ const { screenToFlowPosition, getNodes, fitView } = useReactFlow();
141
+
142
+ // The palette is open by default; the floating `+` toggle (top-left) reopens
143
+ // it after the author collapses it via its header.
144
+ const [isPaletteOpen, setIsPaletteOpen] = useState(true);
145
+
146
+ const translate = useWorkflowTranslate();
147
+ // Tear off only the string lookup so `localizeDefaults` doesn't depend
148
+ // on the React-fragment interpolation path.
149
+ const t = useCallback(
150
+ (key: string, params?: Record<string, string>) =>
151
+ translate(key, params) as string,
152
+ [translate]
153
+ );
154
+
155
+ useWorkflowKeyboard();
156
+
157
+ const isPinned = useCallback(
158
+ (kind: string) => Boolean(getNodeType(kind)?.placement?.pinned),
159
+ [getNodeType]
160
+ );
161
+
162
+ // Local mirror of nodes/edges so React Flow can hold transient state —
163
+ // drag positions and selection — without our graph -> elements derivation
164
+ // snapping them back. We reseed when the graph reference changes.
165
+ const [displayNodes, setDisplayNodes] = useState<WorkflowReactFlowNode[]>(
166
+ () =>
167
+ graphToReactFlow(graph, isPinned, readOnly, {
168
+ nodeId: selectedNodeId,
169
+ edgeId: selectedEdgeId,
170
+ }).nodes
171
+ );
172
+ const [displayEdges, setDisplayEdges] = useState<Edge[]>(
173
+ () =>
174
+ graphToReactFlow(graph, isPinned, readOnly, {
175
+ nodeId: selectedNodeId,
176
+ edgeId: selectedEdgeId,
177
+ }).edges
178
+ );
179
+ const lastSyncedGraphRef = useRef(graph);
180
+ useEffect(() => {
181
+ if (graph === lastSyncedGraphRef.current) return;
182
+ lastSyncedGraphRef.current = graph;
183
+ const next = graphToReactFlow(graph, isPinned, readOnly, {
184
+ nodeId: selectedNodeId,
185
+ edgeId: selectedEdgeId,
186
+ });
187
+ setDisplayNodes(next.nodes);
188
+ setDisplayEdges(next.edges);
189
+ }, [graph, isPinned, readOnly, selectedNodeId, selectedEdgeId]);
190
+
191
+ // Mirror context selection (driven by node/edge clicks AND the edges sidebar)
192
+ // into React Flow's display state so a selection made outside the canvas —
193
+ // e.g. clicking an edge in the sidebar — highlights on the canvas too. Each
194
+ // updater is a no-op (returns `prev`) when nothing needs to change, so this
195
+ // can't loop with the `select` changes that flow back through onNodesChange.
196
+ useEffect(() => {
197
+ setDisplayNodes((prev) =>
198
+ prev.some((n) => Boolean(n.selected) !== (n.id === selectedNodeId))
199
+ ? prev.map((n) =>
200
+ Boolean(n.selected) === (n.id === selectedNodeId)
201
+ ? n
202
+ : { ...n, selected: n.id === selectedNodeId }
203
+ )
204
+ : prev
205
+ );
206
+ }, [selectedNodeId]);
207
+
208
+ useEffect(() => {
209
+ setDisplayEdges((prev) =>
210
+ prev.some((e) => Boolean(e.selected) !== (e.id === selectedEdgeId))
211
+ ? prev.map((e) =>
212
+ Boolean(e.selected) === (e.id === selectedEdgeId)
213
+ ? e
214
+ : { ...e, selected: e.id === selectedEdgeId }
215
+ )
216
+ : prev
217
+ );
218
+ }, [selectedEdgeId]);
219
+
220
+ // Animate the edges along the active path during a test run: an edge flows
221
+ // once its source node has produced output (`done`) and its target is engaged
222
+ // (`running`/`done`). Mirrors run state into the local edge state — which is
223
+ // only reseeded on graph changes — without disturbing positions or selection.
224
+ useEffect(() => {
225
+ setDisplayEdges((prev) => {
226
+ let changed = false;
227
+ const next = prev.map((e) => {
228
+ const active =
229
+ runStates[e.source] === 'done' &&
230
+ (runStates[e.target] === 'running' || runStates[e.target] === 'done');
231
+ if (Boolean(e.animated) === active) return e;
232
+ changed = true;
233
+ return { ...e, animated: active };
234
+ });
235
+ return changed ? next : prev;
236
+ });
237
+ }, [runStates]);
238
+
239
+ // React Flow's one-shot `fitView` prop only fits on first mount. In the
240
+ // read-only preview the container settles its size late (panel layout) and
241
+ // the graph can change underneath us — either one leaves the graph
242
+ // off-centre. Re-fit (deferred a frame so the new size is measured) on graph
243
+ // change and on container resize. Skipped while editing: it would fight the
244
+ // author's own panning and zooming.
245
+ useEffect(() => {
246
+ if (!readOnly) return;
247
+ const raf = requestAnimationFrame(() => fitView(FIT_VIEW_OPTIONS));
248
+ return () => cancelAnimationFrame(raf);
249
+ }, [readOnly, fitView, displayNodes]);
250
+
251
+ useEffect(() => {
252
+ if (!readOnly) return;
253
+ const el = wrapperRef.current;
254
+ if (!el) return;
255
+ let raf = 0;
256
+ const observer = new ResizeObserver(() => {
257
+ cancelAnimationFrame(raf);
258
+ raf = requestAnimationFrame(() => fitView(FIT_VIEW_OPTIONS));
259
+ });
260
+ observer.observe(el);
261
+ return () => {
262
+ cancelAnimationFrame(raf);
263
+ observer.disconnect();
264
+ };
265
+ }, [readOnly, fitView]);
266
+
267
+ const onNodesChange = useCallback(
268
+ (changes: NodeChange<WorkflowReactFlowNode>[]) => {
269
+ // Keep React Flow's transient state (positions during drag, selection) local.
270
+ setDisplayNodes((prev) => applyNodeChanges(changes, prev));
271
+
272
+ for (const change of changes) {
273
+ // Only persist position on drag end — avoids 60fps validator churn.
274
+ if (change.type === 'position' && change.position && !change.dragging) {
275
+ dispatch({
276
+ type: 'updateNodePosition',
277
+ id: change.id,
278
+ position: change.position,
279
+ });
280
+ }
281
+ if (change.type === 'remove') {
282
+ // Pinned nodes are not deletable in React Flow, but defense-in-depth:
283
+ // if a remove change for a pinned node ever leaks through, skip it
284
+ // AND skip the edge-removes for its endpoints to avoid orphaning.
285
+ const node = graph.nodes.find((n) => n.id === change.id);
286
+ const def = node ? getNodeType(node.kind) : undefined;
287
+ if (def?.placement?.pinned) continue;
288
+ dispatch({ type: 'deleteNode', id: change.id });
289
+ }
290
+ if (change.type === 'select') {
291
+ if (change.selected) {
292
+ // Selecting a node clears any edge selection (single active target).
293
+ setSelectedNodeId(change.id);
294
+ setSelectedEdgeId(null);
295
+ // Drag-select is the one selection path that doesn't go through a
296
+ // click handler: keep an already-open inspector following the
297
+ // selection (same invariant clicks maintain) instead of leaving it
298
+ // on a now-deselected element. A closed drawer stays closed.
299
+ if (
300
+ drawerTarget &&
301
+ (drawerTarget.type !== 'node' || drawerTarget.id !== change.id)
302
+ ) {
303
+ setDrawerTarget({ type: 'node', id: change.id });
304
+ }
305
+ } else {
306
+ setSelectedNodeId(null);
307
+ }
308
+ }
309
+ }
310
+ },
311
+ [
312
+ graph.nodes,
313
+ dispatch,
314
+ getNodeType,
315
+ setSelectedNodeId,
316
+ setSelectedEdgeId,
317
+ drawerTarget,
318
+ setDrawerTarget,
319
+ ]
320
+ );
321
+
322
+ const onEdgesChange = useCallback(
323
+ (changes: EdgeChange[]) => {
324
+ // Apply every change locally — crucially `select`, so an edge can enter
325
+ // the selected state that the Delete key binding acts on. Persist removals.
326
+ setDisplayEdges((prev) => applyEdgeChanges(changes, prev));
327
+ for (const change of changes) {
328
+ if (change.type === 'remove') {
329
+ dispatch({ type: 'deleteEdge', id: change.id });
330
+ }
331
+ if (change.type === 'select') {
332
+ if (change.selected) {
333
+ // Selecting an edge clears node selection + opens it in the drawer.
334
+ setSelectedEdgeId(change.id);
335
+ setSelectedNodeId(null);
336
+ setDrawerTarget({ type: 'edge', id: change.id });
337
+ } else {
338
+ setSelectedEdgeId(null);
339
+ }
340
+ }
341
+ }
342
+ },
343
+ [dispatch, setSelectedEdgeId, setSelectedNodeId, setDrawerTarget]
344
+ );
345
+
346
+ const isValidConnection = useCallback<IsValidConnection<Edge>>(
347
+ // React Flow may hand either a `Connection` or an existing `Edge`; both
348
+ // expose the same source/target/handle fields the validator reads.
349
+ (connection) =>
350
+ isValidWorkflowConnection(
351
+ {
352
+ source: connection.source,
353
+ target: connection.target,
354
+ sourceHandle: connection.sourceHandle ?? null,
355
+ targetHandle: connection.targetHandle ?? null,
356
+ },
357
+ graph,
358
+ getNodeType
359
+ ),
360
+ [graph, getNodeType]
361
+ );
362
+
363
+ // Dragging from a handle that already has an edge should move that edge, not
364
+ // stack a new one. React Flow grabs the *edge endpoint* this way already, but
365
+ // a drag from the handle port itself starts a fresh connection. For entries
366
+ // (which permit fan-in) we bridge that gap: if the drag begins on an input
367
+ // handle that holds exactly one edge, remember it so `onConnect` re-routes its
368
+ // source rather than adding a parallel edge. With zero or 2+ edges there's no
369
+ // single edge to grab, so we leave it to the normal add path.
370
+ const onConnectStart = useCallback<OnConnectStart>(
371
+ (_event, { nodeId, handleId, handleType }) => {
372
+ grabbedEntryEdgeRef.current =
373
+ handleType === 'target' && nodeId
374
+ ? (soleEdgeToHandle(graph, getNodeType, nodeId, handleId ?? undefined)
375
+ ?.id ?? null)
376
+ : null;
377
+ },
378
+ [graph, getNodeType]
379
+ );
380
+
381
+ const onConnectEnd = useCallback<OnConnectEnd>(() => {
382
+ grabbedEntryEdgeRef.current = null;
383
+ }, []);
384
+
385
+ const onConnect = useCallback(
386
+ (connection: Connection) => {
387
+ if (!connection.source || !connection.target) return;
388
+ // Defense-in-depth: enforce node-type rules even though React Flow also
389
+ // gates drags through `isValidConnection`.
390
+ if (!isValidWorkflowConnection(connection, graph, getNodeType)) return;
391
+ const sourceHandle = connection.sourceHandle ?? undefined;
392
+ const targetHandle = connection.targetHandle ?? undefined;
393
+ // Drag started on an occupied entry: re-route that edge's source endpoint
394
+ // to the newly chosen source instead of adding a parallel edge. Apply the
395
+ // same single-edge-per-exit guard as a reconnect — if the new source exit
396
+ // already holds a different edge, bail so React Flow snaps back.
397
+ const grabbedId = grabbedEntryEdgeRef.current;
398
+ if (grabbedId) {
399
+ const occupant = existingEdgeFromHandle(
400
+ graph,
401
+ getNodeType,
402
+ connection.source,
403
+ sourceHandle
404
+ );
405
+ if (!occupant || occupant.id === grabbedId) {
406
+ dispatch({
407
+ type: 'reconnectEdge',
408
+ id: grabbedId,
409
+ source: connection.source,
410
+ target: connection.target,
411
+ sourceHandle,
412
+ targetHandle,
413
+ });
414
+ }
415
+ return;
416
+ }
417
+ // An exit point holds at most one edge. Dragging a fresh connection from
418
+ // an exit that already has one MOVES that edge to the new target (keeping
419
+ // its id + label) rather than creating a second edge from the same point.
420
+ const existing = existingEdgeFromHandle(
421
+ graph,
422
+ getNodeType,
423
+ connection.source,
424
+ sourceHandle
425
+ );
426
+ if (existing) {
427
+ dispatch({
428
+ type: 'reconnectEdge',
429
+ id: existing.id,
430
+ source: connection.source,
431
+ target: connection.target,
432
+ sourceHandle,
433
+ targetHandle,
434
+ });
435
+ return;
436
+ }
437
+ dispatch({
438
+ type: 'addEdge',
439
+ edge: {
440
+ id: genId('e'),
441
+ source: connection.source,
442
+ target: connection.target,
443
+ sourceHandle,
444
+ targetHandle,
445
+ },
446
+ });
447
+ },
448
+ [dispatch, graph, getNodeType]
449
+ );
450
+
451
+ // React Flow reconnect lifecycle. `onReconnect` only mutates the edge on a
452
+ // valid commit; an invalid or empty drop is a no-op, so React Flow snaps the
453
+ // dragged endpoint back to its original handle and the edge stays intact.
454
+ // There's no success ref to track because we never tear down and recreate the
455
+ // edge — an unmutated edge needs nothing restored.
456
+ const onReconnect = useCallback<OnReconnect<Edge>>(
457
+ (oldEdge, connection) => {
458
+ if (!connection.source || !connection.target) return;
459
+ // Validate the new endpoints with the same rules as manual connect; an
460
+ // invalid drop is ignored so the original edge snaps back. `connection`
461
+ // here is React Flow's `Connection`, so narrow to the validator's shape.
462
+ const proposed = {
463
+ source: connection.source,
464
+ target: connection.target,
465
+ sourceHandle: connection.sourceHandle ?? null,
466
+ targetHandle: connection.targetHandle ?? null,
467
+ };
468
+ if (!isValidWorkflowConnection(proposed, graph, getNodeType)) return;
469
+ // Keep the single-edge-per-exit invariant (same as `onConnect`): if the
470
+ // dragged source endpoint lands on an exit that already holds a different
471
+ // edge, reject so React Flow snaps back rather than stacking two edges on
472
+ // one handle. The edge being moved is excluded (a target-endpoint drag
473
+ // keeps the same source handle and would otherwise match itself).
474
+ const occupant = existingEdgeFromHandle(
475
+ graph,
476
+ getNodeType,
477
+ connection.source,
478
+ connection.sourceHandle ?? undefined
479
+ );
480
+ if (occupant && occupant.id !== oldEdge.id) return;
481
+ dispatch({
482
+ type: 'reconnectEdge',
483
+ id: oldEdge.id,
484
+ source: connection.source,
485
+ target: connection.target,
486
+ sourceHandle: connection.sourceHandle ?? undefined,
487
+ targetHandle: connection.targetHandle ?? undefined,
488
+ });
489
+ },
490
+ [dispatch, graph, getNodeType]
491
+ );
492
+
493
+ // Single click selects the node AND opens its inspector drawer (no
494
+ // double-click needed). React Flow's own `select` change still fires and
495
+ // syncs `selectedNodeId`, but we set it here too so selection + drawer open
496
+ // atomically on the very first click.
497
+ const onNodeClick = useCallback(
498
+ (_: unknown, node: WorkflowReactFlowNode) => {
499
+ setSelectedNodeId(node.id);
500
+ setSelectedEdgeId(null);
501
+ // revealInspector sets the drawer target (read by a mounted
502
+ // <NodeInspector>, and surfaced to the host via onSelectionChange).
503
+ revealInspector({ type: 'node', id: node.id });
504
+ // Convenience click hook for hosts driving UI outside the canvas.
505
+ const graphNode = graph.nodes.find((n) => n.id === node.id);
506
+ if (graphNode) onNodeClickHost?.(graphNode);
507
+ },
508
+ [
509
+ setSelectedNodeId,
510
+ setSelectedEdgeId,
511
+ revealInspector,
512
+ graph,
513
+ onNodeClickHost,
514
+ ]
515
+ );
516
+
517
+ // Single click selects the edge AND targets the inspector at it — the same
518
+ // surface nodes use — replacing the old left-sidebar edge list.
519
+ const onEdgeClick = useCallback(
520
+ (_: unknown, edge: Edge) => {
521
+ setSelectedEdgeId(edge.id);
522
+ setSelectedNodeId(null);
523
+ revealInspector({ type: 'edge', id: edge.id });
524
+ const graphEdge = graph.edges.find((e) => e.id === edge.id);
525
+ if (graphEdge) onEdgeClickHost?.(graphEdge);
526
+ },
527
+ [
528
+ setSelectedEdgeId,
529
+ setSelectedNodeId,
530
+ revealInspector,
531
+ graph,
532
+ onEdgeClickHost,
533
+ ]
534
+ );
535
+
536
+ const onPaneClick = useCallback(() => {
537
+ setSelectedNodeId(null);
538
+ setSelectedEdgeId(null);
539
+ setDrawerTarget(null);
540
+ }, [setSelectedNodeId, setSelectedEdgeId, setDrawerTarget]);
541
+
542
+ // One-click tidy: lay the graph out left-to-right and dispatch the new
543
+ // positions as a single (undoable) reposition. We feed dagre the REAL
544
+ // rendered node sizes from React Flow so variable-height cards pack tightly,
545
+ // falling back to card defaults for any node not yet measured — plus the
546
+ // trailing room a node's exit labels (e.g. Classify categories) need, since
547
+ // those overflow the measured card and would otherwise sit under the next
548
+ // rank's edges.
549
+ const onAutoArrange = useCallback(() => {
550
+ const nodesById = new Map(graph.nodes.map((n) => [n.id, n]));
551
+ const dimensions: Record<string, NodeDimensions> = {};
552
+ for (const n of getNodes()) {
553
+ const { width, height } = n.measured ?? {};
554
+ if (!width || !height) continue;
555
+ const node = nodesById.get(n.id);
556
+ const def = node ? getNodeType(node.kind) : undefined;
557
+ const outputs = node && def ? def.handles(node.config).outputs : [];
558
+ const labels = outputs
559
+ .map((o) => o.label)
560
+ .filter((label): label is string => Boolean(label));
561
+ dimensions[n.id] = {
562
+ width,
563
+ height,
564
+ trailing: estimateLabelOverhang(labels),
565
+ };
566
+ }
567
+ // The order each node paints its exits, so the layout can lay a fan-out's
568
+ // children out in exit order rather than wiring order (see `outputOrder`).
569
+ const outputOrder: Record<string, string[]> = {};
570
+ for (const node of graph.nodes) {
571
+ const def = getNodeType(node.kind);
572
+ if (!def) continue;
573
+ outputOrder[node.id] = def.handles(node.config).outputs.map((o) => o.id);
574
+ }
575
+ const arranged = autoLayout(graph, dimensions, { outputOrder });
576
+ const positions: Record<string, Position> = {};
577
+ let moved = false;
578
+ for (const n of arranged.nodes) {
579
+ positions[n.id] = n.position;
580
+ const current = nodesById.get(n.id)?.position;
581
+ if (current?.x !== n.position.x || current?.y !== n.position.y) {
582
+ moved = true;
583
+ }
584
+ }
585
+ // Already tidy — skip the dispatch AND the forced save so re-clicking a
586
+ // settled layout doesn't issue a redundant PUT or flip the draft to dirty.
587
+ if (!moved) return;
588
+ dispatch({ type: 'arrangeNodes', positions });
589
+ // A pure reposition wouldn't autosave on its own; let the host persist the
590
+ // tidied layout so it survives a reload (see WorkflowProps.onArrange).
591
+ onArrange?.(arranged);
592
+ // Reframe once the moved nodes have painted.
593
+ window.requestAnimationFrame(() => fitView(ANIMATED_FIT_VIEW_OPTIONS));
594
+ }, [getNodes, graph, getNodeType, dispatch, onArrange, fitView]);
595
+
596
+ const onDragOver = useCallback((e: DragEvent) => {
597
+ if (!e.dataTransfer.types.includes(DRAG_MIME)) return;
598
+ e.preventDefault();
599
+ e.dataTransfer.dropEffect = 'move';
600
+ }, []);
601
+
602
+ const onDrop = useCallback(
603
+ (e: DragEvent) => {
604
+ e.preventDefault();
605
+ const kind = e.dataTransfer.getData(DRAG_MIME);
606
+ if (!kind) return;
607
+ const def = getNodeType(kind);
608
+ if (!def) return;
609
+ const position = screenToFlowPosition({ x: e.clientX, y: e.clientY });
610
+ const base = resolveDefaultConfig(def) as Record<string, unknown>;
611
+ const overlay = def.localizeDefaults?.(t) as
612
+ | Record<string, unknown>
613
+ | undefined;
614
+ // Host-data overlay (e.g. a starting LLM picked from the tenant's live
615
+ // model list) — applied last so it wins over any static placeholder in
616
+ // `defaultConfig`. Keyed on the opaque `hostBridge`; the node type narrows
617
+ // it. Absent on a generic host, leaving the static defaults in place.
618
+ const bridged = def.hostDefaults?.(hostBridge) as
619
+ | Record<string, unknown>
620
+ | undefined;
621
+ const node = {
622
+ id: genId(kind),
623
+ kind,
624
+ position,
625
+ config: { ...base, ...overlay, ...bridged },
626
+ };
627
+
628
+ // Dropped nodes land unconnected — authors wire edges explicitly by
629
+ // dragging from an exit point.
630
+ dispatch({ type: 'addNode', node });
631
+ },
632
+ [dispatch, getNodeType, screenToFlowPosition, t, hostBridge]
633
+ );
634
+
635
+ // Does the canvas top-left corner actually hold overlay chrome the zoom
636
+ // controls should tuck under? The palette toggle docks there when the palette
637
+ // is collapsed, and the error banner when the (editable) graph has issues. If
638
+ // neither is present the controls sit at the corner rather than floating below
639
+ // an empty gap. Read-only preview shows no chrome, so it's always corner-tight.
640
+ const topLeftChromePresent =
641
+ !readOnly && ((showPalette && !isPaletteOpen) || issues.length > 0);
642
+
643
+ return (
644
+ <Box
645
+ display="flex"
646
+ flex="1"
647
+ minHeight={0}
648
+ height="100%"
649
+ // Tint the whole canvas region — not just the React Flow column — so the
650
+ // floating palette (left) and inspector (right) read as cards over a tinted
651
+ // surface instead of white sidebars. Read-only (version preview) drops to a
652
+ // neutral gray so the mode reads as "not your live workspace".
653
+ // Dark mode uses bg.canvas for both: primary.lightest's _dark is blue.900
654
+ // (#04102A), a saturated navy that overpowers the desaturated dark palette
655
+ // as a full-canvas fill, and slate.100's _dark sits ABOVE bg.surface, which
656
+ // would invert the node cards' lift. bg.canvas keeps the cards lifted in
657
+ // both modes; read-only is still cued by the absent editor chrome.
658
+ bgColor={{
659
+ base: readOnly ? 'slate.100' : 'primary.lightest',
660
+ _dark: 'bg.canvas',
661
+ }}
662
+ >
663
+ {showPalette && isPaletteOpen ? (
664
+ <NodePalette onClose={() => setIsPaletteOpen(false)} />
665
+ ) : null}
666
+ <Box
667
+ flex="1"
668
+ minWidth={0}
669
+ position="relative"
670
+ ref={wrapperRef}
671
+ onDragOver={onDragOver}
672
+ onDrop={onDrop}
673
+ css={canvasSelectionCss}
674
+ >
675
+ <ReactFlow
676
+ nodes={displayNodes}
677
+ edges={displayEdges}
678
+ nodeTypes={rfNodeTypes}
679
+ edgeTypes={rfEdgeTypes}
680
+ defaultEdgeOptions={defaultEdgeOptions}
681
+ onNodesChange={onNodesChange}
682
+ onEdgesChange={onEdgesChange}
683
+ // Match the live connection preview to the committed edge shape:
684
+ // both render as angled (smooth-step) paths so releasing a drag
685
+ // doesn't snap a curved preview into an angled edge.
686
+ connectionLineType={ConnectionLineType.SmoothStep}
687
+ onConnect={onConnect}
688
+ onConnectStart={readOnly ? undefined : onConnectStart}
689
+ onConnectEnd={readOnly ? undefined : onConnectEnd}
690
+ onReconnect={readOnly ? undefined : onReconnect}
691
+ onNodeClick={onNodeClick}
692
+ onEdgeClick={onEdgeClick}
693
+ onPaneClick={onPaneClick}
694
+ isValidConnection={isValidConnection}
695
+ nodesDraggable={!readOnly}
696
+ nodesConnectable={!readOnly}
697
+ elementsSelectable
698
+ // The editor's selection model is a single node/edge (see
699
+ // selectedNodeId / selectedEdgeId): disable React Flow's marquee and
700
+ // modifier-click multi-select, which would visually select a group
701
+ // only for the sync effects above to collapse it to one element.
702
+ selectionKeyCode={null}
703
+ multiSelectionKeyCode={null}
704
+ edgesFocusable={!readOnly}
705
+ // Belt-and-suspenders on top of per-node `deletable: false`: also
706
+ // disable the delete keyboard binding entirely in read-only mode.
707
+ deleteKeyCode={readOnly ? null : ['Backspace', 'Delete']}
708
+ // Pan on scroll/trackpad (Figma-style) in addition to click-and-drag;
709
+ // ⌘/Ctrl+scroll zooms. Enabled in read-only too: scroll is a viewing
710
+ // action, and drag-to-pan is already allowed there — this just makes
711
+ // the scroll gesture pan instead of zoom (whether the canvas captures
712
+ // scroll at all is governed separately by `preventScrolling`).
713
+ panOnScroll
714
+ fitView
715
+ fitViewOptions={FIT_VIEW_OPTIONS}
716
+ proOptions={{ hideAttribution: true }}
717
+ >
718
+ <Background />
719
+ <CanvasControls
720
+ readOnly={readOnly}
721
+ onAutoArrange={onAutoArrange}
722
+ fitViewOptions={ANIMATED_FIT_VIEW_OPTIONS}
723
+ topLeftChromePresent={topLeftChromePresent}
724
+ />
725
+ {/* React Flow's stock minimap is a fixed white panel — resolve its
726
+ colors through theme CSS vars so it follows the color mode
727
+ (light values match the stock look). */}
728
+ <MiniMap
729
+ pannable
730
+ zoomable
731
+ bgColor="var(--chakra-colors-bg-surface)"
732
+ nodeColor="var(--chakra-colors-slate-200)"
733
+ maskColor="color-mix(in srgb, var(--chakra-colors-slate-100) 60%, transparent)"
734
+ />
735
+ </ReactFlow>
736
+ {showPalette && !isPaletteOpen ? (
737
+ <NodePaletteToggle onOpen={() => setIsPaletteOpen(true)} />
738
+ ) : null}
739
+ <GraphErrorBanner
740
+ paletteToggleVisible={showPalette && !isPaletteOpen}
741
+ />
742
+ </Box>
743
+ {/* Canvas-anchored overlay slot (React-Flow-style children): the host
744
+ mounts <NodeInspector> here for the built-in drawer, or its own
745
+ surfaces. A left-docked inspector orders itself before the canvas. */}
746
+ {children}
747
+ </Box>
748
+ );
749
+ }
750
+
751
+ export function Canvas({
752
+ showPalette = true,
753
+ onNodeClick,
754
+ onEdgeClick,
755
+ children,
756
+ }: {
757
+ showPalette?: boolean;
758
+ onNodeClick?: (node: GraphNode) => void;
759
+ onEdgeClick?: (edge: GraphEdge) => void;
760
+ children?: ReactNode;
761
+ }) {
762
+ return (
763
+ <ReactFlowProvider>
764
+ <CanvasInner
765
+ showPalette={showPalette}
766
+ onNodeClick={onNodeClick}
767
+ onEdgeClick={onEdgeClick}
768
+ >
769
+ {children}
770
+ </CanvasInner>
771
+ </ReactFlowProvider>
772
+ );
773
+ }