@weasel-js/diagram 1.15.0 → 1.15.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +114 -5
- package/dist/{chunk-GR2DK4S2.js → chunk-EIHPPOAM.js} +1480 -229
- package/dist/chunk-EIHPPOAM.js.map +1 -0
- package/dist/{chunk-AXL4JQBM.js → chunk-EIT4BFDK.js} +3 -3
- package/dist/{chunk-AXL4JQBM.js.map → chunk-EIT4BFDK.js.map} +1 -1
- package/dist/{chunk-DE7UILJA.js → chunk-NEX4QKQQ.js} +183 -23
- package/dist/chunk-NEX4QKQQ.js.map +1 -0
- package/dist/{chunk-FDCODMFW.js → chunk-UOFQBGJY.js} +904 -599
- package/dist/chunk-UOFQBGJY.js.map +1 -0
- package/dist/{chunk-IYUU5KUY.js → chunk-UUMLQEMR.js} +8 -96
- package/dist/chunk-UUMLQEMR.js.map +1 -0
- package/dist/{dataTypes-BIkhAOc4.d.ts → dataTypes-1ch6cMtq.d.ts} +12 -3
- package/dist/effect-audio.d.ts +2 -2
- package/dist/effect-audio.js +3 -3
- package/dist/effect.d.ts +5 -5
- package/dist/effect.js +7 -7
- package/dist/effect.js.map +1 -1
- package/dist/icons.table.js +44 -0
- package/dist/icons.table.js.map +1 -1
- package/dist/icons.table.json +44 -0
- package/dist/index.d.ts +938 -37
- package/dist/index.js +708 -34
- package/dist/index.js.map +1 -1
- package/dist/{labelTrait-BBjRgxbz.d.ts → labelTrait-moIciyXr.d.ts} +4 -0
- package/dist/layout.d.ts +3 -3
- package/dist/{layout.entry-CbmGuqE-.d.ts → layout.entry-zstuljAl.d.ts} +2 -2
- package/dist/layout.js +2 -2
- package/dist/{stageTypes-UiO25hcn.d.ts → stageTypes-B7oF8Lww.d.ts} +1 -1
- package/dist/{types-B0n2CNTW.d.ts → types-D5ybp8Xh.d.ts} +32 -1
- package/package.json +11 -11
- package/dist/chunk-DE7UILJA.js.map +0 -1
- package/dist/chunk-FDCODMFW.js.map +0 -1
- package/dist/chunk-GR2DK4S2.js.map +0 -1
- package/dist/chunk-IYUU5KUY.js.map +0 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { boundsOfPath, transformPath, ellipsePath,
|
|
1
|
+
import { boundsOfPath, transformPath, ellipsePath, pathFromD, polylineFromPoints, worldCoords, PATH_M as PATH_M$1, PATH_CMD_LENGTHS, measurePath, forEachSegment, PATH_L as PATH_L$1, nearestOnLine, PATH_Q as PATH_Q$1, nearestOnQuadratic, PATH_C as PATH_C$1, nearestOnCubic } from '@weasel-js/geom';
|
|
2
2
|
import { PathBuilder, rectPath, polygonFromPoints, AUTO_POSE_DESCRIPTOR, rotatePoint, PATH_M, PATH_L, PATH_C, flattenCubic, PATH_Q, PATH_Z, pointAlongPath } from '@weasel-js/core/math';
|
|
3
3
|
import { cssFamilyName } from '@weasel-js/font/metrics';
|
|
4
4
|
import { createSimulation } from '@weasel-js/simulation';
|
|
@@ -372,7 +372,34 @@ var doubleEllipse = {
|
|
|
372
372
|
},
|
|
373
373
|
boxForContent: (c) => ({ width: c.width * Math.SQRT2 + RING * 2, height: c.height * Math.SQRT2 + RING * 2 })
|
|
374
374
|
};
|
|
375
|
-
var
|
|
375
|
+
var HEAD = 0.24;
|
|
376
|
+
var NECK = 0.04;
|
|
377
|
+
var SHOULDER = 18;
|
|
378
|
+
var FOOT = 6;
|
|
379
|
+
function personParts({ y, width: w, height: h }) {
|
|
380
|
+
const d = Math.min(HEAD * h, 0.4 * w);
|
|
381
|
+
const top = y + d + NECK * h;
|
|
382
|
+
const body = y + h - top;
|
|
383
|
+
return { d, top, body, shoulder: Math.min(SHOULDER, w / 4, body / 2), foot: Math.min(FOOT, w / 6, body / 4) };
|
|
384
|
+
}
|
|
385
|
+
var person = {
|
|
386
|
+
path: (b) => {
|
|
387
|
+
const { x, y, width: w, height: h } = b;
|
|
388
|
+
const { d, top, shoulder: r, foot: f } = personParts(b);
|
|
389
|
+
const k = r * KAPPA;
|
|
390
|
+
const q = f * KAPPA;
|
|
391
|
+
const p = new PathBuilder().moveTo(x + r, top).lineTo(x + w - r, top).curveTo(x + w - r + k, top, x + w, top + r - k, x + w, top + r).lineTo(x + w, y + h - f).curveTo(x + w, y + h - f + q, x + w - f + q, y + h, x + w - f, y + h).lineTo(x + f, y + h).curveTo(x + f - q, y + h, x, y + h - f + q, x, y + h - f).lineTo(x, top + r).curveTo(x, top + r - k, x + r - k, top, x + r, top).close().moveTo(x + w / 2 + d / 2, y + d / 2);
|
|
392
|
+
arc(p, x + w / 2, y + d / 2, d / 2, 0, Math.PI * 2);
|
|
393
|
+
return p.close().build();
|
|
394
|
+
},
|
|
395
|
+
content: (b) => {
|
|
396
|
+
const { top, body, shoulder } = personParts(b);
|
|
397
|
+
const i = shoulder * BITE;
|
|
398
|
+
return { x: b.x + i, y: top + i, width: b.width - i * 2, height: body - i * 2 };
|
|
399
|
+
},
|
|
400
|
+
boxForContent: (c) => ({ width: c.width + SHOULDER * BITE * 2, height: (c.height + SHOULDER * BITE * 2) / (1 - HEAD - NECK) })
|
|
401
|
+
};
|
|
402
|
+
var FIGURE_OUTLINES = { roundRect, triangle, octagon, cloud, actor, doubleEllipse, person };
|
|
376
403
|
|
|
377
404
|
// src/outlines/bpmn.ts
|
|
378
405
|
var STRIP = 32;
|
|
@@ -474,6 +501,10 @@ var globe = device(
|
|
|
474
501
|
ring2(0.5, 0.6, 0.4),
|
|
475
502
|
"M0.1 0.6H0.9M0.1536 0.4H0.8464M0.1536 0.8H0.8464M0.5 0.2V1M0.5 0.2A0.17 0.4 0 0 0 0.5 1A0.17 0.4 0 0 0 0.5 0.2"
|
|
476
503
|
);
|
|
504
|
+
var disk = device(
|
|
505
|
+
"M0.1 0.42H0.9Q0.94 0.42 0.94 0.46V0.96Q0.94 1 0.9 1H0.1Q0.06 1 0.06 0.96V0.46Q0.06 0.42 0.1 0.42Z",
|
|
506
|
+
`${ring2(0.42, 0.71, 0.22)}${ring2(0.42, 0.71, 0.03)}${ring2(0.8, 0.53, 0.03)}M0.78 0.55L0.5 0.8`
|
|
507
|
+
);
|
|
477
508
|
var NETWORK_OUTLINES = {
|
|
478
509
|
server,
|
|
479
510
|
router,
|
|
@@ -484,7 +515,8 @@ var NETWORK_OUTLINES = {
|
|
|
484
515
|
phone,
|
|
485
516
|
printer,
|
|
486
517
|
user,
|
|
487
|
-
globe
|
|
518
|
+
globe,
|
|
519
|
+
disk
|
|
488
520
|
};
|
|
489
521
|
var ICON = { width: 14, height: 12, tab: { width: 6, height: 3 }, margin: 6 };
|
|
490
522
|
var ICON_SIDE = ICON.margin * 2 + ICON.width + ICON.tab.width / 2;
|
|
@@ -520,6 +552,88 @@ var doubleRect = {
|
|
|
520
552
|
boxForContent: (c) => ({ width: c.width + GAP * 2, height: c.height + GAP * 2 })
|
|
521
553
|
};
|
|
522
554
|
var MODELING_OUTLINES = { component, doubleRect };
|
|
555
|
+
function square({ x, y, width: w, height: h }) {
|
|
556
|
+
const side = Math.min(w, h);
|
|
557
|
+
return { x: x + (w - side) / 2, y: y + (h - side) / 2, width: side, height: side };
|
|
558
|
+
}
|
|
559
|
+
function scaled(b, k) {
|
|
560
|
+
const w = b.width * k;
|
|
561
|
+
const h = b.height * k;
|
|
562
|
+
return { x: b.x + (b.width - w) / 2, y: b.y + (b.height - h) / 2, width: w, height: h };
|
|
563
|
+
}
|
|
564
|
+
var BULLSEYE = 0.55;
|
|
565
|
+
var BAR = 6;
|
|
566
|
+
var circle = (b) => ellipsePath(square(b));
|
|
567
|
+
var start = {
|
|
568
|
+
path: circle,
|
|
569
|
+
solid: circle
|
|
570
|
+
};
|
|
571
|
+
var end = {
|
|
572
|
+
path: circle,
|
|
573
|
+
solid: (b) => ellipsePath(scaled(square(b), BULLSEYE))
|
|
574
|
+
};
|
|
575
|
+
function barOf({ x, y, width: w, height: h }) {
|
|
576
|
+
if (w >= h) {
|
|
577
|
+
const t2 = Math.min(BAR, h);
|
|
578
|
+
return { x, y: y + (h - t2) / 2, width: w, height: t2 };
|
|
579
|
+
}
|
|
580
|
+
const t = Math.min(BAR, w);
|
|
581
|
+
return { x: x + (w - t) / 2, y, width: t, height: h };
|
|
582
|
+
}
|
|
583
|
+
var bar = {
|
|
584
|
+
path: (b) => {
|
|
585
|
+
const r = barOf(b);
|
|
586
|
+
return rectPath(r.x, r.y, r.width, r.height);
|
|
587
|
+
},
|
|
588
|
+
solid: (b) => {
|
|
589
|
+
const r = barOf(b);
|
|
590
|
+
return rectPath(r.x, r.y, r.width, r.height);
|
|
591
|
+
}
|
|
592
|
+
};
|
|
593
|
+
var STATE_OUTLINES = { start, end, bar };
|
|
594
|
+
var SHARE2 = 0.75;
|
|
595
|
+
var ring3 = (cx, cy, rx, ry) => `M${cx + rx} ${cy}A${rx} ${ry} 0 1 1 ${cx - rx} ${cy}A${rx} ${ry} 0 1 1 ${cx + rx} ${cy}Z`;
|
|
596
|
+
var boundary = figureOver(outlineFromD(`${ring3(0.7, 0.5, 0.4 / 1.5, 0.4)}M0.04 0.1V0.9M0.04 0.5H${0.7 - 0.4 / 1.5}`), 1.5, SHARE2);
|
|
597
|
+
var control = figureOver(outlineFromD(ring3(0.5, 0.55, 0.42, 0.42), { detail: "M0.6 0.02L0.46 0.13L0.6 0.24" }), 1, SHARE2);
|
|
598
|
+
var entity = figureOver(outlineFromD(`${ring3(0.5, 0.45, 0.42, 0.42)}M0.08 0.97H0.92`), 1, SHARE2);
|
|
599
|
+
var offsetOf = (w, h) => Math.min(6, w / 8, h / 8);
|
|
600
|
+
var collections = {
|
|
601
|
+
path: ({ x, y, width: w, height: h }) => {
|
|
602
|
+
const o = offsetOf(w, h);
|
|
603
|
+
return new PathBuilder().moveTo(x + o, y).lineTo(x + w, y).lineTo(x + w, y + h - o).lineTo(x + w - o, y + h - o).lineTo(x + w - o, y + h).lineTo(x, y + h).lineTo(x, y + o).lineTo(x + o, y + o).close().build();
|
|
604
|
+
},
|
|
605
|
+
detail: ({ x, y, width: w, height: h }) => {
|
|
606
|
+
const o = offsetOf(w, h);
|
|
607
|
+
return new PathBuilder().moveTo(x + o, y + o).lineTo(x + w - o, y + o).lineTo(x + w - o, y + h - o).build();
|
|
608
|
+
},
|
|
609
|
+
content: ({ x, y, width: w, height: h }) => {
|
|
610
|
+
const o = offsetOf(w, h);
|
|
611
|
+
return { x, y: y + o, width: w - o, height: h - o };
|
|
612
|
+
},
|
|
613
|
+
boxForContent: (c) => ({ width: c.width + 6, height: c.height + 6 })
|
|
614
|
+
};
|
|
615
|
+
var capOf2 = (w, h) => Math.min(w * 0.12, h * 0.3);
|
|
616
|
+
var queue = {
|
|
617
|
+
path: ({ x, y, width: w, height: h }) => {
|
|
618
|
+
const r = capOf2(w, h);
|
|
619
|
+
const cy = y + h / 2;
|
|
620
|
+
const ry = h / 2;
|
|
621
|
+
return new PathBuilder().moveTo(x + r, y).lineTo(x + w - r, y).curveTo(x + w - r + r * KAPPA, y, x + w, cy - ry * KAPPA, x + w, cy).curveTo(x + w, cy + ry * KAPPA, x + w - r + r * KAPPA, y + h, x + w - r, y + h).lineTo(x + r, y + h).curveTo(x + r - r * KAPPA, y + h, x, cy + ry * KAPPA, x, cy).curveTo(x, cy - ry * KAPPA, x + r - r * KAPPA, y, x + r, y).close().build();
|
|
622
|
+
},
|
|
623
|
+
detail: ({ x, y, width: w, height: h }) => {
|
|
624
|
+
const r = capOf2(w, h);
|
|
625
|
+
const cy = y + h / 2;
|
|
626
|
+
const ry = h / 2;
|
|
627
|
+
const rim = x + w - r;
|
|
628
|
+
return new PathBuilder().moveTo(rim, y).curveTo(rim - r * KAPPA, y, rim - r, cy - ry * KAPPA, rim - r, cy).curveTo(rim - r, cy + ry * KAPPA, rim - r * KAPPA, y + h, rim, y + h).build();
|
|
629
|
+
},
|
|
630
|
+
content: ({ x, y, width: w, height: h }) => {
|
|
631
|
+
const r = capOf2(w, h);
|
|
632
|
+
return { x: x + r, y, width: Math.max(w - r * 3, 0), height: h };
|
|
633
|
+
},
|
|
634
|
+
boxForContent: (c) => ({ width: c.width / 0.64, height: c.height })
|
|
635
|
+
};
|
|
636
|
+
var PARTICIPANT_OUTLINES = { boundary, control, entity, collections, queue };
|
|
523
637
|
|
|
524
638
|
// src/outlines/table.ts
|
|
525
639
|
var BUILTINS = {
|
|
@@ -528,7 +642,9 @@ var BUILTINS = {
|
|
|
528
642
|
...STORAGE_OUTLINES,
|
|
529
643
|
...NETWORK_OUTLINES,
|
|
530
644
|
...BPMN_OUTLINES,
|
|
531
|
-
...MODELING_OUTLINES
|
|
645
|
+
...MODELING_OUTLINES,
|
|
646
|
+
...STATE_OUTLINES,
|
|
647
|
+
...PARTICIPANT_OUTLINES
|
|
532
648
|
};
|
|
533
649
|
var table = new Map(
|
|
534
650
|
Object.entries(BUILTINS).map(([name, def]) => [name, [def]])
|
|
@@ -563,6 +679,10 @@ function outlineDetail(outline, bounds) {
|
|
|
563
679
|
if (typeof outline !== "string" || bounds.width <= 0 || bounds.height <= 0) return null;
|
|
564
680
|
return resolveOutline(outline).detail?.(bounds) ?? null;
|
|
565
681
|
}
|
|
682
|
+
function outlineSolid(outline, bounds) {
|
|
683
|
+
if (typeof outline !== "string" || bounds.width <= 0 || bounds.height <= 0) return null;
|
|
684
|
+
return resolveOutline(outline).solid?.(bounds) ?? null;
|
|
685
|
+
}
|
|
566
686
|
function contentBox(outline, bounds) {
|
|
567
687
|
if (typeof outline !== "string") return bounds;
|
|
568
688
|
return resolveOutline(outline).content?.(bounds) ?? bounds;
|
|
@@ -681,6 +801,7 @@ var dataKeyReader = (node) => {
|
|
|
681
801
|
if (trait === null || typeof trait !== "object") return null;
|
|
682
802
|
if ("from" in trait && "to" in trait) return null;
|
|
683
803
|
if ("label" in trait || "anchor" in trait || "mark" in trait) return null;
|
|
804
|
+
if ("seq" in trait || "sequence" in trait) return null;
|
|
684
805
|
if (trait.container?.role === "lane") return null;
|
|
685
806
|
return trait;
|
|
686
807
|
};
|
|
@@ -753,7 +874,7 @@ function placerOf(node, pose, opts) {
|
|
|
753
874
|
const cx = bounds.x + bounds.width / 2;
|
|
754
875
|
const cy = bounds.y + bounds.height / 2;
|
|
755
876
|
const poly = trait.outline === void 0 || bounds.width <= 0 || bounds.height <= 0 ? null : outlinePolyline(trait.outline, bounds);
|
|
756
|
-
const
|
|
877
|
+
const place2 = (spec, at2, given) => {
|
|
757
878
|
const anchored = {
|
|
758
879
|
x: bounds.x + at2.u * bounds.width,
|
|
759
880
|
y: bounds.y + at2.v * bounds.height
|
|
@@ -772,7 +893,7 @@ function placerOf(node, pose, opts) {
|
|
|
772
893
|
...extrasOf(spec)
|
|
773
894
|
};
|
|
774
895
|
};
|
|
775
|
-
return { specs: trait.ports ?? DEFAULT_PORTS, place };
|
|
896
|
+
return { specs: trait.ports ?? DEFAULT_PORTS, place: place2 };
|
|
776
897
|
}
|
|
777
898
|
function extrasOf(spec) {
|
|
778
899
|
return {
|
|
@@ -1271,10 +1392,10 @@ function packClusters(graph, rows, preferred2, axes, nodeGap) {
|
|
|
1271
1392
|
}
|
|
1272
1393
|
return items.map((item, i) => ({ item, i })).sort((a, b) => a.item.center - b.item.center || a.i - b.i).map(({ item }) => item);
|
|
1273
1394
|
});
|
|
1274
|
-
const settle2 = (byRow,
|
|
1395
|
+
const settle2 = (byRow, start3, nodeFloor, origin) => {
|
|
1275
1396
|
const nodeAt = /* @__PURE__ */ new Map();
|
|
1276
1397
|
let ends2 = [];
|
|
1277
|
-
for (let pass = 0; pass <=
|
|
1398
|
+
for (let pass = 0; pass <= start3.size; pass++) {
|
|
1278
1399
|
let raised = false;
|
|
1279
1400
|
ends2 = byRow.map((items) => {
|
|
1280
1401
|
let cursor = origin;
|
|
@@ -1285,10 +1406,10 @@ function packClusters(graph, rows, preferred2, axes, nodeGap) {
|
|
|
1285
1406
|
cursor = x2 + width(item.node) + nodeGap;
|
|
1286
1407
|
continue;
|
|
1287
1408
|
}
|
|
1288
|
-
const s =
|
|
1409
|
+
const s = start3.get(item.span);
|
|
1289
1410
|
const x = Math.max(s, cursor);
|
|
1290
1411
|
if (x > s) {
|
|
1291
|
-
|
|
1412
|
+
start3.set(item.span, x);
|
|
1292
1413
|
raised = true;
|
|
1293
1414
|
}
|
|
1294
1415
|
cursor = x + outer(item.span) + nodeGap;
|
|
@@ -1324,15 +1445,15 @@ function packClusters(graph, rows, preferred2, axes, nodeGap) {
|
|
|
1324
1445
|
return blockOf(span).width + inset2.crossLo + inset2.crossHi;
|
|
1325
1446
|
}
|
|
1326
1447
|
const roots = spans.filter((s) => s.parent === void 0);
|
|
1327
|
-
const
|
|
1328
|
-
const { nodeAt: at2 } = settle2(itemsByRow(void 0, roots),
|
|
1329
|
-
const
|
|
1448
|
+
const start2 = new Map(roots.map((s) => [s, centerOf.get(s) - outer(s) / 2]));
|
|
1449
|
+
const { nodeAt: at2 } = settle2(itemsByRow(void 0, roots), start2, pref, -Infinity);
|
|
1450
|
+
const place2 = (span, from) => {
|
|
1330
1451
|
const origin = from + insets.get(span).crossLo;
|
|
1331
1452
|
const block = blockOf(span);
|
|
1332
1453
|
for (const [id, local] of block.nodeAt) at2.set(id, origin + local);
|
|
1333
|
-
for (const [child, local] of block.childAt)
|
|
1454
|
+
for (const [child, local] of block.childAt) place2(child, origin + local);
|
|
1334
1455
|
};
|
|
1335
|
-
for (const root of roots)
|
|
1456
|
+
for (const root of roots) place2(root, start2.get(root));
|
|
1336
1457
|
return at2;
|
|
1337
1458
|
}
|
|
1338
1459
|
function centersOf(spans, rows, center2) {
|
|
@@ -1426,24 +1547,24 @@ function subpathOf(path, index) {
|
|
|
1426
1547
|
if (path.kind !== "polygon") return index === 0 ? path : null;
|
|
1427
1548
|
const { commands, coords } = path;
|
|
1428
1549
|
let seen = -1;
|
|
1429
|
-
let
|
|
1550
|
+
let start2 = -1;
|
|
1430
1551
|
let startCoord = 0;
|
|
1431
1552
|
let coord2 = 0;
|
|
1432
1553
|
for (let i = 0; i <= commands.length; i++) {
|
|
1433
1554
|
const cmd = commands[i];
|
|
1434
1555
|
if (i === commands.length || cmd === PATH_M$1) {
|
|
1435
1556
|
if (seen === index) {
|
|
1436
|
-
if (
|
|
1557
|
+
if (start2 === 0 && i === commands.length) return path;
|
|
1437
1558
|
return {
|
|
1438
1559
|
kind: "polygon",
|
|
1439
1560
|
fillRule: path.fillRule,
|
|
1440
|
-
commands: commands.slice(
|
|
1561
|
+
commands: commands.slice(start2, i),
|
|
1441
1562
|
coords: coords.slice(startCoord, coord2),
|
|
1442
1563
|
...path.origin ? { origin: path.origin } : {}
|
|
1443
1564
|
};
|
|
1444
1565
|
}
|
|
1445
1566
|
seen++;
|
|
1446
|
-
|
|
1567
|
+
start2 = i;
|
|
1447
1568
|
startCoord = coord2;
|
|
1448
1569
|
}
|
|
1449
1570
|
if (cmd !== void 0) coord2 += PATH_CMD_LENGTHS[cmd] ?? 0;
|
|
@@ -1503,7 +1624,12 @@ function labelCenter(whole, label, size) {
|
|
|
1503
1624
|
const at2 = label.placed ?? label;
|
|
1504
1625
|
const station = typeof at2.at === "object" ? nearestStation(path, at2.at.near) ?? pointAlongPath(path, 0.5) : pointAlongPath(path, typeof at2.at === "number" ? at2.at : NAMED[at2.at] ?? 0.5);
|
|
1505
1626
|
if (station === null) return null;
|
|
1506
|
-
|
|
1627
|
+
const beside = besideStation(station.point, station.tangent, at2.offset ?? 0, size);
|
|
1628
|
+
const end2 = label.placed !== void 0 || label.inset === void 0 ? 0 : label.at === "start" ? 1 : label.at === "end" ? -1 : 0;
|
|
1629
|
+
if (end2 === 0) return beside;
|
|
1630
|
+
const { x: tx, y: ty } = station.tangent;
|
|
1631
|
+
const reach = end2 * (label.inset + (Math.abs(tx) * size.width + Math.abs(ty) * size.height) / 2);
|
|
1632
|
+
return { x: beside.x + tx * reach, y: beside.y + ty * reach };
|
|
1507
1633
|
}
|
|
1508
1634
|
function halfDepth(tangent, size) {
|
|
1509
1635
|
return (Math.abs(tangent.y) * size.width + Math.abs(tangent.x) * size.height) / 2;
|
|
@@ -1546,8 +1672,8 @@ function labelSpotAt(whole, center2, size) {
|
|
|
1546
1672
|
}
|
|
1547
1673
|
|
|
1548
1674
|
// src/edgeTrait.ts
|
|
1549
|
-
function layoutOwnsPort(
|
|
1550
|
-
return
|
|
1675
|
+
function layoutOwnsPort(end2) {
|
|
1676
|
+
return end2.port === void 0 || end2.port === end2.laidOut;
|
|
1551
1677
|
}
|
|
1552
1678
|
function layoutOwnsRoute(edge) {
|
|
1553
1679
|
const points = edge.waypoints ?? [];
|
|
@@ -1605,442 +1731,180 @@ function routeHolds(from, to, waypoints, route) {
|
|
|
1605
1731
|
return true;
|
|
1606
1732
|
}
|
|
1607
1733
|
|
|
1608
|
-
// src/
|
|
1609
|
-
function
|
|
1610
|
-
const
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1734
|
+
// src/layered/cycles.ts
|
|
1735
|
+
function backEdges(graph) {
|
|
1736
|
+
const back = /* @__PURE__ */ new Set();
|
|
1737
|
+
const done = /* @__PURE__ */ new Set();
|
|
1738
|
+
const onStack = /* @__PURE__ */ new Set();
|
|
1739
|
+
const walk = (id) => {
|
|
1740
|
+
if (done.has(id)) return;
|
|
1741
|
+
onStack.add(id);
|
|
1742
|
+
for (const edge of graph.outgoing(id)) {
|
|
1743
|
+
if (edge.to === id) continue;
|
|
1744
|
+
if (onStack.has(edge.to)) back.add(edge.id);
|
|
1745
|
+
else walk(edge.to);
|
|
1746
|
+
}
|
|
1747
|
+
onStack.delete(id);
|
|
1748
|
+
done.add(id);
|
|
1749
|
+
};
|
|
1750
|
+
for (const node of graph.nodes) walk(node.id);
|
|
1751
|
+
return back;
|
|
1623
1752
|
}
|
|
1624
|
-
function
|
|
1625
|
-
const
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
for (const m of members) {
|
|
1637
|
-
m.vx += (cx - m.x) * strength * alpha;
|
|
1638
|
-
m.vy += (cy - m.y) * strength * alpha;
|
|
1639
|
-
}
|
|
1753
|
+
function ranksOf(graph, back) {
|
|
1754
|
+
const ranks = /* @__PURE__ */ new Map();
|
|
1755
|
+
const resolving = /* @__PURE__ */ new Set();
|
|
1756
|
+
const rankOf = (id) => {
|
|
1757
|
+
const known = ranks.get(id);
|
|
1758
|
+
if (known !== void 0) return known;
|
|
1759
|
+
if (resolving.has(id)) return 0;
|
|
1760
|
+
resolving.add(id);
|
|
1761
|
+
let rank = 0;
|
|
1762
|
+
for (const edge of graph.incoming(id)) {
|
|
1763
|
+
if (back.has(edge.id) || edge.from === id) continue;
|
|
1764
|
+
rank = Math.max(rank, rankOf(edge.from) + 1);
|
|
1640
1765
|
}
|
|
1766
|
+
resolving.delete(id);
|
|
1767
|
+
ranks.set(id, rank);
|
|
1768
|
+
return rank;
|
|
1641
1769
|
};
|
|
1770
|
+
for (const node of graph.nodes) rankOf(node.id);
|
|
1771
|
+
return ranks;
|
|
1642
1772
|
}
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
|
|
1652
|
-
|
|
1773
|
+
|
|
1774
|
+
// src/route.ts
|
|
1775
|
+
var FACES = {
|
|
1776
|
+
down: { out: "s", in: "n" },
|
|
1777
|
+
up: { out: "n", in: "s" },
|
|
1778
|
+
right: { out: "e", in: "w" },
|
|
1779
|
+
left: { out: "w", in: "e" }
|
|
1780
|
+
};
|
|
1781
|
+
function layeredRoutes(input) {
|
|
1782
|
+
const { ranks, members, compass } = input;
|
|
1783
|
+
const faces = FACES[input.direction ?? "down"];
|
|
1784
|
+
const span = (id) => {
|
|
1785
|
+
const rs = (members.get(id) ?? [id]).map((m) => ranks.get(m)).filter((r) => r !== void 0);
|
|
1786
|
+
return rs.length === 0 ? null : [Math.min(...rs), Math.max(...rs)];
|
|
1787
|
+
};
|
|
1788
|
+
const routes = /* @__PURE__ */ new Map();
|
|
1789
|
+
for (const edge of input.edges) {
|
|
1790
|
+
const from = span(edge.from);
|
|
1791
|
+
const to = span(edge.to);
|
|
1792
|
+
const route = {};
|
|
1793
|
+
if (from !== null && to !== null && (from[1] < to[0] || to[1] < from[0])) {
|
|
1794
|
+
const ahead = from[1] < to[0];
|
|
1795
|
+
if (compass.has(edge.from)) route.fromPort = ahead ? faces.out : faces.in;
|
|
1796
|
+
if (compass.has(edge.to)) route.toPort = ahead ? faces.in : faces.out;
|
|
1797
|
+
}
|
|
1798
|
+
const waypoints = input.waypoints.get(edge.id);
|
|
1799
|
+
if (waypoints !== void 0 && waypoints.length > 0) {
|
|
1800
|
+
route.waypoints = waypoints;
|
|
1801
|
+
const label = input.labels?.get(edge.id);
|
|
1802
|
+
if (label !== void 0) route.labelAt = label;
|
|
1803
|
+
}
|
|
1804
|
+
if (route.fromPort !== void 0 || route.toPort !== void 0 || route.waypoints !== void 0) {
|
|
1805
|
+
routes.set(edge.id, route);
|
|
1806
|
+
}
|
|
1653
1807
|
}
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
1808
|
+
return routes;
|
|
1809
|
+
}
|
|
1810
|
+
function layeredPorts(graph, ranks, direction) {
|
|
1811
|
+
const faces = FACES[direction ?? "down"];
|
|
1812
|
+
const compass = new Set(graph.groups?.map((g) => g.id) ?? []);
|
|
1813
|
+
for (const node of graph.nodes) {
|
|
1814
|
+
if (hasCompassPort(node, faces.out) && hasCompassPort(node, faces.in)) compass.add(node.id);
|
|
1660
1815
|
}
|
|
1661
|
-
const
|
|
1662
|
-
|
|
1816
|
+
const edges = /* @__PURE__ */ new Map();
|
|
1817
|
+
for (const e of graph.edges) {
|
|
1818
|
+
const id = e.origin?.id ?? e.id;
|
|
1819
|
+
if (!edges.has(id)) edges.set(id, { id, from: e.origin?.from ?? e.from, to: e.origin?.to ?? e.to });
|
|
1820
|
+
}
|
|
1821
|
+
const routes = layeredRoutes({
|
|
1822
|
+
edges: [...edges.values()],
|
|
1823
|
+
ranks,
|
|
1824
|
+
waypoints: /* @__PURE__ */ new Map(),
|
|
1825
|
+
members: new Map((graph.groups ?? []).map((g) => [g.id, g.members])),
|
|
1826
|
+
compass,
|
|
1827
|
+
...direction !== void 0 ? { direction } : {}
|
|
1828
|
+
});
|
|
1829
|
+
return new Map([...routes].map(([id, r]) => [id, {
|
|
1830
|
+
...r.fromPort !== void 0 ? { from: r.fromPort } : {},
|
|
1831
|
+
...r.toPort !== void 0 ? { to: r.toPort } : {}
|
|
1832
|
+
}]));
|
|
1663
1833
|
}
|
|
1664
|
-
function
|
|
1665
|
-
const
|
|
1666
|
-
|
|
1667
|
-
if (gapX <= 0 || gapY <= 0) return null;
|
|
1668
|
-
const dx = b.x0 + b.x1 - (a.x0 + a.x1);
|
|
1669
|
-
const dy = b.y0 + b.y1 - (a.y0 + a.y1);
|
|
1670
|
-
return gapX < gapY ? { x: (Math.sign(dx) || 1) * gapX, y: 0 } : { x: 0, y: (Math.sign(dy) || 1) * gapY };
|
|
1834
|
+
function hasCompassPort(node, face) {
|
|
1835
|
+
const point = COMPASS[face];
|
|
1836
|
+
return (node.ports ?? DEFAULT_PORTS).some((p) => p.id === face && p.at.u === point.u && p.at.v === point.v);
|
|
1671
1837
|
}
|
|
1672
|
-
function
|
|
1673
|
-
|
|
1674
|
-
|
|
1838
|
+
function authoredOver(edges, plan) {
|
|
1839
|
+
return new Map(edges.map((e) => {
|
|
1840
|
+
const ports = plan.ports?.get(e.id);
|
|
1841
|
+
const planned = plan.waypoints?.get(e.id);
|
|
1842
|
+
const fromPort = e.fromPort ?? ports?.from;
|
|
1843
|
+
const toPort = e.toPort ?? ports?.to;
|
|
1844
|
+
const waypoints = e.waypoints ?? (planned !== void 0 && planned.length > 0 ? planned : void 0);
|
|
1845
|
+
const labelAt = e.waypoints === void 0 && waypoints !== void 0 ? plan.labels?.get(e.id) : void 0;
|
|
1846
|
+
return [e.id, {
|
|
1847
|
+
...fromPort ? { fromPort } : {},
|
|
1848
|
+
...toPort ? { toPort } : {},
|
|
1849
|
+
...waypoints ? { waypoints } : {},
|
|
1850
|
+
...labelAt !== void 0 ? { labelAt } : {}
|
|
1851
|
+
}];
|
|
1852
|
+
}));
|
|
1853
|
+
}
|
|
1854
|
+
|
|
1855
|
+
// src/layered/rank.ts
|
|
1856
|
+
var GROUP_WEIGHT = 4;
|
|
1857
|
+
function ranksByLength(graph, back) {
|
|
1858
|
+
const index = /* @__PURE__ */ new Map();
|
|
1859
|
+
graph.nodes.forEach((node, i) => index.set(node.id, i));
|
|
1860
|
+
const arcs = [];
|
|
1861
|
+
for (const edge of graph.edges) {
|
|
1862
|
+
const from = index.get(edge.from);
|
|
1863
|
+
const to = index.get(edge.to);
|
|
1864
|
+
if (from === void 0 || to === void 0 || from === to) continue;
|
|
1865
|
+
arcs.push(back.has(edge.id) ? { tail: to, head: from, weight: 1, minlen: 1 } : { tail: from, head: to, weight: 1, minlen: 1 });
|
|
1675
1866
|
}
|
|
1676
|
-
|
|
1867
|
+
let count = graph.nodes.length;
|
|
1868
|
+
for (const group of graph.groups ?? []) {
|
|
1869
|
+
const members = [...new Set(group.members.map((id) => index.get(id)).filter((i) => i !== void 0))];
|
|
1870
|
+
if (members.length < 2) continue;
|
|
1871
|
+
const [top, bottom] = [count, count + 1];
|
|
1872
|
+
count += 2;
|
|
1873
|
+
for (const m of members) {
|
|
1874
|
+
arcs.push({ tail: top, head: m, weight: GROUP_WEIGHT, minlen: 0 });
|
|
1875
|
+
arcs.push({ tail: m, head: bottom, weight: GROUP_WEIGHT, minlen: 0 });
|
|
1876
|
+
}
|
|
1877
|
+
}
|
|
1878
|
+
const real = graph.nodes.length;
|
|
1879
|
+
const start2 = longestPath(count, arcs);
|
|
1880
|
+
const ranks = /* @__PURE__ */ new Map();
|
|
1881
|
+
for (const part of components(count, arcs)) {
|
|
1882
|
+
const rank = part.nodes.map((g) => start2[g]);
|
|
1883
|
+
simplex(part.arcs, rank);
|
|
1884
|
+
const own = part.nodes.flatMap((g, i) => g < real ? [i] : []);
|
|
1885
|
+
const min = Math.min(...own.map((i) => rank[i]));
|
|
1886
|
+
for (const i of own) ranks.set(graph.nodes[part.nodes[i]].id, rank[i] - min);
|
|
1887
|
+
}
|
|
1888
|
+
return ranks;
|
|
1677
1889
|
}
|
|
1678
|
-
function
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
|
|
1890
|
+
function longestPath(count, arcs) {
|
|
1891
|
+
const rank = new Array(count).fill(0);
|
|
1892
|
+
const pending = new Array(count).fill(0);
|
|
1893
|
+
const out = Array.from({ length: count }, () => []);
|
|
1894
|
+
for (const arc2 of arcs) {
|
|
1895
|
+
pending[arc2.head]++;
|
|
1896
|
+
out[arc2.tail].push(arc2);
|
|
1897
|
+
}
|
|
1898
|
+
const ready = [];
|
|
1899
|
+
for (let i = 0; i < count; i++) if (pending[i] === 0) ready.push(i);
|
|
1900
|
+
for (let k = 0; k < ready.length; k++) {
|
|
1901
|
+
const u = ready[k];
|
|
1902
|
+
for (const { head: v, minlen } of out[u]) {
|
|
1903
|
+
rank[v] = Math.max(rank[v], rank[u] + minlen);
|
|
1904
|
+
if (--pending[v] === 0) ready.push(v);
|
|
1905
|
+
}
|
|
1682
1906
|
}
|
|
1683
|
-
|
|
1684
|
-
function separateGroups(groups, bodies, byId, padding) {
|
|
1685
|
-
const resolved = resolve(groups, byId);
|
|
1686
|
-
const memberSets = resolved.map((g) => new Set(g.members));
|
|
1687
|
-
return () => {
|
|
1688
|
-
const boxes = resolved.map(boxOf);
|
|
1689
|
-
for (let i = 0; i < resolved.length; i++) {
|
|
1690
|
-
for (let j = i + 1; j < resolved.length; j++) {
|
|
1691
|
-
if (holds(resolved[i], resolved[j]) || holds(resolved[j], resolved[i])) continue;
|
|
1692
|
-
const push = clearance(boxes[i], boxes[j], padding);
|
|
1693
|
-
if (push === null) continue;
|
|
1694
|
-
shove(resolved[i].members, -push.x / 2, -push.y / 2);
|
|
1695
|
-
shove(resolved[j].members, push.x / 2, push.y / 2);
|
|
1696
|
-
}
|
|
1697
|
-
for (const body of bodies) {
|
|
1698
|
-
if (memberSets[i].has(body)) continue;
|
|
1699
|
-
const box = { x0: body.x - body.hw, y0: body.y - body.hh, x1: body.x + body.hw, y1: body.y + body.hh };
|
|
1700
|
-
const push = clearance(boxes[i], box, padding);
|
|
1701
|
-
if (push === null) continue;
|
|
1702
|
-
shove(resolved[i].members, -push.x / 2, -push.y / 2);
|
|
1703
|
-
body.vx += push.x / 2;
|
|
1704
|
-
body.vy += push.y / 2;
|
|
1705
|
-
}
|
|
1706
|
-
}
|
|
1707
|
-
};
|
|
1708
|
-
}
|
|
1709
|
-
|
|
1710
|
-
// src/force.ts
|
|
1711
|
-
var DEFAULTS = {
|
|
1712
|
-
iterations: 300,
|
|
1713
|
-
linkDistance: 160,
|
|
1714
|
-
linkStrength: 0.35,
|
|
1715
|
-
charge: -3e3,
|
|
1716
|
-
gravity: 0.02,
|
|
1717
|
-
padding: 24,
|
|
1718
|
-
groupStrength: 0.2
|
|
1719
|
-
};
|
|
1720
|
-
var GOLDEN = Math.PI * (3 - Math.sqrt(5));
|
|
1721
|
-
var NUDGE2 = 0.5;
|
|
1722
|
-
function charge(bodies, strength) {
|
|
1723
|
-
return (alpha) => {
|
|
1724
|
-
for (let i = 0; i < bodies.length; i++) {
|
|
1725
|
-
const a = bodies[i];
|
|
1726
|
-
for (let j = i + 1; j < bodies.length; j++) {
|
|
1727
|
-
const b = bodies[j];
|
|
1728
|
-
const dx = b.x - a.x;
|
|
1729
|
-
const dy = b.y - a.y;
|
|
1730
|
-
const d2 = dx * dx + dy * dy;
|
|
1731
|
-
if (d2 === 0) continue;
|
|
1732
|
-
const w = strength * alpha / d2;
|
|
1733
|
-
a.vx += dx * w;
|
|
1734
|
-
a.vy += dy * w;
|
|
1735
|
-
b.vx -= dx * w;
|
|
1736
|
-
b.vy -= dy * w;
|
|
1737
|
-
}
|
|
1738
|
-
}
|
|
1739
|
-
};
|
|
1740
|
-
}
|
|
1741
|
-
function links(bodies, graph, distance, strength) {
|
|
1742
|
-
return (alpha) => {
|
|
1743
|
-
for (const edge of graph.edges) {
|
|
1744
|
-
const a = bodies.get(edge.from);
|
|
1745
|
-
const b = bodies.get(edge.to);
|
|
1746
|
-
if (a === void 0 || b === void 0 || a === b) continue;
|
|
1747
|
-
const dx = b.x - a.x;
|
|
1748
|
-
const dy = b.y - a.y;
|
|
1749
|
-
const d = Math.hypot(dx, dy);
|
|
1750
|
-
if (d === 0) continue;
|
|
1751
|
-
const pull = (d - distance) / d * alpha * strength;
|
|
1752
|
-
a.vx += dx * pull;
|
|
1753
|
-
a.vy += dy * pull;
|
|
1754
|
-
b.vx -= dx * pull;
|
|
1755
|
-
b.vy -= dy * pull;
|
|
1756
|
-
}
|
|
1757
|
-
};
|
|
1758
|
-
}
|
|
1759
|
-
function separateBoxes(bodies, padding) {
|
|
1760
|
-
return () => {
|
|
1761
|
-
for (let i = 0; i < bodies.length; i++) {
|
|
1762
|
-
const a = bodies[i];
|
|
1763
|
-
for (let j = i + 1; j < bodies.length; j++) {
|
|
1764
|
-
const b = bodies[j];
|
|
1765
|
-
const dx = b.x - a.x;
|
|
1766
|
-
const dy = b.y - a.y;
|
|
1767
|
-
const gapX = a.hw + b.hw + padding - Math.abs(dx);
|
|
1768
|
-
const gapY = a.hh + b.hh + padding - Math.abs(dy);
|
|
1769
|
-
if (gapX <= 0 || gapY <= 0) continue;
|
|
1770
|
-
if (gapX < gapY) {
|
|
1771
|
-
const push = (Math.sign(dx) || 1) * gapX * 0.5;
|
|
1772
|
-
a.vx -= push;
|
|
1773
|
-
b.vx += push;
|
|
1774
|
-
} else {
|
|
1775
|
-
const push = (Math.sign(dy) || 1) * gapY * 0.5;
|
|
1776
|
-
a.vy -= push;
|
|
1777
|
-
b.vy += push;
|
|
1778
|
-
}
|
|
1779
|
-
}
|
|
1780
|
-
}
|
|
1781
|
-
};
|
|
1782
|
-
}
|
|
1783
|
-
function gravity(bodies, at2, strength) {
|
|
1784
|
-
return (alpha) => {
|
|
1785
|
-
for (const body of bodies) {
|
|
1786
|
-
body.vx += (at2.x - body.x) * strength * alpha;
|
|
1787
|
-
body.vy += (at2.y - body.y) * strength * alpha;
|
|
1788
|
-
}
|
|
1789
|
-
};
|
|
1790
|
-
}
|
|
1791
|
-
function forceRelaxation(graph, opts = {}) {
|
|
1792
|
-
const {
|
|
1793
|
-
linkDistance = DEFAULTS.linkDistance,
|
|
1794
|
-
linkStrength = DEFAULTS.linkStrength,
|
|
1795
|
-
charge: chargeStrength = DEFAULTS.charge,
|
|
1796
|
-
gravity: gravityStrength = DEFAULTS.gravity,
|
|
1797
|
-
padding = DEFAULTS.padding,
|
|
1798
|
-
groupStrength = DEFAULTS.groupStrength
|
|
1799
|
-
} = opts;
|
|
1800
|
-
const pinned = pinnedSet(graph, opts);
|
|
1801
|
-
const bodies = graph.nodes.map((node) => {
|
|
1802
|
-
const body = {
|
|
1803
|
-
id: node.id,
|
|
1804
|
-
x: center(node.bounds, "x"),
|
|
1805
|
-
y: center(node.bounds, "y"),
|
|
1806
|
-
hw: node.bounds.width / 2,
|
|
1807
|
-
hh: node.bounds.height / 2
|
|
1808
|
-
};
|
|
1809
|
-
if (pinned.has(node.id)) {
|
|
1810
|
-
body.fx = body.x;
|
|
1811
|
-
body.fy = body.y;
|
|
1812
|
-
}
|
|
1813
|
-
return body;
|
|
1814
|
-
});
|
|
1815
|
-
separate(bodies);
|
|
1816
|
-
const byId = new Map(bodies.map((b) => [b.id, b]));
|
|
1817
|
-
const centroid = {
|
|
1818
|
-
x: bodies.reduce((sum, b) => sum + b.x, 0) / bodies.length,
|
|
1819
|
-
y: bodies.reduce((sum, b) => sum + b.y, 0) / bodies.length
|
|
1820
|
-
};
|
|
1821
|
-
const groups = graph.groups ?? [];
|
|
1822
|
-
const sim = createSimulation({
|
|
1823
|
-
nodes: bodies,
|
|
1824
|
-
forces: [
|
|
1825
|
-
charge(bodies, chargeStrength),
|
|
1826
|
-
links(byId, graph, linkDistance, linkStrength),
|
|
1827
|
-
gravity(bodies, centroid, gravityStrength),
|
|
1828
|
-
separateBoxes(bodies, padding),
|
|
1829
|
-
...groups.length > 0 ? [groupCohesion(groups, byId, groupStrength), separateGroups(groups, bodies, byId, padding)] : []
|
|
1830
|
-
]
|
|
1831
|
-
});
|
|
1832
|
-
return {
|
|
1833
|
-
bodies,
|
|
1834
|
-
byId,
|
|
1835
|
-
pinned,
|
|
1836
|
-
sim,
|
|
1837
|
-
placed() {
|
|
1838
|
-
const placed = /* @__PURE__ */ new Map();
|
|
1839
|
-
for (const node of graph.nodes) {
|
|
1840
|
-
const body = byId.get(node.id);
|
|
1841
|
-
placed.set(node.id, {
|
|
1842
|
-
x: body.x - node.bounds.width / 2,
|
|
1843
|
-
y: body.y - node.bounds.height / 2
|
|
1844
|
-
});
|
|
1845
|
-
}
|
|
1846
|
-
return placed;
|
|
1847
|
-
}
|
|
1848
|
-
};
|
|
1849
|
-
}
|
|
1850
|
-
var force = (graph, opts = {}) => {
|
|
1851
|
-
if (graph.nodes.length === 0) return /* @__PURE__ */ new Map();
|
|
1852
|
-
const relaxation = forceRelaxation(graph, opts);
|
|
1853
|
-
relaxation.sim.tick(opts.iterations ?? DEFAULTS.iterations);
|
|
1854
|
-
return translated(graph, relaxation.placed(), relaxation.pinned, opts.tolerance);
|
|
1855
|
-
};
|
|
1856
|
-
function separate(bodies) {
|
|
1857
|
-
const seen = /* @__PURE__ */ new Map();
|
|
1858
|
-
bodies.forEach((body, i) => {
|
|
1859
|
-
const key = `${body.x},${body.y}`;
|
|
1860
|
-
const nth = seen.get(key) ?? 0;
|
|
1861
|
-
seen.set(key, nth + 1);
|
|
1862
|
-
if (nth === 0 || body.fx != null || body.fy != null) return;
|
|
1863
|
-
const angle = GOLDEN * i;
|
|
1864
|
-
const radius = NUDGE2 * nth;
|
|
1865
|
-
body.x += Math.cos(angle) * radius;
|
|
1866
|
-
body.y += Math.sin(angle) * radius;
|
|
1867
|
-
});
|
|
1868
|
-
}
|
|
1869
|
-
|
|
1870
|
-
// src/layered/cycles.ts
|
|
1871
|
-
function backEdges(graph) {
|
|
1872
|
-
const back = /* @__PURE__ */ new Set();
|
|
1873
|
-
const done = /* @__PURE__ */ new Set();
|
|
1874
|
-
const onStack = /* @__PURE__ */ new Set();
|
|
1875
|
-
const walk = (id) => {
|
|
1876
|
-
if (done.has(id)) return;
|
|
1877
|
-
onStack.add(id);
|
|
1878
|
-
for (const edge of graph.outgoing(id)) {
|
|
1879
|
-
if (edge.to === id) continue;
|
|
1880
|
-
if (onStack.has(edge.to)) back.add(edge.id);
|
|
1881
|
-
else walk(edge.to);
|
|
1882
|
-
}
|
|
1883
|
-
onStack.delete(id);
|
|
1884
|
-
done.add(id);
|
|
1885
|
-
};
|
|
1886
|
-
for (const node of graph.nodes) walk(node.id);
|
|
1887
|
-
return back;
|
|
1888
|
-
}
|
|
1889
|
-
function ranksOf(graph, back) {
|
|
1890
|
-
const ranks = /* @__PURE__ */ new Map();
|
|
1891
|
-
const resolving = /* @__PURE__ */ new Set();
|
|
1892
|
-
const rankOf = (id) => {
|
|
1893
|
-
const known = ranks.get(id);
|
|
1894
|
-
if (known !== void 0) return known;
|
|
1895
|
-
if (resolving.has(id)) return 0;
|
|
1896
|
-
resolving.add(id);
|
|
1897
|
-
let rank = 0;
|
|
1898
|
-
for (const edge of graph.incoming(id)) {
|
|
1899
|
-
if (back.has(edge.id) || edge.from === id) continue;
|
|
1900
|
-
rank = Math.max(rank, rankOf(edge.from) + 1);
|
|
1901
|
-
}
|
|
1902
|
-
resolving.delete(id);
|
|
1903
|
-
ranks.set(id, rank);
|
|
1904
|
-
return rank;
|
|
1905
|
-
};
|
|
1906
|
-
for (const node of graph.nodes) rankOf(node.id);
|
|
1907
|
-
return ranks;
|
|
1908
|
-
}
|
|
1909
|
-
|
|
1910
|
-
// src/route.ts
|
|
1911
|
-
var FACES = {
|
|
1912
|
-
down: { out: "s", in: "n" },
|
|
1913
|
-
up: { out: "n", in: "s" },
|
|
1914
|
-
right: { out: "e", in: "w" },
|
|
1915
|
-
left: { out: "w", in: "e" }
|
|
1916
|
-
};
|
|
1917
|
-
function layeredRoutes(input) {
|
|
1918
|
-
const { ranks, members, compass } = input;
|
|
1919
|
-
const faces = FACES[input.direction ?? "down"];
|
|
1920
|
-
const span = (id) => {
|
|
1921
|
-
const rs = (members.get(id) ?? [id]).map((m) => ranks.get(m)).filter((r) => r !== void 0);
|
|
1922
|
-
return rs.length === 0 ? null : [Math.min(...rs), Math.max(...rs)];
|
|
1923
|
-
};
|
|
1924
|
-
const routes = /* @__PURE__ */ new Map();
|
|
1925
|
-
for (const edge of input.edges) {
|
|
1926
|
-
const from = span(edge.from);
|
|
1927
|
-
const to = span(edge.to);
|
|
1928
|
-
const route = {};
|
|
1929
|
-
if (from !== null && to !== null && (from[1] < to[0] || to[1] < from[0])) {
|
|
1930
|
-
const ahead = from[1] < to[0];
|
|
1931
|
-
if (compass.has(edge.from)) route.fromPort = ahead ? faces.out : faces.in;
|
|
1932
|
-
if (compass.has(edge.to)) route.toPort = ahead ? faces.in : faces.out;
|
|
1933
|
-
}
|
|
1934
|
-
const waypoints = input.waypoints.get(edge.id);
|
|
1935
|
-
if (waypoints !== void 0 && waypoints.length > 0) {
|
|
1936
|
-
route.waypoints = waypoints;
|
|
1937
|
-
const label = input.labels?.get(edge.id);
|
|
1938
|
-
if (label !== void 0) route.labelAt = label;
|
|
1939
|
-
}
|
|
1940
|
-
if (route.fromPort !== void 0 || route.toPort !== void 0 || route.waypoints !== void 0) {
|
|
1941
|
-
routes.set(edge.id, route);
|
|
1942
|
-
}
|
|
1943
|
-
}
|
|
1944
|
-
return routes;
|
|
1945
|
-
}
|
|
1946
|
-
function layeredPorts(graph, ranks, direction) {
|
|
1947
|
-
const faces = FACES[direction ?? "down"];
|
|
1948
|
-
const compass = new Set(graph.groups?.map((g) => g.id) ?? []);
|
|
1949
|
-
for (const node of graph.nodes) {
|
|
1950
|
-
if (hasCompassPort(node, faces.out) && hasCompassPort(node, faces.in)) compass.add(node.id);
|
|
1951
|
-
}
|
|
1952
|
-
const edges = /* @__PURE__ */ new Map();
|
|
1953
|
-
for (const e of graph.edges) {
|
|
1954
|
-
const id = e.origin?.id ?? e.id;
|
|
1955
|
-
if (!edges.has(id)) edges.set(id, { id, from: e.origin?.from ?? e.from, to: e.origin?.to ?? e.to });
|
|
1956
|
-
}
|
|
1957
|
-
const routes = layeredRoutes({
|
|
1958
|
-
edges: [...edges.values()],
|
|
1959
|
-
ranks,
|
|
1960
|
-
waypoints: /* @__PURE__ */ new Map(),
|
|
1961
|
-
members: new Map((graph.groups ?? []).map((g) => [g.id, g.members])),
|
|
1962
|
-
compass,
|
|
1963
|
-
...direction !== void 0 ? { direction } : {}
|
|
1964
|
-
});
|
|
1965
|
-
return new Map([...routes].map(([id, r]) => [id, {
|
|
1966
|
-
...r.fromPort !== void 0 ? { from: r.fromPort } : {},
|
|
1967
|
-
...r.toPort !== void 0 ? { to: r.toPort } : {}
|
|
1968
|
-
}]));
|
|
1969
|
-
}
|
|
1970
|
-
function hasCompassPort(node, face) {
|
|
1971
|
-
const point = COMPASS[face];
|
|
1972
|
-
return (node.ports ?? DEFAULT_PORTS).some((p) => p.id === face && p.at.u === point.u && p.at.v === point.v);
|
|
1973
|
-
}
|
|
1974
|
-
function authoredOver(edges, plan) {
|
|
1975
|
-
return new Map(edges.map((e) => {
|
|
1976
|
-
const ports = plan.ports?.get(e.id);
|
|
1977
|
-
const planned = plan.waypoints?.get(e.id);
|
|
1978
|
-
const fromPort = e.fromPort ?? ports?.from;
|
|
1979
|
-
const toPort = e.toPort ?? ports?.to;
|
|
1980
|
-
const waypoints = e.waypoints ?? (planned !== void 0 && planned.length > 0 ? planned : void 0);
|
|
1981
|
-
const labelAt = e.waypoints === void 0 && waypoints !== void 0 ? plan.labels?.get(e.id) : void 0;
|
|
1982
|
-
return [e.id, {
|
|
1983
|
-
...fromPort ? { fromPort } : {},
|
|
1984
|
-
...toPort ? { toPort } : {},
|
|
1985
|
-
...waypoints ? { waypoints } : {},
|
|
1986
|
-
...labelAt !== void 0 ? { labelAt } : {}
|
|
1987
|
-
}];
|
|
1988
|
-
}));
|
|
1989
|
-
}
|
|
1990
|
-
|
|
1991
|
-
// src/layered/rank.ts
|
|
1992
|
-
var GROUP_WEIGHT = 4;
|
|
1993
|
-
function ranksByLength(graph, back) {
|
|
1994
|
-
const index = /* @__PURE__ */ new Map();
|
|
1995
|
-
graph.nodes.forEach((node, i) => index.set(node.id, i));
|
|
1996
|
-
const arcs = [];
|
|
1997
|
-
for (const edge of graph.edges) {
|
|
1998
|
-
const from = index.get(edge.from);
|
|
1999
|
-
const to = index.get(edge.to);
|
|
2000
|
-
if (from === void 0 || to === void 0 || from === to) continue;
|
|
2001
|
-
arcs.push(back.has(edge.id) ? { tail: to, head: from, weight: 1, minlen: 1 } : { tail: from, head: to, weight: 1, minlen: 1 });
|
|
2002
|
-
}
|
|
2003
|
-
let count = graph.nodes.length;
|
|
2004
|
-
for (const group of graph.groups ?? []) {
|
|
2005
|
-
const members = [...new Set(group.members.map((id) => index.get(id)).filter((i) => i !== void 0))];
|
|
2006
|
-
if (members.length < 2) continue;
|
|
2007
|
-
const [top, bottom] = [count, count + 1];
|
|
2008
|
-
count += 2;
|
|
2009
|
-
for (const m of members) {
|
|
2010
|
-
arcs.push({ tail: top, head: m, weight: GROUP_WEIGHT, minlen: 0 });
|
|
2011
|
-
arcs.push({ tail: m, head: bottom, weight: GROUP_WEIGHT, minlen: 0 });
|
|
2012
|
-
}
|
|
2013
|
-
}
|
|
2014
|
-
const real = graph.nodes.length;
|
|
2015
|
-
const start = longestPath(count, arcs);
|
|
2016
|
-
const ranks = /* @__PURE__ */ new Map();
|
|
2017
|
-
for (const part of components(count, arcs)) {
|
|
2018
|
-
const rank = part.nodes.map((g) => start[g]);
|
|
2019
|
-
simplex(part.arcs, rank);
|
|
2020
|
-
const own = part.nodes.flatMap((g, i) => g < real ? [i] : []);
|
|
2021
|
-
const min = Math.min(...own.map((i) => rank[i]));
|
|
2022
|
-
for (const i of own) ranks.set(graph.nodes[part.nodes[i]].id, rank[i] - min);
|
|
2023
|
-
}
|
|
2024
|
-
return ranks;
|
|
2025
|
-
}
|
|
2026
|
-
function longestPath(count, arcs) {
|
|
2027
|
-
const rank = new Array(count).fill(0);
|
|
2028
|
-
const pending = new Array(count).fill(0);
|
|
2029
|
-
const out = Array.from({ length: count }, () => []);
|
|
2030
|
-
for (const arc2 of arcs) {
|
|
2031
|
-
pending[arc2.head]++;
|
|
2032
|
-
out[arc2.tail].push(arc2);
|
|
2033
|
-
}
|
|
2034
|
-
const ready = [];
|
|
2035
|
-
for (let i = 0; i < count; i++) if (pending[i] === 0) ready.push(i);
|
|
2036
|
-
for (let k = 0; k < ready.length; k++) {
|
|
2037
|
-
const u = ready[k];
|
|
2038
|
-
for (const { head: v, minlen } of out[u]) {
|
|
2039
|
-
rank[v] = Math.max(rank[v], rank[u] + minlen);
|
|
2040
|
-
if (--pending[v] === 0) ready.push(v);
|
|
2041
|
-
}
|
|
2042
|
-
}
|
|
2043
|
-
return rank;
|
|
1907
|
+
return rank;
|
|
2044
1908
|
}
|
|
2045
1909
|
function components(count, arcs) {
|
|
2046
1910
|
const near = Array.from({ length: count }, () => []);
|
|
@@ -2194,16 +2058,16 @@ function tighten(rank, arcs, inTree) {
|
|
|
2194
2058
|
const adj = treeAdjacency(rank.length, arcs, inTree);
|
|
2195
2059
|
const seen = rank.map(() => false);
|
|
2196
2060
|
seen[0] = true;
|
|
2197
|
-
const
|
|
2198
|
-
for (let k = 0; k <
|
|
2199
|
-
const v =
|
|
2061
|
+
const queue2 = [0];
|
|
2062
|
+
for (let k = 0; k < queue2.length; k++) {
|
|
2063
|
+
const v = queue2[k];
|
|
2200
2064
|
for (const a of adj[v]) {
|
|
2201
2065
|
const arc2 = arcs[a];
|
|
2202
2066
|
const w = arc2.tail === v ? arc2.head : arc2.tail;
|
|
2203
2067
|
if (seen[w]) continue;
|
|
2204
2068
|
seen[w] = true;
|
|
2205
2069
|
rank[w] = arc2.tail === v ? rank[v] + arc2.minlen : rank[v] - arc2.minlen;
|
|
2206
|
-
|
|
2070
|
+
queue2.push(w);
|
|
2207
2071
|
}
|
|
2208
2072
|
}
|
|
2209
2073
|
}
|
|
@@ -2302,13 +2166,13 @@ function expand(graph, nodeRanks, back, opts) {
|
|
|
2302
2166
|
if (a === null || b === null || a[1] >= b[0]) continue;
|
|
2303
2167
|
if (d.authored && b[0] - a[1] > 1) continue;
|
|
2304
2168
|
const group = sharedGroup(from, to);
|
|
2305
|
-
const
|
|
2306
|
-
const
|
|
2169
|
+
const start2 = crossCenter(from);
|
|
2170
|
+
const end2 = crossCenter(to);
|
|
2307
2171
|
const crossings = b[0] - a[1] - 1;
|
|
2308
2172
|
const now = d.waypoints?.length === crossings * 2 ? d.waypoints : void 0;
|
|
2309
2173
|
const seed = (j) => {
|
|
2310
2174
|
if (now !== void 0) return now[(d.back ? crossings - 1 - j : j) * 2][axes.cross];
|
|
2311
|
-
return
|
|
2175
|
+
return start2 + (end2 - start2) * (j + 1) / (crossings + 1);
|
|
2312
2176
|
};
|
|
2313
2177
|
const labelRow = labeled.labelRow.get(d.id);
|
|
2314
2178
|
let prev = inRank(from, a[1]);
|
|
@@ -2409,22 +2273,22 @@ function settlePlaces(rows, hops) {
|
|
|
2409
2273
|
if (!hops.some((h) => h.fromPlaces !== void 0 || h.toPlaces !== void 0)) return [...hops];
|
|
2410
2274
|
const pos = /* @__PURE__ */ new Map();
|
|
2411
2275
|
for (const row of rows) row.forEach((n, i) => pos.set(n.id, i));
|
|
2412
|
-
const
|
|
2276
|
+
const sides2 = sidesOf(hops);
|
|
2413
2277
|
return hops.map((h) => {
|
|
2414
2278
|
if (h.fromPlaces === void 0 && h.toPlaces === void 0) return h;
|
|
2415
2279
|
const { fromPlaces, toPlaces, ...rest } = h;
|
|
2416
2280
|
return {
|
|
2417
2281
|
...rest,
|
|
2418
|
-
...fromPlaces !== void 0 ? { fromAt: placeAmong(fromPlaces, h.to,
|
|
2419
|
-
...toPlaces !== void 0 ? { toAt: placeAmong(toPlaces, h.from,
|
|
2282
|
+
...fromPlaces !== void 0 ? { fromAt: placeAmong(fromPlaces, h.to, sides2.down.get(h.from) ?? [], pos) } : {},
|
|
2283
|
+
...toPlaces !== void 0 ? { toAt: placeAmong(toPlaces, h.from, sides2.up.get(h.to) ?? [], pos) } : {}
|
|
2420
2284
|
};
|
|
2421
2285
|
});
|
|
2422
2286
|
}
|
|
2423
2287
|
|
|
2424
2288
|
// src/layered/order.ts
|
|
2425
|
-
function ends(p, pos,
|
|
2426
|
-
const fa = p.fromPlaces === void 0 ? p.fromAt : placeAmong(p.fromPlaces, p.to,
|
|
2427
|
-
const fb = p.toPlaces === void 0 ? p.toAt : placeAmong(p.toPlaces, p.from,
|
|
2289
|
+
function ends(p, pos, sides2) {
|
|
2290
|
+
const fa = p.fromPlaces === void 0 ? p.fromAt : placeAmong(p.fromPlaces, p.to, sides2.down.get(p.from) ?? [], pos);
|
|
2291
|
+
const fb = p.toPlaces === void 0 ? p.toAt : placeAmong(p.toPlaces, p.from, sides2.up.get(p.to) ?? [], pos);
|
|
2428
2292
|
return [at(pos.get(p.from), fa), at(pos.get(p.to), fb)];
|
|
2429
2293
|
}
|
|
2430
2294
|
var at = (pos, frac) => pos + 0.25 + frac / 2;
|
|
@@ -2445,16 +2309,16 @@ function positions(rows) {
|
|
|
2445
2309
|
for (const row of rows) row.forEach((n, i) => pos.set(n.id, i));
|
|
2446
2310
|
return pos;
|
|
2447
2311
|
}
|
|
2448
|
-
function pairCrossings(pairs, pos,
|
|
2449
|
-
const met = pairs.map((p) => ends(p, pos,
|
|
2312
|
+
function pairCrossings(pairs, pos, sides2) {
|
|
2313
|
+
const met = pairs.map((p) => ends(p, pos, sides2)).sort((p, q) => p[0] - q[0] || p[1] - q[1]);
|
|
2450
2314
|
const lows = [...new Set(met.map(([, b]) => b))].sort((p, q) => p - q);
|
|
2451
2315
|
const slot = new Map(lows.map((b, i) => [b, i]));
|
|
2452
2316
|
const width = lows.length;
|
|
2453
2317
|
const tree2 = new Array(width + 1).fill(0);
|
|
2454
2318
|
let seen = 0;
|
|
2455
2319
|
let count = 0;
|
|
2456
|
-
for (const [,
|
|
2457
|
-
const b = slot.get(
|
|
2320
|
+
for (const [, end2] of met) {
|
|
2321
|
+
const b = slot.get(end2);
|
|
2458
2322
|
let atMost = 0;
|
|
2459
2323
|
for (let i = b + 1; i > 0; i -= i & -i) atMost += tree2[i];
|
|
2460
2324
|
count += seen - atMost;
|
|
@@ -2463,9 +2327,9 @@ function pairCrossings(pairs, pos, sides) {
|
|
|
2463
2327
|
}
|
|
2464
2328
|
return count;
|
|
2465
2329
|
}
|
|
2466
|
-
function total(rows, byRank, pos,
|
|
2330
|
+
function total(rows, byRank, pos, sides2) {
|
|
2467
2331
|
let sum = 0;
|
|
2468
|
-
for (let r = 0; r + 1 < rows.length; r++) sum += pairCrossings(byRank[r], pos,
|
|
2332
|
+
for (let r = 0; r + 1 < rows.length; r++) sum += pairCrossings(byRank[r], pos, sides2);
|
|
2469
2333
|
return sum;
|
|
2470
2334
|
}
|
|
2471
2335
|
function chainsOf(groups) {
|
|
@@ -2517,10 +2381,10 @@ function sortRank(row, key, chainOf, places = /* @__PURE__ */ new Map()) {
|
|
|
2517
2381
|
});
|
|
2518
2382
|
const out = [];
|
|
2519
2383
|
const flatten = (block) => {
|
|
2520
|
-
const
|
|
2384
|
+
const place2 = block.group === void 0 ? void 0 : places.get(block.group);
|
|
2521
2385
|
const items = block.items.map((item) => {
|
|
2522
|
-
if (
|
|
2523
|
-
const k =
|
|
2386
|
+
if (place2 !== void 0) {
|
|
2387
|
+
const k = place2.get("id" in item ? item.id : item.group) ?? Infinity;
|
|
2524
2388
|
return { item, k, first: "id" in item ? firstOf.get(item) : item.first };
|
|
2525
2389
|
}
|
|
2526
2390
|
if ("id" in item) return { item, k: keyOf.get(item), first: firstOf.get(item) };
|
|
@@ -2600,15 +2464,15 @@ function orderRows(rows, hops, opts = {}) {
|
|
|
2600
2464
|
}
|
|
2601
2465
|
}
|
|
2602
2466
|
const seeded = rows.map((row) => sortRank(row, (_, i) => i, chainOf, places));
|
|
2603
|
-
const
|
|
2604
|
-
const work = { rows: seeded, pos: positions(seeded), ups, downs, sides, chainOf, places };
|
|
2467
|
+
const sides2 = sidesOf(hops);
|
|
2468
|
+
const work = { rows: seeded, pos: positions(seeded), ups, downs, sides: sides2, chainOf, places };
|
|
2605
2469
|
let best = seeded.map((row) => [...row]);
|
|
2606
|
-
let fewest = total(work.rows, byRank, work.pos,
|
|
2470
|
+
let fewest = total(work.rows, byRank, work.pos, sides2);
|
|
2607
2471
|
for (let sweep = 0, stale = 0; sweep < maxSweeps && stale < patience && fewest > 0; sweep++) {
|
|
2608
2472
|
if (sweep % 2 === 0) for (let r = 1; r < work.rows.length; r++) reorder(work, r, ups);
|
|
2609
2473
|
else for (let r = work.rows.length - 2; r >= 0; r--) reorder(work, r, downs);
|
|
2610
2474
|
transpose(work);
|
|
2611
|
-
const n = total(work.rows, byRank, work.pos,
|
|
2475
|
+
const n = total(work.rows, byRank, work.pos, sides2);
|
|
2612
2476
|
if (n < fewest) {
|
|
2613
2477
|
fewest = n;
|
|
2614
2478
|
best = work.rows.map((row) => [...row]);
|
|
@@ -2645,9 +2509,9 @@ function levelRoutes(input) {
|
|
|
2645
2509
|
out.ports.set(id, named(graph, [from, face], [to, face]));
|
|
2646
2510
|
out.waypoints.set(id, around(a, b, others, axes, input.rankGap));
|
|
2647
2511
|
} else {
|
|
2648
|
-
const
|
|
2512
|
+
const sides2 = SIDES[axes.cross];
|
|
2649
2513
|
const ahead = center(a, axes.cross) < center(b, axes.cross);
|
|
2650
|
-
out.ports.set(id, named(graph, [from, ahead ?
|
|
2514
|
+
out.ports.set(id, named(graph, [from, ahead ? sides2.high : sides2.low], [to, ahead ? sides2.low : sides2.high]));
|
|
2651
2515
|
}
|
|
2652
2516
|
}
|
|
2653
2517
|
return out;
|
|
@@ -2916,11 +2780,11 @@ function holdPins(input) {
|
|
|
2916
2780
|
if (pins.length < 2) return { crossAt: new Map(input.crossAt), gaps: [...input.gaps], depths: natural, rankAt, unheld };
|
|
2917
2781
|
const anchor = pins[0];
|
|
2918
2782
|
const a = rowOf.get(anchor.id);
|
|
2919
|
-
let
|
|
2920
|
-
for (let r = 0; r < a; r++)
|
|
2921
|
-
const bandInput = { natural, gaps: input.gaps, minGaps: input.minGaps, home: { rank: a, lo:
|
|
2783
|
+
let start2 = 0;
|
|
2784
|
+
for (let r = 0; r < a; r++) start2 += natural[r] + input.gaps[r];
|
|
2785
|
+
const bandInput = { natural, gaps: input.gaps, minGaps: input.minGaps, home: { rank: a, lo: start2 } };
|
|
2922
2786
|
const anchorExt = extent(anchor.bounds, axes.rank);
|
|
2923
|
-
const anchorRank =
|
|
2787
|
+
const anchorRank = start2 + (natural[a] - anchorExt) / 2;
|
|
2924
2788
|
const anchorWorld = worldOf({ cross: input.crossAt.get(anchor.id), rank: anchorRank }, anchorExt, axes);
|
|
2925
2789
|
const target = (id) => {
|
|
2926
2790
|
const node = graph.node(id);
|
|
@@ -3284,107 +3148,369 @@ function layeredPlan(graph, opts = {}) {
|
|
|
3284
3148
|
}, graph, opts);
|
|
3285
3149
|
return { ...last, moves };
|
|
3286
3150
|
}
|
|
3287
|
-
function routed(edge, plan) {
|
|
3288
|
-
const { waypoints: _, ...rest } = edge;
|
|
3289
|
-
const route = plan.waypoints.get(edge.origin?.id ?? edge.id);
|
|
3290
|
-
return route === void 0 ? rest : { ...rest, waypoints: route };
|
|
3151
|
+
function routed(edge, plan) {
|
|
3152
|
+
const { waypoints: _, ...rest } = edge;
|
|
3153
|
+
const route = plan.waypoints.get(edge.origin?.id ?? edge.id);
|
|
3154
|
+
return route === void 0 ? rest : { ...rest, waypoints: route };
|
|
3155
|
+
}
|
|
3156
|
+
function planOnce(graph, opts = {}) {
|
|
3157
|
+
const axes = axesFor(opts.direction);
|
|
3158
|
+
const nodeGap = opts.nodeGap ?? DEFAULT_NODE_GAP;
|
|
3159
|
+
const rankGap = opts.rankGap ?? DEFAULT_RANK_GAP;
|
|
3160
|
+
const finding = opts.order === "barycenter";
|
|
3161
|
+
const back = backEdges(graph);
|
|
3162
|
+
const ranks = ranksByLength(graph, back);
|
|
3163
|
+
const expanded = expand(graph, ranks, back, { axes, nodeGap });
|
|
3164
|
+
let rows = finding ? orderRows(expanded.rows, expanded.hops, { groups: graph.groups ?? [] }) : expanded.rows;
|
|
3165
|
+
const grouped = (graph.groups?.length ?? 0) > 0;
|
|
3166
|
+
const pinned = pinnedSet(graph, opts);
|
|
3167
|
+
const across = () => {
|
|
3168
|
+
const preferred2 = placeAcross(rows, settlePlaces(rows, expanded.hops), axes.cross, nodeGap);
|
|
3169
|
+
return grouped ? packClusters(graph, rows, preferred2, axes, nodeGap) : preferred2;
|
|
3170
|
+
};
|
|
3171
|
+
let packed = across();
|
|
3172
|
+
for (let turn = 0; turn < rows.length; turn++) {
|
|
3173
|
+
const turned = turnOutward({ graph, rows, crossAt: packed, axes, pinned, hops: expanded.hops });
|
|
3174
|
+
if (turned === void 0) break;
|
|
3175
|
+
rows = turned;
|
|
3176
|
+
packed = across();
|
|
3177
|
+
}
|
|
3178
|
+
const spaced = grouped ? rankGaps(graph, rows, axes, rankGap) : rows.slice(1).map(() => rankGap);
|
|
3179
|
+
const minGaps = spaced.map((gap) => gap - rankGap + rankGap * MIN_GAP);
|
|
3180
|
+
for (const r of expanded.labelRows) {
|
|
3181
|
+
spaced[r - 1] = spaced[r - 1] - rankGap * (1 - LABEL_GAP);
|
|
3182
|
+
spaced[r] = spaced[r] - rankGap * (1 - LABEL_GAP);
|
|
3183
|
+
}
|
|
3184
|
+
const { crossAt, gaps, depths: depths2, rankAt, unheld } = holdPins({ graph, rows, crossAt: packed, gaps: spaced, pinned, axes, nodeGap, minGaps });
|
|
3185
|
+
const slots = /* @__PURE__ */ new Map();
|
|
3186
|
+
const bands = [];
|
|
3187
|
+
let along = 0;
|
|
3188
|
+
for (const [i, row] of rows.entries()) {
|
|
3189
|
+
const depth = depths2[i];
|
|
3190
|
+
bands.push([along, along + depth]);
|
|
3191
|
+
for (const node of row) {
|
|
3192
|
+
slots.set(node.id, { cross: crossAt.get(node.id), rank: rankAt.get(node.id) ?? along + (depth - extent(node.bounds, axes.rank)) / 2 });
|
|
3193
|
+
}
|
|
3194
|
+
along += depth + (gaps[i] ?? 0);
|
|
3195
|
+
}
|
|
3196
|
+
const placed = /* @__PURE__ */ new Map();
|
|
3197
|
+
for (const node of graph.nodes) {
|
|
3198
|
+
const slot = slots.get(node.id);
|
|
3199
|
+
if (slot !== void 0) placed.set(node.id, worldOf(slot, extent(node.bounds, axes.rank), axes));
|
|
3200
|
+
}
|
|
3201
|
+
const moves = translated(graph, placed, pinned, opts.tolerance);
|
|
3202
|
+
const offset = anchorOffset(graph, placed, pinned);
|
|
3203
|
+
const displaced = /* @__PURE__ */ new Set();
|
|
3204
|
+
for (const id of pinned) {
|
|
3205
|
+
const at2 = placed.get(id);
|
|
3206
|
+
const node = graph.node(id);
|
|
3207
|
+
if (at2 === void 0 || node === void 0) continue;
|
|
3208
|
+
if (Math.abs(at2.x + offset.x - node.bounds.x) > 0.5 || Math.abs(at2.y + offset.y - node.bounds.y) > 0.5) displaced.add(id);
|
|
3209
|
+
}
|
|
3210
|
+
const waypoints = /* @__PURE__ */ new Map();
|
|
3211
|
+
const labels = /* @__PURE__ */ new Map();
|
|
3212
|
+
const rankOf = /* @__PURE__ */ new Map();
|
|
3213
|
+
rows.forEach((row, r) => row.forEach((n) => rankOf.set(n.id, r)));
|
|
3214
|
+
const reach = boxReach(graph, rows, axes);
|
|
3215
|
+
const widthOf = new Map(rows.flat().map((n) => [n.id, extent(n.bounds, axes.cross)]));
|
|
3216
|
+
for (const [edge, chain2] of expanded.chains) {
|
|
3217
|
+
if (chain2.ends.some((id) => displaced.has(id))) continue;
|
|
3218
|
+
const beside = chain2.ids.indexOf(expanded.labels.get(edge) ?? "");
|
|
3219
|
+
const points = [];
|
|
3220
|
+
for (const id of chain2.ids) {
|
|
3221
|
+
const cross = crossAt.get(id) + (expanded.wires.get(id) ?? widthOf.get(id) / 2);
|
|
3222
|
+
const r = rankOf.get(id);
|
|
3223
|
+
const [lo, hi] = [bands[r][0] - reach.lo[r], bands[r][1] + reach.hi[r]];
|
|
3224
|
+
for (const rank of chain2.back ? [hi, lo] : [lo, hi]) {
|
|
3225
|
+
const at2 = worldOf({ cross, rank }, 0, axes);
|
|
3226
|
+
points.push({ x: at2.x + offset.x, y: at2.y + offset.y });
|
|
3227
|
+
}
|
|
3228
|
+
}
|
|
3229
|
+
waypoints.set(edge, points);
|
|
3230
|
+
if (beside >= 0) {
|
|
3231
|
+
const [a, b] = [points[beside * 2], points[beside * 2 + 1]];
|
|
3232
|
+
labels.set(edge, { x: (a.x + b.x) / 2, y: (a.y + b.y) / 2 });
|
|
3233
|
+
}
|
|
3234
|
+
}
|
|
3235
|
+
const ports = layeredPorts(graph, ranks, opts.direction);
|
|
3236
|
+
const boxes = new Map(graph.nodes.map((n) => [n.id, { ...n.bounds, ...moves.get(n.id) }]));
|
|
3237
|
+
const level = levelRoutes({ graph, boxes, axes, rankGap, ...opts.direction !== void 0 ? { direction: opts.direction } : {} });
|
|
3238
|
+
for (const [edge, named2] of level.ports) {
|
|
3239
|
+
ports.set(edge, named2);
|
|
3240
|
+
waypoints.delete(edge);
|
|
3241
|
+
labels.delete(edge);
|
|
3242
|
+
}
|
|
3243
|
+
for (const [edge, points] of level.waypoints) waypoints.set(edge, points);
|
|
3244
|
+
return { moves, ranks, back, waypoints, labels, ports, unheld };
|
|
3245
|
+
}
|
|
3246
|
+
|
|
3247
|
+
// src/layered.ts
|
|
3248
|
+
var layered = Object.assign(
|
|
3249
|
+
(graph, opts = {}) => layeredPlan(graph, opts).moves,
|
|
3250
|
+
{ plan: layeredPlan }
|
|
3251
|
+
);
|
|
3252
|
+
|
|
3253
|
+
// src/forceGroups.ts
|
|
3254
|
+
function resolve(groups, byId) {
|
|
3255
|
+
const out = [];
|
|
3256
|
+
for (const group of groups) {
|
|
3257
|
+
const members = group.members.map((id) => byId.get(id)).filter((b) => b !== void 0);
|
|
3258
|
+
if (members.length > 0) out.push({ members, group, children: [] });
|
|
3259
|
+
}
|
|
3260
|
+
const byGroup = new Map(out.map((g) => [g.group.id, g]));
|
|
3261
|
+
for (const g of out) {
|
|
3262
|
+
const parent = g.group.parent === void 0 ? void 0 : byGroup.get(g.group.parent);
|
|
3263
|
+
if (parent === void 0) continue;
|
|
3264
|
+
g.parent = parent;
|
|
3265
|
+
parent.children.push(g);
|
|
3266
|
+
}
|
|
3267
|
+
return out;
|
|
3268
|
+
}
|
|
3269
|
+
function groupCohesion(groups, byId, strength) {
|
|
3270
|
+
const resolved = resolve(groups, byId);
|
|
3271
|
+
return (alpha) => {
|
|
3272
|
+
for (const { members } of resolved) {
|
|
3273
|
+
let cx = 0;
|
|
3274
|
+
let cy = 0;
|
|
3275
|
+
for (const m of members) {
|
|
3276
|
+
cx += m.x;
|
|
3277
|
+
cy += m.y;
|
|
3278
|
+
}
|
|
3279
|
+
cx /= members.length;
|
|
3280
|
+
cy /= members.length;
|
|
3281
|
+
for (const m of members) {
|
|
3282
|
+
m.vx += (cx - m.x) * strength * alpha;
|
|
3283
|
+
m.vy += (cy - m.y) * strength * alpha;
|
|
3284
|
+
}
|
|
3285
|
+
}
|
|
3286
|
+
};
|
|
3287
|
+
}
|
|
3288
|
+
function boxOf(g) {
|
|
3289
|
+
let x0 = Infinity;
|
|
3290
|
+
let y0 = Infinity;
|
|
3291
|
+
let x1 = -Infinity;
|
|
3292
|
+
let y1 = -Infinity;
|
|
3293
|
+
for (const m of g.members) {
|
|
3294
|
+
x0 = Math.min(x0, m.x - m.hw);
|
|
3295
|
+
y0 = Math.min(y0, m.y - m.hh);
|
|
3296
|
+
x1 = Math.max(x1, m.x + m.hw);
|
|
3297
|
+
y1 = Math.max(y1, m.y + m.hh);
|
|
3298
|
+
}
|
|
3299
|
+
for (const child of g.children) {
|
|
3300
|
+
const b = boxOf(child);
|
|
3301
|
+
x0 = Math.min(x0, b.x0);
|
|
3302
|
+
y0 = Math.min(y0, b.y0);
|
|
3303
|
+
x1 = Math.max(x1, b.x1);
|
|
3304
|
+
y1 = Math.max(y1, b.y1);
|
|
3305
|
+
}
|
|
3306
|
+
const { inset: inset2 } = g.group;
|
|
3307
|
+
return { x0: x0 - inset2.left, y0: y0 - inset2.top, x1: x1 + inset2.right, y1: y1 + inset2.bottom };
|
|
3308
|
+
}
|
|
3309
|
+
function clearance(a, b, padding) {
|
|
3310
|
+
const gapX = Math.min(a.x1, b.x1) - Math.max(a.x0, b.x0) + padding;
|
|
3311
|
+
const gapY = Math.min(a.y1, b.y1) - Math.max(a.y0, b.y0) + padding;
|
|
3312
|
+
if (gapX <= 0 || gapY <= 0) return null;
|
|
3313
|
+
const dx = b.x0 + b.x1 - (a.x0 + a.x1);
|
|
3314
|
+
const dy = b.y0 + b.y1 - (a.y0 + a.y1);
|
|
3315
|
+
return gapX < gapY ? { x: (Math.sign(dx) || 1) * gapX, y: 0 } : { x: 0, y: (Math.sign(dy) || 1) * gapY };
|
|
3316
|
+
}
|
|
3317
|
+
function holds(outer, inner) {
|
|
3318
|
+
for (let at2 = inner.parent; at2 !== void 0; at2 = at2.parent) {
|
|
3319
|
+
if (at2 === outer) return true;
|
|
3320
|
+
}
|
|
3321
|
+
return false;
|
|
3322
|
+
}
|
|
3323
|
+
function shove(bodies, x, y) {
|
|
3324
|
+
for (const body of bodies) {
|
|
3325
|
+
body.vx += x;
|
|
3326
|
+
body.vy += y;
|
|
3327
|
+
}
|
|
3328
|
+
}
|
|
3329
|
+
function separateGroups(groups, bodies, byId, padding) {
|
|
3330
|
+
const resolved = resolve(groups, byId);
|
|
3331
|
+
const memberSets = resolved.map((g) => new Set(g.members));
|
|
3332
|
+
return () => {
|
|
3333
|
+
const boxes = resolved.map(boxOf);
|
|
3334
|
+
for (let i = 0; i < resolved.length; i++) {
|
|
3335
|
+
for (let j = i + 1; j < resolved.length; j++) {
|
|
3336
|
+
if (holds(resolved[i], resolved[j]) || holds(resolved[j], resolved[i])) continue;
|
|
3337
|
+
const push = clearance(boxes[i], boxes[j], padding);
|
|
3338
|
+
if (push === null) continue;
|
|
3339
|
+
shove(resolved[i].members, -push.x / 2, -push.y / 2);
|
|
3340
|
+
shove(resolved[j].members, push.x / 2, push.y / 2);
|
|
3341
|
+
}
|
|
3342
|
+
for (const body of bodies) {
|
|
3343
|
+
if (memberSets[i].has(body)) continue;
|
|
3344
|
+
const box = { x0: body.x - body.hw, y0: body.y - body.hh, x1: body.x + body.hw, y1: body.y + body.hh };
|
|
3345
|
+
const push = clearance(boxes[i], box, padding);
|
|
3346
|
+
if (push === null) continue;
|
|
3347
|
+
shove(resolved[i].members, -push.x / 2, -push.y / 2);
|
|
3348
|
+
body.vx += push.x / 2;
|
|
3349
|
+
body.vy += push.y / 2;
|
|
3350
|
+
}
|
|
3351
|
+
}
|
|
3352
|
+
};
|
|
3353
|
+
}
|
|
3354
|
+
|
|
3355
|
+
// src/force.ts
|
|
3356
|
+
var DEFAULTS = {
|
|
3357
|
+
iterations: 300,
|
|
3358
|
+
linkDistance: 160,
|
|
3359
|
+
linkStrength: 0.35,
|
|
3360
|
+
charge: -3e3,
|
|
3361
|
+
gravity: 0.02,
|
|
3362
|
+
padding: 24,
|
|
3363
|
+
groupStrength: 0.2
|
|
3364
|
+
};
|
|
3365
|
+
var GOLDEN = Math.PI * (3 - Math.sqrt(5));
|
|
3366
|
+
var NUDGE2 = 0.5;
|
|
3367
|
+
function charge(bodies, strength) {
|
|
3368
|
+
return (alpha) => {
|
|
3369
|
+
for (let i = 0; i < bodies.length; i++) {
|
|
3370
|
+
const a = bodies[i];
|
|
3371
|
+
for (let j = i + 1; j < bodies.length; j++) {
|
|
3372
|
+
const b = bodies[j];
|
|
3373
|
+
const dx = b.x - a.x;
|
|
3374
|
+
const dy = b.y - a.y;
|
|
3375
|
+
const d2 = dx * dx + dy * dy;
|
|
3376
|
+
if (d2 === 0) continue;
|
|
3377
|
+
const w = strength * alpha / d2;
|
|
3378
|
+
a.vx += dx * w;
|
|
3379
|
+
a.vy += dy * w;
|
|
3380
|
+
b.vx -= dx * w;
|
|
3381
|
+
b.vy -= dy * w;
|
|
3382
|
+
}
|
|
3383
|
+
}
|
|
3384
|
+
};
|
|
3385
|
+
}
|
|
3386
|
+
function links(bodies, graph, distance, strength) {
|
|
3387
|
+
return (alpha) => {
|
|
3388
|
+
for (const edge of graph.edges) {
|
|
3389
|
+
const a = bodies.get(edge.from);
|
|
3390
|
+
const b = bodies.get(edge.to);
|
|
3391
|
+
if (a === void 0 || b === void 0 || a === b) continue;
|
|
3392
|
+
const dx = b.x - a.x;
|
|
3393
|
+
const dy = b.y - a.y;
|
|
3394
|
+
const d = Math.hypot(dx, dy);
|
|
3395
|
+
if (d === 0) continue;
|
|
3396
|
+
const pull = (d - distance) / d * alpha * strength;
|
|
3397
|
+
a.vx += dx * pull;
|
|
3398
|
+
a.vy += dy * pull;
|
|
3399
|
+
b.vx -= dx * pull;
|
|
3400
|
+
b.vy -= dy * pull;
|
|
3401
|
+
}
|
|
3402
|
+
};
|
|
3403
|
+
}
|
|
3404
|
+
function separateBoxes(bodies, padding) {
|
|
3405
|
+
return () => {
|
|
3406
|
+
for (let i = 0; i < bodies.length; i++) {
|
|
3407
|
+
const a = bodies[i];
|
|
3408
|
+
for (let j = i + 1; j < bodies.length; j++) {
|
|
3409
|
+
const b = bodies[j];
|
|
3410
|
+
const dx = b.x - a.x;
|
|
3411
|
+
const dy = b.y - a.y;
|
|
3412
|
+
const gapX = a.hw + b.hw + padding - Math.abs(dx);
|
|
3413
|
+
const gapY = a.hh + b.hh + padding - Math.abs(dy);
|
|
3414
|
+
if (gapX <= 0 || gapY <= 0) continue;
|
|
3415
|
+
if (gapX < gapY) {
|
|
3416
|
+
const push = (Math.sign(dx) || 1) * gapX * 0.5;
|
|
3417
|
+
a.vx -= push;
|
|
3418
|
+
b.vx += push;
|
|
3419
|
+
} else {
|
|
3420
|
+
const push = (Math.sign(dy) || 1) * gapY * 0.5;
|
|
3421
|
+
a.vy -= push;
|
|
3422
|
+
b.vy += push;
|
|
3423
|
+
}
|
|
3424
|
+
}
|
|
3425
|
+
}
|
|
3426
|
+
};
|
|
3291
3427
|
}
|
|
3292
|
-
function
|
|
3293
|
-
|
|
3294
|
-
|
|
3295
|
-
|
|
3296
|
-
|
|
3297
|
-
|
|
3298
|
-
const ranks = ranksByLength(graph, back);
|
|
3299
|
-
const expanded = expand(graph, ranks, back, { axes, nodeGap });
|
|
3300
|
-
let rows = finding ? orderRows(expanded.rows, expanded.hops, { groups: graph.groups ?? [] }) : expanded.rows;
|
|
3301
|
-
const grouped = (graph.groups?.length ?? 0) > 0;
|
|
3302
|
-
const pinned = pinnedSet(graph, opts);
|
|
3303
|
-
const across = () => {
|
|
3304
|
-
const preferred2 = placeAcross(rows, settlePlaces(rows, expanded.hops), axes.cross, nodeGap);
|
|
3305
|
-
return grouped ? packClusters(graph, rows, preferred2, axes, nodeGap) : preferred2;
|
|
3428
|
+
function gravity(bodies, at2, strength) {
|
|
3429
|
+
return (alpha) => {
|
|
3430
|
+
for (const body of bodies) {
|
|
3431
|
+
body.vx += (at2.x - body.x) * strength * alpha;
|
|
3432
|
+
body.vy += (at2.y - body.y) * strength * alpha;
|
|
3433
|
+
}
|
|
3306
3434
|
};
|
|
3307
|
-
|
|
3308
|
-
|
|
3309
|
-
|
|
3310
|
-
|
|
3311
|
-
|
|
3312
|
-
|
|
3313
|
-
|
|
3314
|
-
|
|
3315
|
-
|
|
3316
|
-
|
|
3317
|
-
|
|
3318
|
-
|
|
3319
|
-
|
|
3320
|
-
|
|
3321
|
-
|
|
3322
|
-
|
|
3323
|
-
|
|
3324
|
-
|
|
3325
|
-
|
|
3326
|
-
|
|
3327
|
-
|
|
3328
|
-
|
|
3435
|
+
}
|
|
3436
|
+
function forceRelaxation(graph, opts = {}) {
|
|
3437
|
+
const {
|
|
3438
|
+
linkDistance = DEFAULTS.linkDistance,
|
|
3439
|
+
linkStrength = DEFAULTS.linkStrength,
|
|
3440
|
+
charge: chargeStrength = DEFAULTS.charge,
|
|
3441
|
+
gravity: gravityStrength = DEFAULTS.gravity,
|
|
3442
|
+
padding = DEFAULTS.padding,
|
|
3443
|
+
groupStrength = DEFAULTS.groupStrength
|
|
3444
|
+
} = opts;
|
|
3445
|
+
const pinned = pinnedSet(graph, opts);
|
|
3446
|
+
const bodies = graph.nodes.map((node) => {
|
|
3447
|
+
const body = {
|
|
3448
|
+
id: node.id,
|
|
3449
|
+
x: center(node.bounds, "x"),
|
|
3450
|
+
y: center(node.bounds, "y"),
|
|
3451
|
+
hw: node.bounds.width / 2,
|
|
3452
|
+
hh: node.bounds.height / 2
|
|
3453
|
+
};
|
|
3454
|
+
if (pinned.has(node.id)) {
|
|
3455
|
+
body.fx = body.x;
|
|
3456
|
+
body.fy = body.y;
|
|
3329
3457
|
}
|
|
3330
|
-
|
|
3331
|
-
}
|
|
3332
|
-
|
|
3333
|
-
|
|
3334
|
-
|
|
3335
|
-
|
|
3336
|
-
|
|
3337
|
-
|
|
3338
|
-
const
|
|
3339
|
-
const
|
|
3340
|
-
|
|
3341
|
-
|
|
3342
|
-
|
|
3343
|
-
|
|
3344
|
-
|
|
3345
|
-
|
|
3346
|
-
|
|
3347
|
-
|
|
3348
|
-
|
|
3349
|
-
|
|
3350
|
-
|
|
3351
|
-
|
|
3352
|
-
|
|
3353
|
-
|
|
3354
|
-
|
|
3355
|
-
|
|
3356
|
-
|
|
3357
|
-
|
|
3358
|
-
|
|
3359
|
-
|
|
3360
|
-
|
|
3361
|
-
|
|
3362
|
-
points.push({ x: at2.x + offset.x, y: at2.y + offset.y });
|
|
3458
|
+
return body;
|
|
3459
|
+
});
|
|
3460
|
+
separate(bodies);
|
|
3461
|
+
const byId = new Map(bodies.map((b) => [b.id, b]));
|
|
3462
|
+
const centroid = {
|
|
3463
|
+
x: bodies.reduce((sum, b) => sum + b.x, 0) / bodies.length,
|
|
3464
|
+
y: bodies.reduce((sum, b) => sum + b.y, 0) / bodies.length
|
|
3465
|
+
};
|
|
3466
|
+
const groups = graph.groups ?? [];
|
|
3467
|
+
const sim = createSimulation({
|
|
3468
|
+
nodes: bodies,
|
|
3469
|
+
forces: [
|
|
3470
|
+
charge(bodies, chargeStrength),
|
|
3471
|
+
links(byId, graph, linkDistance, linkStrength),
|
|
3472
|
+
gravity(bodies, centroid, gravityStrength),
|
|
3473
|
+
separateBoxes(bodies, padding),
|
|
3474
|
+
...groups.length > 0 ? [groupCohesion(groups, byId, groupStrength), separateGroups(groups, bodies, byId, padding)] : []
|
|
3475
|
+
]
|
|
3476
|
+
});
|
|
3477
|
+
return {
|
|
3478
|
+
bodies,
|
|
3479
|
+
byId,
|
|
3480
|
+
pinned,
|
|
3481
|
+
sim,
|
|
3482
|
+
placed() {
|
|
3483
|
+
const placed = /* @__PURE__ */ new Map();
|
|
3484
|
+
for (const node of graph.nodes) {
|
|
3485
|
+
const body = byId.get(node.id);
|
|
3486
|
+
placed.set(node.id, {
|
|
3487
|
+
x: body.x - node.bounds.width / 2,
|
|
3488
|
+
y: body.y - node.bounds.height / 2
|
|
3489
|
+
});
|
|
3363
3490
|
}
|
|
3491
|
+
return placed;
|
|
3364
3492
|
}
|
|
3365
|
-
|
|
3366
|
-
|
|
3367
|
-
|
|
3368
|
-
|
|
3369
|
-
|
|
3370
|
-
|
|
3371
|
-
|
|
3372
|
-
|
|
3373
|
-
|
|
3374
|
-
|
|
3375
|
-
|
|
3376
|
-
|
|
3377
|
-
|
|
3378
|
-
|
|
3379
|
-
|
|
3380
|
-
|
|
3493
|
+
};
|
|
3494
|
+
}
|
|
3495
|
+
var force = (graph, opts = {}) => {
|
|
3496
|
+
if (graph.nodes.length === 0) return /* @__PURE__ */ new Map();
|
|
3497
|
+
const relaxation = forceRelaxation(graph, opts);
|
|
3498
|
+
relaxation.sim.tick(opts.iterations ?? DEFAULTS.iterations);
|
|
3499
|
+
return translated(graph, relaxation.placed(), relaxation.pinned, opts.tolerance);
|
|
3500
|
+
};
|
|
3501
|
+
function separate(bodies) {
|
|
3502
|
+
const seen = /* @__PURE__ */ new Map();
|
|
3503
|
+
bodies.forEach((body, i) => {
|
|
3504
|
+
const key = `${body.x},${body.y}`;
|
|
3505
|
+
const nth = seen.get(key) ?? 0;
|
|
3506
|
+
seen.set(key, nth + 1);
|
|
3507
|
+
if (nth === 0 || body.fx != null || body.fy != null) return;
|
|
3508
|
+
const angle = GOLDEN * i;
|
|
3509
|
+
const radius = NUDGE2 * nth;
|
|
3510
|
+
body.x += Math.cos(angle) * radius;
|
|
3511
|
+
body.y += Math.sin(angle) * radius;
|
|
3512
|
+
});
|
|
3381
3513
|
}
|
|
3382
|
-
|
|
3383
|
-
// src/layered.ts
|
|
3384
|
-
var layered = Object.assign(
|
|
3385
|
-
(graph, opts = {}) => layeredPlan(graph, opts).moves,
|
|
3386
|
-
{ plan: layeredPlan }
|
|
3387
|
-
);
|
|
3388
3514
|
|
|
3389
3515
|
// src/chainGroups.ts
|
|
3390
3516
|
function depths(groups) {
|
|
@@ -3446,8 +3572,8 @@ function nearest(members, from, index) {
|
|
|
3446
3572
|
}
|
|
3447
3573
|
return best;
|
|
3448
3574
|
}
|
|
3449
|
-
function clearColumns(graph, ordered, index, owner,
|
|
3450
|
-
const level = new Map(
|
|
3575
|
+
function clearColumns(graph, ordered, index, owner, start2) {
|
|
3576
|
+
const level = new Map(start2);
|
|
3451
3577
|
const columns = /* @__PURE__ */ new Map();
|
|
3452
3578
|
for (const node of graph.nodes) {
|
|
3453
3579
|
if (index.has(node.id)) continue;
|
|
@@ -3482,19 +3608,19 @@ function lineGaps(graph, line, hanging, rankGap, axes, packed) {
|
|
|
3482
3608
|
return bandGaps(graph, columns, axes, columns.slice(1).map(() => rankGap), (id) => packed.get(id)?.rank);
|
|
3483
3609
|
}
|
|
3484
3610
|
function levelGaps(graph, hanging, levelSize, axes, before, base) {
|
|
3485
|
-
const
|
|
3486
|
-
for (const node of graph.nodes) (
|
|
3611
|
+
const levels2 = Array.from(levelSize, () => []);
|
|
3612
|
+
for (const node of graph.nodes) (levels2[hanging.level.get(node.id)] ??= []).push(node);
|
|
3487
3613
|
const outward = { rank: axes.cross, cross: axes.rank, sign: before ? -1 : 1 };
|
|
3488
3614
|
const from = [0];
|
|
3489
3615
|
for (let k = 1; k < levelSize.length; k++) from[k] = from[k - 1] + (levelSize[k - 1] ?? 0);
|
|
3490
|
-
return bandGaps(graph,
|
|
3616
|
+
return bandGaps(graph, levels2, outward, base, (id) => {
|
|
3491
3617
|
const node = graph.node(id);
|
|
3492
3618
|
const at2 = hanging.level.get(id);
|
|
3493
3619
|
if (node === void 0 || at2 === void 0) return void 0;
|
|
3494
3620
|
return at2 === 0 ? (levelSize[0] - extent(node.bounds, outward.rank)) / 2 : from[at2];
|
|
3495
3621
|
});
|
|
3496
3622
|
}
|
|
3497
|
-
function bandGaps(graph, bands, axes, gaps,
|
|
3623
|
+
function bandGaps(graph, bands, axes, gaps, start2) {
|
|
3498
3624
|
const insets = rankGaps(graph, bands, axes, 0);
|
|
3499
3625
|
const out = gaps.map((gap, i) => gap + (insets[i] ?? 0));
|
|
3500
3626
|
const groups = graph.groups ?? [];
|
|
@@ -3507,7 +3633,7 @@ function bandGaps(graph, bands, axes, gaps, start) {
|
|
|
3507
3633
|
const span = (id, now) => {
|
|
3508
3634
|
let [lo, hi] = [Infinity, -Infinity];
|
|
3509
3635
|
for (const m of byId.get(id).members) {
|
|
3510
|
-
const at2 =
|
|
3636
|
+
const at2 = start2(m);
|
|
3511
3637
|
const band = bandOf.get(m);
|
|
3512
3638
|
const node = graph.node(m);
|
|
3513
3639
|
if (at2 === void 0 || band === void 0 || node === void 0) continue;
|
|
@@ -3517,7 +3643,7 @@ function bandGaps(graph, bands, axes, gaps, start) {
|
|
|
3517
3643
|
return { lo, hi };
|
|
3518
3644
|
};
|
|
3519
3645
|
widenForMinWidth(deepestFirst(groups).map((g) => {
|
|
3520
|
-
const placed = g.members.flatMap((id) => bandOf.has(id) &&
|
|
3646
|
+
const placed = g.members.flatMap((id) => bandOf.has(id) && start2(id) !== void 0 ? [bandOf.get(id)] : []);
|
|
3521
3647
|
return {
|
|
3522
3648
|
id: g.id,
|
|
3523
3649
|
...g.minWidth !== void 0 ? { minWidth: g.minWidth } : {},
|
|
@@ -3589,8 +3715,8 @@ function sidesOf2(graph, hanging, moves, axes, before) {
|
|
|
3589
3715
|
return byLine;
|
|
3590
3716
|
}
|
|
3591
3717
|
var SIDE_TRACK_GAP = 12;
|
|
3592
|
-
function turning(
|
|
3593
|
-
const sideways =
|
|
3718
|
+
function turning(sides2) {
|
|
3719
|
+
const sideways = sides2.filter((s) => Math.abs(s.hung - s.port) > 0.5);
|
|
3594
3720
|
return [
|
|
3595
3721
|
sideways.filter((s) => s.hung < s.port).sort((a, b) => a.port - b.port),
|
|
3596
3722
|
sideways.filter((s) => s.hung > s.port).sort((a, b) => b.port - a.port)
|
|
@@ -3598,18 +3724,18 @@ function turning(sides) {
|
|
|
3598
3724
|
}
|
|
3599
3725
|
function tracksNeeded(graph, hanging, moves, axes, before) {
|
|
3600
3726
|
let most = 0;
|
|
3601
|
-
for (const
|
|
3602
|
-
const [low, high] = turning(
|
|
3727
|
+
for (const sides2 of sidesOf2(graph, hanging, moves, axes, before).values()) {
|
|
3728
|
+
const [low, high] = turning(sides2);
|
|
3603
3729
|
most = Math.max(most, low.length, high.length);
|
|
3604
3730
|
}
|
|
3605
3731
|
return most;
|
|
3606
3732
|
}
|
|
3607
3733
|
function sideRoutes(graph, hanging, moves, axes, before) {
|
|
3608
3734
|
const out = /* @__PURE__ */ new Map();
|
|
3609
|
-
for (const
|
|
3610
|
-
const [low, high] = turning(
|
|
3611
|
-
const lineEdge =
|
|
3612
|
-
const hungEdge = before ? Math.max(...
|
|
3735
|
+
for (const sides2 of sidesOf2(graph, hanging, moves, axes, before).values()) {
|
|
3736
|
+
const [low, high] = turning(sides2);
|
|
3737
|
+
const lineEdge = sides2[0].lineEdge;
|
|
3738
|
+
const hungEdge = before ? Math.max(...sides2.map((s) => s.hungEdge)) : Math.min(...sides2.map((s) => s.hungEdge));
|
|
3613
3739
|
const step = (hungEdge - lineEdge) / (Math.max(low.length, high.length) + 1);
|
|
3614
3740
|
for (const run of [low, high]) {
|
|
3615
3741
|
run.forEach((s, k) => {
|
|
@@ -3661,12 +3787,12 @@ function lineOf(graph, ids) {
|
|
|
3661
3787
|
if (given.length > 0) return given;
|
|
3662
3788
|
const back = backEdges(graph);
|
|
3663
3789
|
const ranks = ranksOf(graph, back);
|
|
3664
|
-
let
|
|
3790
|
+
let end2;
|
|
3665
3791
|
for (const node of graph.nodes) {
|
|
3666
|
-
if (
|
|
3792
|
+
if (end2 === void 0 || ranks.get(node.id) > ranks.get(end2.id)) end2 = node;
|
|
3667
3793
|
}
|
|
3668
3794
|
const line = [];
|
|
3669
|
-
for (let at2 =
|
|
3795
|
+
for (let at2 = end2; at2 !== void 0; ) {
|
|
3670
3796
|
line.unshift(at2);
|
|
3671
3797
|
const rank = ranks.get(at2.id);
|
|
3672
3798
|
const edge = graph.incoming(at2.id).find((e) => !back.has(e.id) && ranks.get(e.from) === rank - 1);
|
|
@@ -3728,10 +3854,10 @@ function chainPlan(graph, opts = {}) {
|
|
|
3728
3854
|
};
|
|
3729
3855
|
const slots = (rank, level2) => slotsFor(line, rows, levelSize, axes, { node: nodeGap, rank, level: level2 }, before);
|
|
3730
3856
|
const gaps = grouped ? lineGaps(graph, line, hanging, rankGap, axes, slots(line.map(() => 0), [])) : line.map(() => rankGap);
|
|
3731
|
-
const
|
|
3732
|
-
let moves =
|
|
3857
|
+
const place2 = (side2) => settle(graph, slots(gaps, across(side2)), opts);
|
|
3858
|
+
let moves = place2(nodeGap);
|
|
3733
3859
|
const side = (tracksNeeded(graph, hanging, moves, axes, before) + 1) * SIDE_TRACK_GAP;
|
|
3734
|
-
if (side > nodeGap) moves =
|
|
3860
|
+
if (side > nodeGap) moves = place2(side);
|
|
3735
3861
|
return { moves, waypoints: sideRoutes(graph, hanging, moves, axes, before) };
|
|
3736
3862
|
}
|
|
3737
3863
|
function slotsFor(line, rows, levelSize, axes, gaps, before) {
|
|
@@ -3766,6 +3892,97 @@ function slotsFor(line, rows, levelSize, axes, gaps, before) {
|
|
|
3766
3892
|
return slots;
|
|
3767
3893
|
}
|
|
3768
3894
|
|
|
3895
|
+
// src/grid.ts
|
|
3896
|
+
function levels(graph) {
|
|
3897
|
+
const order = graphOrder(graph);
|
|
3898
|
+
const groups = graph.groups ?? [];
|
|
3899
|
+
const first = new Map(groups.map((g) => [g.id, Math.min(...g.members.map(order))]));
|
|
3900
|
+
const at2 = (id) => first.get(id) ?? order(id);
|
|
3901
|
+
const out = /* @__PURE__ */ new Map();
|
|
3902
|
+
const add = (level, id) => out.set(level, [...out.get(level) ?? [], id]);
|
|
3903
|
+
for (const n of graph.nodes) add(n.group ?? null, n.id);
|
|
3904
|
+
for (const g of groups) add(g.parent ?? null, g.id);
|
|
3905
|
+
for (const ids of out.values()) ids.sort((a, b) => at2(a) - at2(b));
|
|
3906
|
+
return out;
|
|
3907
|
+
}
|
|
3908
|
+
function deal(ids, sizeOf, columns, grid2) {
|
|
3909
|
+
const items = [];
|
|
3910
|
+
let row = 0;
|
|
3911
|
+
let col = 0;
|
|
3912
|
+
for (const id of ids) {
|
|
3913
|
+
col += Math.max(0, Math.floor(grid2.skips?.[id] ?? 0));
|
|
3914
|
+
row += Math.floor(col / columns);
|
|
3915
|
+
col %= columns;
|
|
3916
|
+
const span = Math.min(columns, Math.max(1, Math.floor(grid2.spans?.[id] ?? 1)));
|
|
3917
|
+
if (col + span > columns) {
|
|
3918
|
+
row++;
|
|
3919
|
+
col = 0;
|
|
3920
|
+
}
|
|
3921
|
+
items.push({ id, size: sizeOf(id), row, col, span });
|
|
3922
|
+
col += span;
|
|
3923
|
+
}
|
|
3924
|
+
return { items, columns };
|
|
3925
|
+
}
|
|
3926
|
+
function place(cells, gap, rowGap) {
|
|
3927
|
+
const width = Math.max(0, ...cells.items.map((i) => (i.size.width - (i.span - 1) * gap) / i.span));
|
|
3928
|
+
const rows = [];
|
|
3929
|
+
for (const i of cells.items) rows[i.row] = Math.max(rows[i.row] ?? 0, i.size.height);
|
|
3930
|
+
const tops = [];
|
|
3931
|
+
let y = 0;
|
|
3932
|
+
for (let r = 0; r < rows.length; r++) {
|
|
3933
|
+
tops[r] = y;
|
|
3934
|
+
y += (rows[r] ?? 0) + rowGap;
|
|
3935
|
+
}
|
|
3936
|
+
const at2 = /* @__PURE__ */ new Map();
|
|
3937
|
+
for (const i of cells.items) {
|
|
3938
|
+
const across = i.span * width + (i.span - 1) * gap;
|
|
3939
|
+
at2.set(i.id, { x: i.col * (width + gap) + (across - i.size.width) / 2, y: tops[i.row] + ((rows[i.row] ?? 0) - i.size.height) / 2 });
|
|
3940
|
+
}
|
|
3941
|
+
const used = Math.max(0, ...cells.items.map((i) => i.col + i.span));
|
|
3942
|
+
return { at: at2, size: { width: used === 0 ? 0 : used * width + (used - 1) * gap, height: rows.length === 0 ? 0 : y - rowGap } };
|
|
3943
|
+
}
|
|
3944
|
+
var grid = (graph, opts = {}) => {
|
|
3945
|
+
const gap = opts.nodeGap ?? DEFAULT_NODE_GAP;
|
|
3946
|
+
const rowGap = opts.rankGap ?? gap;
|
|
3947
|
+
const spec = opts.grid ?? {};
|
|
3948
|
+
const byLevel = levels(graph);
|
|
3949
|
+
const groups = new Map((graph.groups ?? []).map((g) => [g.id, g]));
|
|
3950
|
+
const inner = /* @__PURE__ */ new Map();
|
|
3951
|
+
const sizeOf = (id) => {
|
|
3952
|
+
const g = groups.get(id);
|
|
3953
|
+
if (g === void 0) return graph.node(id).bounds;
|
|
3954
|
+
const laid = layOut(id);
|
|
3955
|
+
return {
|
|
3956
|
+
width: Math.max(g.minWidth ?? 0, laid.size.width + g.inset.left + g.inset.right),
|
|
3957
|
+
height: laid.size.height + g.inset.top + g.inset.bottom
|
|
3958
|
+
};
|
|
3959
|
+
};
|
|
3960
|
+
const layOut = (level) => {
|
|
3961
|
+
const done = level === null ? void 0 : inner.get(level);
|
|
3962
|
+
if (done !== void 0) return done;
|
|
3963
|
+
const ids = byLevel.get(level) ?? [];
|
|
3964
|
+
const columns = Math.max(1, Math.floor((level === null ? spec.columns : spec.groupColumns?.[level]) ?? ids.length));
|
|
3965
|
+
const laid = place(deal(ids, sizeOf, columns, spec), gap, rowGap);
|
|
3966
|
+
if (level !== null) inner.set(level, laid);
|
|
3967
|
+
return laid;
|
|
3968
|
+
};
|
|
3969
|
+
const placed = /* @__PURE__ */ new Map();
|
|
3970
|
+
const put = (level, origin) => {
|
|
3971
|
+
for (const [id, p] of layOut(level).at) {
|
|
3972
|
+
const corner = { x: origin.x + p.x, y: origin.y + p.y };
|
|
3973
|
+
const g = groups.get(id);
|
|
3974
|
+
if (g === void 0) {
|
|
3975
|
+
placed.set(id, corner);
|
|
3976
|
+
continue;
|
|
3977
|
+
}
|
|
3978
|
+
const slack = sizeOf(id).width - (inner.get(id).size.width + g.inset.left + g.inset.right);
|
|
3979
|
+
put(id, { x: corner.x + g.inset.left + slack / 2, y: corner.y + g.inset.top });
|
|
3980
|
+
}
|
|
3981
|
+
};
|
|
3982
|
+
put(null, { x: 0, y: 0 });
|
|
3983
|
+
return translated(graph, placed, pinnedSet(graph, opts), opts.tolerance);
|
|
3984
|
+
};
|
|
3985
|
+
|
|
3769
3986
|
// src/tree.ts
|
|
3770
3987
|
function forestOf(graph, crossAxis) {
|
|
3771
3988
|
const order = graphOrder(graph);
|
|
@@ -3866,6 +4083,94 @@ var treeOnce = (graph, opts = {}) => {
|
|
|
3866
4083
|
return settle(graph, slots, opts);
|
|
3867
4084
|
};
|
|
3868
4085
|
|
|
3869
|
-
|
|
3870
|
-
|
|
3871
|
-
|
|
4086
|
+
// src/radial.ts
|
|
4087
|
+
var radial = (graph, opts = {}) => {
|
|
4088
|
+
const nodeGap = opts.nodeGap ?? DEFAULT_NODE_GAP;
|
|
4089
|
+
const rankGap = opts.rankGap ?? DEFAULT_RANK_GAP;
|
|
4090
|
+
const { roots, children } = forestOf(graph, "y");
|
|
4091
|
+
const blocks = subtreeBlocks(children, "y", nodeGap);
|
|
4092
|
+
const order = graphOrder(graph);
|
|
4093
|
+
const placed = /* @__PURE__ */ new Map();
|
|
4094
|
+
let top = 0;
|
|
4095
|
+
for (const root of roots) {
|
|
4096
|
+
const tree2 = mindMap(root, children, order, blocks, nodeGap, rankGap);
|
|
4097
|
+
for (const [id, p] of tree2.at) placed.set(id, { x: p.x, y: p.y - tree2.top + top });
|
|
4098
|
+
top += tree2.bottom - tree2.top + nodeGap;
|
|
4099
|
+
}
|
|
4100
|
+
return translated(graph, placed, pinnedSet(graph, opts), opts.tolerance);
|
|
4101
|
+
};
|
|
4102
|
+
function mindMap(root, children, order, blocks, nodeGap, rankGap) {
|
|
4103
|
+
const at2 = /* @__PURE__ */ new Map([[root.id, { x: -root.bounds.width / 2, y: -root.bounds.height / 2 }]]);
|
|
4104
|
+
let top = -root.bounds.height / 2;
|
|
4105
|
+
let bottom = root.bounds.height / 2;
|
|
4106
|
+
const [right, left] = sides(root, children, order);
|
|
4107
|
+
for (const [sign, branches] of [[1, right], [-1, left]]) {
|
|
4108
|
+
if (branches.length === 0) continue;
|
|
4109
|
+
const span = branches.reduce((sum, b) => sum + blocks.span(b), 0) + (branches.length - 1) * nodeGap;
|
|
4110
|
+
const ys = /* @__PURE__ */ new Map();
|
|
4111
|
+
let cursor = -span / 2;
|
|
4112
|
+
for (const branch of branches) {
|
|
4113
|
+
blocks.lay(branch, cursor, ys);
|
|
4114
|
+
cursor += blocks.span(branch) + nodeGap;
|
|
4115
|
+
}
|
|
4116
|
+
top = Math.min(top, -span / 2);
|
|
4117
|
+
bottom = Math.max(bottom, span / 2);
|
|
4118
|
+
for (const [id, x] of sideColumns(branches, children, root.bounds.width / 2 + rankGap, rankGap, sign)) {
|
|
4119
|
+
at2.set(id, { x, y: ys.get(id) });
|
|
4120
|
+
}
|
|
4121
|
+
}
|
|
4122
|
+
return { at: at2, top, bottom };
|
|
4123
|
+
}
|
|
4124
|
+
function sides(root, children, order) {
|
|
4125
|
+
const weight = (node) => 1 + (children.get(node.id) ?? []).reduce((sum, k) => sum + weight(k), 0);
|
|
4126
|
+
const kids = children.get(root.id) ?? [];
|
|
4127
|
+
const half = root.bounds.width / 2;
|
|
4128
|
+
const mid = root.bounds.x + half;
|
|
4129
|
+
const standing = (k) => {
|
|
4130
|
+
const c = k.bounds.x + k.bounds.width / 2 - mid;
|
|
4131
|
+
return c > half ? 1 : c < -half ? -1 : 0;
|
|
4132
|
+
};
|
|
4133
|
+
const stands = new Map(kids.map((k) => [k, standing(k)]));
|
|
4134
|
+
const arranged = [...stands.values()].includes(1) && [...stands.values()].includes(-1);
|
|
4135
|
+
const right = /* @__PURE__ */ new Set();
|
|
4136
|
+
let r = 0;
|
|
4137
|
+
let l = 0;
|
|
4138
|
+
const dealt = arranged ? kids.filter((k) => stands.get(k) !== 0) : [];
|
|
4139
|
+
for (const k of dealt) {
|
|
4140
|
+
if (stands.get(k) === 1) {
|
|
4141
|
+
right.add(k);
|
|
4142
|
+
r += weight(k);
|
|
4143
|
+
} else l += weight(k);
|
|
4144
|
+
}
|
|
4145
|
+
for (const child of kids.filter((k) => !dealt.includes(k)).sort((a, b) => order(a.id) - order(b.id))) {
|
|
4146
|
+
const w = weight(child);
|
|
4147
|
+
if (r <= l) {
|
|
4148
|
+
right.add(child);
|
|
4149
|
+
r += w;
|
|
4150
|
+
} else l += w;
|
|
4151
|
+
}
|
|
4152
|
+
return [kids.filter((k) => right.has(k)), kids.filter((k) => !right.has(k))];
|
|
4153
|
+
}
|
|
4154
|
+
function sideColumns(branches, children, from, rankGap, sign) {
|
|
4155
|
+
const rows = [];
|
|
4156
|
+
const visit = (node, depth) => {
|
|
4157
|
+
(rows[depth] ??= []).push(node);
|
|
4158
|
+
for (const kid of children.get(node.id) ?? []) visit(kid, depth + 1);
|
|
4159
|
+
};
|
|
4160
|
+
for (const branch of branches) visit(branch, 0);
|
|
4161
|
+
const xs = /* @__PURE__ */ new Map();
|
|
4162
|
+
let start2 = from;
|
|
4163
|
+
for (const row of rows) {
|
|
4164
|
+
const band = Math.max(...row.map((n) => n.bounds.width));
|
|
4165
|
+
for (const node of row) {
|
|
4166
|
+
const near = start2 + (band - node.bounds.width) / 2;
|
|
4167
|
+
xs.set(node.id, sign === 1 ? near : -near - node.bounds.width);
|
|
4168
|
+
}
|
|
4169
|
+
start2 += band + rankGap;
|
|
4170
|
+
}
|
|
4171
|
+
return xs;
|
|
4172
|
+
}
|
|
4173
|
+
|
|
4174
|
+
export { COMPASS, DEFAULT_GROUP_INSET, DEFAULT_NODE_GAP, DEFAULT_PORTS, DEFAULT_RANK_GAP, DEVICE_SIZE, DIAGRAM_TRAIT_KEY, DIVIDER_HEIGHT, EVENT_SIZE, GATEWAY_SIZE, PORT_LABEL_GAP, SIDE_TRACK_GAP, anchorOffset, authoredOver, axesFor, backEdges, bodyOutline, bodyTrait, boxForContent, buildBody, canvasMeasure, center, chain, contentBox, createDiagramNodes, dataKeyReader, diagramEdgeOf, diagramNodeOf, expandGroupEdges, extent, footprintNode, force, forceRelaxation, forestOf, graphOrder, grid, grownBy, insetOf, isPinned, isPromise, labelCenter, labelSpotAt, layered, layeredPlan, layeredRoutes, layoutBody, layoutOwnsPort, layoutOwnsRoute, layoutRowPorts, layoutWritesRoute, marginOf, measureBody, outlineDetail, outlineFromD, outlinePath, outlinePolyline, outlineSolid, packAcross, packClusters, pinnedSet, planOf, plannerPlan, portLabelBox, portLabelsOf, portOf, portSitesOf, portsOf, portsOnOutline, radial, rankGaps, ranksByLength, ranksOf, rayHit, registerOutline, resolveOutline, routeHolds, rowHeights, samePoints, seededOrder, settle, sizeToBody, subpathOf, subtreeBlocks, translated, tree, untilSettled, widenForMinWidth };
|
|
4175
|
+
//# sourceMappingURL=chunk-UOFQBGJY.js.map
|
|
4176
|
+
//# sourceMappingURL=chunk-UOFQBGJY.js.map
|