@synergenius/flow-weaver 0.33.1 → 0.33.2

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.
@@ -11,11 +11,11 @@ export declare const LAYER_GAP_X = 300;
11
11
  export declare const LABEL_CLEARANCE = 42;
12
12
  export declare const MIN_EDGE_GAP = 112;
13
13
  export declare const NODE_GAP_Y = 60;
14
- export declare const LABEL_HEIGHT = 20;
14
+ export declare const LABEL_HEIGHT = 24;
15
15
  export declare const LABEL_GAP = 12;
16
16
  export declare const SCOPE_PADDING_X = 140;
17
17
  export declare const SCOPE_PADDING_Y = 40;
18
- export declare const SCOPE_PORT_COLUMN = 50;
18
+ export declare const SCOPE_PORT_COLUMN = 45;
19
19
  export declare const SCOPE_INNER_GAP_X = 240;
20
20
  export declare const ORTHOGONAL_DISTANCE_THRESHOLD = 300;
21
21
  export declare const STUB_DISTANCE_THRESHOLD = 500;
@@ -26,6 +26,11 @@ export declare function measureText(text: string): number;
26
26
  export declare function portBadgeWidth(port: DiagramPort): number;
27
27
  export declare function computeNodeDimensions(node: DiagramNode): void;
28
28
  export declare function computePortPositions(node: DiagramNode): void;
29
+ /**
30
+ * Compute a quad-curve connection from B towards D with consistent tangent.
31
+ * U is a unit vector from B to C with the same slope as B→D.
32
+ */
33
+ /** Straight-line fallback when orthogonal routing fails (matches platform behaviour). */
29
34
  export declare function computeConnectionPath(sx: number, sy: number, tx: number, ty: number): string;
30
35
  export declare function buildDiagramGraph(ast: TWorkflowAST, options?: DiagramOptions): DiagramGraph;
31
36
  //# sourceMappingURL=geometry.d.ts.map
@@ -15,12 +15,12 @@ export const LAYER_GAP_X = 300; // target center-to-center; actual gap adapts to
15
15
  export const LABEL_CLEARANCE = 42; // breathing room between opposing port label badges
16
16
  export const MIN_EDGE_GAP = 112; // minimum edge-to-edge gap between node boxes
17
17
  export const NODE_GAP_Y = 60;
18
- export const LABEL_HEIGHT = 20; // 13px font + padding
18
+ export const LABEL_HEIGHT = 24; // 18px font + breathing room
19
19
  export const LABEL_GAP = 12; // matches labelRootStyle bottom: calc(100% + 12px)
20
20
  // Scope rendering constants
21
21
  export const SCOPE_PADDING_X = 140; // horizontal padding inside scope (between port columns and children)
22
22
  export const SCOPE_PADDING_Y = 40; // vertical padding inside scope (top/bottom)
23
- export const SCOPE_PORT_COLUMN = 50; // width for scoped port column on inner edges
23
+ export const SCOPE_PORT_COLUMN = 45; // matches platform scopeContainerStyle minWidth/maxWidth
24
24
  export const SCOPE_INNER_GAP_X = 240; // horizontal gap between children inside scope
25
25
  // Routing mode threshold — connections longer than this use orthogonal routing
26
26
  // (midpoint of original 250–350 hysteresis thresholds)
