@crazyhappyone/auto-graph 0.1.3 → 0.1.4
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/dist/cli/index.cjs +143 -13
- package/dist/cli/index.cjs.map +1 -1
- package/dist/cli/index.js +143 -13
- package/dist/cli/index.js.map +1 -1
- package/dist/index.cjs +143 -13
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +143 -13
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -1289,6 +1289,9 @@ function applyLayoutConstraints(input) {
|
|
|
1289
1289
|
const nodeById = new Map(input.nodes.map((node) => [node.id, node]));
|
|
1290
1290
|
applyFixedPositionLocks(input.nodes, boxes, locks, diagnostics);
|
|
1291
1291
|
applyExactPositions(input.constraints, boxes, locks, diagnostics, nodeById);
|
|
1292
|
+
if (input.distributeContainedChildren) {
|
|
1293
|
+
yieldFixedPositionLocks(input, boxes, locks);
|
|
1294
|
+
}
|
|
1292
1295
|
applyContainment(input.constraints, boxes, locks, diagnostics, false);
|
|
1293
1296
|
applyRelative(input.constraints, boxes, locks, diagnostics);
|
|
1294
1297
|
applyAlign(input.constraints, boxes, locks, diagnostics);
|
|
@@ -1302,6 +1305,13 @@ function applyLayoutConstraints(input) {
|
|
|
1302
1305
|
);
|
|
1303
1306
|
applyContainment(input.constraints, boxes, locks, diagnostics, true);
|
|
1304
1307
|
applyDistributeContained(input, boxes, locks, diagnostics);
|
|
1308
|
+
if (input.distributeContainedChildren) {
|
|
1309
|
+
const diagBefore = diagnostics.length;
|
|
1310
|
+
applyContainment(input.constraints, boxes, locks, diagnostics, true);
|
|
1311
|
+
applyDistributeContained(input, boxes, locks, diagnostics);
|
|
1312
|
+
dedupReplayDiagnostics(diagnostics, diagBefore);
|
|
1313
|
+
}
|
|
1314
|
+
removeResolvedConstraintDiagnostics(input.constraints, boxes, diagnostics);
|
|
1305
1315
|
reportOverlaps(boxes, diagnostics, containmentOverlapKeys(input.constraints));
|
|
1306
1316
|
reportIntraContainerOverflow(input, boxes, diagnostics);
|
|
1307
1317
|
return { boxes, locks, diagnostics };
|
|
@@ -1347,6 +1357,62 @@ function applyFixedPositionLocks(nodes, boxes, locks, diagnostics) {
|
|
|
1347
1357
|
locks.set(node.id, { nodeId: node.id, source: "fixed-position" });
|
|
1348
1358
|
}
|
|
1349
1359
|
}
|
|
1360
|
+
function dedupReplayDiagnostics(diagnostics, keepUpTo) {
|
|
1361
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1362
|
+
for (let i = 0; i < keepUpTo && i < diagnostics.length; i += 1) {
|
|
1363
|
+
const d = diagnostics[i];
|
|
1364
|
+
if (d === void 0) continue;
|
|
1365
|
+
seen.add(diagnosticFingerprint(d));
|
|
1366
|
+
}
|
|
1367
|
+
for (let i = diagnostics.length - 1; i >= keepUpTo; i -= 1) {
|
|
1368
|
+
const d = diagnostics[i];
|
|
1369
|
+
if (d === void 0) continue;
|
|
1370
|
+
const fp = diagnosticFingerprint(d);
|
|
1371
|
+
if (seen.has(fp)) {
|
|
1372
|
+
diagnostics.splice(i, 1);
|
|
1373
|
+
} else {
|
|
1374
|
+
seen.add(fp);
|
|
1375
|
+
}
|
|
1376
|
+
}
|
|
1377
|
+
}
|
|
1378
|
+
function diagnosticFingerprint(d) {
|
|
1379
|
+
const nodeId = typeof d.detail?.nodeId === "string" ? d.detail.nodeId : "";
|
|
1380
|
+
const containerId = typeof d.detail?.containerId === "string" ? d.detail.containerId : "";
|
|
1381
|
+
return `${d.code}|${nodeId}|${containerId}`;
|
|
1382
|
+
}
|
|
1383
|
+
function yieldFixedPositionLocks(input, boxes, locks) {
|
|
1384
|
+
for (const c of input.constraints) {
|
|
1385
|
+
if (c.kind !== "containment") continue;
|
|
1386
|
+
const container = boxes.get(c.containerId);
|
|
1387
|
+
if (container === void 0) continue;
|
|
1388
|
+
const content = contentBox(container, c.padding);
|
|
1389
|
+
const mainAxis = input.direction === "LR" || input.direction === "RL" ? "width" : "height";
|
|
1390
|
+
const crossAxis = mainAxis === "width" ? "height" : "width";
|
|
1391
|
+
let eligible = 0;
|
|
1392
|
+
for (const childId of c.childIds) {
|
|
1393
|
+
const box = boxes.get(childId);
|
|
1394
|
+
if (box === void 0) continue;
|
|
1395
|
+
const lock = locks.get(childId);
|
|
1396
|
+
if (lock?.source === "exact-position") continue;
|
|
1397
|
+
const fits = box[mainAxis] <= content[mainAxis] && box[crossAxis] <= content[crossAxis];
|
|
1398
|
+
if (fits) {
|
|
1399
|
+
eligible += 1;
|
|
1400
|
+
}
|
|
1401
|
+
}
|
|
1402
|
+
if (eligible < 2) continue;
|
|
1403
|
+
for (const childId of c.childIds) {
|
|
1404
|
+
const lock = locks.get(childId);
|
|
1405
|
+
if (lock?.source === "fixed-position") {
|
|
1406
|
+
const box = boxes.get(childId);
|
|
1407
|
+
if (box === void 0) continue;
|
|
1408
|
+
const fits = box[mainAxis] <= content[mainAxis] && box[crossAxis] <= content[crossAxis];
|
|
1409
|
+
if (fits) {
|
|
1410
|
+
locks.delete(childId);
|
|
1411
|
+
}
|
|
1412
|
+
}
|
|
1413
|
+
}
|
|
1414
|
+
}
|
|
1415
|
+
}
|
|
1350
1416
|
function applyExactPositions(constraints, boxes, locks, diagnostics, nodeById) {
|
|
1351
1417
|
for (const constraint of constraints) {
|
|
1352
1418
|
if (constraint.kind !== "exact-position") {
|
|
@@ -1419,7 +1485,7 @@ function applyContainment(constraints, boxes, locks, diagnostics, reportOverflow
|
|
|
1419
1485
|
code: "constraints.locked-target-not-moved",
|
|
1420
1486
|
message: `Locked child ${childId} was not moved into containment.`,
|
|
1421
1487
|
path: ["constraints", constraint.id ?? constraint.containerId],
|
|
1422
|
-
detail: { nodeId: childId }
|
|
1488
|
+
detail: { nodeId: childId, containerId: constraint.containerId }
|
|
1423
1489
|
});
|
|
1424
1490
|
if (!isInside(child, content)) {
|
|
1425
1491
|
diagnostics.push({
|
|
@@ -1571,6 +1637,60 @@ function repairOverlaps(input, boxes, locks, diagnostics, siblingPairs) {
|
|
|
1571
1637
|
}
|
|
1572
1638
|
reportOverlaps(boxes, diagnostics, ignoredPairs);
|
|
1573
1639
|
}
|
|
1640
|
+
function removeResolvedConstraintDiagnostics(constraints, boxes, diagnostics) {
|
|
1641
|
+
for (let i = diagnostics.length - 1; i >= 0; i -= 1) {
|
|
1642
|
+
const d = diagnostics[i];
|
|
1643
|
+
if (d === void 0) continue;
|
|
1644
|
+
if (d.code === "constraints.overlap.unresolved") {
|
|
1645
|
+
const aId = d.detail?.firstId;
|
|
1646
|
+
const bId = d.detail?.secondId;
|
|
1647
|
+
if (typeof aId !== "string" || typeof bId !== "string") continue;
|
|
1648
|
+
const a = boxes.get(aId);
|
|
1649
|
+
const b = boxes.get(bId);
|
|
1650
|
+
if (a !== void 0 && b !== void 0 && !intersectsAabb(a, b)) {
|
|
1651
|
+
diagnostics.splice(i, 1);
|
|
1652
|
+
}
|
|
1653
|
+
continue;
|
|
1654
|
+
}
|
|
1655
|
+
if (d.code === "constraints.containment.impossible" || d.code === "constraints.locked-target-not-moved" && typeof d.message === "string" && d.message.includes("not moved into containment")) {
|
|
1656
|
+
const nodeId = d.detail?.nodeId;
|
|
1657
|
+
if (typeof nodeId !== "string") continue;
|
|
1658
|
+
const child = boxes.get(nodeId);
|
|
1659
|
+
if (child === void 0) continue;
|
|
1660
|
+
const diagContainerId = typeof d.detail?.containerId === "string" ? d.detail.containerId : void 0;
|
|
1661
|
+
let resolved = false;
|
|
1662
|
+
for (const c of constraints) {
|
|
1663
|
+
if (c.kind !== "containment") continue;
|
|
1664
|
+
if (!c.childIds.includes(nodeId)) continue;
|
|
1665
|
+
if (diagContainerId !== void 0 && c.containerId !== diagContainerId) {
|
|
1666
|
+
continue;
|
|
1667
|
+
}
|
|
1668
|
+
const container = boxes.get(c.containerId);
|
|
1669
|
+
if (container === void 0) continue;
|
|
1670
|
+
const content = contentBox(container, c.padding);
|
|
1671
|
+
if (isInside(child, content)) {
|
|
1672
|
+
diagnostics.splice(i, 1);
|
|
1673
|
+
resolved = true;
|
|
1674
|
+
}
|
|
1675
|
+
break;
|
|
1676
|
+
}
|
|
1677
|
+
if (!resolved && diagContainerId !== void 0) {
|
|
1678
|
+
for (const c of constraints) {
|
|
1679
|
+
if (c.kind !== "containment") continue;
|
|
1680
|
+
if (c.containerId !== diagContainerId) continue;
|
|
1681
|
+
if (!c.childIds.includes(nodeId)) continue;
|
|
1682
|
+
const container = boxes.get(c.containerId);
|
|
1683
|
+
if (container === void 0) continue;
|
|
1684
|
+
const content = contentBox(container, c.padding);
|
|
1685
|
+
if (isInside(child, content)) {
|
|
1686
|
+
diagnostics.splice(i, 1);
|
|
1687
|
+
}
|
|
1688
|
+
break;
|
|
1689
|
+
}
|
|
1690
|
+
}
|
|
1691
|
+
}
|
|
1692
|
+
}
|
|
1693
|
+
}
|
|
1574
1694
|
function reportOverlaps(boxes, diagnostics, ignoredPairs = /* @__PURE__ */ new Set()) {
|
|
1575
1695
|
const ids = [...boxes.keys()].sort();
|
|
1576
1696
|
const reported = new Set(
|
|
@@ -1878,6 +1998,12 @@ function applyDistributeContained(input, boxes, locks, diagnostics) {
|
|
|
1878
1998
|
continue;
|
|
1879
1999
|
}
|
|
1880
2000
|
if (locks.has(childId)) {
|
|
2001
|
+
const lock = locks.get(childId);
|
|
2002
|
+
if (lock?.source === "fixed-position") {
|
|
2003
|
+
unlocked.push({ id: childId, box });
|
|
2004
|
+
locks.delete(childId);
|
|
2005
|
+
continue;
|
|
2006
|
+
}
|
|
1881
2007
|
diagnostics.push({
|
|
1882
2008
|
severity: "warning",
|
|
1883
2009
|
code: "constraints.locked-target-not-moved",
|
|
@@ -1936,6 +2062,7 @@ function applyDistributeContained(input, boxes, locks, diagnostics) {
|
|
|
1936
2062
|
});
|
|
1937
2063
|
}
|
|
1938
2064
|
boxes.set(child.id, clamped);
|
|
2065
|
+
locks.delete(child.id);
|
|
1939
2066
|
pos = clamped[axis] + clamped[mainSize] + minGap;
|
|
1940
2067
|
}
|
|
1941
2068
|
diagnostics.push({
|
|
@@ -3385,7 +3512,7 @@ function routeEdge(input) {
|
|
|
3385
3512
|
const rerouted = greedyRerouteAroundObstacles(
|
|
3386
3513
|
bestPoints2,
|
|
3387
3514
|
allObstacles,
|
|
3388
|
-
|
|
3515
|
+
maxAttempts
|
|
3389
3516
|
);
|
|
3390
3517
|
const reroutedAvoidsEndpointInteriors = !routeIntersectsEndpointInteriors(
|
|
3391
3518
|
rerouted,
|
|
@@ -4147,9 +4274,7 @@ function solveDiagram(diagram, options = {}) {
|
|
|
4147
4274
|
options?.overlapSpacing ?? 40,
|
|
4148
4275
|
Math.max(0, options?.minLaneGutter ?? 0)
|
|
4149
4276
|
);
|
|
4150
|
-
|
|
4151
|
-
removeResolvedOverlapDiagnostics(diagnostics, constrained.boxes);
|
|
4152
|
-
}
|
|
4277
|
+
removeResolvedOverlapDiagnostics(diagnostics, constrained.boxes);
|
|
4153
4278
|
diagnostics.push(...swimlaneContracts.diagnostics);
|
|
4154
4279
|
const coordinatedNodes = coordinateNodes(
|
|
4155
4280
|
styledNodes,
|
|
@@ -6092,7 +6217,8 @@ function coordinateEdges(edges, nodes, coordinatedNodes, obstacles, softObstacle
|
|
|
6092
6217
|
...softObstacles,
|
|
6093
6218
|
...routeTextObstacles
|
|
6094
6219
|
],
|
|
6095
|
-
hardObstacles
|
|
6220
|
+
hardObstacles,
|
|
6221
|
+
...options.maxRoutingAttempts === void 0 ? {} : { maxRoutingAttempts: options.maxRoutingAttempts }
|
|
6096
6222
|
});
|
|
6097
6223
|
diagnostics.push(
|
|
6098
6224
|
...route.diagnostics.map((diagnostic) => ({
|
|
@@ -6575,7 +6701,8 @@ function edgeLabelAnchor(edge, layout2, edges, obstacleBoxes, placedLabelBoxes,
|
|
|
6575
6701
|
for (const candidate of edgeLabelAnchorCandidates(
|
|
6576
6702
|
edge.points,
|
|
6577
6703
|
placement,
|
|
6578
|
-
layout2
|
|
6704
|
+
layout2,
|
|
6705
|
+
baseOffset
|
|
6579
6706
|
)) {
|
|
6580
6707
|
const labelBox = {
|
|
6581
6708
|
x: candidate.x - layout2.box.width / 2,
|
|
@@ -6607,8 +6734,8 @@ function edgeLabelAnchor(edge, layout2, edges, obstacleBoxes, placedLabelBoxes,
|
|
|
6607
6734
|
}
|
|
6608
6735
|
return placement;
|
|
6609
6736
|
}
|
|
6610
|
-
function edgeLabelAnchorCandidates(points, placement, layout2) {
|
|
6611
|
-
const segment = labelSegmentOnPolyline(points);
|
|
6737
|
+
function edgeLabelAnchorCandidates(points, placement, layout2, baseOffset = 10) {
|
|
6738
|
+
const segment = labelSegmentOnPolyline(points, baseOffset);
|
|
6612
6739
|
if (segment === void 0) {
|
|
6613
6740
|
return [placement];
|
|
6614
6741
|
}
|
|
@@ -6658,7 +6785,7 @@ function edgeLabelAnchorCandidates(points, placement, layout2) {
|
|
|
6658
6785
|
}, 0);
|
|
6659
6786
|
if (totalLen > 200) {
|
|
6660
6787
|
for (const ratio of [0.25, 0.75]) {
|
|
6661
|
-
const qp = labelPlacementAtRatio(points, ratio, totalLen);
|
|
6788
|
+
const qp = labelPlacementAtRatio(points, ratio, totalLen, baseOffset);
|
|
6662
6789
|
if (qp !== void 0) {
|
|
6663
6790
|
candidates.push(qp);
|
|
6664
6791
|
const qTargetDist = totalLen * ratio;
|
|
@@ -6744,7 +6871,7 @@ function labelSegmentOnPolyline(points, baseOffset = 10) {
|
|
|
6744
6871
|
if (last === void 0) {
|
|
6745
6872
|
return void 0;
|
|
6746
6873
|
}
|
|
6747
|
-
const offset = labelOffset2(last);
|
|
6874
|
+
const offset = labelOffset2(last, baseOffset);
|
|
6748
6875
|
return {
|
|
6749
6876
|
start: last.start,
|
|
6750
6877
|
end: last.end,
|
|
@@ -6766,7 +6893,7 @@ function nonZeroSegments2(points) {
|
|
|
6766
6893
|
}
|
|
6767
6894
|
return segments;
|
|
6768
6895
|
}
|
|
6769
|
-
function labelPlacementAtRatio(points, ratio, totalLength) {
|
|
6896
|
+
function labelPlacementAtRatio(points, ratio, totalLength, baseOffset = 10) {
|
|
6770
6897
|
if (points.length < 2 || ratio < 0 || ratio > 1) {
|
|
6771
6898
|
return void 0;
|
|
6772
6899
|
}
|
|
@@ -6784,7 +6911,10 @@ function labelPlacementAtRatio(points, ratio, totalLength) {
|
|
|
6784
6911
|
}
|
|
6785
6912
|
if (travelled + segLen >= targetDist) {
|
|
6786
6913
|
const t = (targetDist - travelled) / segLen;
|
|
6787
|
-
const offset = labelOffset2(
|
|
6914
|
+
const offset = labelOffset2(
|
|
6915
|
+
{ start: prev, end: curr, length: segLen },
|
|
6916
|
+
baseOffset
|
|
6917
|
+
);
|
|
6788
6918
|
return {
|
|
6789
6919
|
x: prev.x + (curr.x - prev.x) * t + offset.x,
|
|
6790
6920
|
y: prev.y + (curr.y - prev.y) * t + offset.y
|