@octaviaflow/core 3.0.18-beta.3 → 3.0.18-beta.30

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 (178) 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-2ZIOFEIS.js +3001 -0
  6. package/dist/chunk-2ZIOFEIS.js.map +1 -0
  7. package/dist/chunk-3DWB2PUF.js +2991 -0
  8. package/dist/chunk-3DWB2PUF.js.map +1 -0
  9. package/dist/chunk-4ZALUTZS.js +2936 -0
  10. package/dist/chunk-4ZALUTZS.js.map +1 -0
  11. package/dist/chunk-5ARKSRED.js +2951 -0
  12. package/dist/chunk-5ARKSRED.js.map +1 -0
  13. package/dist/chunk-5OSGSJMM.js +2981 -0
  14. package/dist/chunk-5OSGSJMM.js.map +1 -0
  15. package/dist/chunk-5YQQMEF3.js +2981 -0
  16. package/dist/chunk-5YQQMEF3.js.map +1 -0
  17. package/dist/chunk-6QCJK7H7.js +2991 -0
  18. package/dist/chunk-6QCJK7H7.js.map +1 -0
  19. package/dist/chunk-6QDYERZD.js +2944 -0
  20. package/dist/chunk-6QDYERZD.js.map +1 -0
  21. package/dist/chunk-76TP67ED.js +2984 -0
  22. package/dist/chunk-76TP67ED.js.map +1 -0
  23. package/dist/chunk-A6KMO4JV.js +2949 -0
  24. package/dist/chunk-A6KMO4JV.js.map +1 -0
  25. package/dist/chunk-B7FTWSTM.js +2938 -0
  26. package/dist/chunk-B7FTWSTM.js.map +1 -0
  27. package/dist/chunk-BCO6M26F.js +2940 -0
  28. package/dist/chunk-BCO6M26F.js.map +1 -0
  29. package/dist/chunk-C3UD2AZ5.js +2637 -0
  30. package/dist/chunk-C3UD2AZ5.js.map +1 -0
  31. package/dist/chunk-CEUP4NK2.js +2850 -0
  32. package/dist/chunk-CEUP4NK2.js.map +1 -0
  33. package/dist/chunk-DBNSBJO7.js +2993 -0
  34. package/dist/chunk-DBNSBJO7.js.map +1 -0
  35. package/dist/chunk-ECIHUVU7.js +2986 -0
  36. package/dist/chunk-ECIHUVU7.js.map +1 -0
  37. package/dist/chunk-EERNYLFL.js +2860 -0
  38. package/dist/chunk-EERNYLFL.js.map +1 -0
  39. package/dist/chunk-EKFDJX4G.js +2872 -0
  40. package/dist/chunk-EKFDJX4G.js.map +1 -0
  41. package/dist/chunk-GJA3GJUZ.js +2844 -0
  42. package/dist/chunk-GJA3GJUZ.js.map +1 -0
  43. package/dist/chunk-HDOTOZNA.js +2936 -0
  44. package/dist/chunk-HDOTOZNA.js.map +1 -0
  45. package/dist/chunk-IOKUV7FD.js +2658 -0
  46. package/dist/chunk-IOKUV7FD.js.map +1 -0
  47. package/dist/chunk-IUIICQU5.js +2946 -0
  48. package/dist/chunk-IUIICQU5.js.map +1 -0
  49. package/dist/chunk-J2UYZI6D.js +2946 -0
  50. package/dist/chunk-J2UYZI6D.js.map +1 -0
  51. package/dist/chunk-J7YASALS.js +2859 -0
  52. package/dist/chunk-J7YASALS.js.map +1 -0
  53. package/dist/chunk-JIEUYBQT.js +2658 -0
  54. package/dist/chunk-JIEUYBQT.js.map +1 -0
  55. package/dist/chunk-K2H7JLQW.js +2952 -0
  56. package/dist/chunk-K2H7JLQW.js.map +1 -0
  57. package/dist/chunk-KUXYBP66.js +2953 -0
  58. package/dist/chunk-KUXYBP66.js.map +1 -0
  59. package/dist/chunk-KYMYNYFV.js +2656 -0
  60. package/dist/chunk-KYMYNYFV.js.map +1 -0
  61. package/dist/chunk-MMXL343D.js +2974 -0
  62. package/dist/chunk-MMXL343D.js.map +1 -0
  63. package/dist/chunk-MXJL3EPE.js +2986 -0
  64. package/dist/chunk-MXJL3EPE.js.map +1 -0
  65. package/dist/chunk-MYZ25B2R.js +2995 -0
  66. package/dist/chunk-MYZ25B2R.js.map +1 -0
  67. package/dist/chunk-NTMEYB7B.js +2949 -0
  68. package/dist/chunk-NTMEYB7B.js.map +1 -0
  69. package/dist/chunk-PVJXX6GP.js +2640 -0
  70. package/dist/chunk-PVJXX6GP.js.map +1 -0
  71. package/dist/chunk-Q6ERDPQR.js +2981 -0
  72. package/dist/chunk-Q6ERDPQR.js.map +1 -0
  73. package/dist/chunk-S2SSBMWJ.js +2658 -0
  74. package/dist/chunk-S2SSBMWJ.js.map +1 -0
  75. package/dist/chunk-SLVDAZSX.js +2946 -0
  76. package/dist/chunk-SLVDAZSX.js.map +1 -0
  77. package/dist/chunk-UQBPYONV.js +2991 -0
  78. package/dist/chunk-UQBPYONV.js.map +1 -0
  79. package/dist/chunk-UXMNBS22.js +2955 -0
  80. package/dist/chunk-UXMNBS22.js.map +1 -0
  81. package/dist/chunk-WEGED7TA.js +2991 -0
  82. package/dist/chunk-WEGED7TA.js.map +1 -0
  83. package/dist/chunk-WEPTBLWX.js +2847 -0
  84. package/dist/chunk-WEPTBLWX.js.map +1 -0
  85. package/dist/chunk-WG4ZQMPS.js +2844 -0
  86. package/dist/chunk-WG4ZQMPS.js.map +1 -0
  87. package/dist/chunk-XEPEBHAW.js +2808 -0
  88. package/dist/chunk-XEPEBHAW.js.map +1 -0
  89. package/dist/chunk-XG2OYFX6.js +2925 -0
  90. package/dist/chunk-XG2OYFX6.js.map +1 -0
  91. package/dist/chunk-ZAMJEU42.js +2992 -0
  92. package/dist/chunk-ZAMJEU42.js.map +1 -0
  93. package/dist/chunk-ZRAM6FXB.js +2949 -0
  94. package/dist/chunk-ZRAM6FXB.js.map +1 -0
  95. package/dist/components/CsvViewer/CsvViewer.d.ts +51 -0
  96. package/dist/components/CsvViewer/CsvViewer.d.ts.map +1 -0
  97. package/dist/components/CsvViewer/index.d.ts +2 -0
  98. package/dist/components/CsvViewer/index.d.ts.map +1 -0
  99. package/dist/components/DataTable/DataTable.d.ts +19 -1
  100. package/dist/components/DataTable/DataTable.d.ts.map +1 -1
  101. package/dist/components/DropdownMenu/DropdownMenu.d.ts +12 -2
  102. package/dist/components/DropdownMenu/DropdownMenu.d.ts.map +1 -1
  103. package/dist/components/ExecutionConsole/ExecutionConsole.d.ts +8 -2
  104. package/dist/components/ExecutionConsole/ExecutionConsole.d.ts.map +1 -1
  105. package/dist/components/FlowMinimap/FlowMinimap.d.ts +17 -1
  106. package/dist/components/FlowMinimap/FlowMinimap.d.ts.map +1 -1
  107. package/dist/components/FlowToolbar/FlowToolbar.d.ts +16 -10
  108. package/dist/components/FlowToolbar/FlowToolbar.d.ts.map +1 -1
  109. package/dist/components/JsonViewer/JsonViewer.d.ts +42 -7
  110. package/dist/components/JsonViewer/JsonViewer.d.ts.map +1 -1
  111. package/dist/components/JsonViewer/index.d.ts +1 -1
  112. package/dist/components/JsonViewer/index.d.ts.map +1 -1
  113. package/dist/components/Select/Select.d.ts.map +1 -1
  114. package/dist/components/WorkflowHeader/WorkflowHeader.d.ts +130 -0
  115. package/dist/components/WorkflowHeader/WorkflowHeader.d.ts.map +1 -0
  116. package/dist/components/WorkflowHeader/WorkflowHeaderExpanded.d.ts +69 -0
  117. package/dist/components/WorkflowHeader/WorkflowHeaderExpanded.d.ts.map +1 -0
  118. package/dist/components/WorkflowHeader/index.d.ts +3 -0
  119. package/dist/components/WorkflowHeader/index.d.ts.map +1 -0
  120. package/dist/components/WorkflowHeader/misc/WorkflowHeaderCentered.d.ts +40 -0
  121. package/dist/components/WorkflowHeader/misc/WorkflowHeaderCentered.d.ts.map +1 -0
  122. package/dist/components/WorkflowHeader/misc/WorkflowHeaderCommand.d.ts +39 -0
  123. package/dist/components/WorkflowHeader/misc/WorkflowHeaderCommand.d.ts.map +1 -0
  124. package/dist/components/WorkflowHeader/misc/WorkflowHeaderMinimal.d.ts +44 -0
  125. package/dist/components/WorkflowHeader/misc/WorkflowHeaderMinimal.d.ts.map +1 -0
  126. package/dist/components/WorkflowHeader/misc/WorkflowHeaderRail.d.ts +45 -0
  127. package/dist/components/WorkflowHeader/misc/WorkflowHeaderRail.d.ts.map +1 -0
  128. package/dist/components/WorkflowHeader/misc/WorkflowHeaderStudio.d.ts +48 -0
  129. package/dist/components/WorkflowHeader/misc/WorkflowHeaderStudio.d.ts.map +1 -0
  130. package/dist/components/WorkflowHeader/misc/WorkflowHeaderTiered.d.ts +52 -0
  131. package/dist/components/WorkflowHeader/misc/WorkflowHeaderTiered.d.ts.map +1 -0
  132. package/dist/components/XmlViewer/XmlViewer.d.ts +26 -1
  133. package/dist/components/XmlViewer/XmlViewer.d.ts.map +1 -1
  134. package/dist/components/XmlViewer/index.d.ts +1 -1
  135. package/dist/components/XmlViewer/index.d.ts.map +1 -1
  136. package/dist/components/YamlViewer/YamlViewer.d.ts +26 -1
  137. package/dist/components/YamlViewer/YamlViewer.d.ts.map +1 -1
  138. package/dist/components/YamlViewer/index.d.ts +1 -1
  139. package/dist/components/YamlViewer/index.d.ts.map +1 -1
  140. package/dist/hooks/useRelativeTime.d.ts +28 -0
  141. package/dist/hooks/useRelativeTime.d.ts.map +1 -0
  142. package/dist/hooks/useWorkflowRuntime.d.ts +20 -0
  143. package/dist/hooks/useWorkflowRuntime.d.ts.map +1 -0
  144. package/dist/index.cjs +4884 -3581
  145. package/dist/index.cjs.map +1 -1
  146. package/dist/index.d.ts +7 -3
  147. package/dist/index.d.ts.map +1 -1
  148. package/dist/index.js +4505 -3515
  149. package/dist/index.js.map +1 -1
  150. package/dist/styles.css +1 -1
  151. package/dist/workflow/components/ConfigPanel/ConfigPanel.d.ts +27 -9
  152. package/dist/workflow/components/ConfigPanel/ConfigPanel.d.ts.map +1 -1
  153. package/dist/workflow/components/FlowCanvas/FlowCanvas.d.ts +49 -1
  154. package/dist/workflow/components/FlowCanvas/FlowCanvas.d.ts.map +1 -1
  155. package/dist/workflow/components/FlowEdge/FlowEdge.d.ts.map +1 -1
  156. package/dist/workflow/components/FxPanel/DataRefButton.d.ts +9 -0
  157. package/dist/workflow/components/FxPanel/DataRefButton.d.ts.map +1 -0
  158. package/dist/workflow/components/FxPanel/FxPanel.d.ts +74 -0
  159. package/dist/workflow/components/FxPanel/FxPanel.d.ts.map +1 -0
  160. package/dist/workflow/components/FxPanel/FxToggleButton.d.ts +9 -0
  161. package/dist/workflow/components/FxPanel/FxToggleButton.d.ts.map +1 -0
  162. package/dist/workflow/components/Handle/Handle.d.ts +9 -1
  163. package/dist/workflow/components/Handle/Handle.d.ts.map +1 -1
  164. package/dist/workflow/components/Handle/handleRegistry.d.ts +19 -0
  165. package/dist/workflow/components/Handle/handleRegistry.d.ts.map +1 -1
  166. package/dist/workflow/components/kinds/index.d.ts +4 -0
  167. package/dist/workflow/components/kinds/index.d.ts.map +1 -1
  168. package/dist/workflow/index.d.ts +3 -1
  169. package/dist/workflow/index.d.ts.map +1 -1
  170. package/dist/workflow/store/selectors.d.ts +12 -0
  171. package/dist/workflow/store/selectors.d.ts.map +1 -1
  172. package/dist/workflow/utils/parenting.d.ts +5 -3
  173. package/dist/workflow/utils/parenting.d.ts.map +1 -1
  174. package/dist/workflow.cjs +1108 -471
  175. package/dist/workflow.cjs.map +1 -1
  176. package/dist/workflow.js +535 -250
  177. package/dist/workflow.js.map +1 -1
  178. package/package.json +8 -3
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/workflow/utils/paths.ts","../src/workflow/hooks/useFlow.ts","../src/workflow/store/selectors.ts","../src/workflow/store/context.ts","../src/workflow/store/changes.ts","../src/workflow/utils/geometry.ts","../src/workflow/utils/parenting.ts","../src/workflow/components/FlowEdge/FlowEdge.tsx","../src/workflow/components/Handle/handleRegistry.ts","../src/workflow/components/FlowNode/FlowNodeContext.tsx","../src/workflow/components/FlowNode/FlowNode.tsx","../src/workflow/components/FlowCanvas/FlowCanvasContext.tsx","../src/workflow/components/FlowNode/nodeKinds.ts","../src/workflow/components/Handle/Handle.tsx","../src/workflow/components/NodeResizer/NodeResizer.tsx","../src/workflow/components/kinds/BaseNode.tsx","../src/workflow/components/kinds/index.tsx","../src/workflow/components/FlowCanvas/FlowCanvas.tsx","../src/workflow/store/createFlowStore.ts","../src/workflow/utils/collision.ts"],"sourcesContent":["// ════════════════════════════════════════════════════════════════════════\n// Edge-path builders — bezier, step, smoothstep, straight.\n// ════════════════════════════════════════════════════════════════════════\n// All builders take two oriented endpoints (a position + the side of the\n// node that the port faces) and return:\n// - `d` — the SVG path attribute\n// - `midX`, `midY` — analytic midpoint used by the label + delete chrome\n//\n// Path style is selected via `edge.routing`. The choice does NOT affect\n// the `edge.type` semantic (default/conditional/loop/error) which still\n// drives stroke colour and dash. They're orthogonal.\n\nimport type { HandlePosition, Position } from \"../editor\";\n\nexport type EdgeRouting = \"bezier\" | \"step\" | \"smoothstep\" | \"straight\";\n\nexport interface PathGeometry {\n d: string;\n midX: number;\n midY: number;\n /** Tangent angle (radians) at the midpoint — useful when callers want\n * to offset the label/delete chrome along or perpendicular to the path. */\n midAngle: number;\n}\n\n// ── Public dispatcher ──────────────────────────────────────────────────\nexport function buildEdgePath(\n routing: EdgeRouting,\n start: Position,\n startSide: HandlePosition,\n end: Position,\n endSide: HandlePosition,\n options: { borderRadius?: number; curvature?: number } = {},\n): PathGeometry {\n switch (routing) {\n case \"step\":\n return stepPath(start, startSide, end, endSide);\n case \"smoothstep\":\n return smoothStepPath(start, startSide, end, endSide, options.borderRadius ?? 8);\n case \"straight\":\n return straightPath(start, end);\n default:\n return bezierPath(start, startSide, end, endSide, options.curvature ?? 0.25);\n }\n}\n\n// ── Bezier — React-Flow-style control-offset algorithm ────────────────\n// `curvature` ∈ [0, 1]. Smaller = tighter; 0.25 is a comfortable default.\n// When the target is *in the port's forward direction*, offset is a linear\n// fraction of axis distance. When *behind* (target is in the opposite\n// direction from where the port faces), offset uses a square-root falloff\n// so the curve fans out without overshooting wildly.\nexport function bezierPath(\n start: Position,\n startSide: HandlePosition,\n end: Position,\n endSide: HandlePosition,\n curvature = 0.25,\n): PathGeometry {\n const sourceOffset = calcControlOffset(start, startSide, end, curvature);\n const targetOffset = calcControlOffset(end, endSide, start, curvature);\n const c1 = offsetAlongSide(start, startSide, sourceOffset);\n const c2 = offsetAlongSide(end, endSide, targetOffset);\n\n const d = `M ${start.x},${start.y} C ${c1.x},${c1.y} ${c2.x},${c2.y} ${end.x},${end.y}`;\n\n // Analytic midpoint of a cubic bezier at t=0.5.\n const midX = 0.125 * start.x + 0.375 * c1.x + 0.375 * c2.x + 0.125 * end.x;\n const midY = 0.125 * start.y + 0.375 * c1.y + 0.375 * c2.y + 0.125 * end.y;\n // Tangent at t=0.5 = 3 * ((c2 - c1) + 0.5 * ((c1 - start) - (end - c2))).\n // Simplified: derivative of the bezier polynomial at 0.5.\n const tx =\n 3 *\n ((1 - 0.5) ** 2 * (c1.x - start.x) +\n 2 * (1 - 0.5) * 0.5 * (c2.x - c1.x) +\n 0.5 ** 2 * (end.x - c2.x));\n const ty =\n 3 *\n ((1 - 0.5) ** 2 * (c1.y - start.y) +\n 2 * (1 - 0.5) * 0.5 * (c2.y - c1.y) +\n 0.5 ** 2 * (end.y - c2.y));\n const midAngle = Math.atan2(ty, tx);\n\n return { d, midX, midY, midAngle };\n}\n\n/**\n * Distance from `from` to `to` along the axis the `side` points in.\n * Positive = `to` is in front of the port; negative = behind.\n */\nfunction axisDistance(from: Position, side: HandlePosition, to: Position): number {\n switch (side) {\n case \"top\":\n return from.y - to.y;\n case \"bottom\":\n return to.y - from.y;\n case \"left\":\n return from.x - to.x;\n case \"right\":\n return to.x - from.x;\n }\n}\n\nfunction calcControlOffset(\n from: Position,\n side: HandlePosition,\n to: Position,\n curvature: number,\n): number {\n const distance = axisDistance(from, side, to);\n if (distance >= 0) {\n // Linear fraction of axis distance — produces gentle S-curves.\n return distance * 0.5 * (1 + curvature);\n }\n // Backward — square-root falloff so the curve fans wide without\n // shooting off into space at extreme distances. The 25-multiplier is\n // tuned to match React Flow's visual behaviour.\n return curvature * 25 * Math.sqrt(-distance);\n}\n\nfunction offsetAlongSide(p: Position, side: HandlePosition, magnitude: number): Position {\n switch (side) {\n case \"top\":\n return { x: p.x, y: p.y - magnitude };\n case \"bottom\":\n return { x: p.x, y: p.y + magnitude };\n case \"left\":\n return { x: p.x - magnitude, y: p.y };\n case \"right\":\n return { x: p.x + magnitude, y: p.y };\n }\n}\n\n// ── Step routing — orthogonal Z/U-bend ────────────────────────────────\n// For top/bottom ports: vertical-horizontal-vertical (Z). For left/right\n// ports: horizontal-vertical-horizontal. Mixed sides produce an L.\nexport function stepPath(\n start: Position,\n startSide: HandlePosition,\n end: Position,\n endSide: HandlePosition,\n): PathGeometry {\n const corners = computeStepCorners(start, startSide, end, endSide);\n const pts = [start, ...corners, end];\n const d = pts.map((p, i) => `${i === 0 ? \"M\" : \"L\"} ${p.x},${p.y}`).join(\" \");\n // Midpoint along the longest segment so label/delete don't overlap a corner.\n const { midX, midY, midAngle } = midpointOnPolyline(pts);\n return { d, midX, midY, midAngle };\n}\n\n// ── Smoothstep — step with rounded corners ────────────────────────────\nexport function smoothStepPath(\n start: Position,\n startSide: HandlePosition,\n end: Position,\n endSide: HandlePosition,\n borderRadius = 8,\n): PathGeometry {\n const corners = computeStepCorners(start, startSide, end, endSide);\n const pts = [start, ...corners, end];\n if (corners.length === 0) {\n return straightPath(start, end);\n }\n // Build SVG path with `Q` arcs at each interior corner.\n const segments: string[] = [`M ${pts[0].x},${pts[0].y}`];\n for (let i = 1; i < pts.length - 1; i++) {\n const prev = pts[i - 1];\n const here = pts[i];\n const next = pts[i + 1];\n // Cap the radius so it never exceeds half of the adjacent segments.\n const r = Math.min(borderRadius, distance(prev, here) / 2, distance(here, next) / 2);\n const enter = pointTowards(here, prev, r);\n const exit = pointTowards(here, next, r);\n segments.push(`L ${enter.x},${enter.y}`);\n segments.push(`Q ${here.x},${here.y} ${exit.x},${exit.y}`);\n }\n const last = pts[pts.length - 1];\n segments.push(`L ${last.x},${last.y}`);\n const d = segments.join(\" \");\n const { midX, midY, midAngle } = midpointOnPolyline(pts);\n return { d, midX, midY, midAngle };\n}\n\n// ── Straight ─────────────────────────────────────────────────────────\nexport function straightPath(start: Position, end: Position): PathGeometry {\n const d = `M ${start.x},${start.y} L ${end.x},${end.y}`;\n return {\n d,\n midX: (start.x + end.x) / 2,\n midY: (start.y + end.y) / 2,\n midAngle: Math.atan2(end.y - start.y, end.x - start.x),\n };\n}\n\n// ── Helpers ───────────────────────────────────────────────────────────\nfunction computeStepCorners(\n start: Position,\n startSide: HandlePosition,\n end: Position,\n endSide: HandlePosition,\n): Position[] {\n const sourceVertical = startSide === \"top\" || startSide === \"bottom\";\n const targetVertical = endSide === \"top\" || endSide === \"bottom\";\n\n if (sourceVertical && targetVertical) {\n // Z-shape: vertical → horizontal → vertical.\n const midY = (start.y + end.y) / 2;\n return [\n { x: start.x, y: midY },\n { x: end.x, y: midY },\n ];\n }\n if (!sourceVertical && !targetVertical) {\n // Same idea horizontally.\n const midX = (start.x + end.x) / 2;\n return [\n { x: midX, y: start.y },\n { x: midX, y: end.y },\n ];\n }\n // Mixed — L-shape (single corner at the intersection).\n if (sourceVertical) {\n return [{ x: end.x, y: start.y }];\n }\n return [{ x: start.x, y: end.y }];\n}\n\nfunction midpointOnPolyline(pts: Position[]): {\n midX: number;\n midY: number;\n midAngle: number;\n} {\n if (pts.length === 2) {\n return {\n midX: (pts[0].x + pts[1].x) / 2,\n midY: (pts[0].y + pts[1].y) / 2,\n midAngle: Math.atan2(pts[1].y - pts[0].y, pts[1].x - pts[0].x),\n };\n }\n // Walk segments accumulating length; pick the segment whose midpoint\n // is closest to the half-length mark. Anchoring the label to the\n // longest segment keeps it readable.\n let totalLen = 0;\n const lens: number[] = [];\n for (let i = 0; i < pts.length - 1; i++) {\n const l = distance(pts[i], pts[i + 1]);\n lens.push(l);\n totalLen += l;\n }\n const half = totalLen / 2;\n let acc = 0;\n for (let i = 0; i < lens.length; i++) {\n if (acc + lens[i] >= half) {\n const seg = lens[i];\n const remaining = half - acc;\n const t = seg === 0 ? 0 : remaining / seg;\n const a = pts[i];\n const b = pts[i + 1];\n return {\n midX: a.x + (b.x - a.x) * t,\n midY: a.y + (b.y - a.y) * t,\n midAngle: Math.atan2(b.y - a.y, b.x - a.x),\n };\n }\n acc += lens[i];\n }\n // Fallback — unreachable in practice.\n return { midX: pts[0].x, midY: pts[0].y, midAngle: 0 };\n}\n\nfunction distance(a: Position, b: Position): number {\n return Math.hypot(b.x - a.x, b.y - a.y);\n}\n\nfunction pointTowards(from: Position, to: Position, dist: number): Position {\n const d = distance(from, to);\n if (d === 0) return from;\n const t = dist / d;\n return { x: from.x + (to.x - from.x) * t, y: from.y + (to.y - from.y) * t };\n}\n","\"use client\";\n\n// ════════════════════════════════════════════════════════════════════════\n// useFlow — imperative instance for the workflow editor.\n// ════════════════════════════════════════════════════════════════════════\n// Consumers reach inside `<FlowCanvas>` via this hook to do things that\n// React's declarative API can't express cleanly:\n//\n// - convert between screen and flow coordinates (drag-from-palette\n// needs to know where the pointer landed in flow space)\n// - imperatively fit the viewport to a set of nodes (\"zoom to error\")\n// - query intersecting nodes for marquee select / dragover hits\n// - patch node data without round-tripping through the parent reducer\n// - request a delete that respects `onBeforeDelete` veto\n//\n// All methods read from the FlowStore via narrow selectors, so the hook\n// itself doesn't trigger re-renders when state changes. The instance\n// reference is stable for the lifetime of the canvas.\n\nimport { createContext, useContext } from \"react\";\nimport type {\n FitViewOptions,\n Position,\n Rect,\n Viewport,\n WorkflowEdge,\n WorkflowNode,\n} from \"../editor\";\n\nexport interface FlowInstance {\n // ── Viewport ───────────────────────────────────────────────────────\n getViewport(): Viewport;\n setViewport(viewport: Viewport, opts?: { duration?: number }): void;\n setCenter(x: number, y: number, opts?: { duration?: number; zoom?: number }): void;\n fitView(opts?: FitViewOptions): Promise<boolean>;\n zoomIn(opts?: { step?: number }): void;\n zoomOut(opts?: { step?: number }): void;\n zoomTo(level: number): void;\n\n // ── Coordinate transforms ──────────────────────────────────────────\n /** Convert a pointer position (relative to the canvas container) into\n * flow-space coordinates. */\n screenToFlowPosition(p: Position): Position;\n /** Inverse of `screenToFlowPosition`. */\n flowToScreenPosition(p: Position): Position;\n\n // ── Data access (snapshot reads) ───────────────────────────────────\n getNodes(): WorkflowNode[];\n getEdges(): WorkflowEdge[];\n getNode(id: string): WorkflowNode | undefined;\n getEdge(id: string): WorkflowEdge | undefined;\n /** Axis-aligned bounding box of the given nodes (or every node when omitted). */\n getNodesBounds(nodes?: { id: string }[]): Rect;\n /** Find every node whose bbox overlaps the given rect.\n * `partially=true` includes partial overlaps; `false` requires full containment. */\n getIntersectingNodes(area: Rect, partially?: boolean): WorkflowNode[];\n\n // ── Mutation (round-tripped through onNodesChange/onEdgesChange) ──\n addNodes(nodes: WorkflowNode | WorkflowNode[]): void;\n addEdges(edges: WorkflowEdge | WorkflowEdge[]): void;\n /** Merge a partial into the node's existing `data` field. Cheap shorthand\n * for the common case of editing a node's payload without rebuilding it. */\n updateNodeData<TData = unknown>(id: string, partial: Partial<TData>): void;\n /** Replace the node entirely (use sparingly — usually `updateNodeData` is enough). */\n updateNode(id: string, partial: Partial<WorkflowNode>): void;\n /** Imperatively remove nodes and/or edges. Returns false if the host's\n * `onBeforeDelete` vetoed; true otherwise. Synchronous for non-async\n * vetoes; awaits the promise when the host returns one. */\n deleteElements(params: { nodes?: { id: string }[]; edges?: { id: string }[] }): Promise<boolean>;\n}\n\nexport const FlowInstanceContext = createContext<FlowInstance | null>(null);\n\n/**\n * Imperative handle for `<FlowCanvas>`. Throws if called outside the\n * canvas — the instance is canvas-scoped (not a global singleton) so\n * multiple canvases on the same page each have their own.\n */\nexport function useFlow(): FlowInstance {\n const instance = useContext(FlowInstanceContext);\n if (!instance) {\n throw new Error(\"[@octaviaflow/core/workflow] useFlow() must be called inside <FlowCanvas>.\");\n }\n return instance;\n}\n","// ════════════════════════════════════════════════════════════════════════\n// Narrow selector hooks — the only sanctioned way to read from the store.\n// Each hook does one thing and subscribes to the smallest possible slice\n// so re-renders are surgical.\n// ════════════════════════════════════════════════════════════════════════\n\nimport { useContext, useMemo, useSyncExternalStore } from \"react\";\nimport type {\n ConnectStartParams,\n FlowStoreSnapshot,\n Viewport,\n WorkflowEdge,\n WorkflowNode,\n} from \"../editor\";\nimport { FlowStoreContext, useFlowStore } from \"./context\";\n\n/**\n * Generic selector hook. Use for one-off reads in tests or rare cases.\n * Public hooks below cover the common paths.\n *\n * NB: `selector` must be stable (referentially equal across renders) or\n * memoised — otherwise it re-subscribes every render. We do NOT do this\n * automatically because it would mask the bug.\n */\nexport function useFlowSelector<T>(\n selector: (snapshot: FlowStoreSnapshot) => T,\n isEqual: (a: T, b: T) => boolean = Object.is,\n): T {\n // Note: useSyncExternalStore uses Object.is internally for change\n // detection. The `isEqual` arg is reserved for a future patch that adds\n // structural equality (e.g. for array selectors); reference it so the\n // arg isn't dead.\n void isEqual;\n const store = useFlowStore();\n return useSyncExternalStore(\n store.subscribe,\n () => selector(store.getSnapshot()),\n () => selector(store.getSnapshot()),\n );\n}\n\n// ── Reads ──────────────────────────────────────────────────────────────\n\nexport function useNodes(): WorkflowNode[] {\n return useFlowSelector((s) => s.nodes);\n}\n\nexport function useEdges(): WorkflowEdge[] {\n return useFlowSelector((s) => s.edges);\n}\n\nexport function useViewport(): Viewport {\n return useFlowSelector((s) => s.viewport);\n}\n\nconst VIEWPORT_OR_NULL_NO_STORE_SUBSCRIBE = (_cb: () => void) => () => {};\nconst VIEWPORT_OR_NULL_NO_STORE_SNAPSHOT = (): Viewport | null => null;\n\n/**\n * Like `useViewport()` but returns `null` when called outside a\n * `<FlowCanvas>`. Useful for shared chrome components (FlowToolbarZoom,\n * minimap previews) that want to auto-subscribe when mounted inside the\n * canvas, but still render correctly in isolation (Storybook, design\n * docs) when no store is present.\n *\n * The subscribe/getSnapshot pair is memoised so React subscribes once per\n * mounted `<FlowCanvas>` ancestor — flipping in/out is rare (only when a\n * canvas is unmounted around the consumer).\n */\nexport function useViewportOrNull(): Viewport | null {\n const store = useContext(FlowStoreContext);\n const { sub, snap } = useMemo(\n () =>\n store\n ? {\n sub: store.subscribe,\n snap: (): Viewport | null => store.getSnapshot().viewport,\n }\n : {\n sub: VIEWPORT_OR_NULL_NO_STORE_SUBSCRIBE,\n snap: VIEWPORT_OR_NULL_NO_STORE_SNAPSHOT,\n },\n [store],\n );\n return useSyncExternalStore(sub, snap, snap);\n}\n\nexport function useNodeById(id: string): WorkflowNode | undefined {\n return useFlowSelector((s) => s.nodes.find((n) => n.id === id));\n}\n\n/**\n * Subscribe to the `data` slice of a single node by id. Re-renders only\n * when this specific node's `data` reference changes — no cross-node\n * leakage. Pair with `FlowStateBag.updateNodeData(id, patch)` to write.\n *\n * Returns undefined when the node is not present; consumers should\n * branch on that. Typed via the generic so callers get their `TData`\n * shape back without casting.\n */\nexport function useNodeData<TData = unknown>(id: string): TData | undefined {\n return useFlowSelector(\n (s) => (s.nodes.find((n) => n.id === id)?.data as TData | undefined) ?? undefined,\n );\n}\n\nexport function useEdgeById(id: string): WorkflowEdge | undefined {\n return useFlowSelector((s) => s.edges.find((e) => e.id === id));\n}\n\nexport function useIsNodeSelected(id: string): boolean {\n return useFlowSelector((s) => s.selectedNodeIds.has(id));\n}\n\nexport function useIsEdgeSelected(id: string): boolean {\n return useFlowSelector((s) => s.selectedEdgeIds.has(id));\n}\n\nexport function useConnection(): ConnectStartParams | null {\n return useFlowSelector((s) => s.connection);\n}\n\nexport function useSelection(): { nodes: WorkflowNode[]; edges: WorkflowEdge[] } {\n // Subscribe to each underlying slice separately so useSyncExternalStore\n // sees stable references — building a fresh object inside the selector\n // would force a re-render every render (snapshot-cache violation).\n const nodes = useNodes();\n const edges = useEdges();\n const selectedNodeIds = useFlowSelector((s) => s.selectedNodeIds);\n const selectedEdgeIds = useFlowSelector((s) => s.selectedEdgeIds);\n return useMemo(\n () => ({\n nodes: nodes.filter((n) => selectedNodeIds.has(n.id)),\n edges: edges.filter((e) => selectedEdgeIds.has(e.id)),\n }),\n [nodes, edges, selectedNodeIds, selectedEdgeIds],\n );\n}\n","// ════════════════════════════════════════════════════════════════════════\n// FlowStoreContext — descendants reach the store through this React\n// context. The store itself is NOT a context value (that would tank\n// perf); only the store *handle* is. Consumers read state via the\n// selector hooks in `./selectors.ts`.\n// ════════════════════════════════════════════════════════════════════════\n\nimport { createContext, useContext } from \"react\";\nimport type { FlowStore } from \"./createFlowStore\";\n\nexport const FlowStoreContext = createContext<FlowStore | null>(null);\n\nexport function useFlowStore(): FlowStore {\n const store = useContext(FlowStoreContext);\n if (!store) {\n throw new Error(\n \"[@octaviaflow/core/workflow] useFlowStore must be called inside a <FlowCanvas>.\",\n );\n }\n return store;\n}\n","// ════════════════════════════════════════════════════════════════════════\n// Change reducers — apply node/edge change arrays in one immutable pass.\n// ════════════════════════════════════════════════════════════════════════\n// Consumers in controlled mode write:\n//\n// <FlowCanvas\n// nodes={nodes}\n// edges={edges}\n// onNodesChange={(changes) => setNodes((ns) => applyNodeChanges(ns, changes))}\n// onEdgesChange={(changes) => setEdges((es) => applyEdgeChanges(es, changes))}\n// />\n//\n// The helpers run in O(n + m) where n is the existing list and m the\n// change count, with one shallow clone per touched item. Add / remove\n// short-circuit when the array is unchanged, so React's reconciler\n// happily reuses references.\n\nimport type { EdgeChange, NodeChange, WorkflowEdge, WorkflowNode } from \"../editor\";\n\n/**\n * Apply a batch of node changes to an existing node list. Returns a\n * **new array** if anything changed, the **same array** otherwise (so\n * React.memo'd children don't re-render unnecessarily).\n */\nexport function applyNodeChanges<TData = unknown>(\n nodes: WorkflowNode<TData>[],\n changes: NodeChange<TData>[],\n): WorkflowNode<TData>[] {\n if (changes.length === 0) return nodes;\n\n // Bucket changes by id for O(1) lookup during the single map pass.\n const byId = new Map<string, NodeChange<TData>[]>();\n const adds: WorkflowNode<TData>[] = [];\n const removes = new Set<string>();\n let touched = false;\n\n for (const change of changes) {\n switch (change.type) {\n case \"add\":\n adds.push(change.item);\n touched = true;\n break;\n case \"remove\":\n removes.add(change.id);\n touched = true;\n break;\n default: {\n const id = change.id;\n const arr = byId.get(id);\n if (arr) arr.push(change);\n else byId.set(id, [change]);\n touched = true;\n break;\n }\n }\n }\n\n if (!touched) return nodes;\n\n const next: WorkflowNode<TData>[] = [];\n for (const node of nodes) {\n if (removes.has(node.id)) continue;\n const patches = byId.get(node.id);\n if (!patches) {\n next.push(node);\n continue;\n }\n let n: WorkflowNode<TData> = node;\n for (const patch of patches) {\n switch (patch.type) {\n case \"position\":\n n = {\n ...n,\n position: patch.position,\n dragging: patch.dragging,\n };\n break;\n case \"dimensions\":\n n = {\n ...n,\n width: patch.dimensions.width,\n height: patch.dimensions.height,\n };\n break;\n case \"select\":\n // Skip if already in the target state — keeps reference stable.\n if (n.selected === patch.selected) break;\n n = { ...n, selected: patch.selected };\n break;\n case \"replace\":\n n = patch.item;\n break;\n }\n }\n next.push(n);\n }\n\n // Adds go to the end. Parents must precede children (caller's\n // responsibility; we don't reorder mid-application because that would\n // make `replace` unpredictable when a child already exists).\n for (const add of adds) next.push(add);\n\n return next;\n}\n\n/**\n * Apply a batch of edge changes. Same shape as `applyNodeChanges`.\n */\nexport function applyEdgeChanges<TData = unknown>(\n edges: WorkflowEdge<TData>[],\n changes: EdgeChange<TData>[],\n): WorkflowEdge<TData>[] {\n if (changes.length === 0) return edges;\n\n const byId = new Map<string, EdgeChange<TData>[]>();\n const adds: WorkflowEdge<TData>[] = [];\n const removes = new Set<string>();\n let touched = false;\n\n for (const change of changes) {\n switch (change.type) {\n case \"add\":\n adds.push(change.item);\n touched = true;\n break;\n case \"remove\":\n removes.add(change.id);\n touched = true;\n break;\n default: {\n const arr = byId.get(change.id);\n if (arr) arr.push(change);\n else byId.set(change.id, [change]);\n touched = true;\n break;\n }\n }\n }\n\n if (!touched) return edges;\n\n const next: WorkflowEdge<TData>[] = [];\n for (const edge of edges) {\n if (removes.has(edge.id)) continue;\n const patches = byId.get(edge.id);\n if (!patches) {\n next.push(edge);\n continue;\n }\n let e: WorkflowEdge<TData> = edge;\n for (const patch of patches) {\n switch (patch.type) {\n case \"select\":\n if (e.selected === patch.selected) break;\n e = { ...e, selected: patch.selected };\n break;\n case \"replace\":\n e = patch.item;\n break;\n }\n }\n next.push(e);\n }\n\n for (const add of adds) next.push(add);\n return next;\n}\n\n// ── Convenience builders ────────────────────────────────────────────────\n// Used by the store / hooks internally. Public consumers usually let the\n// canvas emit changes; these are handy for tests + custom interactions.\n\nexport const change = {\n node: {\n add<TData>(item: WorkflowNode<TData>): NodeChange<TData> {\n return { type: \"add\", item };\n },\n remove<TData>(id: string): NodeChange<TData> {\n return { type: \"remove\", id };\n },\n position<TData>(\n id: string,\n position: { x: number; y: number },\n dragging: boolean,\n ): NodeChange<TData> {\n return { type: \"position\", id, position, dragging };\n },\n dimensions<TData>(\n id: string,\n dimensions: { width: number; height: number },\n ): NodeChange<TData> {\n return { type: \"dimensions\", id, dimensions };\n },\n select<TData>(id: string, selected: boolean): NodeChange<TData> {\n return { type: \"select\", id, selected };\n },\n replace<TData>(id: string, item: WorkflowNode<TData>): NodeChange<TData> {\n return { type: \"replace\", id, item };\n },\n },\n edge: {\n add<TData>(item: WorkflowEdge<TData>): EdgeChange<TData> {\n return { type: \"add\", item };\n },\n remove<TData>(id: string): EdgeChange<TData> {\n return { type: \"remove\", id };\n },\n select<TData>(id: string, selected: boolean): EdgeChange<TData> {\n return { type: \"select\", id, selected };\n },\n replace<TData>(id: string, item: WorkflowEdge<TData>): EdgeChange<TData> {\n return { type: \"replace\", id, item };\n },\n },\n};\n","// ════════════════════════════════════════════════════════════════════════\n// Shared geometry helpers used by FlowNode, FlowEdge, and the connection\n// drag middleware. Pure functions — no state, no DOM.\n// ════════════════════════════════════════════════════════════════════════\n\nimport type { HandlePosition, Position, Viewport, WorkflowNode } from \"../editor\";\n\n// Default node footprint when the renderer hasn't yet measured a custom\n// node. Kept in lockstep with the BaseNode body width (368 px) so the\n// pre-measurement edge math anchors precisely on the handle dot. Height\n// stays 96 — the body min-height clamps the real measurement past that.\nexport const DEFAULT_NODE_WIDTH = 368;\nexport const DEFAULT_NODE_HEIGHT = 96;\n\n// Collapsed container heights — kept in lockstep with the values in\n// `kinds/index.tsx` (GroupNode renders `collapsed ? 36 : ...`,\n// ForEachNode renders `collapsed ? 40 : ...`). When a container is\n// collapsed its visual footprint shrinks to this header strip; edges to\n// the perimeter handles must use the same height or they'll terminate\n// hundreds of pixels below the visible node.\nexport const COLLAPSED_GROUP_HEIGHT = 36;\nexport const COLLAPSED_FOREACH_HEIGHT = 40;\n\n/**\n * The height the node *actually renders at* — accounts for collapsed\n * containers whose visual height differs from `node.height`. All edge\n * geometry should go through this helper instead of reading\n * `node.height` directly.\n */\nexport function effectiveHeight(node: WorkflowNode): number {\n const data = node.data as { collapsed?: boolean } | undefined;\n if (data?.collapsed) {\n if (node.type === \"group\") return COLLAPSED_GROUP_HEIGHT;\n if (node.type === \"forEach\") return COLLAPSED_FOREACH_HEIGHT;\n }\n return node.height ?? DEFAULT_NODE_HEIGHT;\n}\n\n/**\n * Compute the absolute (flow-space) centre of one of a node's handles.\n *\n * The handle's logical position (`top`/`right`/`bottom`/`left`) plus its\n * index among same-side handles determines a deterministic spread along\n * the relevant edge of the node bbox. We do NOT consult the DOM — the\n * source of truth is the node's measured (or default) dimensions.\n *\n * `total` is the count of handles on that side, `index` is this handle's\n * 0-based position among them. A single handle centres; multiple spread\n * evenly with equal margins.\n */\nexport function handleCentre(\n node: WorkflowNode,\n side: HandlePosition,\n index: number,\n total: number,\n): Position {\n const w = node.width ?? DEFAULT_NODE_WIDTH;\n // Use the EFFECTIVE rendered height — collapsed containers report a\n // tall `node.height` but visually render a 36-40px strip. Without this,\n // edges to a collapsed group's perimeter handle terminate hundreds of\n // pixels below the visible pill.\n const h = effectiveHeight(node);\n const x0 = node.position.x;\n const y0 = node.position.y;\n const denom = total + 1;\n const ratio = (index + 1) / denom;\n\n switch (side) {\n case \"top\":\n return { x: x0 + w * ratio, y: y0 };\n case \"bottom\":\n return { x: x0 + w * ratio, y: y0 + h };\n case \"left\":\n return { x: x0, y: y0 + h * ratio };\n case \"right\":\n return { x: x0 + w, y: y0 + h * ratio };\n }\n}\n\n/**\n * Cubic bezier path between two oriented points. The control points are\n * offset along each port's facing direction so the curve leaves and\n * enters along the port's axis (the same routing model as v1).\n */\nexport function bezierPath(\n start: Position,\n startSide: HandlePosition,\n end: Position,\n endSide: HandlePosition,\n): { d: string; midX: number; midY: number } {\n const distance = Math.hypot(end.x - start.x, end.y - start.y);\n const magnitude = Math.max(40, Math.min(160, distance * 0.45));\n const c1 = offsetBySide(start, startSide, magnitude);\n const c2 = offsetBySide(end, endSide, magnitude);\n const d = `M ${start.x},${start.y} C ${c1.x},${c1.y} ${c2.x},${c2.y} ${end.x},${end.y}`;\n // Analytic midpoint of a cubic bezier at t = 0.5.\n const midX = 0.125 * start.x + 0.375 * c1.x + 0.375 * c2.x + 0.125 * end.x;\n const midY = 0.125 * start.y + 0.375 * c1.y + 0.375 * c2.y + 0.125 * end.y;\n return { d, midX, midY };\n}\n\nfunction offsetBySide(p: Position, side: HandlePosition, m: number): Position {\n switch (side) {\n case \"top\":\n return { x: p.x, y: p.y - m };\n case \"bottom\":\n return { x: p.x, y: p.y + m };\n case \"left\":\n return { x: p.x - m, y: p.y };\n case \"right\":\n return { x: p.x + m, y: p.y };\n }\n}\n\n/**\n * Convert a screen-space point (pixels relative to the viewport\n * container's top-left) to flow-space coordinates, given the current\n * viewport.\n */\nexport function screenToFlow(p: Position, vp: Viewport): Position {\n return {\n x: (p.x - vp.x) / vp.zoom,\n y: (p.y - vp.y) / vp.zoom,\n };\n}\n\n/**\n * Inverse of `screenToFlow`.\n */\nexport function flowToScreen(p: Position, vp: Viewport): Position {\n return {\n x: p.x * vp.zoom + vp.x,\n y: p.y * vp.zoom + vp.y,\n };\n}\n","// ════════════════════════════════════════════════════════════════════════\n// Parenting helpers — descendant traversal, extent clamping, descendant\n// position recompute. Used by FlowCanvas's drag middleware to keep\n// subflow semantics consistent.\n// ════════════════════════════════════════════════════════════════════════\n\nimport type { Position, WorkflowNode } from \"../editor\";\nimport { DEFAULT_NODE_WIDTH, effectiveHeight } from \"./geometry\";\n\n/**\n * Returns the transitive descendants of a node — i.e. every node whose\n * `parentId` chain ends at `nodeId`. Stable order (DFS). The root node\n * is NOT included.\n */\nexport function descendantsOf(nodeId: string, nodes: WorkflowNode[]): WorkflowNode[] {\n const childrenByParent = new Map<string, WorkflowNode[]>();\n for (const n of nodes) {\n if (!n.parentId) continue;\n const arr = childrenByParent.get(n.parentId);\n if (arr) arr.push(n);\n else childrenByParent.set(n.parentId, [n]);\n }\n const out: WorkflowNode[] = [];\n const stack = [nodeId];\n // Guard against malformed cycles (a → b → a) which can sneak in via\n // hand-crafted fixtures. Without this the walk is unbounded.\n const visited = new Set<string>([nodeId]);\n while (stack.length) {\n const cur = stack.pop();\n if (cur === undefined) break;\n const list = childrenByParent.get(cur);\n if (!list) continue;\n for (const c of list) {\n if (visited.has(c.id)) continue;\n visited.add(c.id);\n out.push(c);\n stack.push(c.id);\n }\n }\n return out;\n}\n\n/**\n * Walk up the parent chain. Returns the first ancestor that satisfies\n * `predicate`, or undefined.\n */\nexport function findAncestor(\n node: WorkflowNode,\n nodes: WorkflowNode[],\n predicate: (n: WorkflowNode) => boolean,\n): WorkflowNode | undefined {\n let cursor: WorkflowNode | undefined = node;\n const seen = new Set<string>();\n while (cursor?.parentId) {\n if (seen.has(cursor.parentId)) return undefined; // cycle guard\n seen.add(cursor.parentId);\n const parent = nodes.find((n) => n.id === cursor!.parentId);\n if (!parent) return undefined;\n if (predicate(parent)) return parent;\n cursor = parent;\n }\n return undefined;\n}\n\n/**\n * Clamp a proposed child position to its parent's bounding box. The\n * child is kept fully inside the parent — child's bottom-right corner\n * cannot exceed the parent's bottom-right.\n *\n * Returns the original position if the node has no parent or extent\n * isn't `'parent'`.\n */\nexport function clampToParentExtent(\n node: WorkflowNode,\n proposed: Position,\n nodes: WorkflowNode[],\n): Position {\n if (node.extent !== \"parent\" || !node.parentId) return proposed;\n const parent = nodes.find((n) => n.id === node.parentId);\n if (!parent) return proposed;\n const pw = parent.width ?? DEFAULT_NODE_WIDTH;\n const ph = effectiveHeight(parent);\n const w = node.width ?? DEFAULT_NODE_WIDTH;\n const h = effectiveHeight(node);\n const minX = parent.position.x;\n const minY = parent.position.y;\n const maxX = parent.position.x + pw - w;\n const maxY = parent.position.y + ph - h;\n return {\n x: Math.max(minX, Math.min(maxX, proposed.x)),\n y: Math.max(minY, Math.min(maxY, proposed.y)),\n };\n}\n\n/**\n * Hit-test which group node (if any) currently contains the given point.\n * Used by Alt-drop to re-parent a node into a group, and by drop-to-add\n * to scope a new node.\n */\nexport function findContainingGroup(\n point: Position,\n nodes: WorkflowNode[],\n exclude: string[] = [],\n): WorkflowNode | undefined {\n // Walk in reverse z-order so the topmost group wins when nested.\n for (let i = nodes.length - 1; i >= 0; i--) {\n const n = nodes[i];\n if (exclude.includes(n.id)) continue;\n if (n.type !== \"group\") continue;\n if (n.data && typeof n.data === \"object\" && (n.data as { collapsed?: boolean }).collapsed) {\n continue;\n }\n const w = n.width ?? DEFAULT_NODE_WIDTH;\n const h = effectiveHeight(n);\n if (\n point.x >= n.position.x &&\n point.y >= n.position.y &&\n point.x <= n.position.x + w &&\n point.y <= n.position.y + h\n ) {\n return n;\n }\n }\n return undefined;\n}\n","\"use client\";\n\n// ════════════════════════════════════════════════════════════════════════\n// FlowEdge v2 — port-aware path, four routing modes, editable label.\n// ════════════════════════════════════════════════════════════════════════\n// Routing modes: bezier (default), step, smoothstep, straight.\n// Semantic types: default / conditional / loop / error — drive stroke\n// colour and dash pattern, orthogonal to routing.\n//\n// Label + delete chrome are stacked vertically at the midpoint so they\n// don't overlap. Double-clicking the label opens an inline editor;\n// changes commit via `onLabelChange`.\n\nimport {\n memo,\n type KeyboardEvent as ReactKeyboardEvent,\n useEffect,\n useId,\n useRef,\n useState,\n} from \"react\";\nimport { cn } from \"../../../utils/cn\";\nimport type { EdgeKind, WorkflowEdge as WorkflowEdgeType, WorkflowNode } from \"../../editor\";\nimport { handleCentre } from \"../../utils/geometry\";\nimport { buildEdgePath, type EdgeRouting } from \"../../utils/paths\";\nimport { useHandleRegistry } from \"../Handle/handleRegistry\";\n\nexport interface FlowEdgeProps {\n edge: WorkflowEdgeType;\n nodes: WorkflowNode[];\n onSelect?: (id: string) => void;\n onDelete?: (id: string) => void;\n /** Commit a label edit. When omitted, double-click is a no-op. */\n onLabelChange?: (id: string, label: string) => void;\n /** Show the X delete affordance at the midpoint on hover/select. */\n showDelete?: boolean;\n /** Curvature for bezier routing (0–1). Smaller = tighter. Default 0.25. */\n curvature?: number;\n /** Corner radius for smoothstep routing. Default 8 px. */\n borderRadius?: number;\n /**\n * Bust-cache token from FlowCanvas. Bumps whenever the handle registry\n * mutates so this edge re-renders against fresh handle descriptors —\n * fixes stale geometry after collapse/uncollapse of a subflow whose\n * children mount their Handles in a follow-up effect tick.\n */\n handleVersion?: number;\n}\n\nfunction FlowEdgeImpl({\n edge,\n nodes,\n onSelect,\n onDelete,\n onLabelChange,\n showDelete = true,\n curvature = 0.25,\n borderRadius = 8,\n}: FlowEdgeProps) {\n const uid = useId();\n const markerId = `ods-flow-edge-arrow-${uid.replace(/:/g, \"\")}`;\n const registry = useHandleRegistry();\n const [hovered, setHovered] = useState(false);\n const [editing, setEditing] = useState(false);\n const [draftLabel, setDraftLabel] = useState<string>(edge.label ?? \"\");\n const inputRef = useRef<HTMLInputElement>(null);\n\n // Sync the draft when the edge's label changes externally (e.g. after a\n // commit). The local state survives blur/Enter cleanly.\n useEffect(() => {\n if (!editing) setDraftLabel(edge.label ?? \"\");\n }, [edge.label, editing]);\n\n const sourceNode = nodes.find((n) => n.id === edge.source);\n const targetNode = nodes.find((n) => n.id === edge.target);\n\n if (!sourceNode || !targetNode) return null;\n\n // Compute on every render — handle registrations may arrive after the\n // first paint, and the math is cheap.\n const sourceHandleId = edge.sourceHandle ?? \"default\";\n const targetHandleId = edge.targetHandle ?? \"default\";\n const sourceDesc = registry.resolve(sourceNode.id, \"source\", sourceHandleId);\n const targetDesc = registry.resolve(targetNode.id, \"target\", targetHandleId);\n const sourceSide = sourceDesc?.side ?? sourceNode.sourcePosition ?? \"bottom\";\n const targetSide = targetDesc?.side ?? targetNode.targetPosition ?? \"top\";\n const sourceIndex = sourceDesc?.index ?? 0;\n const sourceTotal = sourceDesc?.total ?? 1;\n const targetIndex = targetDesc?.index ?? 0;\n const targetTotal = targetDesc?.total ?? 1;\n const rawStart = handleCentre(sourceNode, sourceSide, sourceIndex, sourceTotal);\n const rawEnd = handleCentre(targetNode, targetSide, targetIndex, targetTotal);\n // Pull the visible path back from each handle dot by ~8 px so the\n // arrowhead sits OUTSIDE the open-circle port instead of vanishing\n // inside it. The hitbox path still uses the raw points so click hit\n // area extends right up to the dot.\n const HANDLE_GAP = 8;\n const start = offsetAlongSide(rawStart, sourceSide, HANDLE_GAP);\n const end = offsetAlongSide(rawEnd, targetSide, HANDLE_GAP);\n const routing: EdgeRouting = edge.routing ?? \"bezier\";\n const { d, midX, midY } = buildEdgePath(routing, start, sourceSide, end, targetSide, {\n curvature,\n borderRadius,\n });\n const { d: hitD } = buildEdgePath(routing, rawStart, sourceSide, rawEnd, targetSide, {\n curvature,\n borderRadius,\n });\n\n const type: EdgeKind = edge.type ?? \"default\";\n const isHot = hovered || edge.selected;\n const stroke =\n type === \"error\"\n ? \"var(--ods-status-failed, #dc2626)\"\n : isHot\n ? \"var(--ods-accent, #4f46e5)\"\n : \"var(--ods-border-strong, #6b7280)\";\n // Explicit `edge.style.strokeDasharray` wins over the type's default —\n // this is what `collapseFor` uses to render boundary edges (sparse-dotted)\n // so the user sees they're a \"summary\" rather than a real connection.\n const typeDash = type === \"conditional\" ? \"6 4\" : type === \"loop\" ? \"4 4\" : undefined;\n const dash = edge.style?.strokeDasharray ?? typeDash;\n const strokeWidth = edge.style?.strokeWidth ?? (isHot ? 2 : 1.4);\n const animateDash = edge.animated === true;\n const label = edge.label;\n const hasDelete = showDelete && (isHot || edge.selected) && !!onDelete;\n\n // Lay label + delete affordance side by side at the midpoint:\n //\n // ┌─────────┐ ⓧ ← inline chrome, both on midY\n // │ label │\n // └─────────┘\n //\n // The foreignObject sits on the bezier's midpoint and holds a flex row\n // that centres its children horizontally. Either child may be absent;\n // remaining child stays centred.\n const showChrome = !!label || editing || hasDelete;\n\n const commitLabel = (next: string) => {\n setEditing(false);\n if (next !== edge.label) onLabelChange?.(edge.id, next);\n };\n\n const onLabelKey = (e: ReactKeyboardEvent<HTMLInputElement>) => {\n if (e.key === \"Enter\") {\n e.preventDefault();\n commitLabel(draftLabel);\n } else if (e.key === \"Escape\") {\n e.preventDefault();\n setEditing(false);\n setDraftLabel(edge.label ?? \"\");\n }\n };\n\n return (\n <g\n className={cn(\n \"ods-flow-edge-v2\",\n `ods-flow-edge-v2--${type}`,\n `ods-flow-edge-v2--routing-${routing}`,\n edge.selected && \"ods-flow-edge-v2--selected\",\n hovered && \"ods-flow-edge-v2--hovered\",\n edge.className,\n )}\n data-edge-id={edge.id}\n data-edge-routing={routing}\n onMouseEnter={() => setHovered(true)}\n onMouseLeave={() => setHovered(false)}\n onClick={(e) => {\n e.stopPropagation();\n onSelect?.(edge.id);\n }}\n >\n <defs>\n <marker\n id={markerId}\n viewBox=\"0 0 10 10\"\n refX=\"9\"\n refY=\"5\"\n markerWidth=\"7\"\n markerHeight=\"7\"\n orient=\"auto-start-reverse\"\n >\n <path d=\"M0 0L10 5L0 10z\" fill={stroke} />\n </marker>\n </defs>\n\n {/* Hitbox — wider stroke than the visible path so the edge is easy\n to click even when zoomed out or routed with sharp corners. Uses\n the un-shortened path so the click target reaches the port. */}\n <path d={hitD} stroke=\"transparent\" strokeWidth={20} fill=\"none\" />\n\n {/* Visible path. */}\n <path\n d={d}\n stroke={stroke}\n strokeWidth={strokeWidth}\n strokeDasharray={dash}\n fill=\"none\"\n markerEnd={`url(#${markerId})`}\n style={\n animateDash\n ? {\n strokeDasharray: dash ?? \"6 4\",\n animation: \"ods-flow-edge-flow 0.6s linear infinite\",\n }\n : undefined\n }\n />\n\n {showChrome && (\n <foreignObject\n x={midX - 140}\n y={midY - 16}\n width={280}\n height={32}\n style={{ overflow: \"visible\", pointerEvents: \"none\" }}\n >\n <div className=\"ods-flow-edge-v2__chrome\">\n {(label || editing) &&\n (editing ? (\n <input\n ref={inputRef}\n className=\"ods-flow-edge-v2__label-input\"\n value={draftLabel}\n autoFocus\n onChange={(e) => setDraftLabel(e.target.value)}\n onBlur={() => commitLabel(draftLabel)}\n onKeyDown={onLabelKey}\n onClick={(e) => e.stopPropagation()}\n onMouseDown={(e) => e.stopPropagation()}\n aria-label=\"Edit edge label\"\n />\n ) : (\n <button\n type=\"button\"\n className=\"ods-flow-edge-v2__label-chip\"\n onDoubleClick={(e) => {\n if (!onLabelChange) return;\n e.stopPropagation();\n setDraftLabel(edge.label ?? \"\");\n setEditing(true);\n }}\n onClick={(e) => {\n e.stopPropagation();\n onSelect?.(edge.id);\n }}\n title={onLabelChange ? \"Double-click to edit\" : undefined}\n tabIndex={onLabelChange ? 0 : -1}\n >\n <span>{label}</span>\n </button>\n ))}\n\n {hasDelete && (\n <button\n type=\"button\"\n className=\"ods-flow-edge-v2__delete-btn\"\n onClick={(e) => {\n e.stopPropagation();\n onDelete?.(edge.id);\n }}\n aria-label=\"Delete edge\"\n >\n <svg width=\"10\" height=\"10\" viewBox=\"0 0 10 10\" aria-hidden=\"true\">\n <path\n d=\"M2 2l6 6M8 2l-6 6\"\n stroke=\"currentColor\"\n strokeWidth={1.5}\n strokeLinecap=\"round\"\n />\n </svg>\n </button>\n )}\n </div>\n </foreignObject>\n )}\n </g>\n );\n}\n\n/**\n * Pull a handle anchor point inward by `gap` px along the side it sits\n * on. Used to leave space between the arrowhead and the open-circle\n * port — the path stops just outside the dot so the arrow stays visible.\n *\n * \"top\" → end is at the node's top edge, pull it UP (smaller y)\n * \"bottom\" → pull DOWN (larger y)\n * \"left\" → pull LEFT (smaller x)\n * \"right\" → pull RIGHT (larger x)\n */\nfunction offsetAlongSide(\n p: { x: number; y: number },\n side: \"top\" | \"right\" | \"bottom\" | \"left\",\n gap: number,\n): { x: number; y: number } {\n switch (side) {\n case \"top\":\n return { x: p.x, y: p.y - gap };\n case \"bottom\":\n return { x: p.x, y: p.y + gap };\n case \"left\":\n return { x: p.x - gap, y: p.y };\n case \"right\":\n return { x: p.x + gap, y: p.y };\n }\n}\n\nexport const FlowEdge = memo(FlowEdgeImpl, (prev, next) => {\n if (prev.edge !== next.edge) return false;\n if (prev.onSelect !== next.onSelect || prev.onDelete !== next.onDelete) return false;\n if (prev.onLabelChange !== next.onLabelChange) return false;\n if (prev.showDelete !== next.showDelete) return false;\n if (prev.curvature !== next.curvature || prev.borderRadius !== next.borderRadius) return false;\n // Bust the cache when the handle registry mutates — otherwise edges\n // referring to handles that mount in a follow-up effect tick (e.g.\n // children inside a subflow that just un-collapsed) freeze at the\n // first-render-with-stale-registry geometry.\n if (prev.handleVersion !== next.handleVersion) return false;\n const ps = prev.nodes.find((n) => n.id === prev.edge.source);\n const pt = prev.nodes.find((n) => n.id === prev.edge.target);\n const ns = next.nodes.find((n) => n.id === next.edge.source);\n const nt = next.nodes.find((n) => n.id === next.edge.target);\n if (ps !== ns || pt !== nt) return false;\n return true;\n});\n","// ════════════════════════════════════════════════════════════════════════\n// Per-canvas handle registry — Edge components look up handle positions\n// via this registry so they don't need to thread DOM refs around.\n// ════════════════════════════════════════════════════════════════════════\n// The Handle component registers itself on mount with its (nodeId,\n// handleId, type, side, index, total) tuple. FlowEdge derives the absolute\n// flow-space centre via `handleCentre()` using `node.position +\n// node.dimensions + side + index/total`.\n//\n// Keys are `(nodeId, type, handleId)` — note the `type`! Input and\n// output handles can legitimately share an id (the default is `\"default\"`\n// for both), and the type disambiguates. Without this, a node with one\n// input + one output (both with id `\"default\"`) would collide and edges\n// would resolve the wrong side.\n\nimport { createContext, useContext } from \"react\";\nimport type { HandlePosition, HandleType } from \"../../editor\";\n\nexport interface HandleDescriptor {\n nodeId: string;\n handleId: string;\n type: HandleType;\n side: HandlePosition;\n /** 0-based position among same-(node, side, type) handles. */\n index: number;\n /** Total handles on the same (node, side, type). */\n total: number;\n}\n\nexport interface HandleRegistry {\n register(d: HandleDescriptor): () => void;\n resolve(nodeId: string, type: HandleType, handleId: string): HandleDescriptor | undefined;\n /**\n * Subscribe to registry mutations. Fires after every register /\n * unregister so listeners (typically the EdgesLayer) can re-render\n * once the new handles are present. Without this, edges resolved\n * during the same React commit as a node remount fall back to default\n * positions because the Handle's `useEffect` hasn't yet written its\n * descriptor — which is what caused the post-collapse stale-edge bug\n * inside subflows.\n */\n subscribe(listener: () => void): () => void;\n}\n\nexport const HandleRegistryContext = createContext<HandleRegistry | null>(null);\n\nexport function useHandleRegistry(): HandleRegistry {\n const r = useContext(HandleRegistryContext);\n if (!r) {\n throw new Error(\"[@octaviaflow/core/workflow] Handle must be used inside <FlowCanvas>.\");\n }\n return r;\n}\n\n/**\n * Build a registry. One per FlowCanvas instance.\n */\nexport function createHandleRegistry(): HandleRegistry {\n const map = new Map<string, HandleDescriptor>();\n const key = (n: string, t: HandleType, h: string) => `${n}::${t}::${h}`;\n const listeners = new Set<() => void>();\n const notify = () => {\n for (const l of listeners) l();\n };\n return {\n register(d) {\n map.set(key(d.nodeId, d.type, d.handleId), d);\n notify();\n return () => {\n // Only delete if our descriptor is still the registered one — guards\n // against races when a node unmounts a Handle and immediately\n // remounts it with the same id during a quick re-render.\n const k = key(d.nodeId, d.type, d.handleId);\n if (map.get(k) === d) {\n map.delete(k);\n notify();\n }\n };\n },\n resolve(nodeId, type, handleId) {\n return map.get(key(nodeId, type, handleId));\n },\n subscribe(listener) {\n listeners.add(listener);\n return () => {\n listeners.delete(listener);\n };\n },\n };\n}\n","\"use client\";\n\n// ════════════════════════════════════════════════════════════════════════\n// FlowNodeContext — descendants of a node (Handle, NodeToolbar, …) read\n// the node id and basic state through this context.\n// ════════════════════════════════════════════════════════════════════════\n\nimport { createContext, useContext } from \"react\";\nimport type { WorkflowNode } from \"../../editor\";\n\nexport interface FlowNodeContextValue {\n id: string;\n node: WorkflowNode;\n selected: boolean;\n}\n\nexport const FlowNodeContext = createContext<FlowNodeContextValue | null>(null);\n\nexport function useFlowNodeContext(): FlowNodeContextValue {\n const v = useContext(FlowNodeContext);\n if (!v) {\n throw new Error(\n \"[@octaviaflow/core/workflow] Handle / NodeToolbar must be inside a node renderer.\",\n );\n }\n return v;\n}\n","\"use client\";\n\n// ════════════════════════════════════════════════════════════════════════\n// FlowNode — wrapper for any node in the v2 editor.\n// ════════════════════════════════════════════════════════════════════════\n// Responsibilities:\n// 1. Position itself absolutely at `node.position` (in flow space).\n// 2. Provide FlowNodeContext so descendants (Handle, NodeToolbar) know\n// which node they live in.\n// 3. Begin drag on pointerdown (the canvas-level pointermove takes over).\n// 4. Begin selection on click.\n// 5. Dispatch to the kind component for the actual chrome.\n//\n// The wrapper does NOT subscribe to its own selected state via the store;\n// instead the parent NodesLayer passes the resolved `selected` flag down\n// — keeps re-render fan-out predictable.\n\nimport { type PointerEvent, useEffect, useMemo, useRef } from \"react\";\nimport { cn } from \"../../../utils/cn\";\nimport type { WorkflowNode } from \"../../editor\";\nimport { useFlowNodeBridge } from \"../FlowCanvas/FlowCanvasContext\";\nimport { FlowNodeContext, type FlowNodeContextValue } from \"./FlowNodeContext\";\nimport type { NodeKindComponent } from \"./nodeKinds\";\n\nexport interface FlowNodeProps {\n node: WorkflowNode;\n selected: boolean;\n dragging: boolean;\n isConnecting: boolean;\n Kind: NodeKindComponent;\n /** Optional fallback width for un-measured nodes — defaults to 240. */\n defaultWidth?: number;\n}\n\nexport function FlowNode({\n node,\n selected,\n dragging,\n isConnecting,\n Kind,\n // Match the BaseNode body's fixed 368 px width so the wrapper bbox and\n // the rendered card line up on the first paint — before the\n // ResizeObserver has had a chance to write back the measured size.\n // Container kinds (group / forEach) opt out by setting `node.width`.\n defaultWidth = 368,\n}: FlowNodeProps) {\n const bridge = useFlowNodeBridge();\n const wrapperRef = useRef<HTMLDivElement>(null);\n\n // ── ResizeObserver — feed real dimensions back through onNodesChange so\n // edges can compute endpoints against the actual rendered footprint.\n // Without this, every node looks 96px tall to the edge layer and arrows\n // land mid-air below tall nodes.\n //\n // Container kinds (`group`, `forEach`) are EXEMPT. Why: when a group is\n // collapsed its rendered height shrinks to 36px; if we measure that the\n // 36px gets written back into `node.height` and the group never restores\n // its expanded height on un-collapse. Container size is consumer-driven\n // (set explicitly via `node.width` / `node.height`) — no measurement.\n useEffect(() => {\n const el = wrapperRef.current;\n if (!el || typeof ResizeObserver === \"undefined\") return;\n if (node.type === \"group\" || node.type === \"forEach\") return;\n const ro = new ResizeObserver(() => {\n // `offsetWidth/Height` are un-affected by ancestor CSS transforms\n // (the canvas viewport applies `scale(zoom)`). `getBoundingClientRect`\n // would scale with zoom and give us wildly wrong values when zoomed\n // in/out.\n bridge.reportDimensions(node.id, el.offsetWidth, el.offsetHeight);\n });\n ro.observe(el);\n return () => ro.disconnect();\n }, [bridge, node.id, node.type]);\n\n const ctx = useMemo<FlowNodeContextValue>(\n () => ({ id: node.id, node, selected }),\n [node, selected],\n );\n\n // Track pointerdown coordinates so we can decide post-pointerup whether\n // this was a click or a drag. DOM fires `click` after a drag too, which\n // would otherwise re-open the config panel when the user only moved the\n // node. 5 px matches the platform's canvas `paneClickDistance` default.\n const downPosRef = useRef<{ x: number; y: number } | null>(null);\n const draggedRef = useRef(false);\n const CLICK_VS_DRAG_PX = 5;\n\n const handlePointerDown = (e: PointerEvent<HTMLDivElement>) => {\n // Skip drag if the pointerdown originated on a handle — that gesture\n // is owned by the connect middleware.\n if ((e.target as HTMLElement).closest(\"[data-handle-id]\")) return;\n // Skip drag inside opt-out regions (allows form controls inside nodes).\n if ((e.target as HTMLElement).closest(\"[data-flow-no-drag='true']\")) return;\n e.stopPropagation();\n downPosRef.current = { x: e.clientX, y: e.clientY };\n draggedRef.current = false;\n // Pass through altKey — the canvas's drag middleware uses it for\n // Alt-detach (drop out of a parent group, or rebind into a new one).\n bridge.beginNodeDrag(node.id, e.pointerId, e.clientX, e.clientY, e.altKey);\n };\n\n const handlePointerMove = (e: PointerEvent<HTMLDivElement>) => {\n const start = downPosRef.current;\n if (!start || draggedRef.current) return;\n if (\n Math.abs(e.clientX - start.x) > CLICK_VS_DRAG_PX ||\n Math.abs(e.clientY - start.y) > CLICK_VS_DRAG_PX\n ) {\n draggedRef.current = true;\n }\n };\n\n const handleClick = (e: PointerEvent<HTMLDivElement>) => {\n if ((e.target as HTMLElement).closest(\"[data-handle-id]\")) return;\n e.stopPropagation();\n // Click that arrives after a drag is a synthetic side-effect — DO NOT\n // re-fire selection or notify the consumer (would re-open the panel\n // they were trying to keep on the original node).\n if (draggedRef.current) {\n draggedRef.current = false;\n downPosRef.current = null;\n return;\n }\n downPosRef.current = null;\n // Selection state was already updated at pointerdown by beginNodeDrag.\n // Here we re-assert it (handles meta-key toggle on already-selected\n // nodes) and ALSO notify the consumer of the click — which `selectNode`\n // intentionally no longer does on its own.\n bridge.selectNode(node.id, e.metaKey || e.ctrlKey || e.shiftKey);\n bridge.notifyNodeClick(node.id);\n };\n\n return (\n <div\n ref={wrapperRef}\n data-node-id={node.id}\n data-node-type={node.type}\n data-node-selected={selected ? \"true\" : \"false\"}\n className={cn(\n \"ods-flow-node-v2\",\n `ods-flow-node-v2--kind-${node.type}`,\n selected && \"ods-flow-node-v2--selected\",\n dragging && \"ods-flow-node-v2--dragging\",\n isConnecting && \"ods-flow-node-v2--connecting\",\n node.className,\n )}\n style={{\n position: \"absolute\",\n left: node.position.x,\n top: node.position.y,\n width: node.width ?? defaultWidth,\n // Z-stack (per architecture doc): groups (20) sit below normal\n // nodes (30) so children render visually on top of their parent\n // frame. Selection raises by 10. Consumer override wins.\n zIndex:\n node.zIndex ??\n (selected ? (node.type === \"group\" ? 35 : 40) : node.type === \"group\" ? 20 : 30),\n ...node.style,\n }}\n onPointerDown={handlePointerDown}\n onPointerMove={handlePointerMove}\n onClick={handleClick}\n >\n <FlowNodeContext.Provider value={ctx}>\n <Kind node={node} selected={selected} dragging={dragging} isConnecting={isConnecting} />\n </FlowNodeContext.Provider>\n </div>\n );\n}\n","\"use client\";\n\n// ════════════════════════════════════════════════════════════════════════\n// FlowCanvasContext — imperative entry points used by Handle + FlowNode.\n// ════════════════════════════════════════════════════════════════════════\n// Each `<FlowCanvas>` creates a private context value containing the\n// callbacks needed by its descendants. We expose these via a \"dispatch\"\n// hook in the spirit of useReducer; the action payload is opaque to\n// descendants — they just know which method to call.\n\nimport { createContext, useContext } from \"react\";\n\nexport interface FlowDispatchAction {\n type: \"connection/start\";\n nodeId: string;\n handleId: string;\n handleType: \"source\" | \"target\";\n pointerId: number;\n clientX: number;\n clientY: number;\n}\n\nexport type FlowDispatch = (action: FlowDispatchAction) => void;\n\nexport const FlowDispatchContext = createContext<FlowDispatch | null>(null);\n\nexport function useFlowDispatch(): FlowDispatch {\n const dispatch = useContext(FlowDispatchContext);\n if (!dispatch) {\n throw new Error(\n \"[@octaviaflow/core/workflow] useFlowDispatch must be called inside <FlowCanvas>.\",\n );\n }\n return dispatch;\n}\n\n/**\n * Internal-only callbacks shared with FlowNode. Not part of the public\n * surface; node renderers use the `useFlowNodeContext` hook instead.\n */\nexport interface FlowNodeBridge {\n beginNodeDrag(\n nodeId: string,\n pointerId: number,\n clientX: number,\n clientY: number,\n altKey?: boolean,\n ): void;\n selectNode(nodeId: string, additive: boolean): void;\n /**\n * Fire the consumer's `onNodeClick` for this node. Split from\n * `selectNode` so drag-start (which selects the node so it carries the\n * selection style) does NOT also fire the click event — otherwise a\n * drag would re-open the config panel.\n */\n notifyNodeClick(nodeId: string): void;\n selectEdge(edgeId: string, additive: boolean): void;\n /**\n * Reports measured DOM dimensions back to the canvas. FlowNode observes\n * itself via ResizeObserver and calls this on size changes. The canvas\n * de-dupes (skips when w/h unchanged) and emits a `dimensions`\n * NodeChange so edges can recompute against the real footprint.\n */\n reportDimensions(nodeId: string, width: number, height: number): void;\n /** Removes a single node. Edges that reference it are dropped too. */\n deleteNode(nodeId: string): void;\n /**\n * Toggle the `data.collapsed` flag on a group / forEach container.\n * Used by the chevron in the GroupNode / ForEachNode header so the\n * user can expand/collapse the subflow without an external toolbar.\n * No-op for non-container kinds.\n */\n toggleNodeCollapse(nodeId: string): void;\n}\n\nexport const FlowNodeBridgeContext = createContext<FlowNodeBridge | null>(null);\n\nexport function useFlowNodeBridge(): FlowNodeBridge {\n const b = useContext(FlowNodeBridgeContext);\n if (!b) {\n throw new Error(\"[@octaviaflow/core/workflow] FlowNode must be a child of <FlowCanvas>.\");\n }\n return b;\n}\n","// ════════════════════════════════════════════════════════════════════════\n// Node-kind registry — maps a `node.type` string to a React component.\n// ════════════════════════════════════════════════════════════════════════\n// We deliberately avoid the \"pass a `nodeTypes` map prop and pray the\n// caller memoises it\" anti-pattern. The registry is a stable map managed\n// internally; consumers can extend it via `useRegisterNodeKind()` or by\n// passing an override prop that is *frozen* by the canvas the first time\n// it sees it.\n\nimport type { ComponentType } from \"react\";\nimport type { WorkflowNode } from \"../../editor\";\n\n/**\n * Props passed to every kind renderer. Matches the public `NodeProps`\n * shape we expose to consumers; we deliberately do NOT duplicate\n * coordinate fields (see ADR-003).\n */\nexport interface NodeKindProps<TData = unknown> {\n /** The full node — kinds read `data`, can mutate via `updateNodeData`. */\n node: WorkflowNode<TData>;\n /** True when this node is the focus of selection. */\n selected: boolean;\n /** True while a drag is in progress on this node. */\n dragging: boolean;\n /** True when any connection drag is in flight and could end here. */\n isConnecting: boolean;\n}\n\nexport type NodeKindComponent<TData = unknown> = ComponentType<NodeKindProps<TData>>;\n\nexport type NodeKindRegistry = Record<string, NodeKindComponent>;\n\n/**\n * Build a registry from a default set plus optional overrides. The result\n * is a frozen object so consumers can't mutate it post-hoc.\n */\nexport function buildNodeKindRegistry(\n defaults: NodeKindRegistry,\n overrides?: NodeKindRegistry,\n): NodeKindRegistry {\n return Object.freeze({ ...defaults, ...(overrides ?? {}) });\n}\n","\"use client\";\n\n// ════════════════════════════════════════════════════════════════════════\n// Handle — a port primitive that custom node renderers drop in.\n// ════════════════════════════════════════════════════════════════════════\n// Responsibilities:\n// 1. Register its descriptor (nodeId, handleId, type, side, index, total)\n// so edges can resolve its absolute centre.\n// 2. Render a visible dot at the configured side.\n// 3. Initiate connection drags via Pointer Events.\n//\n// The Handle does NOT own pointermove / pointerup — those live on the\n// FlowCanvas-level connect middleware, which sees the gesture all the\n// way through even if the pointer leaves the handle.\n\nimport { type CSSProperties, type PointerEvent, useEffect, useRef } from \"react\";\nimport { cn } from \"../../../utils/cn\";\nimport type { HandlePosition, HandleType } from \"../../editor\";\nimport { useFlowDispatch } from \"../FlowCanvas/FlowCanvasContext\";\nimport { useFlowNodeContext } from \"../FlowNode/FlowNodeContext\";\nimport { useHandleRegistry } from \"./handleRegistry\";\n\nexport interface HandleProps {\n /** `source` = connections start here; `target` = connections end here. */\n type: HandleType;\n /** Which side of the node the handle sits on. */\n position: HandlePosition;\n /** Stable id within the node. Default `\"default\"`; required when >1 handle of same type. */\n id?: string;\n /** Defaults to true. Setting false disables both starting and ending here. */\n isConnectable?: boolean;\n /** Allow this handle to *start* a connection. Defaults to `isConnectable`. */\n isConnectableStart?: boolean;\n /** Allow this handle to *end* a connection. Defaults to `isConnectable`. */\n isConnectableEnd?: boolean;\n /** 0-based position among same-(node, side) handles. Defaults to 0. */\n index?: number;\n /** Total handles on the same (node, side). Defaults to 1. */\n total?: number;\n /** Optional caption rendered next to the dot (e.g. \"true\"/\"false\"). */\n label?: string;\n className?: string;\n style?: CSSProperties;\n}\n\nconst DEFAULT_HANDLE_ID = \"default\";\n\nexport function Handle({\n type,\n position,\n id = DEFAULT_HANDLE_ID,\n isConnectable = true,\n isConnectableStart,\n isConnectableEnd,\n index = 0,\n total = 1,\n label,\n className,\n style,\n}: HandleProps) {\n const registry = useHandleRegistry();\n const node = useFlowNodeContext();\n const dispatch = useFlowDispatch();\n const ref = useRef<HTMLDivElement>(null);\n\n const canStart = isConnectableStart ?? isConnectable;\n const canEnd = isConnectableEnd ?? isConnectable;\n\n // Register on every render so changes to side/index/total are visible\n // immediately to edges. The registry de-dupes by (nodeId, handleId).\n useEffect(() => {\n const dispose = registry.register({\n nodeId: node.id,\n handleId: id,\n type,\n side: position,\n index,\n total,\n });\n return dispose;\n }, [registry, node.id, id, type, position, index, total]);\n\n const handlePointerDown = (e: PointerEvent<HTMLDivElement>) => {\n if (!canStart) return;\n e.stopPropagation();\n e.preventDefault();\n dispatch({\n type: \"connection/start\",\n nodeId: node.id,\n handleId: id,\n handleType: type,\n pointerId: e.pointerId,\n clientX: e.clientX,\n clientY: e.clientY,\n });\n };\n\n // Pointerup on a Handle is the \"drop on this handle\" gesture. The\n // FlowCanvas-level pointerup also fires; the canvas resolves the target\n // handle by hit-testing `e.target.closest('[data-handle-id]')`.\n return (\n <div\n ref={ref}\n data-handle-id={id}\n data-handle-node-id={node.id}\n data-handle-type={type}\n data-handle-side={position}\n data-handle-connectable-end={canEnd ? \"true\" : \"false\"}\n className={cn(\n \"ods-flow-handle\",\n `ods-flow-handle--${type}`,\n `ods-flow-handle--side-${position}`,\n !isConnectable && \"ods-flow-handle--disabled\",\n className,\n )}\n style={{\n ...handleSideStyle(position, index, total),\n ...style,\n }}\n onPointerDown={handlePointerDown}\n >\n <div className=\"ods-flow-handle__dot\" />\n {label && <span className=\"ods-flow-handle__label\">{label}</span>}\n </div>\n );\n}\n\n// Position the handle along its side. The visual element is small\n// (12 px), so we offset by half its size so the dot's centre lands on\n// the node's edge. Index/total spread multiple handles evenly.\nfunction handleSideStyle(side: HandlePosition, index: number, total: number): CSSProperties {\n const ratio = ((index + 1) / (total + 1)) * 100;\n switch (side) {\n case \"top\":\n return { position: \"absolute\", top: -6, left: `${ratio}%`, transform: \"translateX(-50%)\" };\n case \"bottom\":\n return { position: \"absolute\", bottom: -6, left: `${ratio}%`, transform: \"translateX(-50%)\" };\n case \"left\":\n return { position: \"absolute\", left: -6, top: `${ratio}%`, transform: \"translateY(-50%)\" };\n case \"right\":\n return { position: \"absolute\", right: -6, top: `${ratio}%`, transform: \"translateY(-50%)\" };\n }\n}\n","\"use client\";\n\n// ════════════════════════════════════════════════════════════════════════\n// NodeResizer — drag-to-resize handles attached to a node.\n// ════════════════════════════════════════════════════════════════════════\n// Dropped inside a custom node renderer. Four corner handles each adjust\n// width/height (and, where appropriate, position so the OPPOSITE corner\n// stays pinned). Width/height changes flow back through the imperative\n// instance via `updateNode`.\n//\n// Visible by default only when the host node is selected. Min/max sizes\n// + aspect-ratio lock keep the resize sensible. We deliberately do NOT\n// ship a `shouldResize` veto (yet) — that's a follow-on.\n\nimport { type CSSProperties, type PointerEvent, useRef } from \"react\";\nimport { cn } from \"../../../utils/cn\";\nimport { useFlow } from \"../../hooks/useFlow\";\nimport { useViewport } from \"../../store/selectors\";\nimport { DEFAULT_NODE_HEIGHT, DEFAULT_NODE_WIDTH } from \"../../utils/geometry\";\nimport { useFlowNodeContext } from \"../FlowNode/FlowNodeContext\";\n\nexport interface NodeResizerProps {\n /** Force-visible. Default: visible iff the host node is selected. */\n isVisible?: boolean;\n /** Lower bound for the resize. Defaults to 80×60. */\n minWidth?: number;\n minHeight?: number;\n /** Upper bound for the resize. Defaults unbounded. */\n maxWidth?: number;\n maxHeight?: number;\n /** Lock width:height ratio at the value computed from the node's\n * current dimensions on resize-start. */\n keepAspectRatio?: boolean;\n /** Fired on every pointermove during resize. */\n onResize?: (size: { width: number; height: number }) => void;\n /** Fired on pointerup (the committed size). */\n onResizeEnd?: (size: { width: number; height: number }) => void;\n /** Override handle colour. */\n color?: string;\n}\n\ntype Corner = \"nw\" | \"ne\" | \"sw\" | \"se\";\n\ninterface DragState {\n pointerId: number;\n corner: Corner;\n startClientX: number;\n startClientY: number;\n startWidth: number;\n startHeight: number;\n startX: number;\n startY: number;\n aspect: number; // w / h\n}\n\nexport function NodeResizer({\n isVisible,\n minWidth = 80,\n minHeight = 60,\n maxWidth,\n maxHeight,\n keepAspectRatio = false,\n onResize,\n onResizeEnd,\n color,\n}: NodeResizerProps) {\n const { node, selected } = useFlowNodeContext();\n const viewport = useViewport();\n const flow = useFlow();\n const dragRef = useRef<DragState | null>(null);\n\n const show = isVisible ?? selected;\n if (!show) return null;\n\n const beginResize = (e: PointerEvent<HTMLDivElement>, corner: Corner) => {\n e.preventDefault();\n e.stopPropagation();\n (e.target as HTMLElement).setPointerCapture(e.pointerId);\n const w = node.width ?? DEFAULT_NODE_WIDTH;\n const h = node.height ?? DEFAULT_NODE_HEIGHT;\n dragRef.current = {\n pointerId: e.pointerId,\n corner,\n startClientX: e.clientX,\n startClientY: e.clientY,\n startWidth: w,\n startHeight: h,\n startX: node.position.x,\n startY: node.position.y,\n aspect: w / Math.max(1, h),\n };\n };\n\n const onMove = (e: PointerEvent<HTMLDivElement>) => {\n const drag = dragRef.current;\n if (!drag || drag.pointerId !== e.pointerId) return;\n const dx = (e.clientX - drag.startClientX) / viewport.zoom;\n const dy = (e.clientY - drag.startClientY) / viewport.zoom;\n let nextW = drag.startWidth;\n let nextH = drag.startHeight;\n let nextX = drag.startX;\n let nextY = drag.startY;\n switch (drag.corner) {\n case \"se\":\n nextW = drag.startWidth + dx;\n nextH = drag.startHeight + dy;\n break;\n case \"sw\":\n nextW = drag.startWidth - dx;\n nextH = drag.startHeight + dy;\n nextX = drag.startX + dx;\n break;\n case \"ne\":\n nextW = drag.startWidth + dx;\n nextH = drag.startHeight - dy;\n nextY = drag.startY + dy;\n break;\n case \"nw\":\n nextW = drag.startWidth - dx;\n nextH = drag.startHeight - dy;\n nextX = drag.startX + dx;\n nextY = drag.startY + dy;\n break;\n }\n if (keepAspectRatio) {\n // Maintain the original ratio — fit height to width.\n nextH = nextW / drag.aspect;\n if (drag.corner === \"nw\" || drag.corner === \"ne\") {\n nextY = drag.startY + (drag.startHeight - nextH);\n }\n }\n nextW = Math.max(minWidth, maxWidth ? Math.min(maxWidth, nextW) : nextW);\n nextH = Math.max(minHeight, maxHeight ? Math.min(maxHeight, nextH) : nextH);\n flow.updateNode(node.id, {\n width: nextW,\n height: nextH,\n position: { x: nextX, y: nextY },\n });\n onResize?.({ width: nextW, height: nextH });\n };\n\n const onUp = (e: PointerEvent<HTMLDivElement>) => {\n if (dragRef.current?.pointerId === e.pointerId) {\n const cur = flow.getNode(node.id);\n if (cur) {\n onResizeEnd?.({\n width: cur.width ?? DEFAULT_NODE_WIDTH,\n height: cur.height ?? DEFAULT_NODE_HEIGHT,\n });\n }\n dragRef.current = null;\n }\n };\n\n const handleColor = color ?? \"var(--ods-accent)\";\n const handleStyle = (corner: Corner): CSSProperties => {\n const base: CSSProperties = {\n position: \"absolute\",\n width: 12,\n height: 12,\n background: \"var(--ods-surface-canvas)\",\n border: `2px solid ${handleColor}`,\n borderRadius: 2,\n cursor: cursorFor(corner),\n touchAction: \"none\",\n // Place each handle so its CENTRE sits on the corresponding corner.\n transform: \"translate(-50%, -50%)\",\n };\n switch (corner) {\n case \"nw\":\n return { ...base, top: 0, left: 0 };\n case \"ne\":\n return { ...base, top: 0, left: \"100%\" };\n case \"sw\":\n return { ...base, top: \"100%\", left: 0 };\n case \"se\":\n return { ...base, top: \"100%\", left: \"100%\" };\n }\n };\n\n return (\n <div className={cn(\"ods-node-resizer\")} data-flow-no-drag=\"true\">\n {([\"nw\", \"ne\", \"sw\", \"se\"] as Corner[]).map((corner) => (\n <div\n key={corner}\n style={handleStyle(corner)}\n onPointerDown={(e) => beginResize(e, corner)}\n onPointerMove={onMove}\n onPointerUp={onUp}\n onPointerCancel={onUp}\n aria-label={`Resize ${corner}`}\n />\n ))}\n </div>\n );\n}\n\nfunction cursorFor(corner: Corner): string {\n // Standard 8-direction resize cursors. We only ship corners for v1; the\n // edge handles (n/s/e/w) can come later.\n switch (corner) {\n case \"nw\":\n case \"se\":\n return \"nwse-resize\";\n case \"ne\":\n case \"sw\":\n return \"nesw-resize\";\n }\n}\n","\"use client\";\n\n// ════════════════════════════════════════════════════════════════════════\n// BaseNode — shared chrome for built-in kinds.\n// ════════════════════════════════════════════════════════════════════════\n// Visual structure (mirrors the finalised platform node):\n//\n// ┌─[ KIND ]──────────────────────────────────┐ ← external pill = node TYPE\n// │ ╭──╮ Title (node NAME) │\n// │ │● │ ▸ [CHIP] description-value │ ← chip + value (config-driven)\n// │ ╰──╯ │\n// │ [×] │ ← delete bottom-right\n// └──────────────────────────────────────────[●] ← status top-right\n//\n// The pill is the node TYPE label (e.g. \"HTTP\", \"WEBHOOK\", \"ACTION\") —\n// not the node name. The name lives in the body title. The body's info\n// line takes an optional `chip` (small inline badge) plus a value, which\n// is the canonical pattern for showing the most-relevant config value\n// (HTTP method + path, condition operator + expression, etc.).\n\nimport { TrashCanIcon } from \"@octaviaflow/icons\";\nimport { type ReactNode, useContext } from \"react\";\nimport { cn } from \"../../../utils/cn\";\nimport { FlowNodeBridgeContext } from \"../FlowCanvas/FlowCanvasContext\";\nimport { FlowNodeContext } from \"../FlowNode/FlowNodeContext\";\n\nexport type BaseNodeStatus = \"idle\" | \"running\" | \"success\" | \"error\" | \"warning\";\n\nexport interface BaseNodeProps {\n /** Pill label — the node TYPE/category (e.g. \"HTTP\", \"WEBHOOK\", \"ACTION\"). */\n kind: ReactNode;\n /** Optional small icon inside the pill, left of the kind label. */\n kindIcon?: ReactNode;\n /** Icon shown in the body bubble (32px circle). */\n icon?: ReactNode;\n /** Bold name shown in the body — this is the user-facing instance name. */\n title: ReactNode;\n /**\n * Optional chip rendered before the description text — used for\n * configuration values like HTTP method (\"GET\"), condition operator\n * (\"==\"), execution mode, etc. Inherits the accent colour.\n */\n chip?: ReactNode;\n /**\n * The body description / value — typically the most-relevant config\n * field (path, url, expression). Clamps to two lines.\n */\n description?: ReactNode;\n /**\n * Generic right-aligned chip slot. Renders inside the info row to the\n * right of the description (e.g. an `/v1/orders/:id` path chip next to\n * a `GET` method `chip`). Inherits the kind accent like `chip` does.\n */\n valueChip?: ReactNode;\n /** Per-kind accent — paints the pill background and the chip. */\n accent?: \"blue\" | \"violet\" | \"amber\" | \"green\" | \"red\" | \"slate\";\n /** Status dot in the top-right corner (config / runtime). */\n status?: BaseNodeStatus;\n /**\n * Delete button click — when set, the corner [×] button uses this. If\n * omitted, BaseNode auto-wires it through the FlowCanvas bridge so the\n * default behaviour is \"this button deletes me\". Pass `false` to hide.\n */\n onDelete?: (() => void) | false;\n /** Footer slot below the description (e.g. additional metadata). */\n footer?: ReactNode;\n className?: string;\n /** Handles + extras — positioned absolutely by the caller. */\n children?: ReactNode;\n}\n\nexport function BaseNode({\n kind,\n kindIcon,\n icon,\n title,\n chip,\n description,\n valueChip,\n accent = \"green\",\n status,\n onDelete,\n footer,\n className,\n children,\n}: BaseNodeProps) {\n // Auto-wire delete via the canvas bridge when the kind didn't pass an\n // explicit handler. `onDelete={false}` disables the button entirely.\n const ctx = useContext(FlowNodeContext);\n const bridge = useContext(FlowNodeBridgeContext);\n const deleteHandler: (() => void) | undefined =\n onDelete === false\n ? undefined\n : (onDelete ?? (ctx && bridge ? () => bridge.deleteNode(ctx.id) : undefined));\n return (\n <div\n className={cn(\n \"ods-flow-base-node\",\n `ods-flow-base-node--accent-${accent}`,\n status && `ods-flow-base-node--status-${status}`,\n className,\n )}\n >\n {/* External pill — the node TYPE label, not the name. */}\n <div className=\"ods-flow-base-node__pill\">\n {kindIcon && (\n <span className=\"ods-flow-base-node__pill-icon\" aria-hidden=\"true\">\n {kindIcon}\n </span>\n )}\n <span className=\"ods-flow-base-node__pill-label\">{kind}</span>\n </div>\n\n {/* Status indicator — top-right of the card. */}\n {status && status !== \"idle\" && (\n <span\n className={cn(\"ods-flow-base-node__status\", `ods-flow-base-node__status--${status}`)}\n aria-hidden=\"true\"\n />\n )}\n\n {/* Body */}\n <div className=\"ods-flow-base-node__body\">\n <div className=\"ods-flow-base-node__content\">\n <div className=\"ods-flow-base-node__bubble\" aria-hidden=\"true\">\n {icon}\n </div>\n <div className=\"ods-flow-base-node__content-text\">\n <div className=\"ods-flow-base-node__content-title\">{title}</div>\n {(chip !== undefined || description !== undefined || valueChip !== undefined) && (\n <div className=\"ods-flow-base-node__content-info\">\n {chip !== undefined && <span className=\"ods-flow-base-node__chip\">{chip}</span>}\n {description !== undefined && (\n <span className=\"ods-flow-base-node__description\">{description}</span>\n )}\n {valueChip !== undefined && (\n <span className=\"ods-flow-base-node__value-chip\">{valueChip}</span>\n )}\n </div>\n )}\n </div>\n </div>\n\n {footer && <div className=\"ods-flow-base-node__footer\">{footer}</div>}\n\n {deleteHandler && (\n <button\n type=\"button\"\n className=\"ods-flow-base-node__delete\"\n onClick={(e) => {\n e.stopPropagation();\n deleteHandler();\n }}\n aria-label=\"Delete node\"\n data-flow-no-drag=\"true\"\n title=\"Delete node\"\n >\n <TrashCanIcon size={16} aria-hidden />\n </button>\n )}\n </div>\n\n {/* Handles + extras slot. */}\n {children}\n </div>\n );\n}\n","\"use client\";\n\n// ════════════════════════════════════════════════════════════════════════\n// Built-in node kinds — Action / Trigger / Condition / Group.\n// ════════════════════════════════════════════════════════════════════════\n// Each kind is a small functional component that composes BaseNode and\n// adds its own Handle layout. Additional kinds (Loop, Parallel, Wait,\n// Output, Error, Sticky) will land in a follow-up pass.\n\nimport type { PointerEvent } from \"react\";\nimport { useFlowNodeBridge } from \"../FlowCanvas/FlowCanvasContext\";\nimport type { NodeKindComponent, NodeKindProps, NodeKindRegistry } from \"../FlowNode/nodeKinds\";\nimport { Handle } from \"../Handle/Handle\";\nimport { NodeResizer } from \"../NodeResizer/NodeResizer\";\nimport { BaseNode, type BaseNodeStatus } from \"./BaseNode\";\n\n// Common payload shape that built-in kinds expect. Consumers can extend\n// `data` with their own fields; the renderer just reads the named slots.\nexport interface BuiltInNodeData {\n /** Pill label override — defaults to the kind's canonical type label\n * (e.g. \"HTTP\", \"WEBHOOK\", \"ACTION\"). Rarely needed; mostly here so\n * consumers can rename \"HTTP\" → \"REST\" without forking the kind. */\n kind?: import(\"react\").ReactNode;\n /** Body name — the user-facing instance label (e.g. \"Fetch Order\"). */\n title?: string;\n /**\n * Optional chip rendered before the description value, used for\n * configuration metadata that should read at a glance — HTTP method,\n * condition operator, schedule frequency, etc. Renders as a coloured\n * inline badge that inherits the kind accent.\n */\n chip?: import(\"react\").ReactNode;\n /** Description / config value — the most-relevant config field (path,\n * url, expression). Clamped to two lines in the body. */\n description?: import(\"react\").ReactNode;\n /**\n * Generic right-aligned chip slot — used when a node has a secondary\n * config value to surface (e.g. the path `/v1/orders/:id` next to an\n * HTTP `GET` method chip). Inherits the kind accent.\n */\n valueChip?: import(\"react\").ReactNode;\n /** Legacy alias for `description` — older fixtures still pass this. */\n subtitle?: import(\"react\").ReactNode;\n /** Legacy alias for `chip` — older fixtures still pass this. */\n badge?: import(\"react\").ReactNode;\n /** Runtime status — drives the pulsing dot in the top-right corner. */\n status?: BaseNodeStatus;\n /** Body bubble icon (32px circle). */\n icon?: import(\"react\").ReactNode;\n // Condition-specific:\n branches?: { id: string; label: string }[];\n // Group-specific:\n collapsed?: boolean;\n /** Populated by `collapseFor()` — number of descendants hidden under\n * this collapsed group; the renderer shows it as a \"N steps\" badge. */\n hiddenCount?: number;\n /** Dim the container's frame to signal \"the engine will skip this\n * subflow + all descendants\". Visual only — semantics enforced by\n * the consumer's execution layer. */\n disabled?: boolean;\n // ForEach-specific:\n iterator?: string;\n // Wait-specific (not yet implemented; reserved):\n waitMs?: number;\n // Webhook / HttpRequest-specific helpers — populate `chip` + `description`\n // automatically when present.\n method?: string;\n path?: string;\n url?: string;\n}\n\n// ────────────────────────────────────────────────────────────────────────\n// ActionNode — generic action; 1 input on top + 1 output on bottom.\n// ────────────────────────────────────────────────────────────────────────\nexport const ActionNode: NodeKindComponent<BuiltInNodeData> = ({\n node,\n}: NodeKindProps<BuiltInNodeData>) => {\n const d = node.data ?? {};\n return (\n <BaseNode\n kind={d.kind ?? \"ACTION\"}\n icon={d.icon}\n title={d.title ?? \"Action\"}\n chip={d.chip ?? d.badge}\n description={d.description ?? d.subtitle}\n valueChip={d.valueChip}\n status={d.status}\n accent=\"green\"\n >\n <Handle type=\"target\" position=\"top\" />\n <Handle type=\"source\" position=\"bottom\" />\n </BaseNode>\n );\n};\n\n// ────────────────────────────────────────────────────────────────────────\n// TriggerNode — no input port; green accent matches the platform.\n// ────────────────────────────────────────────────────────────────────────\nexport const TriggerNode: NodeKindComponent<BuiltInNodeData> = ({\n node,\n}: NodeKindProps<BuiltInNodeData>) => {\n const d = node.data ?? {};\n return (\n <BaseNode\n kind={d.kind ?? \"TRIGGER\"}\n icon={d.icon}\n title={d.title ?? \"Trigger\"}\n chip={d.chip}\n description={d.description ?? \"Manually triggered\"}\n valueChip={d.valueChip}\n status={d.status}\n accent=\"green\"\n >\n <Handle type=\"source\" position=\"bottom\" />\n </BaseNode>\n );\n};\n\n// ────────────────────────────────────────────────────────────────────────\n// ConditionNode — single input on top; multiple labelled outputs along\n// the bottom edge. Default branches: true / false.\n// ────────────────────────────────────────────────────────────────────────\nexport const ConditionNode: NodeKindComponent<BuiltInNodeData> = ({\n node,\n}: NodeKindProps<BuiltInNodeData>) => {\n const d = node.data ?? {};\n const branches = d.branches ?? [\n { id: \"true\", label: \"true\" },\n { id: \"false\", label: \"false\" },\n ];\n return (\n <BaseNode\n kind={d.kind ?? \"CONDITION\"}\n icon={d.icon}\n title={d.title ?? \"Condition\"}\n chip={d.chip ?? d.badge}\n description={d.description ?? d.subtitle}\n valueChip={d.valueChip}\n status={d.status}\n accent=\"amber\"\n >\n <Handle type=\"target\" position=\"top\" />\n {branches.map((b, i) => (\n <Handle\n key={b.id}\n type=\"source\"\n position=\"bottom\"\n id={b.id}\n index={i}\n total={branches.length}\n label={b.label}\n />\n ))}\n </BaseNode>\n );\n};\n\n// ────────────────────────────────────────────────────────────────────────\n// GroupNode — frame container for sub-flows. Children render absolutely\n// positioned (per ADR-003) on top of the frame.\n//\n// When `data.collapsed === true`:\n// - Body collapses to the header strip.\n// - Two perimeter handles are registered (`__group_in` on top,\n// `__group_out` on bottom). The `collapseFor()` helper rewrites\n// edges that cross the boundary so they terminate at these handles\n// instead of dangling at hidden children.\n// - A count badge (\"N steps\") is rendered next to the title.\n// ────────────────────────────────────────────────────────────────────────\nexport const GroupNode: NodeKindComponent<BuiltInNodeData> = ({\n node,\n}: NodeKindProps<BuiltInNodeData>) => {\n const d = node.data ?? {};\n const collapsed = !!d.collapsed;\n const disabled = !!d.disabled;\n // The host (or `collapseFor`) reports the descendant count via\n // `node.data.hiddenCount`. We fall back to undefined → no badge.\n const hiddenCount = (d as { hiddenCount?: number }).hiddenCount;\n const bridge = useFlowNodeBridge();\n // The chevron is a button — clicking it (and only it) toggles collapse.\n // We stop propagation so the click doesn't also bubble up to the node\n // wrapper's selection / drag-start gestures. `data-flow-no-drag` keeps\n // pointerdown from starting a node drag.\n const onChevronClick = (e: PointerEvent<HTMLButtonElement>) => {\n e.stopPropagation();\n bridge.toggleNodeCollapse(node.id);\n };\n return (\n <div\n className=\"ods-flow-group\"\n data-collapsed={collapsed ? \"true\" : \"false\"}\n data-disabled={disabled ? \"true\" : undefined}\n style={{\n width: node.width ?? 360,\n height: collapsed ? 36 : (node.height ?? 200),\n }}\n >\n {/* Built-in corner-resize handles. Hidden when collapsed (resize\n a 36px-tall strip makes no sense). Visibility otherwise\n defaults to \"node is selected\" — driven by FlowNodeContext. */}\n {!collapsed && <NodeResizer minWidth={240} minHeight={120} />}\n\n <div className=\"ods-flow-group__header\" data-flow-no-drag=\"false\">\n <button\n type=\"button\"\n className=\"ods-flow-group__chevron\"\n data-flow-no-drag=\"true\"\n aria-label={collapsed ? \"Expand group\" : \"Collapse group\"}\n aria-expanded={!collapsed}\n onClick={onChevronClick}\n onPointerDown={(e) => e.stopPropagation()}\n >\n {collapsed ? \"▸\" : \"▾\"}\n </button>\n <span className=\"ods-flow-group__title\">{d.title ?? \"Group\"}</span>\n {d.subtitle && <span className=\"ods-flow-group__subtitle\">{d.subtitle}</span>}\n {disabled && (\n <span className=\"ods-flow-group__disabled-badge\" aria-label=\"Disabled subflow\">\n Disabled\n </span>\n )}\n {collapsed && hiddenCount !== undefined && hiddenCount > 0 && (\n <span className=\"ods-flow-group__count\" aria-label={`${hiddenCount} hidden steps`}>\n {hiddenCount} steps\n </span>\n )}\n </div>\n\n {/* Canonical perimeter handles — 1 input on top, 1 output on\n bottom. Visible primary interaction surface (was previously\n muted on expanded mode; now they ARE the user-facing ports).\n Ids stay stable for `collapseFor()` edge rewriting. */}\n <Handle type=\"target\" position=\"top\" id=\"__group_in\" />\n <Handle type=\"source\" position=\"bottom\" id=\"__group_out\" />\n </div>\n );\n};\n\n// ────────────────────────────────────────────────────────────────────────\n// ForEachNode — iterator container. 1 input on top, 2 outputs on bottom:\n//\n// - target (top, `__group_in`, label \"in\") — the array / iterable\n// - source (bottom, `each`, label \"each\") — fans into the body\n// (one fire per item)\n// - source (bottom, `__group_out`, label \"done\") — post-iteration exit\n//\n// Children render absolutely positioned just like a GroupNode. The\n// \"each\" handle drives the inner subflow (per-iteration); \"done\" chains\n// to the post-loop step. The `__group_in/_out` ids match `collapseFor()`'s\n// edge-rewriting target so collapse routing keeps working unchanged.\n//\n// When collapsed: only the two perimeter handles render (the labelled\n// `each` disappears with the frame body) and the container reads as a\n// single block in the chain.\n// ────────────────────────────────────────────────────────────────────────\nexport const ForEachNode: NodeKindComponent<BuiltInNodeData> = ({\n node,\n}: NodeKindProps<BuiltInNodeData>) => {\n const d = node.data ?? {};\n const iteratorExpr = (d as { iterator?: string }).iterator ?? d.description ?? \"items[]\";\n const collapsed = !!d.collapsed;\n const disabled = !!d.disabled;\n const hiddenCount = (d as { hiddenCount?: number }).hiddenCount;\n const bridge = useFlowNodeBridge();\n const onChevronClick = (e: PointerEvent<HTMLButtonElement>) => {\n e.stopPropagation();\n bridge.toggleNodeCollapse(node.id);\n };\n return (\n <div\n className=\"ods-flow-foreach\"\n data-collapsed={collapsed ? \"true\" : \"false\"}\n data-disabled={disabled ? \"true\" : undefined}\n style={{\n width: node.width ?? 420,\n height: collapsed ? 40 : (node.height ?? 260),\n }}\n >\n {!collapsed && <NodeResizer minWidth={240} minHeight={120} />}\n\n <div className=\"ods-flow-foreach__header\">\n <button\n type=\"button\"\n className=\"ods-flow-foreach__chevron\"\n data-flow-no-drag=\"true\"\n aria-label={collapsed ? \"Expand iterator\" : \"Collapse iterator\"}\n aria-expanded={!collapsed}\n onClick={onChevronClick}\n onPointerDown={(e) => e.stopPropagation()}\n >\n {collapsed ? \"▸\" : \"▾\"}\n </button>\n <span className=\"ods-flow-foreach__icon\" aria-hidden=\"true\">\n ↻\n </span>\n <span className=\"ods-flow-foreach__title\">{d.title ?? \"For each\"}</span>\n <code className=\"ods-flow-foreach__iterator\">{iteratorExpr}</code>\n {disabled && (\n <span\n className=\"ods-flow-foreach__disabled-badge\"\n aria-label=\"Disabled subflow\"\n >\n Disabled\n </span>\n )}\n {collapsed && hiddenCount !== undefined && hiddenCount > 0 && (\n <span className=\"ods-flow-foreach__count\" aria-label={`${hiddenCount} hidden steps`}>\n {hiddenCount} steps\n </span>\n )}\n </div>\n\n {/* Top input — same `__group_in` id used by `collapseFor`. */}\n <Handle type=\"target\" position=\"top\" id=\"__group_in\" label={!collapsed ? \"in\" : undefined} />\n\n {collapsed ? (\n // Collapsed: single bottom exit so the container behaves like a\n // regular action in the chain.\n <Handle type=\"source\" position=\"bottom\" id=\"__group_out\" />\n ) : (\n // Expanded: two bottom outputs spread across the bottom edge.\n // Index/total tell the Handle to position them at 33% and 66%\n // along the edge (per `handleSideStyle`). `each` is left of\n // centre, `__group_out` (labelled \"done\") is right of centre.\n <>\n <Handle\n type=\"source\"\n position=\"bottom\"\n id=\"each\"\n label=\"each\"\n index={0}\n total={2}\n />\n <Handle\n type=\"source\"\n position=\"bottom\"\n id=\"__group_out\"\n label=\"done\"\n index={1}\n total={2}\n />\n </>\n )}\n </div>\n );\n};\n\n// ────────────────────────────────────────────────────────────────────────\n// OutputNode — terminal node; no output port. Pill reads \"OUTPUT\".\n// ────────────────────────────────────────────────────────────────────────\nexport const OutputNode: NodeKindComponent<BuiltInNodeData> = ({\n node,\n}: NodeKindProps<BuiltInNodeData>) => {\n const d = node.data ?? {};\n return (\n <BaseNode\n kind={d.kind ?? \"OUTPUT\"}\n icon={d.icon}\n title={d.title ?? \"Output\"}\n chip={d.chip ?? d.badge}\n description={d.description ?? d.subtitle}\n status={d.status}\n accent=\"green\"\n >\n <Handle type=\"target\" position=\"top\" />\n </BaseNode>\n );\n};\n\n// ────────────────────────────────────────────────────────────────────────\n// ErrorNode — failure handler; red accent.\n// ────────────────────────────────────────────────────────────────────────\nexport const ErrorNode: NodeKindComponent<BuiltInNodeData> = ({\n node,\n}: NodeKindProps<BuiltInNodeData>) => {\n const d = node.data ?? {};\n return (\n <BaseNode\n kind={d.kind ?? \"ERROR\"}\n icon={d.icon}\n title={d.title ?? \"On error\"}\n chip={d.chip ?? d.badge}\n description={d.description ?? d.subtitle}\n status={d.status ?? \"error\"}\n accent=\"red\"\n >\n <Handle type=\"target\" position=\"top\" />\n <Handle type=\"source\" position=\"bottom\" />\n </BaseNode>\n );\n};\n\n// ────────────────────────────────────────────────────────────────────────\n// WaitNode — pause execution. Chip surfaces the duration when provided.\n// ────────────────────────────────────────────────────────────────────────\nexport const WaitNode: NodeKindComponent<BuiltInNodeData> = ({\n node,\n}: NodeKindProps<BuiltInNodeData>) => {\n const d = node.data ?? {};\n const waitMs = (d as { waitMs?: number }).waitMs;\n const durationChip = waitMs ? `${Math.round(waitMs / 100) / 10}s` : undefined;\n return (\n <BaseNode\n kind={d.kind ?? \"WAIT\"}\n icon={d.icon}\n title={d.title ?? \"Wait\"}\n chip={d.chip ?? durationChip}\n description={d.description ?? (durationChip ? \"Pause execution\" : undefined)}\n status={d.status}\n accent=\"violet\"\n >\n <Handle type=\"target\" position=\"top\" />\n <Handle type=\"source\" position=\"bottom\" />\n </BaseNode>\n );\n};\n\n// ────────────────────────────────────────────────────────────────────────\n// ParallelNode — fan-out: one input, N parallel outputs.\n// ────────────────────────────────────────────────────────────────────────\nexport const ParallelNode: NodeKindComponent<BuiltInNodeData> = ({\n node,\n}: NodeKindProps<BuiltInNodeData>) => {\n const d = node.data ?? {};\n const branches = d.branches ?? [\n { id: \"a\", label: \"a\" },\n { id: \"b\", label: \"b\" },\n ];\n return (\n <BaseNode\n kind={d.kind ?? \"PARALLEL\"}\n icon={d.icon}\n title={d.title ?? \"Parallel\"}\n chip={d.chip ?? `${branches.length}×`}\n description={d.description ?? \"Fan-out branches\"}\n status={d.status}\n accent=\"blue\"\n >\n <Handle type=\"target\" position=\"top\" />\n {branches.map((b, i) => (\n <Handle\n key={b.id}\n type=\"source\"\n position=\"bottom\"\n id={b.id}\n index={i}\n total={branches.length}\n label={b.label}\n />\n ))}\n </BaseNode>\n );\n};\n\n// ────────────────────────────────────────────────────────────────────────\n// StickyNode — non-executing annotation. No ports. Renders behind nodes.\n// Multi-line `data.description` is the body.\n// ────────────────────────────────────────────────────────────────────────\nexport const StickyNode: NodeKindComponent<BuiltInNodeData> = ({\n node,\n}: NodeKindProps<BuiltInNodeData>) => {\n const d = node.data ?? {};\n return (\n <div\n className=\"ods-flow-sticky\"\n style={{\n width: node.width ?? 240,\n minHeight: node.height ?? 120,\n }}\n >\n {d.title && <div className=\"ods-flow-sticky__title\">{d.title}</div>}\n {d.description && <div className=\"ods-flow-sticky__body\">{d.description}</div>}\n </div>\n );\n};\n\n// ────────────────────────────────────────────────────────────────────────\n// WebhookNode — specialised Trigger. Pill = \"WEBHOOK\"; chip = HTTP\n// method; description = path (the most-relevant config value).\n// ────────────────────────────────────────────────────────────────────────\nexport const WebhookNode: NodeKindComponent<BuiltInNodeData> = ({\n node,\n}: NodeKindProps<BuiltInNodeData>) => {\n const d = node.data ?? {};\n return (\n <BaseNode\n kind={d.kind ?? \"WEBHOOK\"}\n icon={d.icon}\n title={d.title ?? \"Webhook\"}\n chip={d.chip ?? d.method ?? \"POST\"}\n description={d.description ?? d.path ?? \"/hooks/incoming\"}\n valueChip={d.valueChip}\n status={d.status}\n accent=\"blue\"\n >\n <Handle type=\"source\" position=\"bottom\" />\n </BaseNode>\n );\n};\n\n// ────────────────────────────────────────────────────────────────────────\n// HttpRequestNode — Action variant. Pill = \"HTTP\"; chip = HTTP method;\n// description = url (the most-relevant config value).\n// ────────────────────────────────────────────────────────────────────────\nexport const HttpRequestNode: NodeKindComponent<BuiltInNodeData> = ({\n node,\n}: NodeKindProps<BuiltInNodeData>) => {\n const d = node.data ?? {};\n return (\n <BaseNode\n kind={d.kind ?? \"HTTP\"}\n icon={d.icon}\n title={d.title ?? \"HTTP Request\"}\n chip={d.chip ?? d.method ?? \"GET\"}\n description={d.description ?? d.url ?? \"Call an API\"}\n valueChip={d.valueChip}\n status={d.status}\n accent=\"blue\"\n >\n <Handle type=\"target\" position=\"top\" />\n <Handle type=\"source\" position=\"bottom\" />\n </BaseNode>\n );\n};\n\n// ────────────────────────────────────────────────────────────────────────\n// Default registry — the canvas merges this with any consumer overrides.\n// ────────────────────────────────────────────────────────────────────────\nexport const DEFAULT_NODE_KINDS: NodeKindRegistry = {\n action: ActionNode as NodeKindComponent,\n trigger: TriggerNode as NodeKindComponent,\n condition: ConditionNode as NodeKindComponent,\n group: GroupNode as NodeKindComponent,\n forEach: ForEachNode as NodeKindComponent,\n output: OutputNode as NodeKindComponent,\n error: ErrorNode as NodeKindComponent,\n wait: WaitNode as NodeKindComponent,\n parallel: ParallelNode as NodeKindComponent,\n sticky: StickyNode as NodeKindComponent,\n webhook: WebhookNode as NodeKindComponent,\n httpRequest: HttpRequestNode as NodeKindComponent,\n};\n","\"use client\";\n\n// ════════════════════════════════════════════════════════════════════════\n// FlowCanvas v2 — the editor kernel.\n// ════════════════════════════════════════════════════════════════════════\n// Responsibilities:\n// 1. Mount the per-canvas store + handle registry; provide their contexts.\n// 2. Render the viewport (transform: translate(x,y) scale(zoom)).\n// 3. Own Pointer Events for pan, zoom, drag, and connect; route to the\n// right middleware via a single pointermove handler installed on the\n// window during an active gesture.\n// 4. Emit batched onNodesChange / onEdgesChange / onConnect / ...\n// 5. Mirror controlled `nodes` / `edges` props into the store each render\n// so descendants read fresh data via selectors.\n\nimport {\n type CSSProperties,\n memo,\n type PointerEvent,\n type ReactNode,\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n type WheelEvent,\n} from \"react\";\nimport { cn } from \"../../../utils/cn\";\nimport type {\n ConnectEndState,\n Connection,\n ConnectStartParams,\n EdgeChange,\n NodeChange,\n Position,\n Viewport,\n WorkflowEdge,\n WorkflowNode,\n} from \"../../editor\";\nimport { type FlowInstance, FlowInstanceContext } from \"../../hooks/useFlow\";\nimport { change } from \"../../store/changes\";\nimport { FlowStoreContext } from \"../../store/context\";\nimport { createFlowStore } from \"../../store/createFlowStore\";\nimport { resolveNodeCollisions } from \"../../utils/collision\";\nimport {\n DEFAULT_NODE_HEIGHT,\n DEFAULT_NODE_WIDTH,\n effectiveHeight,\n flowToScreen,\n screenToFlow,\n} from \"../../utils/geometry\";\nimport { clampToParentExtent, descendantsOf, findContainingGroup } from \"../../utils/parenting\";\nimport { FlowEdge } from \"../FlowEdge/FlowEdge\";\nimport { FlowNode } from \"../FlowNode/FlowNode\";\nimport { buildNodeKindRegistry, type NodeKindRegistry } from \"../FlowNode/nodeKinds\";\nimport { createHandleRegistry, HandleRegistryContext } from \"../Handle/handleRegistry\";\nimport { type BuiltInNodeData, DEFAULT_NODE_KINDS } from \"../kinds\";\nimport {\n type FlowDispatch,\n type FlowDispatchAction,\n FlowDispatchContext,\n type FlowNodeBridge,\n FlowNodeBridgeContext,\n} from \"./FlowCanvasContext\";\n\nexport interface FlowCanvasProps {\n nodes: WorkflowNode[];\n edges: WorkflowEdge[];\n onNodesChange?: (changes: NodeChange[]) => void;\n onEdgesChange?: (changes: EdgeChange[]) => void;\n\n // Viewport\n viewport?: Viewport;\n defaultViewport?: Viewport;\n onViewportChange?: (viewport: Viewport) => void;\n minZoom?: number;\n maxZoom?: number;\n /**\n * Auto-frame the existing nodes on first mount so the canvas opens\n * centered on content rather than at the {0,0,1} origin. Defaults to\n * `true` when no explicit `viewport` or `defaultViewport` is supplied;\n * when the consumer pins either prop the canvas honours that and skips\n * the auto-fit. Pass `false` to opt out unconditionally. Pass\n * `{ padding, minZoom, maxZoom }` to tune the framing.\n */\n fitViewOnInit?: boolean | { padding?: number; minZoom?: number; maxZoom?: number };\n\n // Node kinds\n nodeKinds?: NodeKindRegistry;\n\n // Connection\n onConnect?: (connection: Connection) => void;\n onConnectStart?: (\n event: PointerEvent | globalThis.PointerEvent,\n params: ConnectStartParams,\n ) => void;\n onConnectEnd?: (event: PointerEvent | globalThis.PointerEvent, state: ConnectEndState) => void;\n isValidConnection?: (connection: Connection) => boolean;\n\n // Selection\n onSelectionChange?: (selection: { nodes: WorkflowNode[]; edges: WorkflowEdge[] }) => void;\n onPaneClick?: () => void;\n onNodeClick?: (node: WorkflowNode) => void;\n onEdgeClick?: (edge: WorkflowEdge) => void;\n /** Double-clicking an edge label opens an inline editor; commit fires\n * this callback. When omitted, labels are not editable. */\n onEdgeLabelChange?: (id: string, label: string) => void;\n /** Fires once when the canvas mounts. Hand-off for the imperative\n * instance — consumers store it to call `fitView`, `addNodes`, etc. */\n onInit?: (instance: FlowInstance) => void;\n /** Async veto for deletions. Return `false` (or a Promise resolving\n * false) to block. Fires from `instance.deleteElements`, Backspace,\n * and the edge X button. */\n onBeforeDelete?: (params: {\n nodes: WorkflowNode[];\n edges: WorkflowEdge[];\n }) => boolean | Promise<boolean>;\n /** Right-click on a node. Consumer must `preventDefault()` to suppress\n * the browser's native menu. */\n onNodeContextMenu?: (event: React.MouseEvent, node: WorkflowNode) => void;\n /** Right-click on an edge. */\n onEdgeContextMenu?: (event: React.MouseEvent, edge: WorkflowEdge) => void;\n /** Right-click on the empty pane. */\n onPaneContextMenu?: (event: React.MouseEvent) => void;\n\n // Policies\n nodesDraggable?: boolean;\n nodesConnectable?: boolean;\n panOnDrag?: boolean;\n zoomOnScroll?: boolean;\n /**\n * Trackpad / touch behaviour preset.\n *\n * - `\"mouse\"` (default): mouse-first. Drag the pane to pan;\n * wheel zooms; pinch zooms.\n * - `\"trackpad\"`: two-finger trackpad scroll pans; pinch zooms;\n * wheel-with-Ctrl zooms. Drag the pane is still pan (`panOnDrag`).\n * - `\"touch\"`: same as trackpad but with enlarged hit areas (44 px\n * on coarse pointers via `@media (pointer: coarse)`) and no pan\n * on plain drag — single-finger drag selects, two-finger pans.\n *\n * Override individual policies (`panOnDrag`, `zoomOnScroll`, etc.)\n * after picking a preset to fine-tune.\n */\n preset?: \"mouse\" | \"trackpad\" | \"touch\";\n /** Pixels of pointer travel during a pane-press before it stops counting\n * as a click (used to decide whether to clear selection on pointerup). */\n paneClickDistance?: number;\n /**\n * Whether a click on the empty canvas pane clears the current node /\n * edge selection. Defaults to `true` (the design-tool standard:\n * \"click background to deselect\"). Set to `false` when selection\n * should persist through pane clicks — e.g. when a side ConfigPanel\n * stays open until the user dismisses it explicitly.\n *\n * `onPaneClick` still fires regardless; this only controls whether\n * the canvas also clears its internal selection state.\n */\n paneClickClearsSelection?: boolean;\n\n // Visual canvas options\n /** Background grid style. Defaults to `\"dots\"`. */\n background?: \"dots\" | \"lines\" | \"cross\" | \"none\";\n /** Grid pitch in flow-space pixels. Defaults to 20. Also used for snap. */\n gridSize?: number;\n /** Snap node positions to the grid on drag-end. Defaults to false. */\n snapToGrid?: boolean;\n /**\n * Minimum gap (px) between sibling nodes during drag. When >= 0, a\n * dragged node is \"magnet snapped\" so it stays at least `nodeCollisionGap`\n * pixels from every other sibling — siblings share the same `parentId`\n * (or are both top-level). `0` means \"no overlap allowed, zero buffer.\"\n * Pass `-1` (the default) to disable collision avoidance entirely.\n */\n nodeCollisionGap?: number;\n /**\n * Same as `nodeCollisionGap` but applied to subflow containers\n * (`type === \"group\" | \"forEach\"`). Lets you keep groups visually\n * separated without applying the rule to the action nodes inside.\n * Default falls back to `nodeCollisionGap`.\n */\n subflowCollisionGap?: number;\n\n /**\n * When `true`, dragging a node into another container's bbox sets\n * the dragged node's `parentId`; dragging out clears it — without\n * requiring the Alt modifier key. Default `false` preserves the\n * legacy Alt-drag-to-reparent behaviour for backward compatibility.\n *\n * Pairs with `autoResizeContainers` to deliver the full \"drop nodes\n * inside a group\" UX consumers usually want from a subflow editor.\n */\n reparentOnDrag?: boolean;\n\n /**\n * When `true`, container kinds (`group` / `forEach`) auto-resize at\n * drag-end so the frame encloses all current children plus padding.\n * The reposition + dimension update is folded into the same\n * `onNodesChange` call as the drag-end position change, so a child\n * dropped near the edge of a container can't miss the parent's\n * post-resize bbox in a follow-up render tick (the host-side race\n * the parented-on-drop UX would otherwise hit).\n *\n * Default `false`. Pair with `reparentOnDrag` for the full flow.\n */\n autoResizeContainers?: boolean;\n\n /**\n * Padding (in flow-space pixels) added around children's bbox when\n * `autoResizeContainers` recomputes a container's frame. Default 32.\n */\n containerAutoResizePadding?: number;\n\n // Layout\n height?: number | string;\n width?: number | string;\n className?: string;\n style?: CSSProperties;\n children?: ReactNode;\n emptyState?: ReactNode;\n}\n\nconst DEFAULT_VIEWPORT: Viewport = { x: 0, y: 0, zoom: 1 };\n\nexport function FlowCanvas(props: FlowCanvasProps) {\n // Capture whether the consumer explicitly handed us either viewport\n // prop. We can't tell from the destructured value alone (the default\n // assignment below would obscure an undefined explicit pass), and the\n // auto-fit fallback needs to know \"did the consumer pin the viewport,\n // or are we free to frame the nodes?\".\n const viewportPropProvided = props.viewport !== undefined || props.defaultViewport !== undefined;\n const {\n nodes,\n edges,\n onNodesChange,\n onEdgesChange,\n viewport: controlledViewport,\n defaultViewport = DEFAULT_VIEWPORT,\n onViewportChange,\n minZoom = 0.25,\n maxZoom = 2,\n fitViewOnInit,\n nodeKinds,\n onConnect,\n onConnectStart,\n onConnectEnd,\n isValidConnection,\n onSelectionChange,\n onPaneClick,\n onNodeClick,\n onEdgeClick,\n onEdgeLabelChange,\n onInit,\n onBeforeDelete,\n onNodeContextMenu,\n onEdgeContextMenu,\n onPaneContextMenu,\n nodesDraggable = true,\n nodesConnectable = true,\n panOnDrag: panOnDragProp,\n zoomOnScroll: zoomOnScrollProp,\n preset = \"mouse\",\n paneClickDistance = 4,\n paneClickClearsSelection = true,\n background = \"dots\",\n gridSize = 20,\n snapToGrid = false,\n nodeCollisionGap = -1,\n subflowCollisionGap,\n reparentOnDrag = false,\n autoResizeContainers = false,\n containerAutoResizePadding = 32,\n height = \"100%\",\n width = \"100%\",\n className,\n style,\n children,\n emptyState,\n } = props;\n // Resolve the preset defaults — individual props override. The presets\n // map to the documented interaction modes:\n // - mouse: pan-on-drag, wheel zoom\n // - trackpad: pan-on-drag still on (so users can grab the pane), but\n // two-finger trackpad scroll also pans (translated as wheel delta);\n // pinch zooms; wheel-zoom remains on for Ctrl+scroll.\n // - touch: drag the pane = box-select intent, no auto-pan\n // (single-finger drag is reserved for selection on touch surfaces).\n const presetDefaults = {\n mouse: { panOnDrag: true, zoomOnScroll: true },\n trackpad: { panOnDrag: true, zoomOnScroll: true },\n touch: { panOnDrag: false, zoomOnScroll: true },\n } as const;\n const panOnDrag = panOnDragProp ?? presetDefaults[preset].panOnDrag;\n const zoomOnScroll = zoomOnScrollProp ?? presetDefaults[preset].zoomOnScroll;\n\n // ── Singletons that live for the lifetime of this canvas ──\n const store = useState(() =>\n createFlowStore({\n initialNodes: nodes,\n initialEdges: edges,\n initialViewport: controlledViewport ?? defaultViewport,\n }),\n )[0];\n const handleRegistry = useState(() => createHandleRegistry())[0];\n\n // Subscribe to handle (un)registrations. Each Handle's `useEffect`\n // commits AFTER the surrounding render, so edges rendered in the same\n // commit as a node remount (typical for subflow collapse/uncollapse)\n // resolve against a stale registry and fall back to default ports.\n // Bumping this counter forces a follow-up render once the effects fire.\n const [handleVersion, setHandleVersion] = useState(0);\n useEffect(() => {\n const unsub = handleRegistry.subscribe(() => {\n setHandleVersion((v) => v + 1);\n });\n return unsub;\n }, [handleRegistry]);\n\n // Merge built-in kinds with consumer overrides. Frozen so consumers\n // can't mutate the registry mid-flight.\n const kinds = useMemo(() => buildNodeKindRegistry(DEFAULT_NODE_KINDS, nodeKinds), [nodeKinds]);\n\n const containerRef = useRef<HTMLDivElement>(null);\n\n // ── Mirror controlled props → store ───────────────────────────────────\n useEffect(() => store.setNodes(nodes), [store, nodes]);\n useEffect(() => store.setEdges(edges), [store, edges]);\n\n // ── Viewport (controlled or uncontrolled) ─────────────────────────────\n const [uncontrolledVp, setUncontrolledVp] = useState(controlledViewport ?? defaultViewport);\n const viewport = controlledViewport ?? uncontrolledVp;\n useEffect(() => store.setViewport(viewport), [store, viewport]);\n const setViewport = useCallback(\n (next: Viewport) => {\n if (controlledViewport === undefined) setUncontrolledVp(next);\n onViewportChange?.(next);\n },\n [controlledViewport, onViewportChange],\n );\n\n // ── Selection — derived from `node.selected` / `edge.selected` in props.\n // We do NOT keep a parallel ref because that would drift the moment a\n // consumer set a node.selected = true via their own state. The single\n // source of truth is the props.\n const selectedNodeIds = useMemo(() => {\n const s = new Set<string>();\n for (const n of nodes) if (n.selected) s.add(n.id);\n return s;\n }, [nodes]);\n const selectedEdgeIds = useMemo(() => {\n const s = new Set<string>();\n for (const e of edges) if (e.selected) s.add(e.id);\n return s;\n }, [edges]);\n\n // Sync resolved selection into the store so descendants can read it.\n useEffect(() => {\n store.setSelection(selectedNodeIds, selectedEdgeIds);\n if (onSelectionChange) {\n onSelectionChange({\n nodes: nodes.filter((n) => selectedNodeIds.has(n.id)),\n edges: edges.filter((e) => selectedEdgeIds.has(e.id)),\n });\n }\n }, [store, selectedNodeIds, selectedEdgeIds, nodes, edges, onSelectionChange]);\n\n // Selection state only — does NOT fire `onNodeClick`. The click event\n // is dispatched separately from the click path in FlowNode, so drag\n // starts (which need to select the node so it carries selection styles)\n // don't accidentally fire the consumer's click handler.\n const selectNode = useCallback(\n (id: string, additive: boolean) => {\n const next: NodeChange[] = [];\n const nextEdges: EdgeChange[] = [];\n if (!additive) {\n for (const n of nodes) {\n if (n.selected && n.id !== id) next.push(change.node.select(n.id, false));\n }\n for (const e of edges) {\n if (e.selected) nextEdges.push(change.edge.select(e.id, false));\n }\n }\n const isSelected = selectedNodeIds.has(id);\n if (additive && isSelected) {\n // Toggle off when meta-clicking an already-selected node.\n next.push(change.node.select(id, false));\n } else if (!isSelected) {\n next.push(change.node.select(id, true));\n }\n if (next.length) onNodesChange?.(next);\n if (nextEdges.length) onEdgesChange?.(nextEdges);\n },\n [nodes, edges, selectedNodeIds, onNodesChange, onEdgesChange],\n );\n\n // Click notification — fires the consumer's `onNodeClick`. FlowNode\n // calls this AFTER `selectNode` only when the gesture was a click,\n // not a drag. Separating the two lets drag-start update selection\n // without firing the click event.\n const notifyNodeClick = useCallback(\n (id: string) => {\n const node = nodes.find((n) => n.id === id);\n if (node) onNodeClick?.(node);\n },\n [nodes, onNodeClick],\n );\n\n const selectEdge = useCallback(\n (id: string, additive: boolean) => {\n const next: EdgeChange[] = [];\n const nextNodes: NodeChange[] = [];\n if (!additive) {\n for (const e of edges) {\n if (e.selected && e.id !== id) next.push(change.edge.select(e.id, false));\n }\n for (const n of nodes) {\n if (n.selected) nextNodes.push(change.node.select(n.id, false));\n }\n }\n const isSelected = selectedEdgeIds.has(id);\n if (additive && isSelected) {\n next.push(change.edge.select(id, false));\n } else if (!isSelected) {\n next.push(change.edge.select(id, true));\n }\n if (next.length) onEdgesChange?.(next);\n if (nextNodes.length) onNodesChange?.(nextNodes);\n const edge = edges.find((e) => e.id === id);\n if (edge) onEdgeClick?.(edge);\n },\n [nodes, edges, selectedEdgeIds, onEdgesChange, onNodesChange, onEdgeClick],\n );\n\n const clearSelection = useCallback(() => {\n const ns: NodeChange[] = [];\n const es: EdgeChange[] = [];\n for (const n of nodes) if (n.selected) ns.push(change.node.select(n.id, false));\n for (const e of edges) if (e.selected) es.push(change.edge.select(e.id, false));\n if (ns.length) onNodesChange?.(ns);\n if (es.length) onEdgesChange?.(es);\n }, [nodes, edges, onNodesChange, onEdgesChange]);\n\n // ── Node drag middleware ──────────────────────────────────────────────\n // Drag also moves transitive descendants (children of a parent move with\n // the parent), respects `extent: 'parent'` clamping, and supports\n // Alt-detach for re-parenting subflow children.\n type DragState = {\n pointerId: number;\n nodeId: string;\n startClientX: number;\n startClientY: number;\n startPosition: Position;\n /** Captured at drag-start so each pointermove can reposition all\n * descendants by the same delta without re-walking the tree. */\n descendants: { id: string; startPosition: Position }[];\n /** Alt held at drag-start — when true and the node has parentId,\n * pointerup strips parentId (detach from group). */\n altDetach: boolean;\n rafScheduled: boolean;\n nextDelta: { dx: number; dy: number } | null;\n };\n const dragRef = useRef<DragState | null>(null);\n const [draggingId, setDraggingId] = useState<string | null>(null);\n\n const beginNodeDrag = useCallback(\n (nodeId: string, pointerId: number, clientX: number, clientY: number, altKey = false) => {\n if (!nodesDraggable) return;\n const node = nodes.find((n) => n.id === nodeId);\n if (!node) return;\n const kids = descendantsOf(nodeId, nodes).map((d) => ({\n id: d.id,\n startPosition: d.position,\n }));\n // `altDetach` flags the drag as \"consider reparenting at drag-end\".\n // Two ways to opt in:\n // 1. The user held Alt while starting the drag (legacy gesture).\n // 2. The consumer set `reparentOnDrag` on the canvas — then every\n // drag is a potential reparent.\n // The flag also short-circuits the parent-extent clamp so the\n // pointer can travel outside the parent's bbox while we evaluate\n // the new parent. Plain (non-reparenting) drags still clamp.\n const wantsReparent = altKey || reparentOnDragRef.current;\n dragRef.current = {\n pointerId,\n nodeId,\n startClientX: clientX,\n startClientY: clientY,\n startPosition: node.position,\n descendants: kids,\n altDetach: wantsReparent,\n rafScheduled: false,\n nextDelta: null,\n };\n setDraggingId(nodeId);\n selectNode(nodeId, false);\n },\n [nodes, nodesDraggable, selectNode],\n );\n\n // ── Connection middleware ─────────────────────────────────────────────\n // `connection` is local state. The ghost-line component subscribes here\n // (via prop), the rest of the canvas does not — so a connection drag\n // does NOT re-render every node. Setting state inside the global\n // pointermove handler still triggers a re-render of FlowCanvas itself,\n // but that's just the SVG ghost; the node list and edges are memoised.\n const [conn, setConn] = useState<{\n pointerId: number;\n from: ConnectStartParams;\n start: Position;\n end: Position;\n } | null>(null);\n // We keep a ref mirror so the global pointermove handler can read the\n // latest value without re-attaching listeners on every state change.\n const connRef = useRef<typeof conn>(null);\n useEffect(() => {\n connRef.current = conn;\n }, [conn]);\n\n const beginConnection = useCallback(\n (\n nodeId: string,\n handleId: string,\n handleType: \"source\" | \"target\",\n pointerId: number,\n clientX: number,\n clientY: number,\n ) => {\n if (!nodesConnectable) return;\n const node = nodes.find((n) => n.id === nodeId);\n if (!node) return;\n // Compute the originating handle's flow-space centre so the ghost\n // line is visible from the very first frame (no flicker).\n const desc = handleRegistry.resolve(nodeId, handleType, handleId);\n const side = desc?.side ?? (handleType === \"source\" ? \"bottom\" : \"top\");\n const index = desc?.index ?? 0;\n const total = desc?.total ?? 1;\n const ratio = (index + 1) / (total + 1);\n // Default width matches the BaseNode body (368 px) so the ghost\n // line origin lands ON the handle dot even before the ResizeObserver\n // has reported the real measured width back through `onNodesChange`.\n const w = node.width ?? 368;\n // Use the effective height — collapsed containers render a tiny\n // strip; without this the ghost line would start far below the\n // visible group when dragging from a perimeter handle.\n const h = effectiveHeight(node);\n const start: Position = (() => {\n switch (side) {\n case \"top\":\n return { x: node.position.x + w * ratio, y: node.position.y };\n case \"bottom\":\n return { x: node.position.x + w * ratio, y: node.position.y + h };\n case \"left\":\n return { x: node.position.x, y: node.position.y + h * ratio };\n case \"right\":\n return { x: node.position.x + w, y: node.position.y + h * ratio };\n }\n })();\n const from: ConnectStartParams = { nodeId, handleId, handleType };\n const rect = containerRef.current?.getBoundingClientRect();\n const end = rect\n ? screenToFlow({ x: clientX - rect.left, y: clientY - rect.top }, viewport)\n : start;\n setConn({ pointerId, from, start, end });\n store.setConnection(from);\n onConnectStart?.({ clientX, clientY, pointerId } as unknown as globalThis.PointerEvent, from);\n },\n [nodes, nodesConnectable, handleRegistry, viewport, store, onConnectStart],\n );\n\n // ── Refs that the global pointer listeners read so they don't depend\n // ── on captured callback identity (avoids listener re-attach storms).\n const viewportRef = useRef(viewport);\n const nodesRef = useRef(nodes);\n const edgesRef = useRef(edges);\n const onNodesChangeRefForInstance = useRef(onNodesChange);\n const onEdgesChangeRefForInstance = useRef(onEdgesChange);\n const onBeforeDeleteRef = useRef(onBeforeDelete);\n const snapToGridRef = useRef(snapToGrid);\n const gridSizeRef = useRef(gridSize);\n const nodeCollisionGapRef = useRef(nodeCollisionGap);\n const subflowCollisionGapRef = useRef(subflowCollisionGap ?? nodeCollisionGap);\n const reparentOnDragRef = useRef(reparentOnDrag);\n const autoResizeContainersRef = useRef(autoResizeContainers);\n const containerAutoResizePaddingRef = useRef(containerAutoResizePadding);\n useEffect(() => {\n edgesRef.current = edges;\n }, [edges]);\n useEffect(() => {\n onNodesChangeRefForInstance.current = onNodesChange;\n }, [onNodesChange]);\n useEffect(() => {\n onEdgesChangeRefForInstance.current = onEdgesChange;\n }, [onEdgesChange]);\n useEffect(() => {\n onBeforeDeleteRef.current = onBeforeDelete;\n }, [onBeforeDelete]);\n useEffect(() => {\n snapToGridRef.current = snapToGrid;\n }, [snapToGrid]);\n useEffect(() => {\n gridSizeRef.current = gridSize;\n }, [gridSize]);\n useEffect(() => {\n nodeCollisionGapRef.current = nodeCollisionGap;\n }, [nodeCollisionGap]);\n useEffect(() => {\n subflowCollisionGapRef.current = subflowCollisionGap ?? nodeCollisionGap;\n }, [subflowCollisionGap, nodeCollisionGap]);\n useEffect(() => {\n reparentOnDragRef.current = reparentOnDrag;\n }, [reparentOnDrag]);\n useEffect(() => {\n autoResizeContainersRef.current = autoResizeContainers;\n }, [autoResizeContainers]);\n useEffect(() => {\n containerAutoResizePaddingRef.current = containerAutoResizePadding;\n }, [containerAutoResizePadding]);\n const onNodesChangeRef = useRef(onNodesChange);\n const onConnectRef = useRef(onConnect);\n const onConnectEndRef = useRef(onConnectEnd);\n const isValidConnectionRef = useRef(isValidConnection);\n useEffect(() => {\n viewportRef.current = viewport;\n }, [viewport]);\n useEffect(() => {\n nodesRef.current = nodes;\n }, [nodes]);\n useEffect(() => {\n onNodesChangeRef.current = onNodesChange;\n }, [onNodesChange]);\n useEffect(() => {\n onConnectRef.current = onConnect;\n }, [onConnect]);\n useEffect(() => {\n onConnectEndRef.current = onConnectEnd;\n }, [onConnectEnd]);\n useEffect(() => {\n isValidConnectionRef.current = isValidConnection;\n }, [isValidConnection]);\n\n // ── Pointer dispatch — single window-level listener installed ONCE.\n // All gesture deps come through refs, so this effect runs once per\n // mount and never re-attaches.\n useEffect(() => {\n const onPointerMove = (e: globalThis.PointerEvent) => {\n const vp = viewportRef.current;\n // Node drag\n const drag = dragRef.current;\n if (drag && drag.pointerId === e.pointerId) {\n const dx = (e.clientX - drag.startClientX) / vp.zoom;\n const dy = (e.clientY - drag.startClientY) / vp.zoom;\n drag.nextDelta = { dx, dy };\n if (!drag.rafScheduled) {\n drag.rafScheduled = true;\n requestAnimationFrame(() => {\n const d = dragRef.current;\n if (!d) return;\n d.rafScheduled = false;\n const delta = d.nextDelta;\n if (!delta) return;\n // Compute the proposed new position for the dragged node.\n const dragNode = nodesRef.current.find((n) => n.id === d.nodeId);\n if (!dragNode) return;\n const proposed = {\n x: d.startPosition.x + delta.dx,\n y: d.startPosition.y + delta.dy,\n };\n // Apply extent:'parent' clamping when applicable AND we're not\n // detaching from the parent. When Alt-detaching the child\n // should move freely so the user can yank it out.\n const clamped = d.altDetach\n ? proposed\n : clampToParentExtent(dragNode, proposed, nodesRef.current);\n // Magnet collision — push out of any sibling we're overlapping\n // (or sitting closer than `gap` to). Subflow containers use\n // `subflowCollisionGap`; regular nodes use `nodeCollisionGap`.\n // Descendants of the dragged node never participate, so a\n // parent can move freely through the space its children occupy.\n const isContainer = dragNode.type === \"group\" || dragNode.type === \"forEach\";\n const gap = isContainer ? subflowCollisionGapRef.current : nodeCollisionGapRef.current;\n const excludeIds = new Set<string>([d.nodeId, ...d.descendants.map((kid) => kid.id)]);\n const finalPos = resolveNodeCollisions(dragNode, clamped, nodesRef.current, {\n gap,\n exclude: excludeIds,\n });\n // The realised delta may differ from the proposed delta after\n // clamping and collision — use it for shifting descendants so\n // they stay glued to the parent.\n const realDx = finalPos.x - d.startPosition.x;\n const realDy = finalPos.y - d.startPosition.y;\n const changes: NodeChange[] = [change.node.position(d.nodeId, finalPos, true)];\n for (const kid of d.descendants) {\n changes.push(\n change.node.position(\n kid.id,\n { x: kid.startPosition.x + realDx, y: kid.startPosition.y + realDy },\n true,\n ),\n );\n }\n onNodesChangeRef.current?.(changes);\n });\n }\n }\n\n // Connection drag — only this branch sets React state, so the\n // re-render is limited to FlowCanvas itself (nodes + edges memoised).\n const c = connRef.current;\n if (c && c.pointerId === e.pointerId) {\n const rect = containerRef.current?.getBoundingClientRect();\n if (rect) {\n const end = screenToFlow({ x: e.clientX - rect.left, y: e.clientY - rect.top }, vp);\n setConn({ ...c, end });\n }\n }\n };\n\n const onPointerUp = (e: globalThis.PointerEvent) => {\n const vp = viewportRef.current;\n const drag = dragRef.current;\n if (drag && drag.pointerId === e.pointerId) {\n const dx = (e.clientX - drag.startClientX) / vp.zoom;\n const dy = (e.clientY - drag.startClientY) / vp.zoom;\n const dragNode = nodesRef.current.find((n) => n.id === drag.nodeId);\n if (dragNode) {\n let proposed = {\n x: drag.startPosition.x + dx,\n y: drag.startPosition.y + dy,\n };\n // Snap to grid on commit only — during drag the node follows\n // the pointer freely, but releases land on the nearest grid\n // intersection. UX is \"smooth move, satisfying click.\"\n if (snapToGridRef.current) {\n const g = gridSizeRef.current;\n proposed = {\n x: Math.round(proposed.x / g) * g,\n y: Math.round(proposed.y / g) * g,\n };\n }\n const clamped = drag.altDetach\n ? proposed\n : clampToParentExtent(dragNode, proposed, nodesRef.current);\n // Run collision once more on commit — guards against a fast\n // pointer-up that bypassed the last rAF tick.\n const isContainer = dragNode.type === \"group\" || dragNode.type === \"forEach\";\n const gap = isContainer ? subflowCollisionGapRef.current : nodeCollisionGapRef.current;\n const excludeIds = new Set<string>([\n drag.nodeId,\n ...drag.descendants.map((kid) => kid.id),\n ]);\n const finalPos = resolveNodeCollisions(dragNode, clamped, nodesRef.current, {\n gap,\n exclude: excludeIds,\n });\n const realDx = finalPos.x - drag.startPosition.x;\n const realDy = finalPos.y - drag.startPosition.y;\n\n // Build the final commit. Dragging now becomes false.\n const changes: NodeChange[] = [change.node.position(drag.nodeId, finalPos, false)];\n for (const kid of drag.descendants) {\n changes.push(\n change.node.position(\n kid.id,\n { x: kid.startPosition.x + realDx, y: kid.startPosition.y + realDy },\n false,\n ),\n );\n }\n\n // Reparent evaluation: when `altDetach` is set (Alt-held OR\n // `reparentOnDrag` prop enabled), hit-test the drop point\n // against existing containers. Three outcomes:\n // • Was parented, dropped outside any container → detach.\n // • Was parented, dropped inside a different container → reparent.\n // • Was top-level, dropped inside a container → adopt.\n // The replace-change is appended to the same `onNodesChange`\n // batch as the position change, so the consumer sees one\n // atomic update — no parentId/position race.\n if (drag.altDetach) {\n const targetGroup = findContainingGroup(\n {\n x: finalPos.x + (dragNode.width ?? 0) / 2,\n y: finalPos.y + (dragNode.height ?? 0) / 2,\n },\n nodesRef.current,\n [drag.nodeId, ...drag.descendants.map((d) => d.id)],\n );\n const nextParentId = targetGroup?.id;\n // Only emit a replace if parentage actually changed —\n // dragging a child around inside its own parent should NOT\n // re-emit the whole node every frame.\n if (nextParentId !== dragNode.parentId) {\n const updated: WorkflowNode = {\n ...dragNode,\n position: finalPos,\n parentId: nextParentId,\n // Preserve extent only when staying in a group.\n extent: nextParentId ? dragNode.extent : undefined,\n };\n changes.push(change.node.replace(drag.nodeId, updated));\n }\n }\n\n // Container auto-resize: recompute each container's bbox from\n // its (post-drag, post-reparent) children + padding. Folded\n // into the same change batch so the consumer can't see a\n // half-resized frame between renders.\n if (autoResizeContainersRef.current) {\n const containerChanges = computeContainerAutoResize(\n nodesRef.current,\n // Projected children: apply the position + reparent\n // changes we just built before measuring bboxes.\n changes,\n containerAutoResizePaddingRef.current,\n );\n for (const c of containerChanges) changes.push(c);\n }\n\n onNodesChangeRef.current?.(changes);\n }\n dragRef.current = null;\n setDraggingId(null);\n }\n\n const c = connRef.current;\n if (c && c.pointerId === e.pointerId) {\n // Walk `elementsFromPoint` instead of `e.target.closest(...)` so\n // the source node's own handles can't mask the real target.\n // Concrete case: an inner child of a container is dragging a\n // wire to that container's edge port — the child's own port\n // hit-area (`::before { inset: -16px }`) extends past the\n // container's edge and overlaps with the parent's port. With\n // `closest`, that overlap returns the child handle first; the\n // same-source-node guard below then cancels the gesture. By\n // skipping handles that belong to `c.from.nodeId` we let the\n // hit pass through to the handle physically behind them.\n let handleEl: HTMLElement | null = null;\n if (typeof document !== \"undefined\") {\n const stack = document.elementsFromPoint(e.clientX, e.clientY);\n for (const el of stack) {\n const candidate = (el as HTMLElement).closest(\n \"[data-handle-id]\",\n ) as HTMLElement | null;\n if (!candidate) continue;\n if (candidate.dataset.handleNodeId === c.from.nodeId) continue;\n handleEl = candidate;\n break;\n }\n }\n let connection: Connection | null = null;\n let connectedTo: ConnectStartParams | undefined;\n if (handleEl) {\n const targetNodeId = handleEl.dataset.handleNodeId!;\n const targetHandleId = handleEl.dataset.handleId!;\n const targetType = handleEl.dataset.handleType as \"source\" | \"target\";\n const connectableEnd = handleEl.dataset.handleConnectableEnd === \"true\";\n if (\n connectableEnd &&\n (targetNodeId !== c.from.nodeId || targetHandleId !== c.from.handleId) &&\n targetType !== c.from.handleType\n ) {\n const source =\n c.from.handleType === \"source\"\n ? c.from\n : { nodeId: targetNodeId, handleId: targetHandleId, handleType: \"source\" as const };\n const target2 =\n c.from.handleType === \"target\"\n ? c.from\n : { nodeId: targetNodeId, handleId: targetHandleId, handleType: \"target\" as const };\n connection = {\n source: source.nodeId,\n sourceHandle: source.handleId,\n target: target2.nodeId,\n targetHandle: target2.handleId,\n };\n connectedTo = {\n nodeId: targetNodeId,\n handleId: targetHandleId,\n handleType: targetType,\n };\n const validator = isValidConnectionRef.current;\n if (validator && !validator(connection)) {\n connection = null;\n connectedTo = undefined;\n }\n }\n }\n const rect = containerRef.current?.getBoundingClientRect();\n const flowPos = rect\n ? screenToFlow({ x: e.clientX - rect.left, y: e.clientY - rect.top }, vp)\n : { x: 0, y: 0 };\n const endState: ConnectEndState = {\n cancelled: !connection,\n position: { x: e.clientX, y: e.clientY },\n flowPosition: flowPos,\n from: c.from,\n to: connectedTo,\n };\n if (connection) onConnectRef.current?.(connection);\n onConnectEndRef.current?.(e, endState);\n setConn(null);\n store.setConnection(null);\n }\n };\n\n const onPointerCancel = () => {\n if (dragRef.current) {\n dragRef.current = null;\n setDraggingId(null);\n }\n if (connRef.current) {\n setConn(null);\n store.setConnection(null);\n }\n };\n\n window.addEventListener(\"pointermove\", onPointerMove);\n window.addEventListener(\"pointerup\", onPointerUp);\n window.addEventListener(\"pointercancel\", onPointerCancel);\n return () => {\n window.removeEventListener(\"pointermove\", onPointerMove);\n window.removeEventListener(\"pointerup\", onPointerUp);\n window.removeEventListener(\"pointercancel\", onPointerCancel);\n };\n }, [store]); // mount-only\n\n // ── Pan (canvas drag) ─────────────────────────────────────────────────\n // We DON'T clear selection on pan-start (issue #4 from the audit). The\n // pointerup handler decides whether this was a click (no movement) and\n // only clears selection then.\n const panRef = useRef<{\n pointerId: number;\n startClientX: number;\n startClientY: number;\n startVp: Viewport;\n moved: boolean;\n } | null>(null);\n const onCanvasPointerDown = (e: PointerEvent<HTMLDivElement>) => {\n if (e.button !== 0) return;\n const t = e.target as HTMLElement;\n if (\n t.closest(\"[data-node-id]\") ||\n t.closest(\"[data-edge-id]\") ||\n t.closest(\"[data-handle-id]\")\n ) {\n return;\n }\n if (!panOnDrag) {\n // Even without pan, a click on the pane should clear selection.\n panRef.current = {\n pointerId: e.pointerId,\n startClientX: e.clientX,\n startClientY: e.clientY,\n startVp: viewport,\n moved: false,\n };\n return;\n }\n panRef.current = {\n pointerId: e.pointerId,\n startClientX: e.clientX,\n startClientY: e.clientY,\n startVp: viewport,\n moved: false,\n };\n };\n\n useEffect(() => {\n const onMove = (e: globalThis.PointerEvent) => {\n const pan = panRef.current;\n if (!pan || pan.pointerId !== e.pointerId) return;\n const dx = e.clientX - pan.startClientX;\n const dy = e.clientY - pan.startClientY;\n if (Math.abs(dx) > paneClickDistance || Math.abs(dy) > paneClickDistance) {\n if (!pan.moved) setPanGesture(true);\n pan.moved = true;\n }\n if (pan.moved && panOnDrag) {\n setViewport({ ...pan.startVp, x: pan.startVp.x + dx, y: pan.startVp.y + dy });\n }\n };\n const onUp = () => {\n const pan = panRef.current;\n if (!pan) return;\n // A genuine \"click\" on the pane (no significant movement) fires\n // onPaneClick. Selection is cleared only when the consumer opts in\n // — consumers that keep a side-panel open through pane clicks pass\n // `paneClickClearsSelection={false}`. A drag-pan does neither.\n if (!pan.moved) {\n onPaneClick?.();\n if (paneClickClearsSelection) clearSelection();\n }\n panRef.current = null;\n setPanGesture(false);\n };\n window.addEventListener(\"pointermove\", onMove);\n window.addEventListener(\"pointerup\", onUp);\n window.addEventListener(\"pointercancel\", onUp);\n return () => {\n window.removeEventListener(\"pointermove\", onMove);\n window.removeEventListener(\"pointerup\", onUp);\n window.removeEventListener(\"pointercancel\", onUp);\n };\n }, [\n setViewport,\n paneClickDistance,\n panOnDrag,\n onPaneClick,\n clearSelection,\n paneClickClearsSelection,\n ]);\n\n // ── Wheel-zoom ────────────────────────────────────────────────────────\n const handleWheel = (e: WheelEvent<HTMLDivElement>) => {\n if (!zoomOnScroll) return;\n e.preventDefault();\n const rect = containerRef.current?.getBoundingClientRect();\n if (!rect) return;\n const px = e.clientX - rect.left;\n const py = e.clientY - rect.top;\n const factor = Math.exp(-e.deltaY * 0.001);\n const nextZoom = Math.max(minZoom, Math.min(maxZoom, viewport.zoom * factor));\n const k = nextZoom / viewport.zoom;\n setViewport({\n zoom: nextZoom,\n x: px - (px - viewport.x) * k,\n y: py - (py - viewport.y) * k,\n });\n };\n\n // ── Dispatch contract for Handle ──────────────────────────────────────\n const dispatch = useCallback<FlowDispatch>(\n (a: FlowDispatchAction) => {\n if (a.type === \"connection/start\") {\n beginConnection(a.nodeId, a.handleId, a.handleType, a.pointerId, a.clientX, a.clientY);\n }\n },\n [beginConnection],\n );\n\n // Dimensions reporter — FlowNode's ResizeObserver calls this on size\n // change. We compare against `nodes[]` (current props) and only emit a\n // change when the value actually differs, so we don't trigger an\n // infinite render loop (dimensions change → parent re-renders nodes →\n // ResizeObserver may fire again from style updates).\n const reportDimensions = useCallback(\n (nodeId: string, width: number, height: number) => {\n const node = nodes.find((n) => n.id === nodeId);\n if (!node) return;\n if (node.width === width && node.height === height) return;\n onNodesChange?.([change.node.dimensions(nodeId, { width, height })]);\n },\n [nodes, onNodesChange],\n );\n\n // Toggle data.collapsed on a container node. Exposed via the bridge so\n // the chevron rendered inside GroupNode / ForEachNode can flip the\n // subflow state from inside the kind component, no external toolbar\n // wiring needed.\n const toggleNodeCollapseImpl = useCallback(\n (nodeId: string) => {\n const node = nodes.find((n) => n.id === nodeId);\n if (!node) return;\n const prevData = (node.data ?? {}) as { collapsed?: boolean } & Record<string, unknown>;\n const nextNode = {\n ...node,\n data: { ...prevData, collapsed: !prevData.collapsed },\n } as WorkflowNode;\n onNodesChange?.([change.node.replace(nodeId, nextNode)]);\n },\n [nodes, onNodesChange],\n );\n\n // Delete one node + its incident edges. Exposed via the FlowNodeBridge\n // so a node-rendered delete button (BaseNode corner [×]) can fire\n // without going through the keyboard / context-menu path.\n const deleteNodeImpl = useCallback(\n (nodeId: string) => {\n const incidentEdgeIds = edgesRef.current\n .filter((e) => e.source === nodeId || e.target === nodeId)\n .map((e) => e.id);\n if (incidentEdgeIds.length > 0) {\n onEdgesChange?.(incidentEdgeIds.map((id) => change.edge.remove(id)));\n }\n onNodesChange?.([change.node.remove(nodeId)]);\n },\n [onNodesChange, onEdgesChange],\n );\n\n // ── Imperative instance — useFlow() and onInit ───────────────────────\n // Methods read through refs each call so they always see fresh state,\n // even though the instance itself is stable across renders. Mutating\n // methods round-trip through the consumer's onNodesChange/onEdgesChange\n // so the canonical state stays single-source-of-truth.\n const instance = useMemo<FlowInstance>(\n () => ({\n // viewport\n getViewport: () => viewportRef.current,\n setViewport: (vp) => setViewport(vp),\n setCenter: (x, y, opts) => {\n const z = opts?.zoom ?? viewportRef.current.zoom;\n const rect = containerRef.current?.getBoundingClientRect();\n if (!rect) return;\n setViewport({\n zoom: z,\n x: rect.width / 2 - x * z,\n y: rect.height / 2 - y * z,\n });\n },\n fitView: async (opts) => {\n const rect = containerRef.current?.getBoundingClientRect();\n if (!rect) return false;\n const padding = opts?.padding ?? 80;\n const targetNodes = opts?.nodes\n ? nodesRef.current.filter((n) => opts.nodes!.some((x) => x.id === n.id))\n : nodesRef.current.filter((n) => !n.hidden);\n if (targetNodes.length === 0) return false;\n let minX = Number.POSITIVE_INFINITY;\n let minY = Number.POSITIVE_INFINITY;\n let maxX = Number.NEGATIVE_INFINITY;\n let maxY = Number.NEGATIVE_INFINITY;\n for (const n of targetNodes) {\n const w = n.width ?? DEFAULT_NODE_WIDTH;\n const h = effectiveHeight(n);\n if (n.position.x < minX) minX = n.position.x;\n if (n.position.y < minY) minY = n.position.y;\n if (n.position.x + w > maxX) maxX = n.position.x + w;\n if (n.position.y + h > maxY) maxY = n.position.y + h;\n }\n const cw = maxX - minX;\n const ch = maxY - minY;\n const zx = (rect.width - padding * 2) / cw;\n const zy = (rect.height - padding * 2) / ch;\n const zoom = Math.max(\n opts?.minZoom ?? 0.25,\n Math.min(opts?.maxZoom ?? 1.5, Math.min(zx, zy)),\n );\n setViewport({\n zoom,\n x: rect.width / 2 - ((minX + maxX) / 2) * zoom,\n y: rect.height / 2 - ((minY + maxY) / 2) * zoom,\n });\n return true;\n },\n zoomIn: (opts) => {\n const step = opts?.step ?? 0.2;\n const next = Math.min(maxZoom, viewportRef.current.zoom * (1 + step));\n setViewport({ ...viewportRef.current, zoom: next });\n },\n zoomOut: (opts) => {\n const step = opts?.step ?? 0.2;\n const next = Math.max(minZoom, viewportRef.current.zoom / (1 + step));\n setViewport({ ...viewportRef.current, zoom: next });\n },\n zoomTo: (level) => {\n setViewport({\n ...viewportRef.current,\n zoom: Math.max(minZoom, Math.min(maxZoom, level)),\n });\n },\n\n // transforms\n screenToFlowPosition: (p) => screenToFlow(p, viewportRef.current),\n flowToScreenPosition: (p) => flowToScreen(p, viewportRef.current),\n\n // reads\n getNodes: () => nodesRef.current.slice(),\n getEdges: () => edgesRef.current.slice(),\n getNode: (id) => nodesRef.current.find((n) => n.id === id),\n getEdge: (id) => edgesRef.current.find((e) => e.id === id),\n getNodesBounds: (subset) => {\n const pool = subset\n ? nodesRef.current.filter((n) => subset.some((x) => x.id === n.id))\n : nodesRef.current.filter((n) => !n.hidden);\n if (pool.length === 0) return { x: 0, y: 0, width: 0, height: 0 };\n let minX = Number.POSITIVE_INFINITY;\n let minY = Number.POSITIVE_INFINITY;\n let maxX = Number.NEGATIVE_INFINITY;\n let maxY = Number.NEGATIVE_INFINITY;\n for (const n of pool) {\n const w = n.width ?? DEFAULT_NODE_WIDTH;\n const h = effectiveHeight(n);\n minX = Math.min(minX, n.position.x);\n minY = Math.min(minY, n.position.y);\n maxX = Math.max(maxX, n.position.x + w);\n maxY = Math.max(maxY, n.position.y + h);\n }\n return { x: minX, y: minY, width: maxX - minX, height: maxY - minY };\n },\n getIntersectingNodes: (area, partially = true) => {\n return nodesRef.current.filter((n) => {\n if (n.hidden) return false;\n const w = n.width ?? DEFAULT_NODE_WIDTH;\n const h = effectiveHeight(n);\n if (partially) {\n // Any overlap counts.\n return (\n n.position.x < area.x + area.width &&\n n.position.x + w > area.x &&\n n.position.y < area.y + area.height &&\n n.position.y + h > area.y\n );\n }\n // Strict containment — node bbox sits entirely inside area.\n return (\n n.position.x >= area.x &&\n n.position.y >= area.y &&\n n.position.x + w <= area.x + area.width &&\n n.position.y + h <= area.y + area.height\n );\n });\n },\n\n // mutations\n addNodes: (nodes) => {\n const arr = Array.isArray(nodes) ? nodes : [nodes];\n onNodesChangeRefForInstance.current?.(arr.map((item) => change.node.add(item)));\n },\n addEdges: (edges) => {\n const arr = Array.isArray(edges) ? edges : [edges];\n onEdgesChangeRefForInstance.current?.(arr.map((item) => change.edge.add(item)));\n },\n updateNodeData: (id, partial) => {\n const cur = nodesRef.current.find((n) => n.id === id);\n if (!cur) return;\n // Merge partial into existing data; the consumer's reducer will\n // apply the resulting `replace` and emit fresh nodes.\n const nextData = { ...((cur.data ?? {}) as object), ...partial } as typeof cur.data;\n onNodesChangeRefForInstance.current?.([\n change.node.replace(id, { ...cur, data: nextData }),\n ]);\n },\n updateNode: (id, partial) => {\n const cur = nodesRef.current.find((n) => n.id === id);\n if (!cur) return;\n onNodesChangeRefForInstance.current?.([change.node.replace(id, { ...cur, ...partial })]);\n },\n deleteElements: async ({ nodes: ns, edges: es }) => {\n const nodesToDelete = (ns ?? [])\n .map((x) => nodesRef.current.find((n) => n.id === x.id))\n .filter((n): n is WorkflowNode => !!n);\n const edgesToDelete = (es ?? [])\n .map((x) => edgesRef.current.find((e) => e.id === x.id))\n .filter((e): e is WorkflowEdge => !!e);\n // Async veto — host can return a Promise<boolean> to confirm\n // (\"this node is referenced by a running execution; really delete?\").\n const before = onBeforeDeleteRef.current;\n if (before) {\n const ok = await before({ nodes: nodesToDelete, edges: edgesToDelete });\n if (!ok) return false;\n }\n if (nodesToDelete.length > 0) {\n onNodesChangeRefForInstance.current?.(nodesToDelete.map((n) => change.node.remove(n.id)));\n }\n if (edgesToDelete.length > 0) {\n onEdgesChangeRefForInstance.current?.(edgesToDelete.map((e) => change.edge.remove(e.id)));\n }\n return true;\n },\n }),\n [setViewport, minZoom, maxZoom],\n );\n\n // Hand the instance to the consumer once on mount. We don't refire on\n // every render because consumers typically stash the ref once. The\n // instance itself is stable (closures read fresh values via refs).\n const initFiredRef = useRef(false);\n useEffect(() => {\n if (initFiredRef.current) return;\n initFiredRef.current = true;\n onInit?.(instance);\n }, [instance, onInit]);\n\n // Auto-frame the existing nodes on first mount. Without this, a\n // canvas that opens with nodes at positions like (1200, 800) shows\n // an empty viewport at the {0,0,1} origin and the user has to pan to\n // find their workflow. The default kicks in only when the consumer\n // didn't pin a viewport themselves and didn't explicitly disable it.\n //\n // Fires on the first frame where `nodes.length > 0` AND the container\n // has measured dimensions (a 0×0 container would yield NaN bounds).\n // The bounding-box math falls back to DEFAULT_NODE_WIDTH / height for\n // un-measured nodes, so the framing is correct even before ResizeObservers\n // have reported real dimensions.\n const fitOnInitFiredRef = useRef(false);\n useEffect(() => {\n if (fitOnInitFiredRef.current) return;\n const opt = fitViewOnInit;\n const shouldFit = opt === false ? false : opt !== undefined ? true : !viewportPropProvided;\n if (!shouldFit) return;\n if (nodes.length === 0) return;\n const rect = containerRef.current?.getBoundingClientRect();\n if (!rect || rect.width === 0 || rect.height === 0) return;\n fitOnInitFiredRef.current = true;\n const fitOpts = typeof opt === \"object\" && opt !== null ? opt : undefined;\n // Defer one frame so any layout effects (e.g. ResizeObservers reporting\n // node dimensions) have settled before we compute bounds.\n const raf = requestAnimationFrame(() => {\n void instance.fitView(fitOpts);\n });\n return () => cancelAnimationFrame(raf);\n }, [fitViewOnInit, viewportPropProvided, nodes.length, instance]);\n\n // ── Keyboard: Backspace / Delete removes the current selection ────────\n // Goes through `instance.deleteElements` so `onBeforeDelete` veto, edge\n // re-routing, and the same change pipeline as the X button fire\n // consistently. We only act when focus is on the canvas (or its\n // children) — typing in a real input shouldn't delete the workflow.\n useEffect(() => {\n const onKey = (e: KeyboardEvent) => {\n if (e.key !== \"Backspace\" && e.key !== \"Delete\") return;\n const target = e.target as HTMLElement | null;\n // Don't hijack typing in form fields. `contentEditable` covers the\n // edge label inline editor.\n if (\n target &&\n (target.tagName === \"INPUT\" ||\n target.tagName === \"TEXTAREA\" ||\n target.tagName === \"SELECT\" ||\n target.isContentEditable)\n ) {\n return;\n }\n // Only fire when the canvas (or something inside it) currently\n // owns focus / pointer interaction. Bare `keydown` on document\n // would steal Backspace from other widgets on the page.\n if (!containerRef.current?.contains(target) && document.activeElement !== document.body) {\n return;\n }\n const sel = store.getSnapshot();\n if (sel.selectedNodeIds.size === 0 && sel.selectedEdgeIds.size === 0) return;\n e.preventDefault();\n void instance.deleteElements({\n nodes: Array.from(sel.selectedNodeIds, (id) => ({ id })),\n edges: Array.from(sel.selectedEdgeIds, (id) => ({ id })),\n });\n };\n window.addEventListener(\"keydown\", onKey);\n return () => window.removeEventListener(\"keydown\", onKey);\n }, [instance, store]);\n\n const bridge = useMemo<FlowNodeBridge>(\n () => ({\n beginNodeDrag,\n selectNode,\n notifyNodeClick,\n selectEdge,\n reportDimensions,\n deleteNode: deleteNodeImpl,\n toggleNodeCollapse: toggleNodeCollapseImpl,\n }),\n [\n beginNodeDrag,\n selectNode,\n notifyNodeClick,\n selectEdge,\n reportDimensions,\n deleteNodeImpl,\n toggleNodeCollapseImpl,\n ],\n );\n\n // ── Cursor feedback ───────────────────────────────────────────────────\n // The user gets immediate visual cues for which gesture they're in:\n // - idle on empty canvas → \"grab\" (or default if panOnDrag = false)\n // - dragging the pane → \"grabbing\"\n // - dragging a connection → \"crosshair\"\n // - dragging a node → handled by FlowNode CSS (\"grabbing\")\n // We use a state-driven class so the cursor flips synchronously with\n // the gesture (vs CSS :active which lags behind pointer-capture).\n const [panGesture, setPanGesture] = useState(false);\n\n // ── Render ────────────────────────────────────────────────────────────\n const isEmpty = nodes.length === 0 && edges.length === 0;\n const isConnecting = conn !== null;\n\n // Filter out hidden nodes + their incident edges. Hidden is a runtime\n // flag (e.g. set by a \"collapse group\" toggle). Edges that reference a\n // hidden node would otherwise dangle in space.\n const visibleNodes = useMemo(() => nodes.filter((n) => !n.hidden), [nodes]);\n const visibleEdges = useMemo(() => {\n if (visibleNodes.length === nodes.length) return edges;\n const visibleIds = new Set(visibleNodes.map((n) => n.id));\n return edges.filter((e) => visibleIds.has(e.source) && visibleIds.has(e.target));\n }, [edges, nodes, visibleNodes]);\n\n // Sort so containers render before their children (lower in DOM = under\n // children when zIndex ties). For NESTED containers (group inside group)\n // we order by depth — outermost first — so an inner group's children\n // can still draw on top of the outer group's frame. Non-container nodes\n // sort last in original-array order.\n //\n // Containers: `group` + `forEach`. Both are frames whose children render\n // above them.\n const orderedNodes = useMemo(() => {\n const isContainer = (n: WorkflowNode) => n.type === \"group\" || n.type === \"forEach\";\n // Cache parent chain depth for stable ordering. Cycles return Infinity.\n const depth = (n: WorkflowNode): number => {\n let d = 0;\n let cursor = n.parentId;\n const seen = new Set<string>();\n while (cursor) {\n if (seen.has(cursor)) return Number.POSITIVE_INFINITY;\n seen.add(cursor);\n d++;\n cursor = visibleNodes.find((x) => x.id === cursor)?.parentId;\n }\n return d;\n };\n const containers = visibleNodes.filter(isContainer);\n const others = visibleNodes.filter((n) => !isContainer(n));\n containers.sort((a, b) => depth(a) - depth(b));\n return [...containers, ...others];\n }, [visibleNodes]);\n\n return (\n <FlowStoreContext.Provider value={store}>\n <FlowInstanceContext.Provider value={instance}>\n <HandleRegistryContext.Provider value={handleRegistry}>\n <FlowDispatchContext.Provider value={dispatch}>\n <FlowNodeBridgeContext.Provider value={bridge}>\n <div\n ref={containerRef}\n className={cn(\n \"ods-flow-canvas-v2\",\n panGesture && \"ods-flow-canvas-v2--panning\",\n isConnecting && \"ods-flow-canvas-v2--connecting\",\n draggingId && \"ods-flow-canvas-v2--dragging\",\n className,\n )}\n style={{\n position: \"relative\",\n width,\n height,\n overflow: \"hidden\",\n userSelect: \"none\",\n touchAction: \"none\",\n // Cursor: state-driven so it flips instantly with the\n // gesture. CSS `:active` would lag behind pointer-capture.\n cursor: panGesture\n ? \"grabbing\"\n : isConnecting\n ? \"crosshair\"\n : panOnDrag\n ? \"grab\"\n : \"default\",\n ...style,\n }}\n onPointerDown={onCanvasPointerDown}\n onWheel={handleWheel}\n onContextMenu={(e) => {\n // Route the right-click to the per-surface handler based on\n // where the pointer landed. Consumers `preventDefault()` to\n // suppress the browser's native menu; we don't do it for\n // them because some workflows prefer the OS menu on pane.\n const t = e.target as HTMLElement;\n const nodeEl = t.closest(\"[data-node-id]\") as HTMLElement | null;\n if (nodeEl && onNodeContextMenu) {\n const id = nodeEl.dataset.nodeId!;\n const node = nodes.find((n) => n.id === id);\n if (node) onNodeContextMenu(e, node);\n return;\n }\n const edgeEl = t.closest(\"[data-edge-id]\") as HTMLElement | null;\n if (edgeEl && onEdgeContextMenu) {\n const id = edgeEl.dataset.edgeId!;\n const edge = edges.find((x) => x.id === id);\n if (edge) onEdgeContextMenu(e, edge);\n return;\n }\n onPaneContextMenu?.(e);\n }}\n data-empty={isEmpty ? \"true\" : undefined}\n >\n {background !== \"none\" && (\n <div\n className={cn(\n \"ods-flow-canvas-v2__grid\",\n `ods-flow-canvas-v2__grid--${background}`,\n )}\n style={\n {\n // Custom property drives the four variants' SCSS.\n \"--ods-flow-grid-size\": `${gridSize * viewport.zoom}px`,\n backgroundPosition: `${viewport.x}px ${viewport.y}px`,\n } as CSSProperties\n }\n />\n )}\n\n <div\n className=\"ods-flow-canvas-v2__viewport\"\n style={{\n position: \"absolute\",\n inset: 0,\n transform: `translate(${viewport.x}px, ${viewport.y}px) scale(${viewport.zoom})`,\n transformOrigin: \"0 0\",\n }}\n >\n <EdgesLayer\n edges={visibleEdges}\n nodes={visibleNodes}\n onSelect={(id) => bridge.selectEdge(id, false)}\n onDelete={(id) => onEdgesChangeRef(id, onEdgesChange)}\n onLabelChange={onEdgeLabelChange}\n ghost={conn ? { start: conn.start, end: conn.end } : null}\n // Bust EdgesLayer's memo when the handle registry\n // changes, so edges recompute geometry against the\n // newly-mounted handles.\n handleVersion={handleVersion}\n />\n\n {orderedNodes.map((node) => {\n const Kind = kinds[node.type] ?? kinds.action;\n if (!Kind) return null;\n return (\n <FlowNode\n key={node.id}\n node={node}\n selected={selectedNodeIds.has(node.id)}\n dragging={draggingId === node.id}\n isConnecting={isConnecting}\n Kind={Kind}\n />\n );\n })}\n </div>\n\n {isEmpty && emptyState && (\n <div className=\"ods-flow-canvas-v2__empty\">{emptyState}</div>\n )}\n\n {children}\n </div>\n </FlowNodeBridgeContext.Provider>\n </FlowDispatchContext.Provider>\n </HandleRegistryContext.Provider>\n </FlowInstanceContext.Provider>\n </FlowStoreContext.Provider>\n );\n}\n\n// Tiny helper — keeps the JSX above clean.\nfunction onEdgesChangeRef(id: string, cb?: (changes: EdgeChange[]) => void) {\n cb?.([change.edge.remove(id)]);\n}\n\n/**\n * Compute auto-resize updates for every container in the graph so each\n * frame encloses its current children + padding.\n *\n * `pending` carries the position / replace changes the canvas is\n * about to dispatch — we PROJECT them onto the current node list\n * before measuring so a drag that just moved a child uses the new\n * position, not the stale committed one. That makes the auto-resize\n * atomic with the drag commit: a single `onNodesChange` call carries\n * both the child's new position AND the parent's new frame.\n *\n * Container frames only GROW (max with current width/height) — the\n * user's manual `<NodeResizer>` choice doesn't get shrunk away on the\n * next drag. The frame also re-positions its top-left to follow the\n * children bbox so children stay visually inside.\n */\nfunction computeContainerAutoResize(\n nodes: WorkflowNode[],\n pending: NodeChange[],\n padding: number,\n): NodeChange[] {\n // Apply pending changes to a transient view of the node list. We\n // care about: `position` (child moves), `replace` (reparent), and\n // `add` (newly-inserted nodes are projected too). Other change\n // types don't affect bbox math.\n const projected = new Map<string, WorkflowNode>();\n for (const n of nodes) projected.set(n.id, n);\n for (const c of pending) {\n if (c.type === \"position\" && c.position) {\n const cur = projected.get(c.id);\n if (cur) projected.set(c.id, { ...cur, position: c.position });\n } else if (c.type === \"replace\" && c.item) {\n projected.set(c.id, { ...projected.get(c.id), ...c.item } as WorkflowNode);\n } else if (c.type === \"add\" && c.item) {\n projected.set((c.item as WorkflowNode).id, c.item as WorkflowNode);\n }\n }\n\n const HEADER = 56; // breathing room above the first child\n const out: NodeChange[] = [];\n for (const parent of projected.values()) {\n if (parent.type !== \"group\" && parent.type !== \"forEach\") continue;\n const children: WorkflowNode[] = [];\n for (const n of projected.values()) {\n if (n.parentId === parent.id) children.push(n);\n }\n if (children.length === 0) continue;\n\n let minX = Number.POSITIVE_INFINITY;\n let minY = Number.POSITIVE_INFINITY;\n let maxX = Number.NEGATIVE_INFINITY;\n let maxY = Number.NEGATIVE_INFINITY;\n for (const c of children) {\n const cw = c.width ?? 240;\n const ch = c.height ?? 96;\n if (c.position.x < minX) minX = c.position.x;\n if (c.position.y < minY) minY = c.position.y;\n if (c.position.x + cw > maxX) maxX = c.position.x + cw;\n if (c.position.y + ch > maxY) maxY = c.position.y + ch;\n }\n const targetX = minX - padding;\n const targetY = minY - padding - HEADER;\n const targetW = maxX - minX + padding * 2;\n const targetH = maxY - minY + padding * 2 + HEADER;\n const curW = parent.width ?? 480;\n const curH = parent.height ?? 240;\n // GROW only — don't shrink past a manual resize choice.\n const nextW = Math.max(curW, targetW);\n const nextH = Math.max(curH, targetH);\n const positionDirty = parent.position.x !== targetX || parent.position.y !== targetY;\n const sizeDirty = curW !== nextW || curH !== nextH;\n if (positionDirty) {\n out.push(change.node.position(parent.id, { x: targetX, y: targetY }, false));\n }\n if (sizeDirty) {\n out.push(change.node.dimensions(parent.id, { width: nextW, height: nextH }));\n }\n }\n return out;\n}\n\n// ────────────────────────────────────────────────────────────────────────\n// EdgesLayer — memoised. Re-renders only when edges/nodes arrays or ghost\n// position change. Edges within use memo on (edge, source/target position,\n// edge.selected/animated) so dragging one node only re-renders edges\n// connected to that node.\n// ────────────────────────────────────────────────────────────────────────\nconst EdgesLayer = memo(function EdgesLayer({\n edges,\n nodes,\n onSelect,\n onDelete,\n onLabelChange,\n ghost,\n handleVersion: _handleVersion,\n}: {\n edges: WorkflowEdge[];\n nodes: WorkflowNode[];\n onSelect: (id: string) => void;\n onDelete: (id: string) => void;\n onLabelChange?: (id: string, label: string) => void;\n ghost: { start: Position; end: Position } | null;\n /** Bust-cache token that flips whenever the handle registry mutates.\n * React.memo's default shallow compare picks up the change and re-\n * renders the layer; FlowEdge inside reads the now-up-to-date\n * registry on the re-render. */\n handleVersion: number;\n}) {\n return (\n <svg\n className=\"ods-flow-canvas-v2__edges\"\n style={{ position: \"absolute\", inset: 0, overflow: \"visible\", pointerEvents: \"none\" }}\n width=\"100%\"\n height=\"100%\"\n >\n <g style={{ pointerEvents: \"auto\" }}>\n {edges.map((edge) => (\n <FlowEdge\n key={edge.id}\n edge={edge}\n nodes={nodes}\n onSelect={onSelect}\n onDelete={onDelete}\n onLabelChange={onLabelChange}\n handleVersion={_handleVersion}\n />\n ))}\n </g>\n {ghost && (\n <path\n d={`M ${ghost.start.x} ${ghost.start.y} L ${ghost.end.x} ${ghost.end.y}`}\n stroke=\"var(--ods-accent, #4f46e5)\"\n strokeWidth={1.5}\n strokeDasharray=\"4 4\"\n fill=\"none\"\n />\n )}\n </svg>\n );\n});\n\n// Type re-export so consumers don't need to import from a deeper path.\nexport type { BuiltInNodeData };\n","// ════════════════════════════════════════════════════════════════════════\n// FlowStore — per-canvas state, exposed only via narrow selector hooks.\n// ════════════════════════════════════════════════════════════════════════\n// We deliberately do NOT export the store instance (see ADR-005). The\n// store lives behind a React context; descendants read via\n// `useFlowSelector(selector)` which under the hood is\n// `useSyncExternalStore` against a single `subscribe` channel.\n//\n// The store is the single source of truth for runtime state\n// (selection, viewport, in-flight connection). Node/edge data is mirrored\n// from the controlled props each render; the store keeps a frozen\n// snapshot so descendants don't have to thread `nodes` / `edges` through\n// component trees.\n\nimport type {\n ConnectStartParams,\n FlowStoreSnapshot,\n Viewport,\n WorkflowEdge,\n WorkflowNode,\n} from \"../editor\";\n\ntype Listener = () => void;\n\nexport interface FlowStore {\n /** React subscription hook contract — used by `useSyncExternalStore`. */\n subscribe(listener: Listener): () => void;\n /** Cheap snapshot getter — must return the same ref between mutations. */\n getSnapshot(): FlowStoreSnapshot;\n /** Imperative setters — called by the canvas internals, never by consumers. */\n setNodes(nodes: WorkflowNode[]): void;\n setEdges(edges: WorkflowEdge[]): void;\n setViewport(viewport: Viewport): void;\n setSelection(nodes: ReadonlySet<string>, edges: ReadonlySet<string>): void;\n setConnection(connection: ConnectStartParams | null): void;\n}\n\nexport interface CreateFlowStoreOptions {\n initialNodes?: WorkflowNode[];\n initialEdges?: WorkflowEdge[];\n initialViewport?: Viewport;\n}\n\nconst DEFAULT_VIEWPORT: Viewport = { x: 0, y: 0, zoom: 1 };\n\n/**\n * Build a FlowStore for one canvas instance. Designed to be created in\n * `useState(() => createFlowStore())` inside FlowCanvas so a single\n * `<FlowCanvas>` owns exactly one store and unmounting cleans it up.\n */\nexport function createFlowStore({\n initialNodes = [],\n initialEdges = [],\n initialViewport = DEFAULT_VIEWPORT,\n}: CreateFlowStoreOptions = {}): FlowStore {\n let snapshot: FlowStoreSnapshot = {\n nodes: initialNodes,\n edges: initialEdges,\n viewport: initialViewport,\n selectedNodeIds: EMPTY_SET,\n selectedEdgeIds: EMPTY_SET,\n connection: null,\n };\n\n const listeners = new Set<Listener>();\n const emit = () => {\n for (const l of listeners) l();\n };\n\n const subscribe = (listener: Listener) => {\n listeners.add(listener);\n return () => {\n listeners.delete(listener);\n };\n };\n\n // Replace the snapshot reference on every change so React's\n // `useSyncExternalStore` triggers a re-render. We never mutate in place.\n const replace = (patch: Partial<FlowStoreSnapshot>) => {\n snapshot = { ...snapshot, ...patch };\n emit();\n };\n\n return {\n subscribe,\n getSnapshot: () => snapshot,\n setNodes(nodes) {\n if (nodes === snapshot.nodes) return;\n replace({ nodes });\n },\n setEdges(edges) {\n if (edges === snapshot.edges) return;\n replace({ edges });\n },\n setViewport(viewport) {\n if (\n viewport.x === snapshot.viewport.x &&\n viewport.y === snapshot.viewport.y &&\n viewport.zoom === snapshot.viewport.zoom\n ) {\n return;\n }\n replace({ viewport });\n },\n setSelection(selectedNodeIds, selectedEdgeIds) {\n replace({ selectedNodeIds, selectedEdgeIds });\n },\n setConnection(connection) {\n if (connection === snapshot.connection) return;\n replace({ connection });\n },\n };\n}\n\nconst EMPTY_SET: ReadonlySet<string> = new Set();\n","// ════════════════════════════════════════════════════════════════════════\n// Collision avoidance — keep nodes from overlapping each other (or from\n// landing closer than a configurable minimum gap).\n// ════════════════════════════════════════════════════════════════════════\n//\n// The function below is a pure axis-aligned bounding-box (AABB) \"minimum\n// translation vector\" resolver. Given a proposed position for one node\n// and a set of other nodes, it shifts the proposed position along the\n// axis of *smallest* overlap correction until either (a) no node is\n// closer than `gap` pixels, or (b) the iteration cap is reached.\n//\n// Why MTV? It produces the smoothest \"magnet snap\" UX — when you nudge a\n// node toward a neighbour, it slides along the contact edge rather than\n// flinging away. The iteration cap (8 by default) handles cascading\n// resolutions where pushing out of one node lands in another.\n\nimport type { Position, WorkflowNode } from \"../editor\";\nimport { DEFAULT_NODE_WIDTH, effectiveHeight } from \"./geometry\";\n\nexport interface CollisionOptions {\n /** Minimum gap (px) the dragged node must keep from each other node.\n *\n * - `gap >= 0` — the resolver is **enabled**. `gap === 0` means\n * \"no overlap, zero buffer\" (strict no-overlap). `gap > 0` enforces\n * a buffer of that many pixels.\n * - `gap < 0` — the resolver is **disabled** (returns the proposed\n * position unchanged). This is the no-op sentinel used by\n * consumers that haven't opted into magnet behaviour. */\n gap: number;\n /** Cap iterative resolutions — prevents infinite loops in pathological\n * geometries (e.g. four nodes hugging a single corner). Default 8. */\n maxIterations?: number;\n /** Node ids that the resolver should ignore — typically the dragged\n * node itself plus its descendants (so a parent doesn't collide with\n * its own children) and its ancestors (so a child doesn't collide\n * with its containing group). */\n exclude?: Set<string>;\n /** When true, only consider nodes that share the same `parentId` as\n * the dragged node (i.e. its siblings). When false, all non-excluded\n * nodes participate. Defaults to true — this is the \"rooms\" model\n * where children of group A never collide with children of group B\n * even if their bboxes overlap in flow space. */\n scopeToSiblings?: boolean;\n}\n\n/**\n * Adjust a proposed (flow-space) position so the node's bbox stays at\n * least `gap` pixels away from every other (non-excluded) node's bbox.\n *\n * The function does NOT mutate the input nodes; it returns a new\n * `Position`. The caller is responsible for emitting the resulting\n * change via `onNodesChange` — collision resolution doesn't dispatch\n * anything on its own.\n */\nexport function resolveNodeCollisions(\n node: WorkflowNode,\n proposed: Position,\n others: WorkflowNode[],\n opts: CollisionOptions,\n): Position {\n const { gap, maxIterations = 8, exclude, scopeToSiblings = true } = opts;\n if (gap < 0 || others.length === 0) return proposed;\n\n const w = node.width ?? DEFAULT_NODE_WIDTH;\n const h = effectiveHeight(node);\n const parentId = node.parentId;\n\n // Pre-filter the candidate list once — keeps the per-iteration loop tight.\n const candidates = others.filter((o) => {\n if (o.id === node.id) return false;\n if (o.hidden) return false;\n if (exclude?.has(o.id)) return false;\n if (scopeToSiblings && (o.parentId ?? undefined) !== (parentId ?? undefined)) {\n return false;\n }\n return true;\n });\n if (candidates.length === 0) return proposed;\n\n let cur = proposed;\n\n for (let iter = 0; iter < maxIterations; iter++) {\n // Find the colliding pair with the SMALLEST overlap correction and\n // resolve that one this iteration. Doing one push per iteration keeps\n // the displacement minimal and lets cascading shifts settle naturally.\n let bestOverlap = Number.POSITIVE_INFINITY;\n let bestPushX = 0;\n let bestPushY = 0;\n let hit = false;\n\n // Inflate our rect by `gap` so any node within `gap` registers as\n // overlap. We add the full gap to one side (rather than gap/2 to\n // both sides) so the resulting min-distance matches user intuition:\n // \"at least `gap` pixels between the two visual edges.\"\n const aLeft = cur.x - gap;\n const aRight = cur.x + w + gap;\n const aTop = cur.y - gap;\n const aBottom = cur.y + h + gap;\n\n for (const o of candidates) {\n const ow = o.width ?? DEFAULT_NODE_WIDTH;\n const oh = effectiveHeight(o);\n const bLeft = o.position.x;\n const bRight = o.position.x + ow;\n const bTop = o.position.y;\n const bBottom = o.position.y + oh;\n\n const overlapX = Math.min(aRight, bRight) - Math.max(aLeft, bLeft);\n const overlapY = Math.min(aBottom, bBottom) - Math.max(aTop, bTop);\n if (overlapX <= 0 || overlapY <= 0) continue;\n\n // Pick the axis with the smaller overlap — that's the cheaper push.\n // Direction: if our centre is \"before\" their centre on that axis,\n // push backward; otherwise push forward.\n let pushX = 0;\n let pushY = 0;\n let overlap: number;\n if (overlapX < overlapY) {\n const aCx = cur.x + w / 2;\n const bCx = o.position.x + ow / 2;\n pushX = aCx < bCx ? -overlapX : overlapX;\n overlap = overlapX;\n } else {\n const aCy = cur.y + h / 2;\n const bCy = o.position.y + oh / 2;\n pushY = aCy < bCy ? -overlapY : overlapY;\n overlap = overlapY;\n }\n\n if (overlap < bestOverlap) {\n bestOverlap = overlap;\n bestPushX = pushX;\n bestPushY = pushY;\n hit = true;\n }\n }\n\n if (!hit) break;\n cur = { x: cur.x + bestPushX, y: cur.y + bestPushY };\n }\n\n return cur;\n}\n"],"mappings":"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","names":["distance","useContext","createContext","useContext","useContext","change","bezierPath","distance","createContext","useContext","offsetAlongSide","createContext","useContext","useEffect","useMemo","useRef","createContext","useContext","jsx","useRef","useEffect","useMemo","useEffect","useRef","jsx","jsxs","useRef","useEffect","useRef","jsx","useRef","useContext","jsx","jsxs","useContext","jsx","jsxs","memo","useEffect","useMemo","useRef","useState","jsx","jsxs","DEFAULT_VIEWPORT","useState","useEffect","useMemo","useRef","c","width","height","nodes","edges","memo","EdgesLayer"]}