@@ -99,49 +99,9 @@ function positionPortList(ports, cx, nodeY, _nodeHeight) {
99
99
  * Compute a quad-curve connection from B towards D with consistent tangent.
100
100
  * U is a unit vector from B to C with the same slope as B→D.
101
101
  */
102
- function quadCurveControl(ax, ay, bx, by, ux, uy) {
103
- const dn = Math.abs(ay - by);
104
- const cx = bx + (ux * dn) / Math.abs(uy);
105
- const cy = ay;
106
- return [cx, cy];
107
- }
102
+ /** Straight-line fallback when orthogonal routing fails (matches platform behaviour). */
108
103
  export function computeConnectionPath(sx, sy, tx, ty) {
109
- const e = 0.0001; // insignificant shift to avoid degenerate tangents
110
- const ax = sx + e;
111
- const ay = sy + e;
112
- const hx = tx - e;
113
- const hy = ty - e;
114
- const ramp = Math.min(20, (hx - ax) / 10);
115
- const bx = ax + ramp;
116
- const by = ay + e;
117
- const gx = hx - ramp;
118
- const gy = hy - e;
119
- const curveSizeX = Math.min(60, Math.abs(ax - hx) / 4);
120
- const curveSizeY = Math.min(60, Math.abs(ay - hy) / 4);
121
- const curveMag = Math.sqrt(curveSizeX * curveSizeX + curveSizeY * curveSizeY);
122
- const bgX = gx - bx;
123
- const bgY = gy - by;
124
- const bgLen = Math.sqrt(bgX * bgX + bgY * bgY);
125
- const bgUx = bgX / bgLen;
126
- const bgUy = bgY / bgLen;
127
- const dx = bx + bgUx * curveMag;
128
- const dy = by + (bgUy * curveMag) / 2;
129
- const ex = gx - bgUx * curveMag;
130
- const ey = gy - (bgUy * curveMag) / 2;
131
- const deX = ex - dx;
132
- const deY = ey - dy;
133
- const deLen = Math.sqrt(deX * deX + deY * deY);
134
- const deUx = deX / deLen;
135
- const deUy = deY / deLen;
136
- const [cx, cy] = quadCurveControl(bx, by, dx, dy, -deUx, -deUy);
137
- const [fx, fy] = quadCurveControl(gx, gy, ex, ey, deUx, deUy);
138
- let path = `M ${cx},${cy} M ${ax},${ay}`;
139
- path += ` L ${bx},${by}`;
140
- path += ` Q ${cx},${cy} ${dx},${dy}`;
141
- path += ` L ${ex},${ey}`;
142
- path += ` Q ${fx},${fy} ${gx},${gy}`;
143
- path += ` L ${hx},${hy}`;
144
- return path;
104
+ return `M ${sx},${sy} L ${tx},${ty}`;
145
105
  }
146
106
  // ---- Port ordering helpers ----
147
107
  /**
@@ -1028,17 +988,20 @@ export function buildDiagramGraph(ast, options = {}) {
1028
988
  color: targetColor,
1029
989
  dashed,
1030
990
  };
991
+ // For static SVG, offset path endpoints past port labels so connections
992
+ // aren't hidden behind opaque label badges. HTML viewer has interactive
993
+ // labels (show/hide on hover), so paths start at port center there.
994
+ const isStaticSvg = options.format !== 'html';
995
+ const pathSx = isStaticSvg ? sx + srcLabelEnd : sx;
996
+ const pathTx = isStaticSvg ? tx - tgtLabelEnd : tx;
1031
997
  let path;
1032
998
  if (xDistance > STUB_DISTANCE_THRESHOLD) {
1033
999
  // Long-distance: static SVG hides the full path, only shows stubs
1034
1000
  path = '';
1035
1001
  }
1036
- else if (!useCurve && distance > ORTHOGONAL_DISTANCE_THRESHOLD) {
1037
- const orthoPath = calculateOrthogonalPathSafe([sx, sy], [tx, ty], nodeBoxes, pc.fromNodeId, pc.toNodeId, { fromPortIndex: pc.fromPortIndex, toPortIndex: pc.toPortIndex }, allocator);
1038
- path = orthoPath ?? computeConnectionPath(sx, sy, tx, ty);
1039
- }
1040
1002
  else {
1041
- path = computeConnectionPath(sx, sy, tx, ty);
1003
+ const orthoPath = calculateOrthogonalPathSafe([pathSx, sy], [pathTx, ty], nodeBoxes, pc.fromNodeId, pc.toNodeId, { fromPortIndex: pc.fromPortIndex, toPortIndex: pc.toPortIndex, allocator });
1004
+ path = orthoPath ?? computeConnectionPath(pathSx, sy, pathTx, ty);
1042
1005
  }
1043
1006
  connections.push({
1044
1007
  fromNode: pc.fromNodeId, fromPort: pc.fromPortName,
@@ -1138,13 +1101,9 @@ export function buildDiagramGraph(ast, options = {}) {
1138
1101
  const ddy = ty - sy;
1139
1102
  const dist = Math.sqrt(ddx * ddx + ddy * ddy);
1140
1103
  const useCurve = spForceCurveSet.has(sp);
1141
- if (!useCurve && dist > ORTHOGONAL_DISTANCE_THRESHOLD) {
1142
- const orthoPath = calculateOrthogonalPathSafe([sx, sy], [tx, ty], nodeBoxes, sp.fromNodeId, sp.toNodeId, { fromPortIndex: sp.fromPortIndex, toPortIndex: sp.toPortIndex }, allocator);
1143
- sp.conn.path = orthoPath ?? computeConnectionPath(sx, sy, tx, ty);
1144
- }
1145
- else {
1146
- sp.conn.path = computeConnectionPath(sx, sy, tx, ty);
1147
- }
1104
+ // Always try orthogonal routing first (matches platform style)
1105
+ const orthoPath = calculateOrthogonalPathSafe([sx, sy], [tx, ty], nodeBoxes, sp.fromNodeId, sp.toNodeId, { fromPortIndex: sp.fromPortIndex, toPortIndex: sp.toPortIndex, allocator });
1106
+ sp.conn.path = orthoPath ?? computeConnectionPath(sx, sy, tx, ty);
1148
1107
  }
1149
1108
  }
1150
1109
  // Extend bounds to include connection paths (routes can go outside node area)
@@ -74,13 +74,12 @@ body.node-active [data-source].dimmed,
74
74
  body.port-active [data-source].dimmed { opacity: 0.1; }
75
75
  body.port-hovered [data-source].dimmed { opacity: 0.25; }
76
76
 
77
- /* Port circles are interactive */
78
- circle[data-port-id] { cursor: pointer; }
79
- circle[data-port-id]:hover { stroke-width: 3; filter: brightness(1.3); }
77
+ /* Port indicators are interactive — expands to circle on hover (matches platform) */
78
+ [data-port-id] { cursor: pointer; }
80
79
 
81
80
  /* Port-click highlighting */
82
81
  [data-source].highlighted { opacity: 1; }
83
- circle[data-port-id].port-selected { filter: drop-shadow(0 0 6px currentColor); stroke-width: 4; }
82
+ [data-port-id].port-selected { filter: drop-shadow(0 0 6px currentColor); }
84
83
 
85
84
  /* Node selection glow */
86
85
  @keyframes select-pop {
@@ -285,7 +284,7 @@ circle[data-port-id].port-selected { filter: drop-shadow(0 0 6px currentColor);
285
284
  <svg id="canvas" xmlns="http://www.w3.org/2000/svg" viewBox="${viewBox}">
286
285
  <defs>
287
286
  <pattern id="viewer-dots" width="20" height="20" patternUnits="userSpaceOnUse">
288
- <circle cx="10" cy="10" r="1.5" fill="${dotColor}" opacity="0.6"/>
287
+ <circle cx="10" cy="10" r="0.75" fill="${dotColor}" opacity="0.4"/>
289
288
  </pattern>
290
289
  </defs>
291
290
  <rect x="-100000" y="-100000" width="200000" height="200000" fill="${bg}" pointer-events="none"/>
@@ -562,33 +561,9 @@ circle[data-port-id].port-selected { filter: drop-shadow(0 0 6px currentColor);
562
561
  var MIN_SEG_LEN = 3, JOG_THRESHOLD = 10, ORTHO_THRESHOLD = 300;
563
562
  var STUB_THRESHOLD = 500, STUB_LEN = 30;
564
563
 
565
- function quadCurveControl(ax, ay, bx, by, ux, uy) {
566
- var dn = Math.abs(ay - by);
567
- return [bx + (ux * dn) / Math.abs(uy), ay];
568
- }
569
-
564
+ // Straight-line fallback when orthogonal routing fails (matches platform)
570
565
  function computeConnectionPath(sx, sy, tx, ty) {
571
- var e = 0.0001;
572
- var ax = sx + e, ay = sy + e, hx = tx - e, hy = ty - e;
573
- var ramp = Math.min(20, (hx - ax) / 10);
574
- var bx = ax + ramp, by = ay + e, gx = hx - ramp, gy = hy - e;
575
- var curveSizeX = Math.min(60, Math.abs(ax - hx) / 4);
576
- var curveSizeY = Math.min(60, Math.abs(ay - hy) / 4);
577
- var curveMag = Math.sqrt(curveSizeX * curveSizeX + curveSizeY * curveSizeY);
578
- var bgX = gx - bx, bgY = gy - by;
579
- var bgLen = Math.sqrt(bgX * bgX + bgY * bgY);
580
- var bgUx = bgX / bgLen, bgUy = bgY / bgLen;
581
- var dx = bx + bgUx * curveMag, dy = by + (bgUy * curveMag) / 2;
582
- var ex = gx - bgUx * curveMag, ey = gy - (bgUy * curveMag) / 2;
583
- var deX = ex - dx, deY = ey - dy;
584
- var deLen = Math.sqrt(deX * deX + deY * deY);
585
- var deUx = deX / deLen, deUy = deY / deLen;
586
- var c = quadCurveControl(bx, by, dx, dy, -deUx, -deUy);
587
- var f = quadCurveControl(gx, gy, ex, ey, deUx, deUy);
588
- return 'M ' + c[0] + ',' + c[1] + ' M ' + ax + ',' + ay +
589
- ' L ' + bx + ',' + by + ' Q ' + c[0] + ',' + c[1] + ' ' + dx + ',' + dy +
590
- ' L ' + ex + ',' + ey + ' Q ' + f[0] + ',' + f[1] + ' ' + gx + ',' + gy +
591
- ' L ' + hx + ',' + hy;
566
+ return 'M ' + sx + ',' + sy + ' L ' + tx + ',' + ty;
592
567
  }
593
568
 
594
569
  // ---- Orthogonal router (ported from orthogonal-router.ts) ----
@@ -871,7 +846,16 @@ circle[data-port-id].port-selected { filter: drop-shadow(0 0 6px currentColor);
871
846
  var portPositions = {};
872
847
  content.querySelectorAll('[data-port-id]').forEach(function(el) {
873
848
  var id = el.getAttribute('data-port-id');
874
- portPositions[id] = { cx: parseFloat(el.getAttribute('cx')), cy: parseFloat(el.getAttribute('cy')) };
849
+ // Ports may be circle (cx/cy) or rect (x/y/width/height) elements
850
+ var cx, cy;
851
+ if (el.tagName === 'circle') {
852
+ cx = parseFloat(el.getAttribute('cx'));
853
+ cy = parseFloat(el.getAttribute('cy'));
854
+ } else {
855
+ cx = parseFloat(el.getAttribute('x')) + parseFloat(el.getAttribute('width')) / 2;
856
+ cy = parseFloat(el.getAttribute('y')) + parseFloat(el.getAttribute('height')) / 2;
857
+ }
858
+ portPositions[id] = { cx: cx, cy: cy };
875
859
  });
876
860
 
877
861
  // Extract node bounding boxes from SVG rect elements
@@ -1033,14 +1017,9 @@ circle[data-port-id].port-selected { filter: drop-shadow(0 0 6px currentColor);
1033
1017
  }
1034
1018
  } else {
1035
1019
  // Path mode: show path, hide stubs
1036
- var ddx = tx - sx, ddy = ty - sy, dist = Math.sqrt(ddx * ddx + ddy * ddy);
1037
- var path;
1038
- if (dist > ORTHO_THRESHOLD) {
1039
- path = calcOrthogonalPath([sx, sy], [tx, ty], boxes, c.srcNode, c.tgtNode, c.srcIdx, c.tgtIdx, alloc);
1040
- if (!path) path = computeConnectionPath(sx, sy, tx, ty);
1041
- } else {
1042
- path = computeConnectionPath(sx, sy, tx, ty);
1043
- }
1020
+ // Always try orthogonal routing first (matches platform)
1021
+ var path = calcOrthogonalPath([sx, sy], [tx, ty], boxes, c.srcNode, c.tgtNode, c.srcIdx, c.tgtIdx, alloc);
1022
+ if (!path) path = computeConnectionPath(sx, sy, tx, ty);
1044
1023
  c.el.setAttribute('d', path);
1045
1024
  c.el.removeAttribute('display');
1046
1025
  if (c.stubs) {
@@ -1323,14 +1302,79 @@ circle[data-port-id].port-selected { filter: drop-shadow(0 0 6px currentColor);
1323
1302
  });
1324
1303
  });
1325
1304
 
1326
- // Port hover: show this port's label + all connected port labels
1305
+ // Port hover: animated ring→circle expansion (matches platform 0.12s ease-out)
1306
+ var OUTER_W = 6, OUTER_H = 18, OUTER_RX = 4;
1307
+ var HOVER_OUTER = 20, HOVER_OUTER_RX = 10;
1308
+ var HOVER_INNER = 14, HOVER_INNER_RX = 7;
1309
+ var PORT_ANIM_MS = 120; // matches platform transition duration
1310
+
1311
+ // Tween an SVG rect from current attrs to target attrs
1312
+ function tweenRect(el, target, duration, onDone) {
1313
+ if (!el) { if (onDone) onDone(); return; }
1314
+ var start = {
1315
+ x: parseFloat(el.getAttribute('x')),
1316
+ y: parseFloat(el.getAttribute('y')),
1317
+ w: parseFloat(el.getAttribute('width')),
1318
+ h: parseFloat(el.getAttribute('height')),
1319
+ rx: parseFloat(el.getAttribute('rx'))
1320
+ };
1321
+ var t0 = null;
1322
+ var frameId = el.__tweenFrame;
1323
+ if (frameId) cancelAnimationFrame(frameId);
1324
+ function step(ts) {
1325
+ if (!t0) t0 = ts;
1326
+ var p = Math.min((ts - t0) / duration, 1);
1327
+ // ease-out: cubic
1328
+ var e = 1 - Math.pow(1 - p, 3);
1329
+ el.setAttribute('x', String(start.x + (target.x - start.x) * e));
1330
+ el.setAttribute('y', String(start.y + (target.y - start.y) * e));
1331
+ el.setAttribute('width', String(start.w + (target.w - start.w) * e));
1332
+ el.setAttribute('height', String(start.h + (target.h - start.h) * e));
1333
+ el.setAttribute('rx', String(start.rx + (target.rx - start.rx) * e));
1334
+ if (p < 1) {
1335
+ el.__tweenFrame = requestAnimationFrame(step);
1336
+ } else {
1337
+ el.__tweenFrame = null;
1338
+ if (onDone) onDone();
1339
+ }
1340
+ }
1341
+ el.__tweenFrame = requestAnimationFrame(step);
1342
+ }
1343
+
1327
1344
  content.querySelectorAll('[data-port-id]').forEach(function(portEl) {
1328
1345
  var portId = portEl.getAttribute('data-port-id');
1329
1346
  var nodeId = portId.split('.')[0];
1330
1347
  var peers = (portConnections[portId] || []).concat(portId);
1331
1348
 
1349
+ var origX = parseFloat(portEl.getAttribute('x'));
1350
+ var origY = parseFloat(portEl.getAttribute('y'));
1351
+ var innerBar = portEl.nextElementSibling;
1352
+ var hasInner = innerBar && innerBar.getAttribute('pointer-events') === 'none';
1353
+ var innerOrig = hasInner ? {
1354
+ x: parseFloat(innerBar.getAttribute('x')),
1355
+ y: parseFloat(innerBar.getAttribute('y')),
1356
+ w: parseFloat(innerBar.getAttribute('width')),
1357
+ h: parseFloat(innerBar.getAttribute('height')),
1358
+ rx: parseFloat(innerBar.getAttribute('rx'))
1359
+ } : null;
1360
+
1361
+ var cx = origX + OUTER_W / 2;
1362
+ var cy = origY + OUTER_H / 2;
1363
+
1332
1364
  portEl.addEventListener('mouseenter', function() {
1333
1365
  hoveredPort = portId;
1366
+ if (portEl.tagName === 'rect') {
1367
+ tweenRect(portEl, {
1368
+ x: cx - HOVER_OUTER / 2, y: cy - HOVER_OUTER / 2,
1369
+ w: HOVER_OUTER, h: HOVER_OUTER, rx: HOVER_OUTER_RX
1370
+ }, PORT_ANIM_MS);
1371
+ if (hasInner) {
1372
+ tweenRect(innerBar, {
1373
+ x: cx - HOVER_INNER / 2, y: cy - HOVER_INNER / 2,
1374
+ w: HOVER_INNER, h: HOVER_INNER, rx: HOVER_INNER_RX
1375
+ }, PORT_ANIM_MS);
1376
+ }
1377
+ }
1334
1378
  batchLabelChanges(function() {
1335
1379
  hideLabelsFor(nodeId);
1336
1380
  peers.forEach(showLabel);
@@ -1347,6 +1391,18 @@ circle[data-port-id].port-selected { filter: drop-shadow(0 0 6px currentColor);
1347
1391
  });
1348
1392
  portEl.addEventListener('mouseleave', function() {
1349
1393
  hoveredPort = null;
1394
+ if (portEl.tagName === 'rect') {
1395
+ tweenRect(portEl, {
1396
+ x: origX, y: origY,
1397
+ w: OUTER_W, h: OUTER_H, rx: OUTER_RX
1398
+ }, PORT_ANIM_MS);
1399
+ if (hasInner) {
1400
+ tweenRect(innerBar, {
1401
+ x: innerOrig.x, y: innerOrig.y,
1402
+ w: innerOrig.w, h: innerOrig.h, rx: innerOrig.rx
1403
+ }, PORT_ANIM_MS);
1404
+ }
1405
+ }
1350
1406
  // Defer so if entering another port, its mouseenter sets hoveredPort first
1351
1407
  var myPeers = peers, myNodeId = nodeId;
1352
1408
  Promise.resolve().then(function() {
@@ -1391,7 +1447,7 @@ circle[data-port-id].port-selected { filter: drop-shadow(0 0 6px currentColor);
1391
1447
  if (!selectedPortId) return;
1392
1448
  selectedPortId = null;
1393
1449
  document.body.classList.remove('port-active');
1394
- content.querySelectorAll('circle.port-selected').forEach(function(c) {
1450
+ content.querySelectorAll('.port-selected').forEach(function(c) {
1395
1451
  c.classList.remove('port-selected');
1396
1452
  });
1397
1453
  content.querySelectorAll('[data-source].dimmed, [data-source].highlighted').forEach(function(p) {
@@ -1,17 +1,8 @@
1
1
  /**
2
2
  * Orthogonal connection router for SVG diagram rendering.
3
3
  *
4
- * Ported from the original React-based editor's orthogonalRouter.ts.
5
- * Removed gl-matrix dependency — uses plain [number, number] tuples.
6
- *
7
- * Features:
8
- * - L-shape and S-shape routing with rounded corners
9
- * - Node collision avoidance via inflated bounding boxes
10
- * - Track allocator prevents parallel connections from overlapping
11
- * - Crossing minimization (evaluates up to 11 candidates per allocation)
12
- * - Per-port-index stub spacing
13
- * - Waypoint simplification (collinear removal, jog collapse)
14
- * - Backward/self connection escape routing
4
+ * 1-1 port of the platform's orthogonalRouter.ts.
5
+ * Only change: removed gl-matrix dependency — uses plain [number, number] tuples.
15
6
  */
16
7
  export interface NodeBox {
17
8
  id: string;
@@ -28,52 +19,26 @@ export interface OrthogonalRouteOptions {
28
19
  maxStubLength?: number;
29
20
  fromPortIndex?: number;
30
21
  toPortIndex?: number;
22
+ /** When true, treat same-node connections as forward (not self-loop). Used for scoped port connections. */
23
+ scopedInternal?: boolean;
24
+ /** Track allocator for preventing connections from overlapping on the same horizontal track. */
25
+ allocator?: TrackAllocator;
31
26
  }
32
27
  type Vec2 = [number, number];
33
- type InflatedBox = {
34
- left: number;
35
- right: number;
36
- top: number;
37
- bottom: number;
38
- };
28
+ /**
29
+ * Prevents connections from running on the same horizontal track.
30
+ * Create one instance per render batch and pass it to all routing calls.
31
+ * Tracks are snapped to TRACK_SPACING grid; only connections whose X corridors
32
+ * overlap can conflict.
33
+ */
39
34
  export declare class TrackAllocator {
40
35
  private claims;
41
- private verticalClaims;
42
- /** Check if a Y value is too close to any claimed segment whose X range overlaps. */
43
- private isOccupied;
44
- /** Check if an X value is too close to any claimed vertical segment whose Y range overlaps. */
45
- private isOccupiedVertical;
46
- /** Check if a horizontal segment at Y passes through any inflated node box. */
47
- private isBlockedByNode;
48
- /** Check if a vertical segment at X passes through any inflated node box. */
49
- private isBlockedByNodeVertical;
50
- /** Count claimed vertical segments that a horizontal segment at Y would cross. */
51
- countHorizontalCrossings(xMin: number, xMax: number, y: number): number;
52
- /** Count claimed horizontal segments that a vertical segment at X would cross. */
53
- countVerticalCrossings(yMin: number, yMax: number, x: number): number;
54
- /**
55
- * Find the nearest free Y to candidateY in the given X range, preferring fewer crossings.
56
- * When nodeBoxes is provided, candidates inside inflated node boxes are rejected (hard constraint).
57
- */
58
- findFreeY(xMin: number, xMax: number, candidateY: number, nodeBoxes?: InflatedBox[]): number;
59
- /**
60
- * Find the nearest free X to candidateX in the given Y range, preferring fewer crossings.
61
- * When nodeBoxes is provided, candidates inside inflated node boxes are rejected (hard constraint).
62
- */
63
- findFreeX(yMin: number, yMax: number, candidateX: number, nodeBoxes?: InflatedBox[]): number;
64
- /** Claim a horizontal segment so later connections avoid it. */
65
- claim(xMin: number, xMax: number, y: number): void;
66
- /** Claim a vertical segment so later connections avoid it. */
67
- claimVertical(yMin: number, yMax: number, x: number): void;
36
+ claim(xMin: number, xMax: number, candidateY: number): number;
68
37
  }
38
+ export declare function calculateOrthogonalPath(from: Vec2, to: Vec2, nodeBoxes: NodeBox[], sourceNodeId: string, targetNodeId: string, options?: OrthogonalRouteOptions): string | null;
69
39
  /**
70
- * Calculate an orthogonal SVG path between two ports.
71
- * Returns null if the path should fall back to bezier (e.g. nearly aligned ports).
72
- */
73
- export declare function calculateOrthogonalPath(from: Vec2, to: Vec2, nodeBoxes: NodeBox[], sourceNodeId: string, targetNodeId: string, options?: OrthogonalRouteOptions, allocator?: TrackAllocator): string | null;
74
- /**
75
- * Safe wrapper — returns null if routing fails, caller falls back to bezier.
40
+ * Safe wrapper: returns null if routing fails, caller falls back to straight line.
76
41
  */
77
- export declare function calculateOrthogonalPathSafe(from: Vec2, to: Vec2, nodeBoxes: NodeBox[], sourceNodeId: string, targetNodeId: string, options?: OrthogonalRouteOptions, allocator?: TrackAllocator): string | null;
42
+ export declare function calculateOrthogonalPathSafe(from: Vec2, to: Vec2, nodeBoxes: NodeBox[], sourceNodeId: string, targetNodeId: string, options?: OrthogonalRouteOptions): string | null;
78
43
  export {};
79
44
  //# sourceMappingURL=orthogonal-router.d.ts.map