@pixerate/editor 0.53.0 → 0.54.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agent/index.cjs +14 -6
- package/dist/agent/index.cjs.map +1 -1
- package/dist/agent/index.d.cts +4 -3
- package/dist/agent/index.d.ts +4 -3
- package/dist/agent/index.js +12 -4
- package/dist/agent/index.js.map +1 -1
- package/dist/animation/index.cjs +15 -1
- package/dist/animation/index.cjs.map +1 -1
- package/dist/animation/index.d.cts +3 -226
- package/dist/animation/index.d.ts +3 -226
- package/dist/animation/index.js +14 -0
- package/dist/bridge/cli.cjs +36 -0
- package/dist/bridge/cli.cjs.map +1 -0
- package/dist/bridge/cli.d.cts +1 -0
- package/dist/bridge/cli.d.ts +1 -0
- package/dist/bridge/cli.js +36 -0
- package/dist/bridge/cli.js.map +1 -0
- package/dist/bridge/index.cjs +16 -0
- package/dist/bridge/index.cjs.map +1 -0
- package/dist/bridge/index.d.cts +65 -0
- package/dist/bridge/index.d.ts +65 -0
- package/dist/bridge/index.js +16 -0
- package/dist/bridge/index.js.map +1 -0
- package/dist/bridge-client-C5OziCRK.d.cts +148 -0
- package/dist/bridge-client-C5dRjrz5.d.ts +148 -0
- package/dist/canvas/index.cjs +1308 -528
- package/dist/canvas/index.cjs.map +1 -1
- package/dist/canvas/index.d.cts +309 -5
- package/dist/canvas/index.d.ts +309 -5
- package/dist/canvas/index.js +1295 -515
- package/dist/canvas/index.js.map +1 -1
- package/dist/chart/index.cjs +34 -76
- package/dist/chart/index.cjs.map +1 -1
- package/dist/chart/index.d.cts +9 -38
- package/dist/chart/index.d.ts +9 -38
- package/dist/chart/index.js +23 -65
- package/dist/chart/index.js.map +1 -1
- package/dist/chunk-AWKPSOSX.js +401 -0
- package/dist/chunk-AWKPSOSX.js.map +1 -0
- package/dist/chunk-B6DSIEXA.js +96 -0
- package/dist/chunk-B6DSIEXA.js.map +1 -0
- package/dist/chunk-EGFUVXKK.cjs +96 -0
- package/dist/chunk-EGFUVXKK.cjs.map +1 -0
- package/dist/{chunk-AMWXSYCI.js → chunk-GPWNYQ7R.js} +2 -370
- package/dist/chunk-GPWNYQ7R.js.map +1 -0
- package/dist/chunk-H5K77C7Y.cjs +3848 -0
- package/dist/chunk-H5K77C7Y.cjs.map +1 -0
- package/dist/chunk-K73CKYUM.cjs +458 -0
- package/dist/chunk-K73CKYUM.cjs.map +1 -0
- package/dist/chunk-NV22EMOZ.cjs +401 -0
- package/dist/chunk-NV22EMOZ.cjs.map +1 -0
- package/dist/chunk-PTMIGXZ2.js +467 -0
- package/dist/chunk-PTMIGXZ2.js.map +1 -0
- package/dist/chunk-QIWFEEWG.cjs +467 -0
- package/dist/chunk-QIWFEEWG.cjs.map +1 -0
- package/dist/chunk-WWJNC7SX.js +3848 -0
- package/dist/chunk-WWJNC7SX.js.map +1 -0
- package/dist/commands/index.d.cts +1 -1
- package/dist/commands/index.d.ts +1 -1
- package/dist/diagram/index.cjs +1146 -0
- package/dist/diagram/index.cjs.map +1 -0
- package/dist/diagram/index.d.cts +787 -0
- package/dist/diagram/index.d.ts +787 -0
- package/dist/diagram/index.js +1146 -0
- package/dist/diagram/index.js.map +1 -0
- package/dist/{easing-DTmX99QG.d.cts → easing-CNGk-W6d.d.cts} +1 -1
- package/dist/{easing-DTmX99QG.d.ts → easing-CNGk-W6d.d.ts} +1 -1
- package/dist/generation/index.d.cts +2 -2
- package/dist/generation/index.d.ts +2 -2
- package/dist/image-editor/index.d.cts +1 -1
- package/dist/image-editor/index.d.ts +1 -1
- package/dist/parameters/index.d.cts +1 -1
- package/dist/parameters/index.d.ts +1 -1
- package/dist/player-DSMjdgQ9.d.cts +225 -0
- package/dist/player-DdfVrKWq.d.ts +225 -0
- package/dist/presence-Cb6WhcrQ.d.cts +77 -0
- package/dist/presence-Cb6WhcrQ.d.ts +77 -0
- package/dist/{registry-CSlH4iUn.d.ts → registry-7AZFuand.d.ts} +1 -1
- package/dist/{registry-B4l-lYts.d.cts → registry-DIpIaCkH.d.cts} +1 -1
- package/dist/tools/index.cjs +10 -2
- package/dist/tools/index.cjs.map +1 -1
- package/dist/tools/index.d.cts +3 -74
- package/dist/tools/index.d.ts +3 -74
- package/dist/tools/index.js +12 -4
- package/dist/types-BULrFyuQ.d.cts +316 -0
- package/dist/types-BULrFyuQ.d.ts +316 -0
- package/dist/vector/index.d.cts +1 -1
- package/dist/vector/index.d.ts +1 -1
- package/package.json +14 -1
- package/dist/chunk-AMWXSYCI.js.map +0 -1
- package/dist/chunk-XFYUFVAX.cjs +0 -826
- package/dist/chunk-XFYUFVAX.cjs.map +0 -1
package/dist/canvas/index.js
CHANGED
|
@@ -88,6 +88,9 @@ import {
|
|
|
88
88
|
windingNumber,
|
|
89
89
|
xorPolygons
|
|
90
90
|
} from "../chunk-TO22LX34.js";
|
|
91
|
+
import {
|
|
92
|
+
parseMermaid
|
|
93
|
+
} from "../chunk-WWJNC7SX.js";
|
|
91
94
|
import {
|
|
92
95
|
DEFAULT_NODE_HEIGHT,
|
|
93
96
|
DEFAULT_NODE_WIDTH,
|
|
@@ -407,7 +410,7 @@ function calculateDirectionalDisplacement(params) {
|
|
|
407
410
|
}
|
|
408
411
|
if (spreadSiblingLanes && (direction === "right" || direction === "left")) {
|
|
409
412
|
for (const [nodeId, pos] of displacedMap.entries()) {
|
|
410
|
-
const node = existingNodes.find((
|
|
413
|
+
const node = existingNodes.find((n2) => n2.id === nodeId);
|
|
411
414
|
if (node && Math.abs(node.position.y - originNode.position.y) < siblingTolerance) {
|
|
412
415
|
const isAbove = node.position.y < originNode.position.y;
|
|
413
416
|
displacedMap.set(nodeId, {
|
|
@@ -441,12 +444,12 @@ function calculateDagreReflowDisplacement(params) {
|
|
|
441
444
|
defaultNodeWidth = 200,
|
|
442
445
|
defaultNodeHeight = 60
|
|
443
446
|
} = options;
|
|
444
|
-
const anchorNode = currentNodes.find((
|
|
447
|
+
const anchorNode = currentNodes.find((n2) => n2.id === anchorNodeId);
|
|
445
448
|
if (!anchorNode) return /* @__PURE__ */ new Map();
|
|
446
449
|
const g = new dagre.graphlib.Graph();
|
|
447
450
|
g.setDefaultEdgeLabel(() => ({}));
|
|
448
451
|
g.setGraph({ rankdir: direction, ranksep, nodesep });
|
|
449
|
-
const nodeIds = new Set(futureNodes.map((
|
|
452
|
+
const nodeIds = new Set(futureNodes.map((n2) => n2.id));
|
|
450
453
|
futureNodes.forEach((node) => {
|
|
451
454
|
const nodeWidth = node.measured?.width ?? node.width ?? defaultNodeWidth;
|
|
452
455
|
const nodeHeight = node.measured?.height ?? node.height ?? defaultNodeHeight;
|
|
@@ -575,15 +578,15 @@ function remapPastedNodes(nodes, edges = [], offset = { x: 30, y: 30 }, idGenera
|
|
|
575
578
|
}
|
|
576
579
|
function repositionNodesTo(nodes, targetOrigin) {
|
|
577
580
|
if (nodes.length === 0) return [];
|
|
578
|
-
const minX = Math.min(...nodes.map((
|
|
579
|
-
const minY = Math.min(...nodes.map((
|
|
581
|
+
const minX = Math.min(...nodes.map((n2) => n2.position.x));
|
|
582
|
+
const minY = Math.min(...nodes.map((n2) => n2.position.y));
|
|
580
583
|
const deltaX = targetOrigin.x - minX;
|
|
581
584
|
const deltaY = targetOrigin.y - minY;
|
|
582
|
-
return nodes.map((
|
|
583
|
-
...
|
|
585
|
+
return nodes.map((n2) => ({
|
|
586
|
+
...n2,
|
|
584
587
|
position: {
|
|
585
|
-
x:
|
|
586
|
-
y:
|
|
588
|
+
x: n2.position.x + deltaX,
|
|
589
|
+
y: n2.position.y + deltaY
|
|
587
590
|
}
|
|
588
591
|
}));
|
|
589
592
|
}
|
|
@@ -626,7 +629,7 @@ function mix(a, b, t) {
|
|
|
626
629
|
}
|
|
627
630
|
function blendLayout(from, to, t) {
|
|
628
631
|
if (t >= 1) return to;
|
|
629
|
-
const fromMap = new Map(from.map((
|
|
632
|
+
const fromMap = new Map(from.map((n2) => [n2.id, n2]));
|
|
630
633
|
return to.map((target) => {
|
|
631
634
|
const origin = fromMap.get(target.id);
|
|
632
635
|
if (!origin) return target;
|
|
@@ -854,7 +857,7 @@ function getAbsolutePosition(node, lookup) {
|
|
|
854
857
|
return { x, y };
|
|
855
858
|
}
|
|
856
859
|
function createNodeLookup(nodes) {
|
|
857
|
-
return new Map(nodes.map((
|
|
860
|
+
return new Map(nodes.map((n2) => [n2.id, n2]));
|
|
858
861
|
}
|
|
859
862
|
function getNodeRect(node, lookup, options) {
|
|
860
863
|
const { x, y } = node.parentId && lookup ? getAbsolutePosition(node, lookup) : node.position;
|
|
@@ -897,7 +900,7 @@ function unlockNodes(nodes, ids) {
|
|
|
897
900
|
}
|
|
898
901
|
function toggleLockNodes(nodes, ids) {
|
|
899
902
|
const idSet = new Set(ids);
|
|
900
|
-
const anyUnlocked = nodes.some((
|
|
903
|
+
const anyUnlocked = nodes.some((n2) => idSet.has(n2.id) && !isLocked(n2));
|
|
901
904
|
return anyUnlocked ? lockNodes(nodes, idSet) : unlockNodes(nodes, idSet);
|
|
902
905
|
}
|
|
903
906
|
function collect(nodes, ids, options) {
|
|
@@ -934,27 +937,27 @@ function alignNodes(nodes, ids, edge, options = {}) {
|
|
|
934
937
|
if (items.length === 0 || !fixed && items.length < 2) return [];
|
|
935
938
|
const bounds = fixed ?? boundsOf(items.map((i) => i.rect));
|
|
936
939
|
const targets = /* @__PURE__ */ new Map();
|
|
937
|
-
for (const { node, rect, locked } of items) {
|
|
940
|
+
for (const { node, rect: rect2, locked } of items) {
|
|
938
941
|
if (locked) continue;
|
|
939
|
-
let { x, y } =
|
|
942
|
+
let { x, y } = rect2;
|
|
940
943
|
switch (edge) {
|
|
941
944
|
case "left":
|
|
942
945
|
x = bounds.x;
|
|
943
946
|
break;
|
|
944
947
|
case "center":
|
|
945
|
-
x = bounds.x + bounds.width / 2 -
|
|
948
|
+
x = bounds.x + bounds.width / 2 - rect2.width / 2;
|
|
946
949
|
break;
|
|
947
950
|
case "right":
|
|
948
|
-
x = bounds.x + bounds.width -
|
|
951
|
+
x = bounds.x + bounds.width - rect2.width;
|
|
949
952
|
break;
|
|
950
953
|
case "top":
|
|
951
954
|
y = bounds.y;
|
|
952
955
|
break;
|
|
953
956
|
case "middle":
|
|
954
|
-
y = bounds.y + bounds.height / 2 -
|
|
957
|
+
y = bounds.y + bounds.height / 2 - rect2.height / 2;
|
|
955
958
|
break;
|
|
956
959
|
case "bottom":
|
|
957
|
-
y = bounds.y + bounds.height -
|
|
960
|
+
y = bounds.y + bounds.height - rect2.height;
|
|
958
961
|
break;
|
|
959
962
|
}
|
|
960
963
|
targets.set(node.id, { x, y });
|
|
@@ -969,7 +972,7 @@ function distributeAxis(items, horizontal, mode, gapOverride, targets) {
|
|
|
969
972
|
);
|
|
970
973
|
const first = sorted[0].rect;
|
|
971
974
|
const last = sorted[sorted.length - 1].rect;
|
|
972
|
-
const
|
|
975
|
+
const n2 = sorted.length;
|
|
973
976
|
const set = (item, value) => {
|
|
974
977
|
if (item.locked) return;
|
|
975
978
|
const current = targets.get(item.node.id) ?? { x: item.rect.x, y: item.rect.y };
|
|
@@ -978,13 +981,13 @@ function distributeAxis(items, horizontal, mode, gapOverride, targets) {
|
|
|
978
981
|
if (mode === "centres") {
|
|
979
982
|
const c0 = start(first) + size(first) / 2;
|
|
980
983
|
const c1 = start(last) + size(last) / 2;
|
|
981
|
-
const step = (c1 - c0) / (
|
|
984
|
+
const step = (c1 - c0) / (n2 - 1);
|
|
982
985
|
sorted.forEach((item, i) => set(item, c0 + step * i - size(item.rect) / 2));
|
|
983
986
|
return;
|
|
984
987
|
}
|
|
985
988
|
const span = start(last) + size(last) - start(first);
|
|
986
989
|
const total = sorted.reduce((sum, item) => sum + size(item.rect), 0);
|
|
987
|
-
const gap = gapOverride ?? (span - total) / (
|
|
990
|
+
const gap = gapOverride ?? (span - total) / (n2 - 1);
|
|
988
991
|
let cursor = start(first);
|
|
989
992
|
for (const item of sorted) {
|
|
990
993
|
set(item, cursor);
|
|
@@ -1016,16 +1019,16 @@ function matchSize(nodes, ids, dimension, options = {}) {
|
|
|
1016
1019
|
const width = dimension !== "height" ? pick("width") : void 0;
|
|
1017
1020
|
const height = dimension !== "width" ? pick("height") : void 0;
|
|
1018
1021
|
const updates = [];
|
|
1019
|
-
for (const { node, rect, locked } of items) {
|
|
1022
|
+
for (const { node, rect: rect2, locked } of items) {
|
|
1020
1023
|
if (locked) continue;
|
|
1021
1024
|
const update = { id: node.id };
|
|
1022
|
-
if (width !== void 0 && width !==
|
|
1023
|
-
if (height !== void 0 && height !==
|
|
1025
|
+
if (width !== void 0 && width !== rect2.width) update.width = width;
|
|
1026
|
+
if (height !== void 0 && height !== rect2.height) update.height = height;
|
|
1024
1027
|
if (update.width === void 0 && update.height === void 0) continue;
|
|
1025
1028
|
if (options.keepCentre) {
|
|
1026
1029
|
update.position = {
|
|
1027
|
-
x: node.position.x - ((update.width ??
|
|
1028
|
-
y: node.position.y - ((update.height ??
|
|
1030
|
+
x: node.position.x - ((update.width ?? rect2.width) - rect2.width) / 2,
|
|
1031
|
+
y: node.position.y - ((update.height ?? rect2.height) - rect2.height) / 2
|
|
1029
1032
|
};
|
|
1030
1033
|
}
|
|
1031
1034
|
updates.push(update);
|
|
@@ -1046,18 +1049,18 @@ function reorderNodes(nodes, ids, operation, options = {}) {
|
|
|
1046
1049
|
}
|
|
1047
1050
|
const updates = [];
|
|
1048
1051
|
for (const siblings of groups.values()) {
|
|
1049
|
-
if (!siblings.some((
|
|
1052
|
+
if (!siblings.some((n2) => targetIds.has(n2.id))) continue;
|
|
1050
1053
|
const order = siblings.map((node, index) => ({ node, index, z: typeof node.zIndex === "number" ? node.zIndex : 0 })).sort((a, b) => a.z - b.z || a.index - b.index).map((entry) => entry.node);
|
|
1051
|
-
const isTarget = (
|
|
1054
|
+
const isTarget = (n2) => targetIds.has(n2.id);
|
|
1052
1055
|
let next;
|
|
1053
1056
|
if (operation === "bringToFront") {
|
|
1054
|
-
next = [...order.filter((
|
|
1057
|
+
next = [...order.filter((n2) => !isTarget(n2)), ...order.filter(isTarget)];
|
|
1055
1058
|
} else if (operation === "sendToBack") {
|
|
1056
|
-
next = [...order.filter(isTarget), ...order.filter((
|
|
1059
|
+
next = [...order.filter(isTarget), ...order.filter((n2) => !isTarget(n2))];
|
|
1057
1060
|
} else {
|
|
1058
1061
|
next = [...order];
|
|
1059
1062
|
const forward = operation === "bringForward";
|
|
1060
|
-
const rects = new Map(next.map((
|
|
1063
|
+
const rects = new Map(next.map((n2) => [n2.id, getNodeRect(n2, lookup, options)]));
|
|
1061
1064
|
const intersects = (a, b) => a.x < b.x + b.width && a.x + a.width > b.x && a.y < b.y + b.height && a.y + a.height > b.y;
|
|
1062
1065
|
const indices = next.map((_, i) => i);
|
|
1063
1066
|
if (forward) indices.reverse();
|
|
@@ -1165,11 +1168,11 @@ function createGuideIndex(rects) {
|
|
|
1165
1168
|
const centreX = [];
|
|
1166
1169
|
const edgeY = [];
|
|
1167
1170
|
const centreY = [];
|
|
1168
|
-
for (const
|
|
1169
|
-
edgeX.push({ value:
|
|
1170
|
-
centreX.push({ value:
|
|
1171
|
-
edgeY.push({ value:
|
|
1172
|
-
centreY.push({ value:
|
|
1171
|
+
for (const rect2 of rects) {
|
|
1172
|
+
edgeX.push({ value: rect2.x, rect: rect2 }, { value: rect2.x + rect2.width, rect: rect2 });
|
|
1173
|
+
centreX.push({ value: rect2.x + rect2.width / 2, rect: rect2 });
|
|
1174
|
+
edgeY.push({ value: rect2.y, rect: rect2 }, { value: rect2.y + rect2.height, rect: rect2 });
|
|
1175
|
+
centreY.push({ value: rect2.y + rect2.height / 2, rect: rect2 });
|
|
1173
1176
|
}
|
|
1174
1177
|
return {
|
|
1175
1178
|
rects,
|
|
@@ -1316,12 +1319,12 @@ function computeSnapGuides(moving, targets, options = {}) {
|
|
|
1316
1319
|
if (useCentres) {
|
|
1317
1320
|
lines.push({ value: start + size / 2, kind: "centre", axis: horizontal ? index.centreX : index.centreY });
|
|
1318
1321
|
}
|
|
1319
|
-
for (const
|
|
1320
|
-
const aligned = matches(
|
|
1322
|
+
for (const line3 of lines) {
|
|
1323
|
+
const aligned = matches(line3.axis, line3.value, eps);
|
|
1321
1324
|
if (aligned.length === 0) continue;
|
|
1322
1325
|
const span = boundsOf([snapped, ...aligned]);
|
|
1323
1326
|
guides.push(
|
|
1324
|
-
horizontal ? { orientation: "vertical", kind:
|
|
1327
|
+
horizontal ? { orientation: "vertical", kind: line3.kind, x1: line3.value, y1: span.y, x2: line3.value, y2: span.y + span.height } : { orientation: "horizontal", kind: line3.kind, x1: span.x, y1: line3.value, x2: span.x + span.width, y2: line3.value }
|
|
1325
1328
|
);
|
|
1326
1329
|
}
|
|
1327
1330
|
};
|
|
@@ -1374,7 +1377,7 @@ function createNodeGuideIndex(nodes, draggingIds, options = {}) {
|
|
|
1374
1377
|
function snapNodeDrag(nodes, draggingIds, options = {}) {
|
|
1375
1378
|
const ids = new Set(draggingIds);
|
|
1376
1379
|
const lookup = createNodeLookup(nodes);
|
|
1377
|
-
const dragged = [...ids].map((id) => lookup.get(id)).filter((
|
|
1380
|
+
const dragged = [...ids].map((id) => lookup.get(id)).filter((n2) => !!n2);
|
|
1378
1381
|
const empty = {
|
|
1379
1382
|
position: { x: 0, y: 0 },
|
|
1380
1383
|
offset: { x: 0, y: 0 },
|
|
@@ -1384,7 +1387,7 @@ function snapNodeDrag(nodes, draggingIds, options = {}) {
|
|
|
1384
1387
|
updates: []
|
|
1385
1388
|
};
|
|
1386
1389
|
if (dragged.length === 0) return empty;
|
|
1387
|
-
const bounds = boundsOf(dragged.map((
|
|
1390
|
+
const bounds = boundsOf(dragged.map((n2) => getNodeRect(n2, lookup, options)));
|
|
1388
1391
|
const index = options.index ?? createNodeGuideIndex(nodes, ids, options);
|
|
1389
1392
|
const result = computeSnapGuides(bounds, index, options);
|
|
1390
1393
|
const { x: dx, y: dy } = result.offset;
|
|
@@ -1438,16 +1441,16 @@ function oppositePosition(position) {
|
|
|
1438
1441
|
return "left";
|
|
1439
1442
|
}
|
|
1440
1443
|
}
|
|
1441
|
-
function handlePoint(
|
|
1444
|
+
function handlePoint(rect2, position) {
|
|
1442
1445
|
switch (position) {
|
|
1443
1446
|
case "top":
|
|
1444
|
-
return { x:
|
|
1447
|
+
return { x: rect2.x + rect2.width / 2, y: rect2.y };
|
|
1445
1448
|
case "bottom":
|
|
1446
|
-
return { x:
|
|
1449
|
+
return { x: rect2.x + rect2.width / 2, y: rect2.y + rect2.height };
|
|
1447
1450
|
case "left":
|
|
1448
|
-
return { x:
|
|
1451
|
+
return { x: rect2.x, y: rect2.y + rect2.height / 2 };
|
|
1449
1452
|
default:
|
|
1450
|
-
return { x:
|
|
1453
|
+
return { x: rect2.x + rect2.width, y: rect2.y + rect2.height / 2 };
|
|
1451
1454
|
}
|
|
1452
1455
|
}
|
|
1453
1456
|
function findConnectorSnap(pointer, targets, options = {}) {
|
|
@@ -1458,14 +1461,14 @@ function findConnectorSnap(pointer, targets, options = {}) {
|
|
|
1458
1461
|
let best = null;
|
|
1459
1462
|
for (const target of targets) {
|
|
1460
1463
|
if (exclude.has(target.id)) continue;
|
|
1461
|
-
const { rect } = target;
|
|
1462
|
-
if (pointer.x <
|
|
1464
|
+
const { rect: rect2 } = target;
|
|
1465
|
+
if (pointer.x < rect2.x - radius || pointer.x > rect2.x + rect2.width + radius || pointer.y < rect2.y - radius || pointer.y > rect2.y + rect2.height + radius) {
|
|
1463
1466
|
continue;
|
|
1464
1467
|
}
|
|
1465
|
-
const inside2 = pointer.x >=
|
|
1468
|
+
const inside2 = pointer.x >= rect2.x && pointer.x <= rect2.x + rect2.width && pointer.y >= rect2.y && pointer.y <= rect2.y + rect2.height;
|
|
1466
1469
|
for (const position of target.positions ?? all) {
|
|
1467
|
-
const point = options.mode === "edge" ? closestPointOnSide(
|
|
1468
|
-
const sidePoint = closestPointOnSide(
|
|
1470
|
+
const point = options.mode === "edge" ? closestPointOnSide(rect2, position, pointer) : handlePoint(rect2, position);
|
|
1471
|
+
const sidePoint = closestPointOnSide(rect2, position, pointer);
|
|
1469
1472
|
const rank = Math.hypot(pointer.x - sidePoint.x, pointer.y - sidePoint.y);
|
|
1470
1473
|
const distance = Math.hypot(pointer.x - point.x, pointer.y - point.y);
|
|
1471
1474
|
if (!inside2 && rank > radius) continue;
|
|
@@ -1479,18 +1482,18 @@ function findConnectorSnap(pointer, targets, options = {}) {
|
|
|
1479
1482
|
const { inside: _inside, rank: _rank, ...snap } = best;
|
|
1480
1483
|
return snap;
|
|
1481
1484
|
}
|
|
1482
|
-
function closestPointOnSide(
|
|
1483
|
-
const clampX = Math.min(
|
|
1484
|
-
const clampY = Math.min(
|
|
1485
|
+
function closestPointOnSide(rect2, position, p) {
|
|
1486
|
+
const clampX = Math.min(rect2.x + rect2.width, Math.max(rect2.x, p.x));
|
|
1487
|
+
const clampY = Math.min(rect2.y + rect2.height, Math.max(rect2.y, p.y));
|
|
1485
1488
|
switch (position) {
|
|
1486
1489
|
case "top":
|
|
1487
|
-
return { x: clampX, y:
|
|
1490
|
+
return { x: clampX, y: rect2.y };
|
|
1488
1491
|
case "bottom":
|
|
1489
|
-
return { x: clampX, y:
|
|
1492
|
+
return { x: clampX, y: rect2.y + rect2.height };
|
|
1490
1493
|
case "left":
|
|
1491
|
-
return { x:
|
|
1494
|
+
return { x: rect2.x, y: clampY };
|
|
1492
1495
|
default:
|
|
1493
|
-
return { x:
|
|
1496
|
+
return { x: rect2.x + rect2.width, y: clampY };
|
|
1494
1497
|
}
|
|
1495
1498
|
}
|
|
1496
1499
|
function nearestHandlePositions(source, target) {
|
|
@@ -1595,9 +1598,9 @@ var CanvasScenesStore = class {
|
|
|
1595
1598
|
/** First unused "Scene N" name. */
|
|
1596
1599
|
nextDefaultName() {
|
|
1597
1600
|
const names = new Set(this.scenes.map((s) => s.name));
|
|
1598
|
-
let
|
|
1599
|
-
while (names.has(`Scene ${
|
|
1600
|
-
return `Scene ${
|
|
1601
|
+
let n2 = this.scenes.length + 1;
|
|
1602
|
+
while (names.has(`Scene ${n2}`)) n2 += 1;
|
|
1603
|
+
return `Scene ${n2}`;
|
|
1601
1604
|
}
|
|
1602
1605
|
/**
|
|
1603
1606
|
* Adds a scene (appended, or inserted at `index`) and makes it current.
|
|
@@ -1716,20 +1719,20 @@ var CanvasScenesStore = class {
|
|
|
1716
1719
|
function createCanvasScenesStore(options) {
|
|
1717
1720
|
return new CanvasScenesStore(options);
|
|
1718
1721
|
}
|
|
1719
|
-
function fitViewportToRect(
|
|
1722
|
+
function fitViewportToRect(rect2, size, options = {}) {
|
|
1720
1723
|
const { padding = 0.1, minZoom = 0.1, maxZoom = 2 } = options;
|
|
1721
|
-
const paddedWidth = Math.max(
|
|
1722
|
-
const paddedHeight = Math.max(
|
|
1724
|
+
const paddedWidth = Math.max(rect2.width * (1 + padding * 2), 1);
|
|
1725
|
+
const paddedHeight = Math.max(rect2.height * (1 + padding * 2), 1);
|
|
1723
1726
|
const raw = Math.min(size.width / paddedWidth, size.height / paddedHeight);
|
|
1724
1727
|
const zoom = Math.min(maxZoom, Math.max(minZoom, raw));
|
|
1725
|
-
const cx =
|
|
1726
|
-
const cy =
|
|
1728
|
+
const cx = rect2.x + rect2.width / 2;
|
|
1729
|
+
const cy = rect2.y + rect2.height / 2;
|
|
1727
1730
|
return { x: size.width / 2 - cx * zoom, y: size.height / 2 - cy * zoom, zoom };
|
|
1728
1731
|
}
|
|
1729
1732
|
function fitViewportToNodes(nodes, size, ids, options = {}) {
|
|
1730
1733
|
const lookup = createNodeLookup(nodes);
|
|
1731
1734
|
const wanted = ids ? new Set(ids) : null;
|
|
1732
|
-
const rects = nodes.filter((
|
|
1735
|
+
const rects = nodes.filter((n2) => wanted ? wanted.has(n2.id) : true).map((n2) => getNodeRect(n2, lookup, options));
|
|
1733
1736
|
const bounds = boundsOf(rects);
|
|
1734
1737
|
return bounds ? fitViewportToRect(bounds, size, options) : null;
|
|
1735
1738
|
}
|
|
@@ -1806,10 +1809,10 @@ function stackOrder(nodes, ids) {
|
|
|
1806
1809
|
}
|
|
1807
1810
|
function canCombineShapeNodes(nodes, ids) {
|
|
1808
1811
|
const idSet = new Set(ids);
|
|
1809
|
-
const shapes = nodes.filter((
|
|
1810
|
-
if (shapes.some((
|
|
1812
|
+
const shapes = nodes.filter((n2) => idSet.has(n2.id) && isShapeNode(n2));
|
|
1813
|
+
if (shapes.some((n2) => isLocked(n2))) return { ok: false, reason: "locked" };
|
|
1811
1814
|
if (shapes.length < 2) return { ok: false, reason: "too-few" };
|
|
1812
|
-
return { ok: true, shapeIds: shapes.map((
|
|
1815
|
+
return { ok: true, shapeIds: shapes.map((n2) => n2.id) };
|
|
1813
1816
|
}
|
|
1814
1817
|
function combineShapeNodes(nodes, ids, operation, options = {}) {
|
|
1815
1818
|
const idList = [...ids];
|
|
@@ -1818,7 +1821,7 @@ function combineShapeNodes(nodes, ids, operation, options = {}) {
|
|
|
1818
1821
|
const lookup = createNodeLookup(nodes);
|
|
1819
1822
|
const shapeIds = new Set(check.shapeIds);
|
|
1820
1823
|
const ordered = stackOrder(nodes, shapeIds);
|
|
1821
|
-
const parentIds = new Set(ordered.map((
|
|
1824
|
+
const parentIds = new Set(ordered.map((n2) => n2.parentId ?? ""));
|
|
1822
1825
|
const sharedParent = parentIds.size === 1 ? ordered[0].parentId : void 0;
|
|
1823
1826
|
const parentOrigin = sharedParent && lookup.get(sharedParent) ? getAbsolutePosition(lookup.get(sharedParent), lookup) : { x: 0, y: 0 };
|
|
1824
1827
|
const pickSource = () => {
|
|
@@ -1887,7 +1890,7 @@ function combineShapeNodes(nodes, ids, operation, options = {}) {
|
|
|
1887
1890
|
const done2 = {
|
|
1888
1891
|
ok: true,
|
|
1889
1892
|
operation,
|
|
1890
|
-
removeIds: ordered.map((
|
|
1893
|
+
removeIds: ordered.map((n2) => n2.id),
|
|
1891
1894
|
nodes: created,
|
|
1892
1895
|
engine: report.engine
|
|
1893
1896
|
};
|
|
@@ -1949,8 +1952,8 @@ function roundSize(value) {
|
|
|
1949
1952
|
}
|
|
1950
1953
|
function applyShapeCombination(nodes, change, options = {}) {
|
|
1951
1954
|
const remove = new Set(change.removeIds);
|
|
1952
|
-
const insertAt = nodes.findIndex((
|
|
1953
|
-
const deselect = options.deselect !== false && change.nodes.some((
|
|
1955
|
+
const insertAt = nodes.findIndex((n2) => remove.has(n2.id));
|
|
1956
|
+
const deselect = options.deselect !== false && change.nodes.some((n2) => n2.selected);
|
|
1954
1957
|
const out = [];
|
|
1955
1958
|
nodes.forEach((node, index) => {
|
|
1956
1959
|
if (index === insertAt) out.push(...change.nodes);
|
|
@@ -1961,11 +1964,11 @@ function applyShapeCombination(nodes, change, options = {}) {
|
|
|
1961
1964
|
return out;
|
|
1962
1965
|
}
|
|
1963
1966
|
function revertShapeCombination(nodes, change, previous) {
|
|
1964
|
-
const created = new Set(change.nodes.map((
|
|
1967
|
+
const created = new Set(change.nodes.map((n2) => n2.id));
|
|
1965
1968
|
const removed = new Set(change.removeIds);
|
|
1966
|
-
const out = nodes.filter((
|
|
1969
|
+
const out = nodes.filter((n2) => !created.has(n2.id));
|
|
1967
1970
|
previous.forEach((node, index) => {
|
|
1968
|
-
if (!removed.has(node.id) || out.some((
|
|
1971
|
+
if (!removed.has(node.id) || out.some((n2) => n2.id === node.id)) return;
|
|
1969
1972
|
out.splice(Math.min(index, out.length), 0, node);
|
|
1970
1973
|
});
|
|
1971
1974
|
return out;
|
|
@@ -1987,21 +1990,21 @@ function hasVisibleFill(shape) {
|
|
|
1987
1990
|
}
|
|
1988
1991
|
function shapeTargets(nodes, ids) {
|
|
1989
1992
|
const idSet = new Set(ids);
|
|
1990
|
-
return nodes.filter((
|
|
1993
|
+
return nodes.filter((n2) => idSet.has(n2.id) && isShapeNode(n2));
|
|
1991
1994
|
}
|
|
1992
1995
|
function canOffsetShapeNodes(nodes, ids) {
|
|
1993
1996
|
const shapes = shapeTargets(nodes, ids);
|
|
1994
|
-
if (shapes.some((
|
|
1997
|
+
if (shapes.some((n2) => isLocked(n2))) return { ok: false, reason: "locked" };
|
|
1995
1998
|
if (shapes.length === 0) return { ok: false, reason: "no-shapes" };
|
|
1996
|
-
return { ok: true, shapeIds: shapes.map((
|
|
1999
|
+
return { ok: true, shapeIds: shapes.map((n2) => n2.id) };
|
|
1997
2000
|
}
|
|
1998
2001
|
function canOutlineShapeNodeStrokes(nodes, ids) {
|
|
1999
2002
|
const shapes = shapeTargets(nodes, ids);
|
|
2000
|
-
if (shapes.some((
|
|
2003
|
+
if (shapes.some((n2) => isLocked(n2))) return { ok: false, reason: "locked" };
|
|
2001
2004
|
if (shapes.length === 0) return { ok: false, reason: "no-shapes" };
|
|
2002
|
-
const stroked = shapes.filter((
|
|
2005
|
+
const stroked = shapes.filter((n2) => hasVisibleStroke(getNodeShape(n2)));
|
|
2003
2006
|
if (stroked.length === 0) return { ok: false, reason: "no-stroke" };
|
|
2004
|
-
return { ok: true, shapeIds: stroked.map((
|
|
2007
|
+
return { ok: true, shapeIds: stroked.map((n2) => n2.id) };
|
|
2005
2008
|
}
|
|
2006
2009
|
function editPlacement(node, lookup) {
|
|
2007
2010
|
const parent = node.parentId ? lookup.get(node.parentId) : void 0;
|
|
@@ -2104,8 +2107,8 @@ function outlineShapeNodeStrokes(nodes, ids, options = {}) {
|
|
|
2104
2107
|
}
|
|
2105
2108
|
function applyShapeReplacement(nodes, change, options = {}) {
|
|
2106
2109
|
const byId = new Map(change.replacements.map((r) => [r.id, r.nodes]));
|
|
2107
|
-
const created = new Set(change.replacements.flatMap((r) => r.nodes.map((
|
|
2108
|
-
const deselect = options.deselect !== false && change.replacements.some((r) => r.nodes.some((
|
|
2110
|
+
const created = new Set(change.replacements.flatMap((r) => r.nodes.map((n2) => n2.id)));
|
|
2111
|
+
const deselect = options.deselect !== false && change.replacements.some((r) => r.nodes.some((n2) => n2.selected));
|
|
2109
2112
|
const out = [];
|
|
2110
2113
|
for (const node of nodes) {
|
|
2111
2114
|
const replacement = byId.get(node.id);
|
|
@@ -2165,7 +2168,7 @@ function matching(axis, v, eps) {
|
|
|
2165
2168
|
for (let i = 0; i < values.length; i++) if (Math.abs(values[i] - v) <= eps) out.push(rects[i]);
|
|
2166
2169
|
return out;
|
|
2167
2170
|
}
|
|
2168
|
-
function snapResize(
|
|
2171
|
+
function snapResize(rect2, handle, targets, options = {}) {
|
|
2169
2172
|
const index = Array.isArray(targets) ? createGuideIndex(targets) : targets;
|
|
2170
2173
|
const zoom = options.zoom && options.zoom > 0 ? options.zoom : 1;
|
|
2171
2174
|
const tolerance = (options.threshold ?? 6) / zoom;
|
|
@@ -2174,12 +2177,12 @@ function snapResize(rect, handle, targets, options = {}) {
|
|
|
2174
2177
|
const useCentres = options.centres !== false;
|
|
2175
2178
|
const grid = options.gridSize ?? 0;
|
|
2176
2179
|
const axes = resizeHandleAxes(handle);
|
|
2177
|
-
const unchanged = { rect: { ...
|
|
2178
|
-
if (![
|
|
2179
|
-
const x0 =
|
|
2180
|
-
const x1 =
|
|
2181
|
-
const y0 =
|
|
2182
|
-
const y1 =
|
|
2180
|
+
const unchanged = { rect: { ...rect2 }, guides: [], snappedX: false, snappedY: false, changed: false };
|
|
2181
|
+
if (![rect2.x, rect2.y, rect2.width, rect2.height].every(Number.isFinite)) return unchanged;
|
|
2182
|
+
const x0 = rect2.x;
|
|
2183
|
+
const x1 = rect2.x + rect2.width;
|
|
2184
|
+
const y0 = rect2.y;
|
|
2185
|
+
const y1 = rect2.y + rect2.height;
|
|
2183
2186
|
const bestHit = (horizontal) => {
|
|
2184
2187
|
const dir = horizontal ? axes.x : axes.y;
|
|
2185
2188
|
if (dir === 0) return null;
|
|
@@ -2219,7 +2222,7 @@ function snapResize(rect, handle, targets, options = {}) {
|
|
|
2219
2222
|
};
|
|
2220
2223
|
let hitX = bestHit(true);
|
|
2221
2224
|
let hitY = bestHit(false);
|
|
2222
|
-
const ratio =
|
|
2225
|
+
const ratio = rect2.height > 0 ? rect2.width / rect2.height : 0;
|
|
2223
2226
|
if (options.keepAspectRatio && ratio > 0 && (hitX || hitY)) {
|
|
2224
2227
|
if (axes.x !== 0 && axes.y !== 0) {
|
|
2225
2228
|
const dist = (h, horizontal) => h ? Math.abs(h.value - (horizontal ? axes.x < 0 ? x0 : x1 : axes.y < 0 ? y0 : y1)) : Infinity;
|
|
@@ -2271,7 +2274,7 @@ function snapResize(rect, handle, targets, options = {}) {
|
|
|
2271
2274
|
};
|
|
2272
2275
|
guideFor(true, hitX);
|
|
2273
2276
|
guideFor(false, hitY);
|
|
2274
|
-
const changed = out.x !==
|
|
2277
|
+
const changed = out.x !== rect2.x || out.y !== rect2.y || out.width !== rect2.width || out.height !== rect2.height;
|
|
2275
2278
|
return {
|
|
2276
2279
|
rect: out,
|
|
2277
2280
|
guides,
|
|
@@ -2280,14 +2283,14 @@ function snapResize(rect, handle, targets, options = {}) {
|
|
|
2280
2283
|
changed
|
|
2281
2284
|
};
|
|
2282
2285
|
}
|
|
2283
|
-
function snapNodeResize(nodes, id,
|
|
2286
|
+
function snapNodeResize(nodes, id, rect2, handle, options = {}) {
|
|
2284
2287
|
const lookup = createNodeLookup(nodes);
|
|
2285
2288
|
const node = lookup.get(id);
|
|
2286
2289
|
if (!node || isLocked(node)) {
|
|
2287
|
-
return { rect: { ...
|
|
2290
|
+
return { rect: { ...rect2 }, guides: [], snappedX: false, snappedY: false, changed: false, updates: [] };
|
|
2288
2291
|
}
|
|
2289
2292
|
const index = options.index ?? createNodeGuideIndex(nodes, [id], options);
|
|
2290
|
-
const result = snapResize(
|
|
2293
|
+
const result = snapResize(rect2, handle, index, options);
|
|
2291
2294
|
if (!result.changed) return { ...result, updates: [] };
|
|
2292
2295
|
const parent = node.parentId ? lookup.get(node.parentId) : void 0;
|
|
2293
2296
|
const origin = parent ? getAbsolutePosition(parent, lookup) : { x: 0, y: 0 };
|
|
@@ -2431,8 +2434,8 @@ function flowChildren(s, frame) {
|
|
|
2431
2434
|
const f = s.boxes.get(frame);
|
|
2432
2435
|
if (!f) return [];
|
|
2433
2436
|
return f.kids.filter((k) => {
|
|
2434
|
-
const
|
|
2435
|
-
return
|
|
2437
|
+
const n2 = s.boxes.get(k).node;
|
|
2438
|
+
return n2.hidden !== true && !getChildLayout(n2).absolute;
|
|
2436
2439
|
});
|
|
2437
2440
|
}
|
|
2438
2441
|
function fitHugText(s, id) {
|
|
@@ -2460,7 +2463,7 @@ function enforceLimits(s, id) {
|
|
|
2460
2463
|
if (isText(s, b)) setSize(s, id, nw, nh);
|
|
2461
2464
|
else resizeChild(s, id, nw, nh);
|
|
2462
2465
|
}
|
|
2463
|
-
function itemBaseline(s, id,
|
|
2466
|
+
function itemBaseline(s, id, depth2) {
|
|
2464
2467
|
const b = s.boxes.get(id);
|
|
2465
2468
|
if (!b) return void 0;
|
|
2466
2469
|
if (isText(s, b)) {
|
|
@@ -2468,9 +2471,9 @@ function itemBaseline(s, id, depth) {
|
|
|
2468
2471
|
return typeof v === "number" && Number.isFinite(v) ? v : void 0;
|
|
2469
2472
|
}
|
|
2470
2473
|
const layout2 = getAutoLayout(b.node);
|
|
2471
|
-
if (!layout2 || layout2.mode === "grid" ||
|
|
2474
|
+
if (!layout2 || layout2.mode === "grid" || depth2 >= 32) return void 0;
|
|
2472
2475
|
for (const k of flowChildren(s, id)) {
|
|
2473
|
-
const base = itemBaseline(s, k,
|
|
2476
|
+
const base = itemBaseline(s, k, depth2 + 1);
|
|
2474
2477
|
if (base !== void 0) return s.boxes.get(k).y + base;
|
|
2475
2478
|
}
|
|
2476
2479
|
return void 0;
|
|
@@ -2488,17 +2491,17 @@ function resizeChild(s, id, w, h) {
|
|
|
2488
2491
|
if (b.kids.length > 0) constrain(s, id, ow, oh);
|
|
2489
2492
|
if (getAutoLayout(b.node)) layout(s, id);
|
|
2490
2493
|
}
|
|
2491
|
-
function mainOffsets(align, inner, total,
|
|
2492
|
-
const gaps = gap * Math.max(
|
|
2494
|
+
function mainOffsets(align, inner, total, n2, gap) {
|
|
2495
|
+
const gaps = gap * Math.max(n2 - 1, 0);
|
|
2493
2496
|
const free = inner - total;
|
|
2494
|
-
const k = Math.max(
|
|
2497
|
+
const k = Math.max(n2, 1);
|
|
2495
2498
|
switch (align) {
|
|
2496
2499
|
case "center":
|
|
2497
2500
|
return [(free - gaps) / 2, gap];
|
|
2498
2501
|
case "end":
|
|
2499
2502
|
return [free - gaps, gap];
|
|
2500
2503
|
case "space-between":
|
|
2501
|
-
return [0,
|
|
2504
|
+
return [0, n2 > 1 ? Math.max(free / (n2 - 1), 0) : 0];
|
|
2502
2505
|
case "space-around": {
|
|
2503
2506
|
const g = Math.max(free / k, 0);
|
|
2504
2507
|
return [g / 2, g];
|
|
@@ -2616,10 +2619,10 @@ function layoutFrameInner(s, frame) {
|
|
|
2616
2619
|
} else {
|
|
2617
2620
|
lines.push(items.map((_, i) => i));
|
|
2618
2621
|
}
|
|
2619
|
-
for (const
|
|
2620
|
-
const fixed =
|
|
2621
|
-
const gaps = gap * Math.max(
|
|
2622
|
-
const fills =
|
|
2622
|
+
for (const line3 of lines) {
|
|
2623
|
+
const fixed = line3.filter((i) => !items[i].fillMain).reduce((sum, i) => sum + items[i].main, 0);
|
|
2624
|
+
const gaps = gap * Math.max(line3.length - 1, 0);
|
|
2625
|
+
const fills = line3.filter((i) => items[i].fillMain);
|
|
2623
2626
|
if (fills.length > 0) distribute(items, fills, innerMainFixed - fixed - (autoGap ? 0 : gaps));
|
|
2624
2627
|
}
|
|
2625
2628
|
for (const it of items) {
|
|
@@ -2632,11 +2635,11 @@ function layoutFrameInner(s, frame) {
|
|
|
2632
2635
|
for (const it of items) if (!it.fillCross) it.baseline = itemBaseline(s, it.id, 0);
|
|
2633
2636
|
}
|
|
2634
2637
|
const extents = [];
|
|
2635
|
-
for (const
|
|
2636
|
-
const gaps = gap * Math.max(
|
|
2637
|
-
const lineBase =
|
|
2638
|
-
for (const i of
|
|
2639
|
-
const inLine =
|
|
2638
|
+
for (const line3 of lines) {
|
|
2639
|
+
const gaps = gap * Math.max(line3.length - 1, 0);
|
|
2640
|
+
const lineBase = line3.reduce((m, i) => Math.max(m, items[i].baseline ?? 0), 0);
|
|
2641
|
+
for (const i of line3) items[i].baseOff = items[i].baseline !== void 0 ? lineBase - items[i].baseline : 0;
|
|
2642
|
+
const inLine = line3.map((i) => items[i]);
|
|
2640
2643
|
const mainUsed = inLine.reduce((sum, it) => sum + it.main, 0) + gaps;
|
|
2641
2644
|
const allFill = inLine.every((it) => it.fillCross);
|
|
2642
2645
|
const cross = inLine.filter((it) => allFill || !it.fillCross).reduce((m, it) => Math.max(m, it.baseOff + it.cross), 0);
|
|
@@ -2683,13 +2686,13 @@ function layoutFrameInner(s, frame) {
|
|
|
2683
2686
|
}
|
|
2684
2687
|
}
|
|
2685
2688
|
}
|
|
2686
|
-
lines.forEach((
|
|
2689
|
+
lines.forEach((line3, li) => {
|
|
2687
2690
|
const [used, ownCross] = extents[li];
|
|
2688
2691
|
const lineCross = single ? innerCross : ownCross;
|
|
2689
|
-
const total = used - gap * Math.max(
|
|
2690
|
-
let [pos, step] = mainOffsets(alignMain, innerMain, total,
|
|
2692
|
+
const total = used - gap * Math.max(line3.length - 1, 0);
|
|
2693
|
+
let [pos, step] = mainOffsets(alignMain, innerMain, total, line3.length, gap);
|
|
2691
2694
|
pos += horizontal ? pl : pt;
|
|
2692
|
-
for (const i of
|
|
2695
|
+
for (const i of line3) {
|
|
2693
2696
|
const it = items[i];
|
|
2694
2697
|
const crossSize = it.fillCross ? clampLayoutSize(lineCross, it.minCross, it.maxCross) : it.cross;
|
|
2695
2698
|
let off = 0;
|
|
@@ -2717,8 +2720,8 @@ function parseTrack(track) {
|
|
|
2717
2720
|
}
|
|
2718
2721
|
function trackList(spec, fallback) {
|
|
2719
2722
|
if (Array.isArray(spec)) return { count: Math.min(Math.max(spec.length, 1), MAX_TRACKS), tracks: spec.map(parseTrack) };
|
|
2720
|
-
const
|
|
2721
|
-
return { count: Math.min(Math.max(
|
|
2723
|
+
const n2 = typeof spec === "number" && Number.isFinite(spec) ? Math.floor(spec) : fallback;
|
|
2724
|
+
return { count: Math.min(Math.max(n2, 1), MAX_TRACKS), tracks: [] };
|
|
2722
2725
|
}
|
|
2723
2726
|
function trackSpec(tracks, i) {
|
|
2724
2727
|
const t = tracks[i] ?? { sizing: "fill", value: 1 };
|
|
@@ -2838,21 +2841,21 @@ function resolveTracks(tracks, content, avail) {
|
|
|
2838
2841
|
}
|
|
2839
2842
|
return out;
|
|
2840
2843
|
}
|
|
2841
|
-
function trackContent(cells, sizes, tracks,
|
|
2844
|
+
function trackContent(cells, sizes, tracks, n2, gap, columns, hug) {
|
|
2842
2845
|
const byContent = (i) => trackSpec(tracks, i).sizing !== "fixed";
|
|
2843
|
-
const content = Array.from({ length:
|
|
2846
|
+
const content = Array.from({ length: n2 }, (_, i) => {
|
|
2844
2847
|
const t = trackSpec(tracks, i);
|
|
2845
2848
|
return t.sizing === "fixed" ? t.value : 0;
|
|
2846
2849
|
});
|
|
2847
2850
|
const span = (c) => columns ? [c.column, c.columnSpan] : [c.row, c.rowSpan];
|
|
2848
2851
|
cells.forEach((c, k) => {
|
|
2849
2852
|
const [start, len] = span(c);
|
|
2850
|
-
if (len === 1 && byContent(start) && start <
|
|
2853
|
+
if (len === 1 && byContent(start) && start < n2) content[start] = Math.max(content[start], sizes[k]);
|
|
2851
2854
|
});
|
|
2852
2855
|
cells.forEach((c, k) => {
|
|
2853
2856
|
const [start, len] = span(c);
|
|
2854
2857
|
if (len < 2) return;
|
|
2855
|
-
const range = Array.from({ length: len }, (_, j) => start + j).filter((i) => i <
|
|
2858
|
+
const range = Array.from({ length: len }, (_, j) => start + j).filter((i) => i < n2);
|
|
2856
2859
|
if (!hug && range.some((i) => trackSpec(tracks, i).sizing === "fill")) return;
|
|
2857
2860
|
const have = range.reduce((sum, i) => sum + content[i], 0) + gap * (len - 1);
|
|
2858
2861
|
const grow = range.filter(byContent);
|
|
@@ -3041,9 +3044,9 @@ function postOrder(s, nodes) {
|
|
|
3041
3044
|
for (const k of s.boxes.get(id)?.kids ?? []) visit(k);
|
|
3042
3045
|
out.push(id);
|
|
3043
3046
|
};
|
|
3044
|
-
const roots = nodes.filter((
|
|
3047
|
+
const roots = nodes.filter((n2) => !n2.parentId || !s.boxes.has(n2.parentId));
|
|
3045
3048
|
for (const r of roots) visit(r.id);
|
|
3046
|
-
for (const
|
|
3049
|
+
for (const n2 of nodes) visit(n2.id);
|
|
3047
3050
|
return out;
|
|
3048
3051
|
}
|
|
3049
3052
|
function layoutAll(nodes, options = {}) {
|
|
@@ -3057,9 +3060,9 @@ function layoutUp(nodes, changedId, options = {}) {
|
|
|
3057
3060
|
function layoutUpMany(nodes, changedIds, options = {}) {
|
|
3058
3061
|
const s = new LayoutState(nodes, options);
|
|
3059
3062
|
const chains = [...new Set(changedIds)].filter((id) => s.boxes.has(id)).map((id) => [id, ...s.ancestors(id)]);
|
|
3060
|
-
const
|
|
3061
|
-
for (const chain of chains) chain.forEach((id, i) =>
|
|
3062
|
-
const order = [...
|
|
3063
|
+
const depth2 = /* @__PURE__ */ new Map();
|
|
3064
|
+
for (const chain of chains) chain.forEach((id, i) => depth2.set(id, Math.max(depth2.get(id) ?? 0, chain.length - 1 - i)));
|
|
3065
|
+
const order = [...depth2.keys()].sort((a, b) => depth2.get(b) - depth2.get(a));
|
|
3063
3066
|
for (const id of order) if (getAutoLayout(s.boxes.get(id).node)) layout(s, id);
|
|
3064
3067
|
return s.updates();
|
|
3065
3068
|
}
|
|
@@ -3072,7 +3075,7 @@ function getAutoLayoutGrid(nodes, frameId, options = {}) {
|
|
|
3072
3075
|
return gridGeometryOf(new LayoutState(nodes, options), frameId);
|
|
3073
3076
|
}
|
|
3074
3077
|
function getFlowChildren(nodes, frameId) {
|
|
3075
|
-
return nodes.filter((
|
|
3078
|
+
return nodes.filter((n2) => n2.parentId === frameId && n2.id !== frameId && n2.hidden !== true && !getChildLayout(n2).absolute).map((n2) => n2.id);
|
|
3076
3079
|
}
|
|
3077
3080
|
function getLayoutParent(nodes, id) {
|
|
3078
3081
|
const lookup = createNodeLookup(nodes);
|
|
@@ -3083,7 +3086,7 @@ function getLayoutParent(nodes, id) {
|
|
|
3083
3086
|
}
|
|
3084
3087
|
function makeSizingCoherent(nodes, id, options = {}) {
|
|
3085
3088
|
const lookup = createNodeLookup(nodes);
|
|
3086
|
-
const targets = /* @__PURE__ */ new Set([id, ...nodes.filter((
|
|
3089
|
+
const targets = /* @__PURE__ */ new Set([id, ...nodes.filter((n2) => n2.parentId === id).map((n2) => n2.id)]);
|
|
3087
3090
|
if (!lookup.has(id)) return nodes;
|
|
3088
3091
|
let changed = false;
|
|
3089
3092
|
const next = nodes.map((node) => {
|
|
@@ -3152,42 +3155,42 @@ function getAutoLayoutInsertTarget(nodes, frameId, point, options = {}) {
|
|
|
3152
3155
|
return { frameId, index, guide };
|
|
3153
3156
|
}
|
|
3154
3157
|
function moveLayoutChild(nodes, childId, index) {
|
|
3155
|
-
const child = nodes.find((
|
|
3158
|
+
const child = nodes.find((n2) => n2.id === childId);
|
|
3156
3159
|
if (!child?.parentId) return nodes;
|
|
3157
|
-
const siblings = nodes.filter((
|
|
3158
|
-
const flow = siblings.filter((
|
|
3160
|
+
const siblings = nodes.filter((n2) => n2.parentId === child.parentId && n2.id !== child.parentId);
|
|
3161
|
+
const flow = siblings.filter((n2) => n2.hidden !== true && !getChildLayout(n2).absolute && n2.id !== childId);
|
|
3159
3162
|
const clamped = Math.min(Math.max(Math.floor(Number.isFinite(index) ? index : 0), 0), flow.length);
|
|
3160
|
-
const order = siblings.filter((
|
|
3163
|
+
const order = siblings.filter((n2) => n2.id !== childId);
|
|
3161
3164
|
const anchor = flow[clamped];
|
|
3162
3165
|
const at = anchor ? order.indexOf(anchor) : flow.length > 0 ? order.indexOf(flow[flow.length - 1]) + 1 : order.length;
|
|
3163
3166
|
order.splice(at, 0, child);
|
|
3164
|
-
if (order.every((
|
|
3167
|
+
if (order.every((n2, i) => n2 === siblings[i])) return nodes;
|
|
3165
3168
|
let k = 0;
|
|
3166
3169
|
const parentId = child.parentId;
|
|
3167
|
-
const placed = nodes.map((
|
|
3170
|
+
const placed = nodes.map((n2) => n2.parentId === parentId && n2.id !== parentId ? order[k++] : n2);
|
|
3168
3171
|
return parentsFirst(placed);
|
|
3169
3172
|
}
|
|
3170
3173
|
function parentsFirst(nodes) {
|
|
3171
|
-
const ids = new Set(nodes.map((
|
|
3174
|
+
const ids = new Set(nodes.map((n2) => n2.id));
|
|
3172
3175
|
const pending = /* @__PURE__ */ new Map();
|
|
3173
3176
|
const done2 = /* @__PURE__ */ new Set();
|
|
3174
3177
|
const out = [];
|
|
3175
|
-
const emit = (
|
|
3176
|
-
out.push(
|
|
3177
|
-
done2.add(
|
|
3178
|
-
const waiting = pending.get(
|
|
3178
|
+
const emit = (n2) => {
|
|
3179
|
+
out.push(n2);
|
|
3180
|
+
done2.add(n2.id);
|
|
3181
|
+
const waiting = pending.get(n2.id);
|
|
3179
3182
|
if (waiting) {
|
|
3180
|
-
pending.delete(
|
|
3183
|
+
pending.delete(n2.id);
|
|
3181
3184
|
for (const w of waiting) emit(w);
|
|
3182
3185
|
}
|
|
3183
3186
|
};
|
|
3184
|
-
for (const
|
|
3185
|
-
if (
|
|
3186
|
-
if (!pending.has(
|
|
3187
|
-
pending.get(
|
|
3188
|
-
} else emit(
|
|
3187
|
+
for (const n2 of nodes) {
|
|
3188
|
+
if (n2.parentId && ids.has(n2.parentId) && !done2.has(n2.parentId) && n2.parentId !== n2.id) {
|
|
3189
|
+
if (!pending.has(n2.parentId)) pending.set(n2.parentId, []);
|
|
3190
|
+
pending.get(n2.parentId).push(n2);
|
|
3191
|
+
} else emit(n2);
|
|
3189
3192
|
}
|
|
3190
|
-
for (const waiting of pending.values()) for (const
|
|
3193
|
+
for (const waiting of pending.values()) for (const n2 of waiting) if (!done2.has(n2.id)) emit(n2);
|
|
3191
3194
|
return out;
|
|
3192
3195
|
}
|
|
3193
3196
|
|
|
@@ -3201,7 +3204,7 @@ function createCanvasArrangeController(options) {
|
|
|
3201
3204
|
let resizeStart = null;
|
|
3202
3205
|
let resizeIndex = null;
|
|
3203
3206
|
let lastResized = null;
|
|
3204
|
-
const selectedIds = (ids) => ids ? [...ids] : options.getSelectedIds?.() ?? options.getNodes().filter((
|
|
3207
|
+
const selectedIds = (ids) => ids ? [...ids] : options.getSelectedIds?.() ?? options.getNodes().filter((n2) => n2.selected).map((n2) => n2.id);
|
|
3205
3208
|
const setGuides = (next) => {
|
|
3206
3209
|
if (next.length === 0 && guides.length === 0) return;
|
|
3207
3210
|
guides = next;
|
|
@@ -3231,7 +3234,7 @@ function createCanvasArrangeController(options) {
|
|
|
3231
3234
|
function setLocked(name, ids, locked) {
|
|
3232
3235
|
const nodes = options.getNodes();
|
|
3233
3236
|
const set = new Set(ids);
|
|
3234
|
-
const changed = nodes.filter((
|
|
3237
|
+
const changed = nodes.filter((n2) => set.has(n2.id) && isLocked(n2) !== locked).map((n2) => n2.id);
|
|
3235
3238
|
if (changed.length === 0) return changed;
|
|
3236
3239
|
const lock = () => options.setNodes(lockNodes(options.getNodes(), changed));
|
|
3237
3240
|
const unlock = () => options.setNodes(unlockNodes(options.getNodes(), changed));
|
|
@@ -3241,29 +3244,29 @@ function createCanvasArrangeController(options) {
|
|
|
3241
3244
|
else unlock();
|
|
3242
3245
|
return changed;
|
|
3243
3246
|
}
|
|
3244
|
-
const
|
|
3247
|
+
const rect2 = () => options.rectOptions ?? {};
|
|
3245
3248
|
const controller = {
|
|
3246
3249
|
get guides() {
|
|
3247
3250
|
return guides;
|
|
3248
3251
|
},
|
|
3249
3252
|
apply,
|
|
3250
3253
|
align(edge, ids, alignOptions = {}) {
|
|
3251
|
-
return apply(`Align ${edge}`, alignNodes(options.getNodes(), selectedIds(ids), edge, { ...
|
|
3254
|
+
return apply(`Align ${edge}`, alignNodes(options.getNodes(), selectedIds(ids), edge, { ...rect2(), ...alignOptions }));
|
|
3252
3255
|
},
|
|
3253
3256
|
distribute(axis, mode = "gaps", ids, distributeOptions = {}) {
|
|
3254
3257
|
return apply(
|
|
3255
3258
|
`Distribute ${axis}`,
|
|
3256
|
-
distributeNodes(options.getNodes(), selectedIds(ids), axis, mode, { ...
|
|
3259
|
+
distributeNodes(options.getNodes(), selectedIds(ids), axis, mode, { ...rect2(), ...distributeOptions })
|
|
3257
3260
|
);
|
|
3258
3261
|
},
|
|
3259
3262
|
matchSize(dimension, ids, sizeOptions = {}) {
|
|
3260
3263
|
return apply(
|
|
3261
3264
|
"Make Same Size",
|
|
3262
|
-
matchSize(options.getNodes(), selectedIds(ids), dimension, { ...
|
|
3265
|
+
matchSize(options.getNodes(), selectedIds(ids), dimension, { ...rect2(), ...sizeOptions })
|
|
3263
3266
|
);
|
|
3264
3267
|
},
|
|
3265
3268
|
reorder(operation, ids) {
|
|
3266
|
-
return apply(operation, reorderNodes(options.getNodes(), selectedIds(ids), operation,
|
|
3269
|
+
return apply(operation, reorderNodes(options.getNodes(), selectedIds(ids), operation, rect2()));
|
|
3267
3270
|
},
|
|
3268
3271
|
bringForward: (ids) => controller.reorder("bringForward", ids),
|
|
3269
3272
|
sendBackward: (ids) => controller.reorder("sendBackward", ids),
|
|
@@ -3274,10 +3277,10 @@ function createCanvasArrangeController(options) {
|
|
|
3274
3277
|
toggleLock(ids) {
|
|
3275
3278
|
const list = selectedIds(ids);
|
|
3276
3279
|
const set = new Set(list);
|
|
3277
|
-
const anyUnlocked = options.getNodes().some((
|
|
3280
|
+
const anyUnlocked = options.getNodes().some((n2) => set.has(n2.id) && !isLocked(n2));
|
|
3278
3281
|
return anyUnlocked ? controller.lock(list) : controller.unlock(list);
|
|
3279
3282
|
},
|
|
3280
|
-
isLocked: (id) => isLocked(options.getNodes().find((
|
|
3283
|
+
isLocked: (id) => isLocked(options.getNodes().find((n2) => n2.id === id)),
|
|
3281
3284
|
/**
|
|
3282
3285
|
* Freeform shape operation (Unite / Intersect / Subtract / Exclude / Divide) on the
|
|
3283
3286
|
* shape nodes among `ids` (default: the selection). Replaces them with the result as
|
|
@@ -3286,7 +3289,7 @@ function createCanvasArrangeController(options) {
|
|
|
3286
3289
|
*/
|
|
3287
3290
|
combineShapes(operation, ids, combineOptions = {}) {
|
|
3288
3291
|
const before = options.getNodes();
|
|
3289
|
-
const result = combineShapeNodes(before, selectedIds(ids), operation, { ...
|
|
3292
|
+
const result = combineShapeNodes(before, selectedIds(ids), operation, { ...rect2(), ...combineOptions });
|
|
3290
3293
|
if (!result.ok) return result;
|
|
3291
3294
|
const name = `${operation[0].toUpperCase()}${operation.slice(1)} Shapes`;
|
|
3292
3295
|
const run = () => options.setNodes(applyShapeCombination(options.getNodes(), result));
|
|
@@ -3310,7 +3313,7 @@ function createCanvasArrangeController(options) {
|
|
|
3310
3313
|
*/
|
|
3311
3314
|
offsetShapes(distance, ids, offsetOptions = {}) {
|
|
3312
3315
|
const before = options.getNodes();
|
|
3313
|
-
const result = offsetShapeNodes(before, selectedIds(ids), distance, { ...
|
|
3316
|
+
const result = offsetShapeNodes(before, selectedIds(ids), distance, { ...rect2(), ...offsetOptions });
|
|
3314
3317
|
if (!result.ok) return result;
|
|
3315
3318
|
const run = () => options.setNodes(applyShapeReplacement(options.getNodes(), result));
|
|
3316
3319
|
const undo = () => options.setNodes(revertShapeCombination(options.getNodes(), result, before));
|
|
@@ -3327,7 +3330,7 @@ function createCanvasArrangeController(options) {
|
|
|
3327
3330
|
*/
|
|
3328
3331
|
outlineStroke(ids, outlineOptions = {}) {
|
|
3329
3332
|
const before = options.getNodes();
|
|
3330
|
-
const result = outlineShapeNodeStrokes(before, selectedIds(ids), { ...
|
|
3333
|
+
const result = outlineShapeNodeStrokes(before, selectedIds(ids), { ...rect2(), ...outlineOptions });
|
|
3331
3334
|
if (!result.ok) return result;
|
|
3332
3335
|
const run = () => options.setNodes(applyShapeReplacement(options.getNodes(), result));
|
|
3333
3336
|
const undo = () => options.setNodes(revertShapeCombination(options.getNodes(), result, before));
|
|
@@ -3393,7 +3396,7 @@ function createCanvasArrangeController(options) {
|
|
|
3393
3396
|
beginDrag(ids) {
|
|
3394
3397
|
const list = selectedIds(ids);
|
|
3395
3398
|
dragKey = list.slice().sort().join("\0");
|
|
3396
|
-
dragIndex = createNodeGuideIndex(options.getNodes(), list,
|
|
3399
|
+
dragIndex = createNodeGuideIndex(options.getNodes(), list, rect2());
|
|
3397
3400
|
},
|
|
3398
3401
|
/**
|
|
3399
3402
|
* Snaps the dragged nodes (as currently positioned in `getNodes()`) to the other
|
|
@@ -3406,7 +3409,7 @@ function createCanvasArrangeController(options) {
|
|
|
3406
3409
|
const key = list.slice().sort().join("\0");
|
|
3407
3410
|
if (!dragIndex || key !== dragKey) controller.beginDrag(list);
|
|
3408
3411
|
const result = snapNodeDrag(options.getNodes(), list, {
|
|
3409
|
-
...
|
|
3412
|
+
...rect2(),
|
|
3410
3413
|
...options.guides,
|
|
3411
3414
|
zoom: options.getZoom?.() ?? 1,
|
|
3412
3415
|
index: dragIndex
|
|
@@ -3442,9 +3445,9 @@ function createCanvasArrangeController(options) {
|
|
|
3442
3445
|
const key = ids.slice().sort().join("\0");
|
|
3443
3446
|
if (!dragIndex || key !== dragKey) controller.beginDrag(ids);
|
|
3444
3447
|
const proposed = new Map(dragging.map((c) => [c.id, c.position]));
|
|
3445
|
-
const nodes = options.getNodes().map((
|
|
3448
|
+
const nodes = options.getNodes().map((n2) => proposed.has(n2.id) ? { ...n2, position: proposed.get(n2.id) } : n2);
|
|
3446
3449
|
const result = snapNodeDrag(nodes, ids, {
|
|
3447
|
-
...
|
|
3450
|
+
...rect2(),
|
|
3448
3451
|
...options.guides,
|
|
3449
3452
|
zoom: options.getZoom?.() ?? 1,
|
|
3450
3453
|
index: dragIndex
|
|
@@ -3453,7 +3456,7 @@ function createCanvasArrangeController(options) {
|
|
|
3453
3456
|
const { x: dx, y: dy } = result.offset;
|
|
3454
3457
|
lastSnapped = /* @__PURE__ */ new Map();
|
|
3455
3458
|
if (dx === 0 && dy === 0) return changes;
|
|
3456
|
-
const parents = new Map(nodes.map((
|
|
3459
|
+
const parents = new Map(nodes.map((n2) => [n2.id, n2.parentId]));
|
|
3457
3460
|
const shift = new Set(ids.filter((id) => !proposed.has(parents.get(id) ?? "")));
|
|
3458
3461
|
return changes.map((c) => {
|
|
3459
3462
|
if (!(c.type === "position" && c.position && c.dragging && c.id !== void 0 && shift.has(c.id))) return c;
|
|
@@ -3471,8 +3474,8 @@ function createCanvasArrangeController(options) {
|
|
|
3471
3474
|
const lookup = createNodeLookup(nodes);
|
|
3472
3475
|
const node = lookup.get(id);
|
|
3473
3476
|
resizeId = id;
|
|
3474
|
-
resizeStart = node ? getResizingNodeRect(node, lookup,
|
|
3475
|
-
resizeIndex = createNodeGuideIndex(nodes, [id],
|
|
3477
|
+
resizeStart = node ? getResizingNodeRect(node, lookup, rect2()) : null;
|
|
3478
|
+
resizeIndex = createNodeGuideIndex(nodes, [id], rect2());
|
|
3476
3479
|
lastResized = null;
|
|
3477
3480
|
},
|
|
3478
3481
|
/**
|
|
@@ -3488,11 +3491,11 @@ function createCanvasArrangeController(options) {
|
|
|
3488
3491
|
const lookup = createNodeLookup(nodes);
|
|
3489
3492
|
const node = lookup.get(id);
|
|
3490
3493
|
if (!node || !resizeStart) return null;
|
|
3491
|
-
const proposed = getResizingNodeRect(node, lookup,
|
|
3494
|
+
const proposed = getResizingNodeRect(node, lookup, rect2());
|
|
3492
3495
|
if (isLocked(node)) {
|
|
3493
3496
|
const start = resizeStart;
|
|
3494
3497
|
const parent = node.parentId ? lookup.get(node.parentId) : void 0;
|
|
3495
|
-
const origin = parent ? getResizingNodeRect(parent, lookup,
|
|
3498
|
+
const origin = parent ? getResizingNodeRect(parent, lookup, rect2()) : { x: 0, y: 0 };
|
|
3496
3499
|
if (proposed.x !== start.x || proposed.y !== start.y || proposed.width !== start.width || proposed.height !== start.height) {
|
|
3497
3500
|
options.setNodes(
|
|
3498
3501
|
applyNodeUpdates(nodes, [
|
|
@@ -3509,7 +3512,7 @@ function createCanvasArrangeController(options) {
|
|
|
3509
3512
|
return null;
|
|
3510
3513
|
}
|
|
3511
3514
|
const result = snapNodeResize(nodes, id, proposed, h, {
|
|
3512
|
-
...
|
|
3515
|
+
...rect2(),
|
|
3513
3516
|
...options.guides,
|
|
3514
3517
|
...options.resize,
|
|
3515
3518
|
zoom: options.getZoom?.() ?? 1,
|
|
@@ -3533,7 +3536,7 @@ function createCanvasArrangeController(options) {
|
|
|
3533
3536
|
setGuides([]);
|
|
3534
3537
|
const update = last?.updates[0];
|
|
3535
3538
|
if (!update) return;
|
|
3536
|
-
const node = options.getNodes().find((
|
|
3539
|
+
const node = options.getNodes().find((n2) => n2.id === update.id);
|
|
3537
3540
|
if (!node) return;
|
|
3538
3541
|
const drift = node.position.x !== update.position.x || node.position.y !== update.position.y || node.width !== update.width || node.height !== update.height;
|
|
3539
3542
|
if (drift) options.setNodes(applyNodeUpdates(options.getNodes(), [update]));
|
|
@@ -3572,7 +3575,7 @@ function createCanvasArrangeController(options) {
|
|
|
3572
3575
|
if (!resizeStart) return changes;
|
|
3573
3576
|
const posChange = changes.find((c) => c.id === id && c.type === "position" && !!c.position);
|
|
3574
3577
|
const parent = node.parentId ? lookup.get(node.parentId) : void 0;
|
|
3575
|
-
const origin = parent ? getResizingNodeRect(parent, lookup,
|
|
3578
|
+
const origin = parent ? getResizingNodeRect(parent, lookup, rect2()) : { x: 0, y: 0 };
|
|
3576
3579
|
const position = posChange?.position ?? node.position;
|
|
3577
3580
|
const proposed = {
|
|
3578
3581
|
x: position.x + origin.x,
|
|
@@ -3586,7 +3589,7 @@ function createCanvasArrangeController(options) {
|
|
|
3586
3589
|
return changes;
|
|
3587
3590
|
}
|
|
3588
3591
|
const result = snapNodeResize(nodes, id, proposed, handle, {
|
|
3589
|
-
...
|
|
3592
|
+
...rect2(),
|
|
3590
3593
|
...options.guides,
|
|
3591
3594
|
...options.resize,
|
|
3592
3595
|
zoom: options.getZoom?.() ?? 1,
|
|
@@ -3619,9 +3622,9 @@ function createCanvasArrangeController(options) {
|
|
|
3619
3622
|
setGuides([]);
|
|
3620
3623
|
if (snapped.size === 0) return;
|
|
3621
3624
|
const nodes = options.getNodes();
|
|
3622
|
-
const drift = nodes.some((
|
|
3623
|
-
const p = snapped.get(
|
|
3624
|
-
return !!p && (
|
|
3625
|
+
const drift = nodes.some((n2) => {
|
|
3626
|
+
const p = snapped.get(n2.id);
|
|
3627
|
+
return !!p && (n2.position.x !== p.x || n2.position.y !== p.y);
|
|
3625
3628
|
});
|
|
3626
3629
|
if (drift) {
|
|
3627
3630
|
options.setNodes(applyNodeUpdates(nodes, [...snapped].map(([id, position]) => ({ id, position }))));
|
|
@@ -3726,21 +3729,21 @@ function measureToLine(a, orientation, at) {
|
|
|
3726
3729
|
function measureSelection(nodes, selectedIds, hoveredId, options = {}) {
|
|
3727
3730
|
const none = (selection2 = null) => ({ guides: [], target: null, selection: selection2 });
|
|
3728
3731
|
const lookup = createNodeLookup(nodes);
|
|
3729
|
-
const selected = [...new Set(selectedIds)].map((id) => lookup.get(id)).filter((
|
|
3732
|
+
const selected = [...new Set(selectedIds)].map((id) => lookup.get(id)).filter((n2) => !!n2 && n2.hidden !== true);
|
|
3730
3733
|
if (selected.length === 0) return none();
|
|
3731
|
-
const selection = boundsOf(selected.map((
|
|
3734
|
+
const selection = boundsOf(selected.map((n2) => getNodeRect(n2, lookup, options)));
|
|
3732
3735
|
if (!selection) return none();
|
|
3733
|
-
const selectedSet = new Set(selected.map((
|
|
3736
|
+
const selectedSet = new Set(selected.map((n2) => n2.id));
|
|
3734
3737
|
let targetId = hoveredId ?? null;
|
|
3735
3738
|
if (targetId === null || selectedSet.has(targetId)) {
|
|
3736
3739
|
const parentId = selected[0].parentId;
|
|
3737
|
-
const sameParent = selected.every((
|
|
3740
|
+
const sameParent = selected.every((n2) => n2.parentId === parentId);
|
|
3738
3741
|
targetId = parentId && sameParent && !selectedSet.has(parentId) ? parentId : null;
|
|
3739
3742
|
}
|
|
3740
3743
|
const target = targetId !== null ? lookup.get(targetId) : void 0;
|
|
3741
3744
|
if (!target || target.hidden === true) return none(selection);
|
|
3742
|
-
const
|
|
3743
|
-
return { guides: measureBetween(selection,
|
|
3745
|
+
const rect2 = getNodeRect(target, lookup, options);
|
|
3746
|
+
return { guides: measureBetween(selection, rect2), target: rect2, selection };
|
|
3744
3747
|
}
|
|
3745
3748
|
function isMeasureModifierHeld(event) {
|
|
3746
3749
|
if (!event) return false;
|
|
@@ -3825,12 +3828,12 @@ function createCanvasAutoLayoutController(options) {
|
|
|
3825
3828
|
*/
|
|
3826
3829
|
addNode(node, addOptions = {}) {
|
|
3827
3830
|
const forward = (nodes) => {
|
|
3828
|
-
if (nodes.some((
|
|
3831
|
+
if (nodes.some((n2) => n2.id === node.id)) return nodes;
|
|
3829
3832
|
let next = [...nodes, node];
|
|
3830
3833
|
if (addOptions.index !== void 0 && node.parentId) next = moveLayoutChild(next, node.id, addOptions.index);
|
|
3831
3834
|
return next;
|
|
3832
3835
|
};
|
|
3833
|
-
const backward = (nodes) => nodes.filter((
|
|
3836
|
+
const backward = (nodes) => nodes.filter((n2) => n2.id !== node.id);
|
|
3834
3837
|
return run("Add Node", forward, backward, () => [node.id]);
|
|
3835
3838
|
},
|
|
3836
3839
|
/** Removes nodes (and their descendants) and lays out the frames they leave, as one step. */
|
|
@@ -3840,20 +3843,20 @@ function createCanvasAutoLayoutController(options) {
|
|
|
3840
3843
|
let grew = true;
|
|
3841
3844
|
while (grew) {
|
|
3842
3845
|
grew = false;
|
|
3843
|
-
for (const
|
|
3844
|
-
if (
|
|
3845
|
-
remove.add(
|
|
3846
|
+
for (const n2 of before) {
|
|
3847
|
+
if (n2.parentId && remove.has(n2.parentId) && !remove.has(n2.id)) {
|
|
3848
|
+
remove.add(n2.id);
|
|
3846
3849
|
grew = true;
|
|
3847
3850
|
}
|
|
3848
3851
|
}
|
|
3849
3852
|
}
|
|
3850
|
-
const removed = before.map((
|
|
3853
|
+
const removed = before.map((n2, i) => [i, n2]).filter(([, n2]) => remove.has(n2.id));
|
|
3851
3854
|
if (removed.length === 0) return [];
|
|
3852
|
-
const parents = [...new Set(removed.map(([,
|
|
3853
|
-
const forward = (nodes) => nodes.filter((
|
|
3855
|
+
const parents = [...new Set(removed.map(([, n2]) => n2.parentId).filter((p) => !!p && !remove.has(p)))];
|
|
3856
|
+
const forward = (nodes) => nodes.filter((n2) => !remove.has(n2.id));
|
|
3854
3857
|
const backward = (nodes) => {
|
|
3855
3858
|
const next = [...nodes];
|
|
3856
|
-
for (const [i,
|
|
3859
|
+
for (const [i, n2] of removed) next.splice(Math.min(i, next.length), 0, n2);
|
|
3857
3860
|
return next;
|
|
3858
3861
|
};
|
|
3859
3862
|
return run("Delete", forward, backward, () => parents);
|
|
@@ -3864,7 +3867,7 @@ function createCanvasAutoLayoutController(options) {
|
|
|
3864
3867
|
*/
|
|
3865
3868
|
resizeNode(id, size) {
|
|
3866
3869
|
const nodes = options.getNodes();
|
|
3867
|
-
const node = nodes.find((
|
|
3870
|
+
const node = nodes.find((n2) => n2.id === id);
|
|
3868
3871
|
if (!node) return [];
|
|
3869
3872
|
const old = getNodeSize(node, options.rectOptions);
|
|
3870
3873
|
const update = { id };
|
|
@@ -3877,7 +3880,7 @@ function createCanvasAutoLayoutController(options) {
|
|
|
3877
3880
|
/** Moves flow child `childId` to flow index `index` in its frame and lays it out, as one step. */
|
|
3878
3881
|
moveChild(childId, index) {
|
|
3879
3882
|
const before = options.getNodes();
|
|
3880
|
-
const order = before.map((
|
|
3883
|
+
const order = before.map((n2) => n2.id);
|
|
3881
3884
|
const forward = (nodes) => moveLayoutChild(nodes, childId, index);
|
|
3882
3885
|
const backward = (nodes) => restoreOrder(nodes, order);
|
|
3883
3886
|
if (forward(before) === before) return [];
|
|
@@ -3889,13 +3892,13 @@ function createCanvasAutoLayoutController(options) {
|
|
|
3889
3892
|
const frame = getLayoutParent(nodes, id);
|
|
3890
3893
|
if (!frame) return void 0;
|
|
3891
3894
|
const lookup = createNodeLookup(nodes);
|
|
3892
|
-
const
|
|
3893
|
-
const at = point ?? { x:
|
|
3895
|
+
const rect2 = getNodeRect(lookup.get(id), lookup, options.rectOptions);
|
|
3896
|
+
const at = point ?? { x: rect2.x + rect2.width / 2, y: rect2.y + rect2.height / 2 };
|
|
3894
3897
|
return getAutoLayoutInsertTarget(nodes, frame.id, at, { ...layoutOptions(), excludeId: id });
|
|
3895
3898
|
},
|
|
3896
3899
|
/** Records the start position of a reorder drag. Optional: `dragReorder` records it lazily. */
|
|
3897
3900
|
beginReorderDrag(id) {
|
|
3898
|
-
const node = options.getNodes().find((
|
|
3901
|
+
const node = options.getNodes().find((n2) => n2.id === id);
|
|
3899
3902
|
if (node && getLayoutParent(options.getNodes(), id)) dragStarts.set(id, { ...node.position });
|
|
3900
3903
|
},
|
|
3901
3904
|
/**
|
|
@@ -3921,7 +3924,7 @@ function createCanvasAutoLayoutController(options) {
|
|
|
3921
3924
|
const target = controller.getInsertTarget(id, point);
|
|
3922
3925
|
if (!target) return [];
|
|
3923
3926
|
const before = options.getNodes();
|
|
3924
|
-
const order = before.map((
|
|
3927
|
+
const order = before.map((n2) => n2.id);
|
|
3925
3928
|
const forward = (nodes) => moveLayoutChild(nodes, id, target.index);
|
|
3926
3929
|
const backward = (nodes) => restoreOrder(nodes, order);
|
|
3927
3930
|
return run("Reorder", forward, backward, () => [id], [], start && { id, position: start });
|
|
@@ -3976,8 +3979,8 @@ function createCanvasAutoLayoutController(options) {
|
|
|
3976
3979
|
noteRemoved(removed) {
|
|
3977
3980
|
const gone = /* @__PURE__ */ new Set();
|
|
3978
3981
|
const list = [...removed];
|
|
3979
|
-
for (const
|
|
3980
|
-
for (const
|
|
3982
|
+
for (const n2 of list) gone.add(n2.id);
|
|
3983
|
+
for (const n2 of list) if (n2.parentId && !gone.has(n2.parentId)) pendingIds.add(n2.parentId);
|
|
3981
3984
|
},
|
|
3982
3985
|
/** Whether `noteChanges` left work for `flush`. */
|
|
3983
3986
|
get hasPending() {
|
|
@@ -4002,12 +4005,12 @@ function createCanvasAutoLayoutController(options) {
|
|
|
4002
4005
|
let nodes = options.getNodes();
|
|
4003
4006
|
let updates = [];
|
|
4004
4007
|
for (const [id, previous] of pendingResizes) {
|
|
4005
|
-
if (!nodes.some((
|
|
4008
|
+
if (!nodes.some((n2) => n2.id === id)) continue;
|
|
4006
4009
|
const constrained = applyConstraints(nodes, id, previous, layoutOptions());
|
|
4007
4010
|
nodes = applyNodeUpdates(nodes, constrained);
|
|
4008
4011
|
updates = mergeNodeUpdates(updates, constrained);
|
|
4009
4012
|
}
|
|
4010
|
-
const layout2 = pendingAll ? layoutAll(nodes, layoutOptions()) : relayoutUpdates(nodes, [...pendingIds].filter((id) => nodes.some((
|
|
4013
|
+
const layout2 = pendingAll ? layoutAll(nodes, layoutOptions()) : relayoutUpdates(nodes, [...pendingIds].filter((id) => nodes.some((n2) => n2.id === id)), layoutOptions());
|
|
4011
4014
|
updates = mergeNodeUpdates(updates, layout2);
|
|
4012
4015
|
pendingIds.clear();
|
|
4013
4016
|
pendingResizes.clear();
|
|
@@ -4016,13 +4019,13 @@ function createCanvasAutoLayoutController(options) {
|
|
|
4016
4019
|
return mergeNodeUpdates(applied, updates);
|
|
4017
4020
|
},
|
|
4018
4021
|
/** Whether `id` is an auto layout frame. */
|
|
4019
|
-
isFrame: (id) => isAutoLayoutFrame(options.getNodes().find((
|
|
4022
|
+
isFrame: (id) => isAutoLayoutFrame(options.getNodes().find((n2) => n2.id === id))
|
|
4020
4023
|
};
|
|
4021
4024
|
return controller;
|
|
4022
4025
|
}
|
|
4023
4026
|
function restoreOrder(nodes, order) {
|
|
4024
4027
|
const rank = new Map(order.map((id, i) => [id, i]));
|
|
4025
|
-
const indexed = nodes.map((
|
|
4028
|
+
const indexed = nodes.map((n2, i) => ({ n: n2, r: rank.get(n2.id) ?? order.length + i }));
|
|
4026
4029
|
indexed.sort((a, b) => a.r - b.r);
|
|
4027
4030
|
return indexed.every((e, i) => e.n === nodes[i]) ? nodes : indexed.map((e) => e.n);
|
|
4028
4031
|
}
|
|
@@ -4033,7 +4036,7 @@ var TOKEN_MODES_DATA_KEY = "tokenModes";
|
|
|
4033
4036
|
var kebab = (prop) => prop.replace(/[A-Z]/g, (c) => `-${c.toLowerCase()}`);
|
|
4034
4037
|
function parseDeclarations(style) {
|
|
4035
4038
|
const parts = [];
|
|
4036
|
-
let
|
|
4039
|
+
let depth2 = 0;
|
|
4037
4040
|
let quote = "";
|
|
4038
4041
|
let start = 0;
|
|
4039
4042
|
for (let i = 0; i < style.length; i++) {
|
|
@@ -4042,9 +4045,9 @@ function parseDeclarations(style) {
|
|
|
4042
4045
|
if (ch === "\\") i++;
|
|
4043
4046
|
else if (ch === quote) quote = "";
|
|
4044
4047
|
} else if (ch === '"' || ch === "'") quote = ch;
|
|
4045
|
-
else if (ch === "(")
|
|
4046
|
-
else if (ch === ")")
|
|
4047
|
-
else if (ch === ";" &&
|
|
4048
|
+
else if (ch === "(") depth2++;
|
|
4049
|
+
else if (ch === ")") depth2 = Math.max(0, depth2 - 1);
|
|
4050
|
+
else if (ch === ";" && depth2 === 0) {
|
|
4048
4051
|
parts.push(style.slice(start, i));
|
|
4049
4052
|
start = i + 1;
|
|
4050
4053
|
}
|
|
@@ -4094,8 +4097,8 @@ function writeNodeStyleProperty(style, prop, value, unitless = false) {
|
|
|
4094
4097
|
function px(value) {
|
|
4095
4098
|
if (typeof value === "number") return Number.isFinite(value) ? value : void 0;
|
|
4096
4099
|
if (typeof value === "string") {
|
|
4097
|
-
const
|
|
4098
|
-
return Number.isFinite(
|
|
4100
|
+
const n2 = parseFloat(value);
|
|
4101
|
+
return Number.isFinite(n2) ? n2 : void 0;
|
|
4099
4102
|
}
|
|
4100
4103
|
return void 0;
|
|
4101
4104
|
}
|
|
@@ -4294,7 +4297,7 @@ function getTokensForProperty(state, property, node) {
|
|
|
4294
4297
|
return state.variables.filter((v) => v.type === property.type && isTokenInScope(v, scope));
|
|
4295
4298
|
}
|
|
4296
4299
|
function lookupOf(nodes) {
|
|
4297
|
-
return new Map(nodes.map((
|
|
4300
|
+
return new Map(nodes.map((n2) => [n2.id, n2]));
|
|
4298
4301
|
}
|
|
4299
4302
|
function validModes(state, modes, into) {
|
|
4300
4303
|
for (const [collectionId, modeId] of Object.entries(modes)) {
|
|
@@ -4473,8 +4476,8 @@ var ANIMATION_DATA_KEY = "animation";
|
|
|
4473
4476
|
var num = (value) => {
|
|
4474
4477
|
if (typeof value === "number") return Number.isFinite(value) ? value : void 0;
|
|
4475
4478
|
if (typeof value === "string") {
|
|
4476
|
-
const
|
|
4477
|
-
return Number.isFinite(
|
|
4479
|
+
const n2 = parseFloat(value);
|
|
4480
|
+
return Number.isFinite(n2) ? n2 : void 0;
|
|
4478
4481
|
}
|
|
4479
4482
|
return void 0;
|
|
4480
4483
|
};
|
|
@@ -4723,9 +4726,9 @@ function coerceValue(property, value) {
|
|
|
4723
4726
|
if (color === null) throw new AnimationEditError("invalid_value", `"${String(value)}" is not a colour.`);
|
|
4724
4727
|
return color;
|
|
4725
4728
|
}
|
|
4726
|
-
const
|
|
4727
|
-
if (typeof
|
|
4728
|
-
return clampAnimationValue(property,
|
|
4729
|
+
const n2 = typeof value === "string" && value.trim() !== "" ? Number(value) : value;
|
|
4730
|
+
if (typeof n2 !== "number" || !Number.isFinite(n2)) throw new AnimationEditError("invalid_value", `"${String(value)}" is not a number.`);
|
|
4731
|
+
return clampAnimationValue(property, n2);
|
|
4729
4732
|
}
|
|
4730
4733
|
function coerceEasing(easing) {
|
|
4731
4734
|
if (typeof easing === "string") {
|
|
@@ -4742,7 +4745,7 @@ var Draft = class {
|
|
|
4742
4745
|
constructor(nodes, options = {}) {
|
|
4743
4746
|
this.nodes = nodes;
|
|
4744
4747
|
this.options = options;
|
|
4745
|
-
this.byId = new Map(nodes.map((
|
|
4748
|
+
this.byId = new Map(nodes.map((n2) => [n2.id, n2]));
|
|
4746
4749
|
}
|
|
4747
4750
|
nodes;
|
|
4748
4751
|
options;
|
|
@@ -4916,7 +4919,7 @@ function deleteKeyframes(nodes, refs, options = {}) {
|
|
|
4916
4919
|
if (left.length === 0) {
|
|
4917
4920
|
const p = draft.property(property);
|
|
4918
4921
|
const last = keys.find((k) => sameTime(k.time, lane[lane.length - 1].time)) ?? keys[keys.length - 1];
|
|
4919
|
-
if (p && property !== "motionPath") draft.writeNode(nodeId, (
|
|
4922
|
+
if (p && property !== "motionPath") draft.writeNode(nodeId, (n2) => p.write(n2, last.value));
|
|
4920
4923
|
}
|
|
4921
4924
|
draft.setKeys(nodeId, property, left);
|
|
4922
4925
|
}
|
|
@@ -4936,7 +4939,7 @@ function removeTrack(nodes, nodeId, property, options = {}) {
|
|
|
4936
4939
|
const p = draft.property(property);
|
|
4937
4940
|
if (options.keepValueAt !== void 0 && p && property !== "motionPath") {
|
|
4938
4941
|
const value = evaluateTrack(track, options.keepValueAt, p.type);
|
|
4939
|
-
if (value !== void 0) draft.writeNode(nodeId, (
|
|
4942
|
+
if (value !== void 0) draft.writeNode(nodeId, (n2) => p.write(n2, value));
|
|
4940
4943
|
}
|
|
4941
4944
|
draft.setKeys(nodeId, property, []);
|
|
4942
4945
|
if (property === "motionPath") draft.setMotionPath(nodeId, void 0);
|
|
@@ -5107,8 +5110,8 @@ function pasteKeyframes(nodes, clipboard, time, options = {}) {
|
|
|
5107
5110
|
var sameValue = (a, b) => typeof a === "number" && typeof b === "number" ? Math.abs(a - b) <= 1e-9 : a === b;
|
|
5108
5111
|
function recordAnimationChanges(base, before, after, time, options = {}) {
|
|
5109
5112
|
const properties = (options.properties ?? ANIMATABLE_PROPERTIES).filter((p) => p.key !== "motionPath");
|
|
5110
|
-
const baseById = new Map(base.map((
|
|
5111
|
-
const beforeById = new Map(before.map((
|
|
5113
|
+
const baseById = new Map(base.map((n2) => [n2.id, n2]));
|
|
5114
|
+
const beforeById = new Map(before.map((n2) => [n2.id, n2]));
|
|
5112
5115
|
const t = coerceTime(time);
|
|
5113
5116
|
const keyed = [];
|
|
5114
5117
|
const out = after.map((next) => {
|
|
@@ -5258,7 +5261,7 @@ function sampledStops(duration, fps, keyTimes, valueAt) {
|
|
|
5258
5261
|
return [...times].sort((a, b) => a - b).map((t) => ({ offset: Math.min(1, t / duration), value: valueAt(t), easing: "linear" }));
|
|
5259
5262
|
}
|
|
5260
5263
|
function getCssPropertyAnimations(nodes, nodeId, options = {}) {
|
|
5261
|
-
const node = nodes.find((
|
|
5264
|
+
const node = nodes.find((n2) => n2.id === nodeId);
|
|
5262
5265
|
const animation = getNodeAnimation(node);
|
|
5263
5266
|
if (!node || !animation) return [];
|
|
5264
5267
|
const duration = options.duration ?? getAnimationDuration([node]);
|
|
@@ -5328,7 +5331,7 @@ function timing(options, duration) {
|
|
|
5328
5331
|
}
|
|
5329
5332
|
var cssIdent = (text) => text.replace(/[^A-Za-z0-9_-]/g, "-").replace(/^(\d)/, "_$1");
|
|
5330
5333
|
function exportCssAnimation(nodes, nodeId, options = {}) {
|
|
5331
|
-
const duration = options.duration ?? getAnimationDuration(nodes.filter((
|
|
5334
|
+
const duration = options.duration ?? getAnimationDuration(nodes.filter((n2) => n2.id === nodeId));
|
|
5332
5335
|
const props = getCssPropertyAnimations(nodes, nodeId, { ...options, duration });
|
|
5333
5336
|
const base = cssIdent(options.name ?? `anim-${nodeId}`);
|
|
5334
5337
|
const t = timing(options, duration);
|
|
@@ -5359,7 +5362,7 @@ ${selector} {
|
|
|
5359
5362
|
return { css, animation, animations, exact: props.every((p) => p.exact) };
|
|
5360
5363
|
}
|
|
5361
5364
|
function toWebAnimations(nodes, nodeId, options = {}) {
|
|
5362
|
-
const duration = options.duration ?? getAnimationDuration(nodes.filter((
|
|
5365
|
+
const duration = options.duration ?? getAnimationDuration(nodes.filter((n2) => n2.id === nodeId));
|
|
5363
5366
|
const t = timing(options, duration);
|
|
5364
5367
|
return getCssPropertyAnimations(nodes, nodeId, { ...options, duration }).map((prop) => ({
|
|
5365
5368
|
property: prop.property,
|
|
@@ -5381,7 +5384,7 @@ function isKeyframeSelected(selection, ref) {
|
|
|
5381
5384
|
}
|
|
5382
5385
|
var defaultLabel = (node) => typeof node.data?.label === "string" && node.data.label.trim() ? node.data.label : node.id;
|
|
5383
5386
|
function getTimelineRows(nodes, ids, options = {}) {
|
|
5384
|
-
const byId = new Map(nodes.map((
|
|
5387
|
+
const byId = new Map(nodes.map((n2) => [n2.id, n2]));
|
|
5385
5388
|
const selection = options.selection ?? [];
|
|
5386
5389
|
const labelOf = options.labelOf ?? defaultLabel;
|
|
5387
5390
|
const rows = [];
|
|
@@ -5489,7 +5492,7 @@ function createCanvasAnimationController(options) {
|
|
|
5489
5492
|
for (const listener of listeners) listener(state);
|
|
5490
5493
|
};
|
|
5491
5494
|
player.subscribe(notify);
|
|
5492
|
-
const selectedIds = () => options.getSelectedIds?.() ?? options.getNodes().filter((
|
|
5495
|
+
const selectedIds = () => options.getSelectedIds?.() ?? options.getNodes().filter((n2) => n2.selected).map((n2) => n2.id);
|
|
5493
5496
|
const KEEP_FIELDS = ["selected", "dragging", "measured"];
|
|
5494
5497
|
const replaceNodes = (nodes, replacements, animationOnly = false) => nodes.map((node) => {
|
|
5495
5498
|
const replacement = replacements.get(node.id);
|
|
@@ -5512,7 +5515,7 @@ function createCanvasAnimationController(options) {
|
|
|
5512
5515
|
const before = options.getNodes();
|
|
5513
5516
|
const after = edit(before);
|
|
5514
5517
|
if (after === before) return false;
|
|
5515
|
-
const beforeById = new Map(before.map((
|
|
5518
|
+
const beforeById = new Map(before.map((n2) => [n2.id, n2]));
|
|
5516
5519
|
const undoMap = /* @__PURE__ */ new Map();
|
|
5517
5520
|
const redoMap = /* @__PURE__ */ new Map();
|
|
5518
5521
|
for (const node of after) {
|
|
@@ -5534,7 +5537,7 @@ function createCanvasAnimationController(options) {
|
|
|
5534
5537
|
}
|
|
5535
5538
|
function pruneSelection() {
|
|
5536
5539
|
if (selection.length === 0) return;
|
|
5537
|
-
const byId = new Map(options.getNodes().map((
|
|
5540
|
+
const byId = new Map(options.getNodes().map((n2) => [n2.id, n2]));
|
|
5538
5541
|
const kept = selection.filter((ref) => {
|
|
5539
5542
|
const track = getNodeAnimation(byId.get(ref.nodeId))?.tracks[ref.property];
|
|
5540
5543
|
return !!track && normalizeKeyframes(track.keyframes).some((k) => Math.abs(k.time - ref.time) <= ANIMATION_TIME_EPSILON);
|
|
@@ -5640,27 +5643,27 @@ function createCanvasAnimationController(options) {
|
|
|
5640
5643
|
return [];
|
|
5641
5644
|
}
|
|
5642
5645
|
const ids = new Set(keyed.map((k) => k.nodeId));
|
|
5643
|
-
const baseById = new Map(base.map((
|
|
5644
|
-
const staticNodes = nodes.map((
|
|
5645
|
-
if (!ids.has(
|
|
5646
|
-
const old = baseById.get(
|
|
5647
|
-
const data = { ...
|
|
5646
|
+
const baseById = new Map(base.map((n2) => [n2.id, n2]));
|
|
5647
|
+
const staticNodes = nodes.map((n2) => {
|
|
5648
|
+
if (!ids.has(n2.id)) return n2;
|
|
5649
|
+
const old = baseById.get(n2.id)?.data?.[ANIMATION_DATA_KEY];
|
|
5650
|
+
const data = { ...n2.data ?? {} };
|
|
5648
5651
|
if (old === void 0) delete data[ANIMATION_DATA_KEY];
|
|
5649
5652
|
else data[ANIMATION_DATA_KEY] = old;
|
|
5650
|
-
return { ...
|
|
5653
|
+
return { ...n2, data };
|
|
5651
5654
|
});
|
|
5652
|
-
const animationOf = new Map(nodes.filter((
|
|
5655
|
+
const animationOf = new Map(nodes.filter((n2) => ids.has(n2.id)).map((n2) => [n2.id, n2.data?.[ANIMATION_DATA_KEY]]));
|
|
5653
5656
|
options.setNodes(staticNodes);
|
|
5654
5657
|
const tag = `animation.record:${[...ids].sort().join(",")}`;
|
|
5655
5658
|
commit(
|
|
5656
5659
|
"Record Keyframe",
|
|
5657
|
-
(current) => current.map((
|
|
5658
|
-
if (!animationOf.has(
|
|
5659
|
-
const data = { ...
|
|
5660
|
-
const value = animationOf.get(
|
|
5660
|
+
(current) => current.map((n2) => {
|
|
5661
|
+
if (!animationOf.has(n2.id)) return n2;
|
|
5662
|
+
const data = { ...n2.data ?? {} };
|
|
5663
|
+
const value = animationOf.get(n2.id);
|
|
5661
5664
|
if (value === void 0) delete data[ANIMATION_DATA_KEY];
|
|
5662
5665
|
else data[ANIMATION_DATA_KEY] = value;
|
|
5663
|
-
return { ...
|
|
5666
|
+
return { ...n2, data };
|
|
5664
5667
|
}),
|
|
5665
5668
|
{ tag, animationOnly: true }
|
|
5666
5669
|
);
|
|
@@ -6157,12 +6160,12 @@ function fieldGroup(field) {
|
|
|
6157
6160
|
var Graph = class {
|
|
6158
6161
|
constructor(nodes) {
|
|
6159
6162
|
this.nodes = nodes;
|
|
6160
|
-
this.byId = new Map(nodes.map((
|
|
6161
|
-
for (const
|
|
6162
|
-
if (!
|
|
6163
|
-
let list = this.kids.get(
|
|
6164
|
-
if (!list) this.kids.set(
|
|
6165
|
-
list.push(
|
|
6163
|
+
this.byId = new Map(nodes.map((n2) => [n2.id, n2]));
|
|
6164
|
+
for (const n2 of nodes) {
|
|
6165
|
+
if (!n2.parentId || !this.byId.has(n2.parentId)) continue;
|
|
6166
|
+
let list = this.kids.get(n2.parentId);
|
|
6167
|
+
if (!list) this.kids.set(n2.parentId, list = []);
|
|
6168
|
+
list.push(n2.id);
|
|
6166
6169
|
}
|
|
6167
6170
|
}
|
|
6168
6171
|
nodes;
|
|
@@ -6192,7 +6195,7 @@ var Graph = class {
|
|
|
6192
6195
|
}
|
|
6193
6196
|
/** Whether `a` is a strict ancestor of `b`. */
|
|
6194
6197
|
isAncestor(a, b) {
|
|
6195
|
-
return this.chain(b, false).some((
|
|
6198
|
+
return this.chain(b, false).some((n2) => n2.id === a);
|
|
6196
6199
|
}
|
|
6197
6200
|
/** `id` and its descendants, pre-order. */
|
|
6198
6201
|
subtree(id) {
|
|
@@ -6322,7 +6325,7 @@ function componentDepsIn(g, componentId) {
|
|
|
6322
6325
|
}
|
|
6323
6326
|
function createsCycleIn(g, componentId, parentId) {
|
|
6324
6327
|
if (!parentId) return false;
|
|
6325
|
-
const hosts = g.chain(parentId).filter(isCanvasComponent).map((
|
|
6328
|
+
const hosts = g.chain(parentId).filter(isCanvasComponent).map((n2) => n2.id);
|
|
6326
6329
|
if (hosts.length === 0) return false;
|
|
6327
6330
|
const deps = componentDepsIn(g, componentId);
|
|
6328
6331
|
deps.add(componentId);
|
|
@@ -6345,7 +6348,7 @@ function isInsideInstance(nodes, id) {
|
|
|
6345
6348
|
return enclosingInstanceIn(new Graph(nodes), id) !== void 0;
|
|
6346
6349
|
}
|
|
6347
6350
|
function getComponentInstances(nodes, componentId) {
|
|
6348
|
-
return nodes.filter((
|
|
6351
|
+
return nodes.filter((n2) => getInstanceData(n2)?.componentId === componentId).map((n2) => n2.id);
|
|
6349
6352
|
}
|
|
6350
6353
|
function getInstanceStatus(nodes, id) {
|
|
6351
6354
|
const g = new Graph(nodes);
|
|
@@ -6384,19 +6387,19 @@ function getInstanceProperties(nodes, id) {
|
|
|
6384
6387
|
function listCanvasComponents(nodes) {
|
|
6385
6388
|
const g = new Graph(nodes);
|
|
6386
6389
|
const counts = /* @__PURE__ */ new Map();
|
|
6387
|
-
for (const
|
|
6388
|
-
const c = getInstanceData(
|
|
6390
|
+
for (const n2 of nodes) {
|
|
6391
|
+
const c = getInstanceData(n2)?.componentId;
|
|
6389
6392
|
if (c) counts.set(c, (counts.get(c) ?? 0) + 1);
|
|
6390
6393
|
}
|
|
6391
6394
|
const components = [];
|
|
6392
|
-
for (const
|
|
6393
|
-
if (!isCanvasComponent(
|
|
6394
|
-
const set = variantSetIn(g,
|
|
6395
|
+
for (const n2 of nodes) {
|
|
6396
|
+
if (!isCanvasComponent(n2)) continue;
|
|
6397
|
+
const set = variantSetIn(g, n2.id);
|
|
6395
6398
|
components.push({
|
|
6396
|
-
id:
|
|
6397
|
-
name: getLayerName(
|
|
6398
|
-
...set ? { setId: set.id, variant: getVariantValues(
|
|
6399
|
-
instanceCount: counts.get(
|
|
6399
|
+
id: n2.id,
|
|
6400
|
+
name: getLayerName(n2) || n2.id,
|
|
6401
|
+
...set ? { setId: set.id, variant: getVariantValues(n2) } : {},
|
|
6402
|
+
instanceCount: counts.get(n2.id) ?? 0
|
|
6400
6403
|
});
|
|
6401
6404
|
}
|
|
6402
6405
|
const sets = nodes.filter(isCanvasComponentSet).map((s) => ({
|
|
@@ -6463,15 +6466,15 @@ function clearRuntime(node, old) {
|
|
|
6463
6466
|
else delete node[k];
|
|
6464
6467
|
}
|
|
6465
6468
|
}
|
|
6466
|
-
function tokenDrivenGroups(
|
|
6467
|
-
const mine = stringRecord2(dataOf(
|
|
6469
|
+
function tokenDrivenGroups(n2, options) {
|
|
6470
|
+
const mine = stringRecord2(dataOf(n2).tokenBindings);
|
|
6468
6471
|
const out = [];
|
|
6469
6472
|
for (const key of Object.keys(mine)) {
|
|
6470
6473
|
const property = getCanvasTokenProperty(key, options);
|
|
6471
|
-
if (!property || !property.appliesTo(
|
|
6472
|
-
const current = property.read(
|
|
6474
|
+
if (!property || !property.appliesTo(n2)) continue;
|
|
6475
|
+
const current = property.read(n2);
|
|
6473
6476
|
const probe = typeof current === "number" ? current + 1 : typeof current === "boolean" ? !current : `${current ?? ""}`;
|
|
6474
|
-
for (const g of diffOverrideGroups(
|
|
6477
|
+
for (const g of diffOverrideGroups(n2, property.write(n2, probe))) if (!out.includes(g)) out.push(g);
|
|
6475
6478
|
}
|
|
6476
6479
|
return out;
|
|
6477
6480
|
}
|
|
@@ -6535,9 +6538,9 @@ function buildInstance(g, instId, opts, taken) {
|
|
|
6535
6538
|
const byParentSource = /* @__PURE__ */ new Map();
|
|
6536
6539
|
const bySource = /* @__PURE__ */ new Map();
|
|
6537
6540
|
for (const id of oldIds) {
|
|
6538
|
-
const
|
|
6539
|
-
const s = getComponentSourceId(
|
|
6540
|
-
const key = `${
|
|
6541
|
+
const n2 = old.get(id);
|
|
6542
|
+
const s = getComponentSourceId(n2);
|
|
6543
|
+
const key = `${n2.parentId}\0${s}`;
|
|
6541
6544
|
if (!byParentSource.has(key)) byParentSource.set(key, id);
|
|
6542
6545
|
bySource.set(s, bySource.has(s) ? null : id);
|
|
6543
6546
|
}
|
|
@@ -6547,10 +6550,10 @@ function buildInstance(g, instId, opts, taken) {
|
|
|
6547
6550
|
const walk = (parent, prefix) => {
|
|
6548
6551
|
const counts = /* @__PURE__ */ new Map();
|
|
6549
6552
|
for (const c of g.children(parent)) {
|
|
6550
|
-
const
|
|
6551
|
-
const src = getComponentSourceId(
|
|
6553
|
+
const n2 = g.get(c);
|
|
6554
|
+
const src = getComponentSourceId(n2);
|
|
6552
6555
|
if (src === void 0) continue;
|
|
6553
|
-
const name = getLayerName(g.get(src) ??
|
|
6556
|
+
const name = getLayerName(g.get(src) ?? n2);
|
|
6554
6557
|
const k = counts.get(name) ?? 0;
|
|
6555
6558
|
counts.set(name, k + 1);
|
|
6556
6559
|
const path = `${prefix}/${k === 0 ? name : `${name}#${k}`}`;
|
|
@@ -6571,7 +6574,7 @@ function buildInstance(g, instId, opts, taken) {
|
|
|
6571
6574
|
};
|
|
6572
6575
|
const instProps = /* @__PURE__ */ new Map();
|
|
6573
6576
|
const out = [];
|
|
6574
|
-
const isText2 = (
|
|
6577
|
+
const isText2 = (n2) => typeof n2.type === "string" && opts.textTypes.includes(n2.type);
|
|
6575
6578
|
const copyLayer = (s, o, id, parentId) => {
|
|
6576
6579
|
const next = { ...s, id, parentId };
|
|
6577
6580
|
const data = stripLook(dataOf(s));
|
|
@@ -6579,7 +6582,7 @@ function buildInstance(g, instId, opts, taken) {
|
|
|
6579
6582
|
data[COMPONENT_SOURCE_DATA_KEY] = s.id;
|
|
6580
6583
|
next.data = data;
|
|
6581
6584
|
clearRuntime(next, o);
|
|
6582
|
-
let
|
|
6585
|
+
let n2 = next;
|
|
6583
6586
|
if (o) {
|
|
6584
6587
|
let groups = [...getNodeOverrides(o)];
|
|
6585
6588
|
const from = g.get(getComponentSourceId(o));
|
|
@@ -6587,16 +6590,16 @@ function buildInstance(g, instId, opts, taken) {
|
|
|
6587
6590
|
const differs = new Set(diffOverrideGroups(from, s));
|
|
6588
6591
|
groups = groups.filter((gr) => !differs.has(gr));
|
|
6589
6592
|
}
|
|
6590
|
-
|
|
6591
|
-
|
|
6592
|
-
|
|
6593
|
+
n2 = copyGroups(o, n2, groups);
|
|
6594
|
+
n2 = keepLaidOut(s, o, n2, groups);
|
|
6595
|
+
n2 = setOverrides(n2, groups);
|
|
6593
6596
|
}
|
|
6594
|
-
return fixMeasured(
|
|
6597
|
+
return fixMeasured(n2, o);
|
|
6595
6598
|
};
|
|
6596
|
-
const keepLaidOut = (s, o,
|
|
6597
|
-
if (o.parentId !==
|
|
6598
|
-
const flows = !getChildLayout(
|
|
6599
|
-
let next =
|
|
6599
|
+
const keepLaidOut = (s, o, n2, groups) => {
|
|
6600
|
+
if (o.parentId !== n2.parentId || groups.includes("size") || groups.includes("position")) return n2;
|
|
6601
|
+
const flows = !getChildLayout(n2).absolute && !!getAutoLayout(g.get(s.parentId));
|
|
6602
|
+
let next = n2;
|
|
6600
6603
|
if (flows) next = writeOverrideGroup(next, "position", o.position);
|
|
6601
6604
|
const derived = (axis) => {
|
|
6602
6605
|
const sizing = getLayoutSizing(next, axis);
|
|
@@ -6625,27 +6628,27 @@ function buildInstance(g, instId, opts, taken) {
|
|
|
6625
6628
|
data[COMPONENT_SOURCE_DATA_KEY] = sourceId;
|
|
6626
6629
|
next.data = data;
|
|
6627
6630
|
clearRuntime(next, old2);
|
|
6628
|
-
let
|
|
6631
|
+
let n2 = next;
|
|
6629
6632
|
const own = /* @__PURE__ */ new Set();
|
|
6630
6633
|
listGroups(place2, own);
|
|
6631
|
-
listGroups(
|
|
6632
|
-
|
|
6634
|
+
listGroups(n2, own);
|
|
6635
|
+
n2 = copyGroups(place2, n2, [...own].filter((gr) => isOwnRootGroup(gr) && gr !== "component" && gr !== "props"));
|
|
6633
6636
|
let groups = old2 ? getNodeOverrides(old2).filter((gr) => !topLevel || !isOwnRootGroup(gr)) : [];
|
|
6634
6637
|
if (old2 && previousComponent && siblingVariants(g, previousComponent, look.id)) {
|
|
6635
6638
|
const differs = new Set(diffOverrideGroups(g.get(previousComponent), look));
|
|
6636
6639
|
groups = groups.filter((gr) => gr === "data.label" || gr === "data.name" || !differs.has(gr));
|
|
6637
6640
|
}
|
|
6638
|
-
if (old2)
|
|
6639
|
-
return fixMeasured(setOverrides(
|
|
6641
|
+
if (old2) n2 = copyGroups(old2, n2, groups.filter((gr) => gr !== "component" && gr !== "props"));
|
|
6642
|
+
return fixMeasured(setOverrides(n2, groups), old2);
|
|
6640
6643
|
};
|
|
6641
|
-
const applyChainProps = (
|
|
6644
|
+
const applyChainProps = (n2, s, enc) => {
|
|
6642
6645
|
const chain = [s];
|
|
6643
6646
|
while (chain.length < enc.length) {
|
|
6644
6647
|
const next2 = g.get(getComponentSourceId(chain[chain.length - 1]));
|
|
6645
6648
|
if (!next2) break;
|
|
6646
6649
|
chain.push(next2);
|
|
6647
6650
|
}
|
|
6648
|
-
let next =
|
|
6651
|
+
let next = n2;
|
|
6649
6652
|
for (let j = chain.length - 1; j >= 0; j--) {
|
|
6650
6653
|
const props = instProps.get(enc[j]);
|
|
6651
6654
|
if (!props) continue;
|
|
@@ -6657,7 +6660,7 @@ function buildInstance(g, instId, opts, taken) {
|
|
|
6657
6660
|
}
|
|
6658
6661
|
return next;
|
|
6659
6662
|
};
|
|
6660
|
-
const copyChildren = (srcParent, newParent, prefix, enc, expanding,
|
|
6663
|
+
const copyChildren = (srcParent, newParent, prefix, enc, expanding, depth2) => {
|
|
6661
6664
|
const counts = /* @__PURE__ */ new Map();
|
|
6662
6665
|
for (const sid of g.children(srcParent)) {
|
|
6663
6666
|
const s = g.get(sid);
|
|
@@ -6679,39 +6682,39 @@ function buildInstance(g, instId, opts, taken) {
|
|
|
6679
6682
|
if (oid !== void 0) used.add(oid);
|
|
6680
6683
|
const o = oid !== void 0 ? old.get(oid) : void 0;
|
|
6681
6684
|
const id = oid ?? fresh(sid);
|
|
6682
|
-
let
|
|
6683
|
-
const nested = getInstanceData(
|
|
6684
|
-
if (nested &&
|
|
6685
|
+
let n2 = applyChainProps(copyLayer(s, o, id, newParent), s, enc);
|
|
6686
|
+
const nested = getInstanceData(n2);
|
|
6687
|
+
if (nested && depth2 < MAX_DEPTH) {
|
|
6685
6688
|
const target = nested.componentId;
|
|
6686
6689
|
instProps.set(id, effectivePropsIn(g, target, nested.properties));
|
|
6687
6690
|
if (getInstanceData(s)?.componentId !== target) {
|
|
6688
6691
|
const main = g.get(target);
|
|
6689
6692
|
if (isCanvasComponent(main) && !expanding.includes(target) && !g.isAncestor(target, instId)) {
|
|
6690
6693
|
const previousComponent = o ? getInstanceData(o)?.componentId : void 0;
|
|
6691
|
-
|
|
6692
|
-
out.push(
|
|
6693
|
-
copyChildren(target, id, path, [id], [...expanding, target],
|
|
6694
|
+
n2 = applyChainProps(instanceRoot(main, s, o, id, newParent, sid, nested, previousComponent, false), s, enc);
|
|
6695
|
+
out.push(n2);
|
|
6696
|
+
copyChildren(target, id, path, [id], [...expanding, target], depth2 + 1);
|
|
6694
6697
|
continue;
|
|
6695
6698
|
}
|
|
6696
6699
|
}
|
|
6697
|
-
out.push(
|
|
6698
|
-
copyChildren(sid, id, path, [...enc, id], expanding,
|
|
6700
|
+
out.push(n2);
|
|
6701
|
+
copyChildren(sid, id, path, [...enc, id], expanding, depth2);
|
|
6699
6702
|
continue;
|
|
6700
6703
|
}
|
|
6701
|
-
out.push(
|
|
6702
|
-
copyChildren(sid, id, path, enc, expanding,
|
|
6704
|
+
out.push(n2);
|
|
6705
|
+
copyChildren(sid, id, path, enc, expanding, depth2);
|
|
6703
6706
|
}
|
|
6704
6707
|
};
|
|
6705
6708
|
const root = instanceRoot(comp, inst, inst, instId, inst.parentId, compId, instData, getComponentSourceId(inst), true);
|
|
6706
6709
|
instProps.set(instId, effectivePropsIn(g, compId, instData.properties));
|
|
6707
6710
|
copyChildren(compId, instId, "", [instId], [compId], 0);
|
|
6708
|
-
const placed = /* @__PURE__ */ new Set([instId, ...out.map((
|
|
6711
|
+
const placed = /* @__PURE__ */ new Set([instId, ...out.map((n2) => n2.id)]);
|
|
6709
6712
|
const keptForeign = [];
|
|
6710
6713
|
for (const id of foreign) {
|
|
6711
|
-
const
|
|
6712
|
-
if (
|
|
6714
|
+
const n2 = g.get(id);
|
|
6715
|
+
if (n2.parentId && placed.has(n2.parentId)) {
|
|
6713
6716
|
placed.add(id);
|
|
6714
|
-
keptForeign.push(
|
|
6717
|
+
keptForeign.push(n2);
|
|
6715
6718
|
}
|
|
6716
6719
|
}
|
|
6717
6720
|
const removed = /* @__PURE__ */ new Set([instId, ...oldIds, ...foreign]);
|
|
@@ -6719,17 +6722,17 @@ function buildInstance(g, instId, opts, taken) {
|
|
|
6719
6722
|
const compSize = getNodeSize(comp);
|
|
6720
6723
|
const rootSize = getNodeSize(root);
|
|
6721
6724
|
if (!getAutoLayout(root) && (Math.abs(compSize.width - rootSize.width) > 1e-9 || Math.abs(compSize.height - rootSize.height) > 1e-9)) {
|
|
6722
|
-
const fixed = new Set(out.filter((
|
|
6725
|
+
const fixed = new Set(out.filter((n2) => getNodeOverrides(n2).some((gr) => gr === "size" || gr === "position")).map((n2) => n2.id));
|
|
6723
6726
|
const updates = applyConstraints(block, instId, compSize, opts.layout || {}).filter((u) => !fixed.has(u.id));
|
|
6724
6727
|
block = applyNodeUpdates(block, updates);
|
|
6725
6728
|
}
|
|
6726
6729
|
if (opts.layout) {
|
|
6727
|
-
const frames = block.filter((
|
|
6730
|
+
const frames = block.filter((n2) => getAutoLayout(n2)).map((n2) => n2.id);
|
|
6728
6731
|
if (frames.length) block = applyNodeUpdates(block, layoutUpMany(block, frames, opts.layout));
|
|
6729
6732
|
}
|
|
6730
|
-
block = block.map((
|
|
6731
|
-
const prev = g.get(
|
|
6732
|
-
return prev && prev !==
|
|
6733
|
+
block = block.map((n2) => {
|
|
6734
|
+
const prev = g.get(n2.id);
|
|
6735
|
+
return prev && prev !== n2 && same(prev, n2) ? prev : n2;
|
|
6733
6736
|
});
|
|
6734
6737
|
return { block, removed };
|
|
6735
6738
|
}
|
|
@@ -6747,20 +6750,20 @@ function rebuildBatch(nodes, ids, opts) {
|
|
|
6747
6750
|
const removed = /* @__PURE__ */ new Set();
|
|
6748
6751
|
for (const b of built.values()) for (const id of b.removed) removed.add(id);
|
|
6749
6752
|
let result = [];
|
|
6750
|
-
for (const
|
|
6751
|
-
const b = built.get(
|
|
6753
|
+
for (const n2 of nodes) {
|
|
6754
|
+
const b = built.get(n2.id);
|
|
6752
6755
|
if (b) result.push(...b.block);
|
|
6753
|
-
else if (!removed.has(
|
|
6756
|
+
else if (!removed.has(n2.id)) result.push(n2);
|
|
6754
6757
|
}
|
|
6755
6758
|
if (opts.layout) {
|
|
6756
|
-
const lookup = new Map(result.map((
|
|
6759
|
+
const lookup = new Map(result.map((n2) => [n2.id, n2]));
|
|
6757
6760
|
const inFrames = [...built.keys()].filter((r) => {
|
|
6758
6761
|
const parent = lookup.get(lookup.get(r)?.parentId ?? "");
|
|
6759
6762
|
return !!getAutoLayout(parent);
|
|
6760
6763
|
});
|
|
6761
6764
|
if (inFrames.length) result = applyNodeUpdates(result, layoutUpMany(result, inFrames, opts.layout));
|
|
6762
6765
|
}
|
|
6763
|
-
return result.length === nodes.length && result.every((
|
|
6766
|
+
return result.length === nodes.length && result.every((n2, i) => n2 === nodes[i]) ? nodes : result;
|
|
6764
6767
|
}
|
|
6765
6768
|
function rebuildInstances(nodes, comps, resync, opts) {
|
|
6766
6769
|
let current = nodes;
|
|
@@ -6775,10 +6778,10 @@ function rebuildInstances(nodes, comps, resync, opts) {
|
|
|
6775
6778
|
if (comps.size === 0) return current;
|
|
6776
6779
|
const g = new Graph(current);
|
|
6777
6780
|
const rootsOf = /* @__PURE__ */ new Map();
|
|
6778
|
-
for (const
|
|
6779
|
-
const inst = getInstanceData(
|
|
6781
|
+
for (const n2 of current) {
|
|
6782
|
+
const inst = getInstanceData(n2);
|
|
6780
6783
|
if (!inst) continue;
|
|
6781
|
-
const root = rootInstanceIn(g,
|
|
6784
|
+
const root = rootInstanceIn(g, n2.id) ?? n2.id;
|
|
6782
6785
|
let set = rootsOf.get(inst.componentId);
|
|
6783
6786
|
if (!set) rootsOf.set(inst.componentId, set = /* @__PURE__ */ new Set());
|
|
6784
6787
|
set.add(root);
|
|
@@ -6812,7 +6815,7 @@ function rebuildInstances(nodes, comps, resync, opts) {
|
|
|
6812
6815
|
function finish(original, result, opts) {
|
|
6813
6816
|
let out = result;
|
|
6814
6817
|
if (opts.tokens?.state) out = resolveCanvasTokens(out, opts.tokens.state, opts.tokens);
|
|
6815
|
-
if (out.length === original.length && out.every((
|
|
6818
|
+
if (out.length === original.length && out.every((n2, i) => n2 === original[i])) return original;
|
|
6816
6819
|
return out;
|
|
6817
6820
|
}
|
|
6818
6821
|
function syncCanvasInstance(nodes, instanceId, options = {}) {
|
|
@@ -6821,7 +6824,7 @@ function syncCanvasInstance(nodes, instanceId, options = {}) {
|
|
|
6821
6824
|
}
|
|
6822
6825
|
function syncAllCanvasInstances(nodes, options = {}) {
|
|
6823
6826
|
const opts = resolveSync(options);
|
|
6824
|
-
const comps = new Set(nodes.filter(isCanvasComponent).map((
|
|
6827
|
+
const comps = new Set(nodes.filter(isCanvasComponent).map((n2) => n2.id));
|
|
6825
6828
|
return finish(nodes, rebuildInstances([...nodes], comps, /* @__PURE__ */ new Set(), opts), opts);
|
|
6826
6829
|
}
|
|
6827
6830
|
function rebaseInstance(nodes, instId, tokens) {
|
|
@@ -6836,8 +6839,8 @@ function rebaseInstance(nodes, instId, tokens) {
|
|
|
6836
6839
|
const walk = (parent, prefix) => {
|
|
6837
6840
|
const counts = /* @__PURE__ */ new Map();
|
|
6838
6841
|
for (const c of g.children(parent)) {
|
|
6839
|
-
const
|
|
6840
|
-
const name = getLayerName(viaSource && g.get(getComponentSourceId(
|
|
6842
|
+
const n2 = g.get(c);
|
|
6843
|
+
const name = getLayerName(viaSource && g.get(getComponentSourceId(n2)) || n2);
|
|
6841
6844
|
const k = counts.get(name) ?? 0;
|
|
6842
6845
|
counts.set(name, k + 1);
|
|
6843
6846
|
const path = `${prefix}/${k === 0 ? name : `${name}#${k}`}`;
|
|
@@ -6853,9 +6856,9 @@ function rebaseInstance(nodes, instId, tokens) {
|
|
|
6853
6856
|
paths(instId, true, mine, false);
|
|
6854
6857
|
const updates = /* @__PURE__ */ new Map();
|
|
6855
6858
|
for (const [id, path] of mine) {
|
|
6856
|
-
const
|
|
6859
|
+
const n2 = g.get(id);
|
|
6857
6860
|
let main;
|
|
6858
|
-
let cur = getComponentSourceId(
|
|
6861
|
+
let cur = getComponentSourceId(n2);
|
|
6859
6862
|
for (let i = 0; cur && i < MAX_DEPTH; i++) {
|
|
6860
6863
|
if (cur !== compId && g.get(cur) && g.isAncestor(compId, cur)) {
|
|
6861
6864
|
main = cur;
|
|
@@ -6865,15 +6868,15 @@ function rebaseInstance(nodes, instId, tokens) {
|
|
|
6865
6868
|
}
|
|
6866
6869
|
main ??= comp ? theirs.get(path) : void 0;
|
|
6867
6870
|
const m = g.get(main);
|
|
6868
|
-
let next =
|
|
6871
|
+
let next = n2;
|
|
6869
6872
|
if (m) {
|
|
6870
|
-
const bound = /* @__PURE__ */ new Set([...propertyDrivenGroups(g, m), ...tokenDrivenGroups(
|
|
6871
|
-
const groups = new Set(getNodeOverrides(
|
|
6872
|
-
for (const gr of diffOverrideGroups(m,
|
|
6873
|
-
if (isCanvasInstance(m) && isCanvasInstance(
|
|
6874
|
-
next = setOverrides(withData(
|
|
6875
|
-
} else next = unlinked(
|
|
6876
|
-
if (next !==
|
|
6873
|
+
const bound = /* @__PURE__ */ new Set([...propertyDrivenGroups(g, m), ...tokenDrivenGroups(n2, tokens)]);
|
|
6874
|
+
const groups = new Set(getNodeOverrides(n2).filter((gr) => gr !== "component" && gr !== "props"));
|
|
6875
|
+
for (const gr of diffOverrideGroups(m, n2)) if (gr !== "size" && gr !== "position" && !bound.has(gr)) groups.add(gr);
|
|
6876
|
+
if (isCanvasInstance(m) && isCanvasInstance(n2) && getInstanceData(m).componentId !== getInstanceData(n2).componentId) groups.add("component");
|
|
6877
|
+
next = setOverrides(withData(n2, { ...dataOf(n2), [COMPONENT_SOURCE_DATA_KEY]: m.id }), groups);
|
|
6878
|
+
} else next = unlinked(n2);
|
|
6879
|
+
if (next !== n2) updates.set(id, next);
|
|
6877
6880
|
}
|
|
6878
6881
|
const root = g.get(instId);
|
|
6879
6882
|
let nextRoot = withData(root, { ...dataOf(root), [COMPONENT_SOURCE_DATA_KEY]: compId });
|
|
@@ -6885,7 +6888,7 @@ function rebaseInstance(nodes, instId, tokens) {
|
|
|
6885
6888
|
nextRoot = setOverrides(nextRoot, groups);
|
|
6886
6889
|
}
|
|
6887
6890
|
updates.set(instId, nextRoot);
|
|
6888
|
-
return nodes.map((
|
|
6891
|
+
return nodes.map((n2) => updates.get(n2.id) ?? n2);
|
|
6889
6892
|
}
|
|
6890
6893
|
function sizeFromLayout(g, node) {
|
|
6891
6894
|
const parentFlows = !!getAutoLayout(g.get(node.parentId)) && !getChildLayout(node).absolute;
|
|
@@ -6900,7 +6903,7 @@ function syncCanvasComponents(before, after, options = {}) {
|
|
|
6900
6903
|
const prev = new Graph(before);
|
|
6901
6904
|
let nodes = [...after];
|
|
6902
6905
|
const resync = /* @__PURE__ */ new Set();
|
|
6903
|
-
const afterIds = new Set(after.map((
|
|
6906
|
+
const afterIds = new Set(after.map((n2) => n2.id));
|
|
6904
6907
|
const restore = [];
|
|
6905
6908
|
for (const b of before) {
|
|
6906
6909
|
if (afterIds.has(b.id) || getComponentSourceId(b) === void 0 || isCanvasInstance(b) && !enclosingInstanceIn(prev, b.id)) continue;
|
|
@@ -6909,7 +6912,7 @@ function syncCanvasComponents(before, after, options = {}) {
|
|
|
6909
6912
|
restore.push(b);
|
|
6910
6913
|
}
|
|
6911
6914
|
if (restore.length) {
|
|
6912
|
-
const restoring = new Set(restore.map((
|
|
6915
|
+
const restoring = new Set(restore.map((n2) => n2.id));
|
|
6913
6916
|
for (const b of restore) nodes.push(b.parentId && restoring.has(b.parentId) ? b : writeOverrideGroup(b, "hidden", true));
|
|
6914
6917
|
for (const b of restore) {
|
|
6915
6918
|
const r = rootInstanceIn(prev, b.id);
|
|
@@ -6917,104 +6920,104 @@ function syncCanvasComponents(before, after, options = {}) {
|
|
|
6917
6920
|
}
|
|
6918
6921
|
}
|
|
6919
6922
|
let g = new Graph(nodes);
|
|
6920
|
-
const added = nodes.filter((
|
|
6923
|
+
const added = nodes.filter((n2) => !prev.byId.has(n2.id));
|
|
6921
6924
|
if (added.length) {
|
|
6922
|
-
const addedIds = new Set(added.map((
|
|
6925
|
+
const addedIds = new Set(added.map((n2) => n2.id));
|
|
6923
6926
|
const moves = /* @__PURE__ */ new Map();
|
|
6924
|
-
for (const
|
|
6925
|
-
if (!
|
|
6926
|
-
const r = rootInstanceIn(g,
|
|
6927
|
+
for (const n2 of added) {
|
|
6928
|
+
if (!n2.parentId || addedIds.has(n2.parentId)) continue;
|
|
6929
|
+
const r = rootInstanceIn(g, n2.parentId);
|
|
6927
6930
|
if (!r || addedIds.has(r)) continue;
|
|
6928
6931
|
const rootNode = g.get(r);
|
|
6929
|
-
const abs = getAbsolutePosition(
|
|
6932
|
+
const abs = getAbsolutePosition(n2, g.byId);
|
|
6930
6933
|
const parent = g.get(rootNode.parentId);
|
|
6931
6934
|
const base = parent ? getAbsolutePosition(parent, g.byId) : { x: 0, y: 0 };
|
|
6932
|
-
const moved = { ...
|
|
6935
|
+
const moved = { ...n2, position: { x: abs.x - base.x, y: abs.y - base.y } };
|
|
6933
6936
|
if (rootNode.parentId) moved.parentId = rootNode.parentId;
|
|
6934
6937
|
else delete moved.parentId;
|
|
6935
|
-
moves.set(
|
|
6938
|
+
moves.set(n2.id, moved);
|
|
6936
6939
|
}
|
|
6937
6940
|
if (moves.size) {
|
|
6938
|
-
nodes = nodes.map((
|
|
6941
|
+
nodes = nodes.map((n2) => moves.get(n2.id) ?? n2);
|
|
6939
6942
|
g = new Graph(nodes);
|
|
6940
6943
|
}
|
|
6941
6944
|
const rebase = [];
|
|
6942
6945
|
const strips = /* @__PURE__ */ new Map();
|
|
6943
|
-
for (const
|
|
6944
|
-
const cur = g.get(
|
|
6946
|
+
for (const n2 of added) {
|
|
6947
|
+
const cur = g.get(n2.id);
|
|
6945
6948
|
if (isCanvasInstance(cur)) {
|
|
6946
|
-
if (enclosingInstanceIn(g,
|
|
6949
|
+
if (enclosingInstanceIn(g, n2.id) === void 0 && getComponentSourceId(cur) !== getInstanceData(cur).componentId) rebase.push(n2.id);
|
|
6947
6950
|
continue;
|
|
6948
6951
|
}
|
|
6949
6952
|
if (getComponentSourceId(cur) === void 0 && getNodeOverrides(cur).length === 0) continue;
|
|
6950
|
-
const r = rootInstanceIn(g,
|
|
6951
|
-
if (!r || !addedIds.has(r) || moves.has(
|
|
6953
|
+
const r = rootInstanceIn(g, n2.id);
|
|
6954
|
+
if (!r || !addedIds.has(r) || moves.has(n2.id)) strips.set(n2.id, unlinked(cur, true));
|
|
6952
6955
|
}
|
|
6953
|
-
if (strips.size) nodes = nodes.map((
|
|
6956
|
+
if (strips.size) nodes = nodes.map((n2) => strips.get(n2.id) ?? n2);
|
|
6954
6957
|
for (const id of rebase) nodes = rebaseInstance(nodes, id, opts.tokens);
|
|
6955
6958
|
g = new Graph(nodes);
|
|
6956
6959
|
}
|
|
6957
6960
|
const overrideUpdates = /* @__PURE__ */ new Map();
|
|
6958
|
-
for (const
|
|
6959
|
-
const b = prev.get(
|
|
6960
|
-
if (!b || b ===
|
|
6961
|
-
const inst = owningInstanceIn(g,
|
|
6962
|
-
if (!inst || getComponentSourceId(
|
|
6963
|
-
const topRoot = inst ===
|
|
6961
|
+
for (const n2 of nodes) {
|
|
6962
|
+
const b = prev.get(n2.id);
|
|
6963
|
+
if (!b || b === n2) continue;
|
|
6964
|
+
const inst = owningInstanceIn(g, n2.id);
|
|
6965
|
+
if (!inst || getComponentSourceId(n2) === void 0 && inst !== n2.id) continue;
|
|
6966
|
+
const topRoot = inst === n2.id && enclosingInstanceIn(g, n2.id) === void 0;
|
|
6964
6967
|
const bi = getInstanceData(b);
|
|
6965
|
-
const ni = getInstanceData(
|
|
6966
|
-
const raw = diffOverrideGroups(b,
|
|
6968
|
+
const ni = getInstanceData(n2);
|
|
6969
|
+
const raw = diffOverrideGroups(b, n2);
|
|
6967
6970
|
if (topRoot) {
|
|
6968
|
-
if (bi && ni && (bi.componentId !== ni.componentId || !same(bi.properties ?? {}, ni.properties ?? {}))) resync.add(
|
|
6969
|
-
if (raw.includes("size")) resync.add(
|
|
6971
|
+
if (bi && ni && (bi.componentId !== ni.componentId || !same(bi.properties ?? {}, ni.properties ?? {}))) resync.add(n2.id);
|
|
6972
|
+
if (raw.includes("size")) resync.add(n2.id);
|
|
6970
6973
|
}
|
|
6971
|
-
let groups = raw.filter((gr) => gr !== "position" && (gr !== "size" || topRoot && !sizeFromLayout(g,
|
|
6974
|
+
let groups = raw.filter((gr) => gr !== "position" && (gr !== "size" || topRoot && !sizeFromLayout(g, n2)));
|
|
6972
6975
|
if (topRoot) groups = groups.filter((gr) => !isOwnRootGroup(gr));
|
|
6973
6976
|
let cleared = [];
|
|
6974
|
-
const srcId = topRoot ? ni?.componentId : getComponentSourceId(
|
|
6977
|
+
const srcId = topRoot ? ni?.componentId : getComponentSourceId(n2);
|
|
6975
6978
|
const src = g.get(srcId);
|
|
6976
6979
|
if (src) {
|
|
6977
6980
|
const reference = topRoot ? rootReference(g, src) : src;
|
|
6978
|
-
const differs = new Set(diffOverrideGroups(reference,
|
|
6979
|
-
const driven = new Set(tokenDrivenGroups(
|
|
6981
|
+
const differs = new Set(diffOverrideGroups(reference, n2));
|
|
6982
|
+
const driven = new Set(tokenDrivenGroups(n2, opts.tokens));
|
|
6980
6983
|
groups = groups.filter((gr) => differs.has(gr) && !driven.has(gr));
|
|
6981
|
-
cleared = raw.filter((gr) => gr !== "size" && gr !== "position" && !differs.has(gr) && getNodeOverrides(
|
|
6984
|
+
cleared = raw.filter((gr) => gr !== "size" && gr !== "position" && !differs.has(gr) && getNodeOverrides(n2).includes(gr));
|
|
6982
6985
|
if (topRoot) cleared = cleared.filter((gr) => !isOwnRootGroup(gr));
|
|
6983
6986
|
}
|
|
6984
|
-
const lost = getNodeOverrides(b).some((gr) => !getNodeOverrides(
|
|
6987
|
+
const lost = getNodeOverrides(b).some((gr) => !getNodeOverrides(n2).includes(gr));
|
|
6985
6988
|
const nestedSwitch = !topRoot && raw.some((gr) => gr === "component" || gr === "props");
|
|
6986
6989
|
if (groups.length || cleared.length) {
|
|
6987
|
-
const set = new Set(getNodeOverrides(
|
|
6990
|
+
const set = new Set(getNodeOverrides(n2));
|
|
6988
6991
|
for (const gr of groups) set.add(gr);
|
|
6989
6992
|
for (const gr of cleared) set.delete(gr);
|
|
6990
|
-
const updated = setOverrides(
|
|
6991
|
-
if (updated !==
|
|
6993
|
+
const updated = setOverrides(n2, set);
|
|
6994
|
+
if (updated !== n2) overrideUpdates.set(n2.id, updated);
|
|
6992
6995
|
}
|
|
6993
6996
|
if (lost || nestedSwitch) {
|
|
6994
|
-
const r = rootInstanceIn(g,
|
|
6997
|
+
const r = rootInstanceIn(g, n2.id);
|
|
6995
6998
|
if (r) resync.add(r);
|
|
6996
6999
|
}
|
|
6997
7000
|
}
|
|
6998
7001
|
if (overrideUpdates.size) {
|
|
6999
|
-
nodes = nodes.map((
|
|
7002
|
+
nodes = nodes.map((n2) => overrideUpdates.get(n2.id) ?? n2);
|
|
7000
7003
|
g = new Graph(nodes);
|
|
7001
7004
|
}
|
|
7002
7005
|
const comps = /* @__PURE__ */ new Set();
|
|
7003
|
-
for (const
|
|
7004
|
-
const b = prev.get(
|
|
7005
|
-
if (b ===
|
|
7006
|
-
const c = owningComponentIn(g,
|
|
7007
|
-
if (isCanvasComponentSet(
|
|
7008
|
-
for (const v of variantsIn(g,
|
|
7006
|
+
for (const n2 of nodes) {
|
|
7007
|
+
const b = prev.get(n2.id);
|
|
7008
|
+
if (b === n2) continue;
|
|
7009
|
+
const c = owningComponentIn(g, n2.id);
|
|
7010
|
+
if (isCanvasComponentSet(n2) && (!b || !same(dataOf(b)[COMPONENT_SET_DATA_KEY], dataOf(n2)[COMPONENT_SET_DATA_KEY]))) {
|
|
7011
|
+
for (const v of variantsIn(g, n2.id)) comps.add(v.id);
|
|
7009
7012
|
}
|
|
7010
7013
|
if (!c) continue;
|
|
7011
7014
|
if (!b) {
|
|
7012
7015
|
comps.add(c);
|
|
7013
7016
|
continue;
|
|
7014
7017
|
}
|
|
7015
|
-
const structural = b.parentId !==
|
|
7016
|
-
const diff = diffOverrideGroups(b,
|
|
7017
|
-
if (!structural && (diff.length === 0 ||
|
|
7018
|
+
const structural = b.parentId !== n2.parentId || !same(dataOf(b)[COMPONENT_DATA_KEY], dataOf(n2)[COMPONENT_DATA_KEY]) || !same(getComponentPropertyRefs(b), getComponentPropertyRefs(n2)) || getComponentSourceId(b) !== getComponentSourceId(n2) || !same(getNodeOverrides(b), getNodeOverrides(n2));
|
|
7019
|
+
const diff = diffOverrideGroups(b, n2);
|
|
7020
|
+
if (!structural && (diff.length === 0 || n2.id === c && diff.every(isOwnRootGroup))) continue;
|
|
7018
7021
|
comps.add(c);
|
|
7019
7022
|
}
|
|
7020
7023
|
for (const b of before) {
|
|
@@ -7025,7 +7028,7 @@ function syncCanvasComponents(before, after, options = {}) {
|
|
|
7025
7028
|
{
|
|
7026
7029
|
const order = (list) => {
|
|
7027
7030
|
const m = /* @__PURE__ */ new Map();
|
|
7028
|
-
for (const
|
|
7031
|
+
for (const n2 of list) if (n2.parentId) m.set(n2.parentId, [...m.get(n2.parentId) ?? [], n2.id]);
|
|
7029
7032
|
return m;
|
|
7030
7033
|
};
|
|
7031
7034
|
const ob = order(before);
|
|
@@ -7060,12 +7063,12 @@ function wrapInFrame(nodes, ids, frame) {
|
|
|
7060
7063
|
let minY = Infinity;
|
|
7061
7064
|
let maxX = -Infinity;
|
|
7062
7065
|
let maxY = -Infinity;
|
|
7063
|
-
for (const
|
|
7064
|
-
const { width: width2, height: height2 } = getNodeSize(
|
|
7065
|
-
minX = Math.min(minX,
|
|
7066
|
-
minY = Math.min(minY,
|
|
7067
|
-
maxX = Math.max(maxX,
|
|
7068
|
-
maxY = Math.max(maxY,
|
|
7066
|
+
for (const n2 of roots) {
|
|
7067
|
+
const { width: width2, height: height2 } = getNodeSize(n2);
|
|
7068
|
+
minX = Math.min(minX, n2.position.x);
|
|
7069
|
+
minY = Math.min(minY, n2.position.y);
|
|
7070
|
+
maxX = Math.max(maxX, n2.position.x + width2);
|
|
7071
|
+
maxY = Math.max(maxY, n2.position.y + height2);
|
|
7069
7072
|
}
|
|
7070
7073
|
minX -= frame.padding;
|
|
7071
7074
|
minY -= frame.padding;
|
|
@@ -7085,11 +7088,11 @@ function wrapInFrame(nodes, ids, frame) {
|
|
|
7085
7088
|
...parentId ? { parentId } : {}
|
|
7086
7089
|
};
|
|
7087
7090
|
const selected = new Set(ids);
|
|
7088
|
-
const firstIndex = nodes.findIndex((
|
|
7091
|
+
const firstIndex = nodes.findIndex((n2) => selected.has(n2.id));
|
|
7089
7092
|
const out = [];
|
|
7090
|
-
nodes.forEach((
|
|
7093
|
+
nodes.forEach((n2, i) => {
|
|
7091
7094
|
if (i === firstIndex) out.push(wrapper);
|
|
7092
|
-
out.push(selected.has(
|
|
7095
|
+
out.push(selected.has(n2.id) ? { ...n2, parentId: frame.id, position: { x: n2.position.x - minX, y: n2.position.y - minY } } : n2);
|
|
7093
7096
|
});
|
|
7094
7097
|
return out;
|
|
7095
7098
|
}
|
|
@@ -7110,7 +7113,7 @@ function createCanvasComponent(nodes, ids, options = {}) {
|
|
|
7110
7113
|
const node = g.get(roots[0]);
|
|
7111
7114
|
const frameLike = !isCanvasInstance(node) && (g.children(node.id).length > 0 || typeof node.type === "string" && frameTypes.includes(node.type) || !!getAutoLayout(node));
|
|
7112
7115
|
if (frameLike) {
|
|
7113
|
-
const after2 = nodes.map((
|
|
7116
|
+
const after2 = nodes.map((n2) => n2.id === node.id ? withData(n2, { ...dataOf(n2), [COMPONENT_DATA_KEY]: {} }) : n2);
|
|
7114
7117
|
return done(nodes, after2, [node.id], options);
|
|
7115
7118
|
}
|
|
7116
7119
|
}
|
|
@@ -7127,7 +7130,7 @@ function combineCanvasComponentsAsVariants(nodes, ids, options = {}) {
|
|
|
7127
7130
|
if (picked.some((id2) => variantSetIn(g, id2))) return fail(nodes, "invalid", "A component is already a variant of a set.");
|
|
7128
7131
|
if (picked.some((id2) => owningInstanceIn(g, id2))) return fail(nodes, "inside-instance", "Components inside an instance can't be combined.");
|
|
7129
7132
|
if (new Set(picked.map((id2) => g.get(id2).parentId ?? "")).size > 1) return fail(nodes, "invalid", "Select components that share a parent.");
|
|
7130
|
-
const ordered = nodes.filter((
|
|
7133
|
+
const ordered = nodes.filter((n2) => picked.includes(n2.id)).map((n2) => n2.id);
|
|
7131
7134
|
const first = g.get(ordered[0]);
|
|
7132
7135
|
const firstName = getLayerName(first);
|
|
7133
7136
|
const name = options.name ?? (firstName && !firstName.includes("=") ? firstName.split("/")[0].trim() : "Component");
|
|
@@ -7140,13 +7143,13 @@ function combineCanvasComponentsAsVariants(nodes, ids, options = {}) {
|
|
|
7140
7143
|
});
|
|
7141
7144
|
const order = [];
|
|
7142
7145
|
for (const vid of ordered) for (const k of Object.keys(getVariantValues(g.get(vid)))) if (!order.includes(k)) order.push(k);
|
|
7143
|
-
after = after.map((
|
|
7144
|
-
const k = ordered.indexOf(
|
|
7145
|
-
if (k < 0) return
|
|
7146
|
-
let variant = getVariantValues(
|
|
7146
|
+
after = after.map((n2) => {
|
|
7147
|
+
const k = ordered.indexOf(n2.id);
|
|
7148
|
+
if (k < 0) return n2;
|
|
7149
|
+
let variant = getVariantValues(n2);
|
|
7147
7150
|
if (Object.keys(variant).length === 0) variant = { "Property 1": k === 0 ? "Default" : `Variant${k + 1}` };
|
|
7148
|
-
const comp = { ...getComponentData(
|
|
7149
|
-
return withData(
|
|
7151
|
+
const comp = { ...getComponentData(n2) ?? {}, variant };
|
|
7152
|
+
return withData(n2, { ...dataOf(n2), [COMPONENT_DATA_KEY]: comp, label: formatVariantName(variant, order) });
|
|
7150
7153
|
});
|
|
7151
7154
|
return done(nodes, after, [id], options);
|
|
7152
7155
|
}
|
|
@@ -7207,7 +7210,7 @@ function detachCanvasInstance(nodes, ids, options = {}) {
|
|
|
7207
7210
|
delete data[COMPONENT_SOURCE_DATA_KEY];
|
|
7208
7211
|
delete data[COMPONENT_OVERRIDES_DATA_KEY];
|
|
7209
7212
|
updates.set(id, withData(root, data));
|
|
7210
|
-
current = current.map((
|
|
7213
|
+
current = current.map((n2) => updates.get(n2.id) ?? n2);
|
|
7211
7214
|
for (const nn of nested) current = rebaseInstance(current, nn, options.tokens);
|
|
7212
7215
|
doneIds.push(id);
|
|
7213
7216
|
}
|
|
@@ -7221,10 +7224,10 @@ function resetCanvasInstanceOverrides(nodes, id, group, options = {}) {
|
|
|
7221
7224
|
if (!node || !inst) return fail(nodes, "not-found", "Select an instance or a layer inside one.");
|
|
7222
7225
|
const top = inst === id && enclosingInstanceIn(g, id) === void 0;
|
|
7223
7226
|
const updates = /* @__PURE__ */ new Map();
|
|
7224
|
-
const resetProps = (
|
|
7225
|
-
const data = getInstanceData(
|
|
7227
|
+
const resetProps = (n2) => {
|
|
7228
|
+
const data = getInstanceData(n2);
|
|
7226
7229
|
const defaults = effectivePropsIn(g, data.componentId, void 0);
|
|
7227
|
-
return same(data.properties ?? {}, defaults) ?
|
|
7230
|
+
return same(data.properties ?? {}, defaults) ? n2 : withData(n2, { ...dataOf(n2), [INSTANCE_DATA_KEY]: { ...data, properties: defaults } });
|
|
7228
7231
|
};
|
|
7229
7232
|
if (group !== void 0) {
|
|
7230
7233
|
let next = setOverrides(node, getNodeOverrides(node).filter((gr) => gr !== group));
|
|
@@ -7232,14 +7235,14 @@ function resetCanvasInstanceOverrides(nodes, id, group, options = {}) {
|
|
|
7232
7235
|
updates.set(id, next);
|
|
7233
7236
|
} else if (inst === id) {
|
|
7234
7237
|
for (const d of g.subtree(id)) {
|
|
7235
|
-
const
|
|
7236
|
-
const keep = d === id && top ? getNodeOverrides(
|
|
7237
|
-
updates.set(d, setOverrides(
|
|
7238
|
+
const n2 = g.get(d);
|
|
7239
|
+
const keep = d === id && top ? getNodeOverrides(n2).filter((gr) => gr === "size") : [];
|
|
7240
|
+
updates.set(d, setOverrides(n2, keep));
|
|
7238
7241
|
}
|
|
7239
7242
|
if (top) updates.set(id, resetProps(updates.get(id)));
|
|
7240
7243
|
} else updates.set(id, setOverrides(node, []));
|
|
7241
|
-
const after = nodes.map((
|
|
7242
|
-
const changed = after.some((
|
|
7244
|
+
const after = nodes.map((n2) => updates.get(n2.id) ?? n2);
|
|
7245
|
+
const changed = after.some((n2, i) => n2 !== nodes[i]);
|
|
7243
7246
|
if (!changed) return { ok: true, nodes, ids: [] };
|
|
7244
7247
|
const synced = syncCanvasComponents(nodes, after, options);
|
|
7245
7248
|
return { ok: true, nodes: synced, ids: [inst] };
|
|
@@ -7253,21 +7256,21 @@ function pushCanvasInstanceOverrides(nodes, id, options = {}) {
|
|
|
7253
7256
|
const updates = /* @__PURE__ */ new Map();
|
|
7254
7257
|
let pushed = 0;
|
|
7255
7258
|
for (const d of g.subtree(inst)) {
|
|
7256
|
-
const
|
|
7257
|
-
const overrides = getNodeOverrides(
|
|
7259
|
+
const n2 = g.get(d);
|
|
7260
|
+
const overrides = getNodeOverrides(n2);
|
|
7258
7261
|
if (overrides.length === 0) continue;
|
|
7259
|
-
const src = d === inst ? compId : getComponentSourceId(
|
|
7262
|
+
const src = d === inst ? compId : getComponentSourceId(n2);
|
|
7260
7263
|
if (!src || !g.get(src) || src !== compId && !g.isAncestor(compId, src)) continue;
|
|
7261
7264
|
const groups = overrides.filter(
|
|
7262
7265
|
(gr) => gr !== "size" && gr !== "position" && gr !== "component" && gr !== "props" && !(d === inst && (gr === "data.label" || gr === "data.name" || isOwnRootGroup(gr)))
|
|
7263
7266
|
);
|
|
7264
7267
|
if (groups.length === 0) continue;
|
|
7265
7268
|
pushed++;
|
|
7266
|
-
updates.set(src, copyGroups(
|
|
7267
|
-
updates.set(d, setOverrides(
|
|
7269
|
+
updates.set(src, copyGroups(n2, updates.get(src) ?? g.get(src), groups));
|
|
7270
|
+
updates.set(d, setOverrides(n2, overrides.filter((gr) => !groups.includes(gr))));
|
|
7268
7271
|
}
|
|
7269
7272
|
if (pushed === 0) return fail(nodes, "no-overrides", "The instance has no changes to push.");
|
|
7270
|
-
const after = nodes.map((
|
|
7273
|
+
const after = nodes.map((n2) => updates.get(n2.id) ?? n2);
|
|
7271
7274
|
return done(nodes, after, [inst], options);
|
|
7272
7275
|
}
|
|
7273
7276
|
function swapCanvasInstance(nodes, ids, componentId, options = {}) {
|
|
@@ -7277,14 +7280,14 @@ function swapCanvasInstance(nodes, ids, componentId, options = {}) {
|
|
|
7277
7280
|
const updates = /* @__PURE__ */ new Map();
|
|
7278
7281
|
const list = [...new Set(ids)];
|
|
7279
7282
|
for (const id of list) {
|
|
7280
|
-
const
|
|
7281
|
-
const inst = getInstanceData(
|
|
7282
|
-
if (!
|
|
7283
|
-
if (g.isAncestor(main, id) || createsCycleIn(g, main,
|
|
7283
|
+
const n2 = g.get(id);
|
|
7284
|
+
const inst = getInstanceData(n2);
|
|
7285
|
+
if (!n2 || !inst) return fail(nodes, "invalid", `"${id}" is not an instance.`);
|
|
7286
|
+
if (g.isAncestor(main, id) || createsCycleIn(g, main, n2.parentId)) return fail(nodes, "cycle", "An instance can't show the component it is inside.");
|
|
7284
7287
|
const defaults = effectivePropsIn(g, main, void 0);
|
|
7285
7288
|
const properties = {};
|
|
7286
7289
|
for (const [k, d] of Object.entries(defaults)) properties[k] = inst.properties?.[k] !== void 0 && typeof inst.properties[k] === typeof d ? inst.properties[k] : d;
|
|
7287
|
-
updates.set(id, withData(
|
|
7290
|
+
updates.set(id, withData(n2, { ...dataOf(n2), [INSTANCE_DATA_KEY]: { ...inst, componentId: main, properties } }));
|
|
7288
7291
|
if (options.keepTextOverridesOnly) {
|
|
7289
7292
|
for (const d of g.subtree(id)) {
|
|
7290
7293
|
const layer = updates.get(d) ?? g.get(d);
|
|
@@ -7295,7 +7298,7 @@ function swapCanvasInstance(nodes, ids, componentId, options = {}) {
|
|
|
7295
7298
|
}
|
|
7296
7299
|
}
|
|
7297
7300
|
if (list.length === 0) return fail(nodes, "invalid", "Select an instance.");
|
|
7298
|
-
const after = nodes.map((
|
|
7301
|
+
const after = nodes.map((n2) => updates.get(n2.id) ?? n2);
|
|
7299
7302
|
return done(nodes, after, list, options);
|
|
7300
7303
|
}
|
|
7301
7304
|
function setCanvasInstanceProperties(nodes, ids, properties, options = {}) {
|
|
@@ -7304,9 +7307,9 @@ function setCanvasInstanceProperties(nodes, ids, properties, options = {}) {
|
|
|
7304
7307
|
const list = [...new Set(ids)];
|
|
7305
7308
|
if (list.length === 0) return fail(nodes, "invalid", "Select an instance.");
|
|
7306
7309
|
for (const id of list) {
|
|
7307
|
-
const
|
|
7308
|
-
const inst = getInstanceData(
|
|
7309
|
-
if (!
|
|
7310
|
+
const n2 = g.get(id);
|
|
7311
|
+
const inst = getInstanceData(n2);
|
|
7312
|
+
if (!n2 || !inst) return fail(nodes, "invalid", `"${id}" is not an instance.`);
|
|
7310
7313
|
const set = variantSetIn(g, inst.componentId);
|
|
7311
7314
|
const options_ = set ? variantOptionsIn(g, set.id) : [];
|
|
7312
7315
|
const wanted = { ...getVariantValues(g.get(inst.componentId)) };
|
|
@@ -7339,16 +7342,16 @@ function setCanvasInstanceProperties(nodes, ids, properties, options = {}) {
|
|
|
7339
7342
|
} else {
|
|
7340
7343
|
const main = typeof v === "string" ? mainOfIn(g, v) : void 0;
|
|
7341
7344
|
if (!main) return fail(nodes, "type-mismatch", `"${k}" takes a component id.`);
|
|
7342
|
-
if (main === target || componentDepsIn(g, main).has(target) || createsCycleIn(g, main,
|
|
7345
|
+
if (main === target || componentDepsIn(g, main).has(target) || createsCycleIn(g, main, n2.parentId)) {
|
|
7343
7346
|
return fail(nodes, "cycle", `"${k}" can't show a component that contains this one.`);
|
|
7344
7347
|
}
|
|
7345
7348
|
values[k] = main;
|
|
7346
7349
|
}
|
|
7347
7350
|
}
|
|
7348
7351
|
const properties2 = effectivePropsIn(g, target, values);
|
|
7349
|
-
updates.set(id, withData(
|
|
7352
|
+
updates.set(id, withData(n2, { ...dataOf(n2), [INSTANCE_DATA_KEY]: { ...inst, componentId: target, properties: properties2 } }));
|
|
7350
7353
|
}
|
|
7351
|
-
const after = nodes.map((
|
|
7354
|
+
const after = nodes.map((n2) => updates.get(n2.id) ?? n2);
|
|
7352
7355
|
return done(nodes, after, list, options);
|
|
7353
7356
|
}
|
|
7354
7357
|
function setCanvasComponentProperty(nodes, componentId, name, def, options = {}) {
|
|
@@ -7384,8 +7387,8 @@ function setCanvasComponentProperty(nodes, componentId, name, def, options = {})
|
|
|
7384
7387
|
if (renamed !== name) {
|
|
7385
7388
|
for (const c of comps) {
|
|
7386
7389
|
for (const d of g.subtree(c)) {
|
|
7387
|
-
const
|
|
7388
|
-
const refs = { ...getComponentPropertyRefs(
|
|
7390
|
+
const n2 = updates.get(d) ?? g.get(d);
|
|
7391
|
+
const refs = { ...getComponentPropertyRefs(n2) };
|
|
7389
7392
|
let touched = false;
|
|
7390
7393
|
for (const [field, prop] of Object.entries(refs)) {
|
|
7391
7394
|
if (prop !== name) continue;
|
|
@@ -7394,23 +7397,23 @@ function setCanvasComponentProperty(nodes, componentId, name, def, options = {})
|
|
|
7394
7397
|
else refs[field] = renamed;
|
|
7395
7398
|
}
|
|
7396
7399
|
if (!touched) continue;
|
|
7397
|
-
const data = { ...dataOf(
|
|
7400
|
+
const data = { ...dataOf(n2), [COMPONENT_PROPERTY_REFS_DATA_KEY]: refs };
|
|
7398
7401
|
if (Object.keys(refs).length === 0) delete data[COMPONENT_PROPERTY_REFS_DATA_KEY];
|
|
7399
|
-
updates.set(d, withData(
|
|
7402
|
+
updates.set(d, withData(n2, data));
|
|
7400
7403
|
}
|
|
7401
7404
|
}
|
|
7402
|
-
for (const
|
|
7403
|
-
const inst = getInstanceData(
|
|
7405
|
+
for (const n2 of nodes) {
|
|
7406
|
+
const inst = getInstanceData(n2);
|
|
7404
7407
|
if (!inst || !comps.includes(inst.componentId) || !inst.properties || !(name in inst.properties)) continue;
|
|
7405
7408
|
const props = { ...inst.properties };
|
|
7406
7409
|
const v = props[name];
|
|
7407
7410
|
delete props[name];
|
|
7408
7411
|
if (renamed !== null) props[renamed] = v;
|
|
7409
|
-
const cur = updates.get(
|
|
7410
|
-
updates.set(
|
|
7412
|
+
const cur = updates.get(n2.id) ?? n2;
|
|
7413
|
+
updates.set(n2.id, withData(cur, { ...dataOf(cur), [INSTANCE_DATA_KEY]: { ...inst, properties: props } }));
|
|
7411
7414
|
}
|
|
7412
7415
|
}
|
|
7413
|
-
const after = nodes.map((
|
|
7416
|
+
const after = nodes.map((n2) => updates.get(n2.id) ?? n2);
|
|
7414
7417
|
return done(nodes, after, [owner.id], options);
|
|
7415
7418
|
}
|
|
7416
7419
|
function bindCanvasComponentProperty(nodes, layerId, field, name, options = {}) {
|
|
@@ -7432,7 +7435,7 @@ function bindCanvasComponentProperty(nodes, layerId, field, name, options = {})
|
|
|
7432
7435
|
const data = { ...dataOf(layer) };
|
|
7433
7436
|
if (Object.keys(refs).length) data[COMPONENT_PROPERTY_REFS_DATA_KEY] = refs;
|
|
7434
7437
|
else delete data[COMPONENT_PROPERTY_REFS_DATA_KEY];
|
|
7435
|
-
const after = nodes.map((
|
|
7438
|
+
const after = nodes.map((n2) => n2.id === layerId ? withData(n2, data) : n2);
|
|
7436
7439
|
return done(nodes, after, [layerId], options);
|
|
7437
7440
|
}
|
|
7438
7441
|
function restoreCanvasMainComponent(nodes, id, options = {}) {
|
|
@@ -7444,7 +7447,7 @@ function restoreCanvasMainComponent(nodes, id, options = {}) {
|
|
|
7444
7447
|
const compId = inst.componentId;
|
|
7445
7448
|
const sub = g.subtree(id);
|
|
7446
7449
|
const map = /* @__PURE__ */ new Map([[id, compId]]);
|
|
7447
|
-
const taken = new Set(nodes.map((
|
|
7450
|
+
const taken = new Set(nodes.map((n2) => n2.id));
|
|
7448
7451
|
taken.add(compId);
|
|
7449
7452
|
for (const d of sub) {
|
|
7450
7453
|
if (d === id) continue;
|
|
@@ -7457,10 +7460,10 @@ function restoreCanvasMainComponent(nodes, id, options = {}) {
|
|
|
7457
7460
|
const nested = [];
|
|
7458
7461
|
const replaced = /* @__PURE__ */ new Map();
|
|
7459
7462
|
for (const d of sub) {
|
|
7460
|
-
let
|
|
7463
|
+
let n2 = g.get(d);
|
|
7461
7464
|
const nid = map.get(d) ?? d;
|
|
7462
|
-
const parentId =
|
|
7463
|
-
|
|
7465
|
+
const parentId = n2.parentId !== void 0 ? map.get(n2.parentId) ?? n2.parentId : void 0;
|
|
7466
|
+
n2 = { ...n2, id: nid, ...parentId !== void 0 ? { parentId } : {} };
|
|
7464
7467
|
if (d === id) {
|
|
7465
7468
|
const defs = {};
|
|
7466
7469
|
for (const [k, v] of Object.entries(inst.properties ?? {})) {
|
|
@@ -7468,19 +7471,19 @@ function restoreCanvasMainComponent(nodes, id, options = {}) {
|
|
|
7468
7471
|
else if (typeof v === "string" && isCanvasComponent(g.get(v))) defs[k] = { type: "instanceSwap", default: v };
|
|
7469
7472
|
else if (typeof v === "string") defs[k] = { type: "text", default: v };
|
|
7470
7473
|
}
|
|
7471
|
-
const data = { ...dataOf(
|
|
7474
|
+
const data = { ...dataOf(n2) };
|
|
7472
7475
|
delete data[INSTANCE_DATA_KEY];
|
|
7473
7476
|
delete data[COMPONENT_SOURCE_DATA_KEY];
|
|
7474
7477
|
delete data[COMPONENT_OVERRIDES_DATA_KEY];
|
|
7475
7478
|
data[COMPONENT_DATA_KEY] = Object.keys(defs).length ? { properties: defs } : {};
|
|
7476
|
-
|
|
7479
|
+
n2 = withData(n2, data);
|
|
7477
7480
|
} else if (enclosingInstanceIn(g, d) === id) {
|
|
7478
|
-
if (isCanvasInstance(
|
|
7479
|
-
else
|
|
7481
|
+
if (isCanvasInstance(n2)) nested.push(nid);
|
|
7482
|
+
else n2 = unlinked(n2);
|
|
7480
7483
|
}
|
|
7481
|
-
replaced.set(d,
|
|
7484
|
+
replaced.set(d, n2);
|
|
7482
7485
|
}
|
|
7483
|
-
let after = nodes.map((
|
|
7486
|
+
let after = nodes.map((n2) => replaced.get(n2.id) ?? n2);
|
|
7484
7487
|
for (const nn of nested) after = rebaseInstance(after, nn, options.tokens);
|
|
7485
7488
|
return done(nodes, after, [compId], options);
|
|
7486
7489
|
}
|
|
@@ -7588,7 +7591,7 @@ function getNextVariantValues(nodes, setId, from) {
|
|
|
7588
7591
|
return nextVariantValuesIn(g, setId, from ?? defaultVariantIn(g, setId));
|
|
7589
7592
|
}
|
|
7590
7593
|
function relayoutSet(nodes, setId, options) {
|
|
7591
|
-
if (options.layout === false || !getAutoLayout(nodes.find((
|
|
7594
|
+
if (options.layout === false || !getAutoLayout(nodes.find((n2) => n2.id === setId))) return nodes;
|
|
7592
7595
|
return applyNodeUpdates(nodes, layoutUpMany(nodes, [setId], typeof options.layout === "object" ? options.layout : {}));
|
|
7593
7596
|
}
|
|
7594
7597
|
function addCanvasVariant(nodes, setId, options = {}) {
|
|
@@ -7632,23 +7635,23 @@ function addCanvasVariant(nodes, setId, options = {}) {
|
|
|
7632
7635
|
}
|
|
7633
7636
|
const order = variantOrder([...edit.variants.map((v) => v.id), id], edit.values);
|
|
7634
7637
|
const subSet = new Set(sub);
|
|
7635
|
-
const copies = nodes.filter((
|
|
7636
|
-
const next = { ...
|
|
7637
|
-
if (
|
|
7638
|
+
const copies = nodes.filter((n2) => subSet.has(n2.id)).map((n2) => {
|
|
7639
|
+
const next = { ...n2, id: map.get(n2.id) };
|
|
7640
|
+
if (n2.parentId !== void 0 && n2.id !== fromId) next.parentId = map.get(n2.parentId) ?? n2.parentId;
|
|
7638
7641
|
for (const k of RUNTIME_KEYS) delete next[k];
|
|
7639
|
-
if (
|
|
7642
|
+
if (n2.id !== fromId) return next;
|
|
7640
7643
|
next.position = position;
|
|
7641
7644
|
return withVariantValues(next, edit.values.get(id), order);
|
|
7642
7645
|
});
|
|
7643
7646
|
const updates = writeVariantEdit(edit, [id]);
|
|
7644
7647
|
const inSet = new Set(g.subtree(setId));
|
|
7645
7648
|
let last = -1;
|
|
7646
|
-
nodes.forEach((
|
|
7647
|
-
if (inSet.has(
|
|
7649
|
+
nodes.forEach((n2, i) => {
|
|
7650
|
+
if (inSet.has(n2.id)) last = i;
|
|
7648
7651
|
});
|
|
7649
7652
|
let after = [];
|
|
7650
|
-
nodes.forEach((
|
|
7651
|
-
after.push(updates.get(
|
|
7653
|
+
nodes.forEach((n2, i) => {
|
|
7654
|
+
after.push(updates.get(n2.id) ?? n2);
|
|
7652
7655
|
if (i === last) after.push(...copies);
|
|
7653
7656
|
});
|
|
7654
7657
|
if (autoLayout && !options.position) after = relayoutSet(after, setId, options);
|
|
@@ -7669,10 +7672,10 @@ function removeCanvasVariant(nodes, variantId, options = {}) {
|
|
|
7669
7672
|
if (others.length === 0) return fail(nodes, "invalid", "A component set needs at least one variant: delete the set instead.");
|
|
7670
7673
|
const replacement = closestVariant(others, getVariantValues(g.get(variantId)));
|
|
7671
7674
|
const swap = (v) => v === variantId ? replacement : v;
|
|
7672
|
-
const repointed = nodes.map((
|
|
7673
|
-
const data = dataOf(
|
|
7675
|
+
const repointed = nodes.map((n2) => {
|
|
7676
|
+
const data = dataOf(n2);
|
|
7674
7677
|
let next;
|
|
7675
|
-
const inst = getInstanceData(
|
|
7678
|
+
const inst = getInstanceData(n2);
|
|
7676
7679
|
if (inst) {
|
|
7677
7680
|
const moved = { ...inst, componentId: swap(inst.componentId) };
|
|
7678
7681
|
if (inst.properties) moved.properties = Object.fromEntries(Object.entries(inst.properties).map(([k, v]) => [k, swap(v)]));
|
|
@@ -7687,12 +7690,12 @@ function removeCanvasVariant(nodes, variantId, options = {}) {
|
|
|
7687
7690
|
}
|
|
7688
7691
|
if (!same(defs, owner.properties)) next = { ...next ?? data, [key]: { ...owner, properties: defs } };
|
|
7689
7692
|
}
|
|
7690
|
-
return next ? withData(
|
|
7693
|
+
return next ? withData(n2, next) : n2;
|
|
7691
7694
|
});
|
|
7692
7695
|
const mid = syncCanvasComponents(nodes, repointed, options);
|
|
7693
7696
|
const gone = new Set(new Graph(mid).subtree(variantId));
|
|
7694
7697
|
const after = relayoutSet(
|
|
7695
|
-
mid.filter((
|
|
7698
|
+
mid.filter((n2) => !gone.has(n2.id)),
|
|
7696
7699
|
set.id,
|
|
7697
7700
|
options
|
|
7698
7701
|
);
|
|
@@ -7713,17 +7716,17 @@ function setCanvasVariantProperties(nodes, variantId, values, options = {}) {
|
|
|
7713
7716
|
if (dup) return fail(nodes, "invalid", `A variant with ${dup} exists already.`);
|
|
7714
7717
|
const updates = writeVariantEdit(edit);
|
|
7715
7718
|
if (updates.size === 0) return { ok: true, nodes, ids: [variantId] };
|
|
7716
|
-
return done(nodes, nodes.map((
|
|
7719
|
+
return done(nodes, nodes.map((n2) => updates.get(n2.id) ?? n2), [variantId], options);
|
|
7717
7720
|
}
|
|
7718
7721
|
function updateInstanceValues(g, setId, updates, fn) {
|
|
7719
7722
|
const ids = new Set(variantsIn(g, setId).map((v) => v.id));
|
|
7720
|
-
for (const
|
|
7721
|
-
const inst = getInstanceData(
|
|
7723
|
+
for (const n2 of g.nodes) {
|
|
7724
|
+
const inst = getInstanceData(n2);
|
|
7722
7725
|
if (!inst?.properties || !ids.has(inst.componentId)) continue;
|
|
7723
7726
|
const props = fn({ ...inst.properties });
|
|
7724
7727
|
if (same(props, inst.properties)) continue;
|
|
7725
|
-
const cur = updates.get(
|
|
7726
|
-
updates.set(
|
|
7728
|
+
const cur = updates.get(n2.id) ?? n2;
|
|
7729
|
+
updates.set(n2.id, withData(cur, { ...dataOf(cur), [INSTANCE_DATA_KEY]: { ...inst, properties: props } }));
|
|
7727
7730
|
}
|
|
7728
7731
|
}
|
|
7729
7732
|
function renameCanvasVariantProperty(nodes, setId, name, newName, options = {}) {
|
|
@@ -7742,7 +7745,7 @@ function renameCanvasVariantProperty(nodes, setId, name, newName, options = {})
|
|
|
7742
7745
|
for (const [id, v] of edit.values) edit.values.set(id, rename(v));
|
|
7743
7746
|
const updates = writeVariantEdit(edit);
|
|
7744
7747
|
updateInstanceValues(g, setId, updates, (props) => name in props ? rename(props) : props);
|
|
7745
|
-
return done(nodes, nodes.map((
|
|
7748
|
+
return done(nodes, nodes.map((n2) => updates.get(n2.id) ?? n2), [setId], options);
|
|
7746
7749
|
}
|
|
7747
7750
|
function renameCanvasVariantValue(nodes, setId, property, value, newValue, options = {}) {
|
|
7748
7751
|
const g = new Graph(nodes);
|
|
@@ -7765,34 +7768,34 @@ function renameCanvasVariantValue(nodes, setId, property, value, newValue, optio
|
|
|
7765
7768
|
if (dup) return fail(nodes, "invalid", `A variant with ${dup} exists already.`);
|
|
7766
7769
|
const updates = writeVariantEdit(edit);
|
|
7767
7770
|
updateInstanceValues(g, setId, updates, (props) => props[property] === value ? { ...props, [property]: to } : props);
|
|
7768
|
-
return done(nodes, nodes.map((
|
|
7771
|
+
return done(nodes, nodes.map((n2) => updates.get(n2.id) ?? n2), [setId], options);
|
|
7769
7772
|
}
|
|
7770
7773
|
|
|
7771
7774
|
// src/canvas/componentsController.ts
|
|
7772
7775
|
function makePatch(from, to) {
|
|
7773
|
-
const fromIds = new Map(from.map((
|
|
7774
|
-
const toIds = new Set(to.map((
|
|
7776
|
+
const fromIds = new Map(from.map((n2) => [n2.id, n2]));
|
|
7777
|
+
const toIds = new Set(to.map((n2) => n2.id));
|
|
7775
7778
|
const changes = /* @__PURE__ */ new Map();
|
|
7776
|
-
for (const
|
|
7777
|
-
for (const
|
|
7778
|
-
return { changes, order: to.map((
|
|
7779
|
+
for (const n2 of to) if (fromIds.get(n2.id) !== n2) changes.set(n2.id, n2);
|
|
7780
|
+
for (const n2 of from) if (!toIds.has(n2.id)) changes.set(n2.id, null);
|
|
7781
|
+
return { changes, order: to.map((n2) => n2.id) };
|
|
7779
7782
|
}
|
|
7780
7783
|
function applyPatch(current, patch) {
|
|
7781
|
-
const byId = new Map(current.map((
|
|
7782
|
-
for (const [id,
|
|
7783
|
-
if (
|
|
7784
|
+
const byId = new Map(current.map((n2) => [n2.id, n2]));
|
|
7785
|
+
for (const [id, n2] of patch.changes) {
|
|
7786
|
+
if (n2) byId.set(id, n2);
|
|
7784
7787
|
else byId.delete(id);
|
|
7785
7788
|
}
|
|
7786
7789
|
const out = [];
|
|
7787
7790
|
const placed = /* @__PURE__ */ new Set();
|
|
7788
7791
|
for (const id of patch.order) {
|
|
7789
|
-
const
|
|
7790
|
-
if (
|
|
7791
|
-
out.push(
|
|
7792
|
+
const n2 = byId.get(id);
|
|
7793
|
+
if (n2 && !placed.has(id)) {
|
|
7794
|
+
out.push(n2);
|
|
7792
7795
|
placed.add(id);
|
|
7793
7796
|
}
|
|
7794
7797
|
}
|
|
7795
|
-
for (const
|
|
7798
|
+
for (const n2 of current) if (!placed.has(n2.id) && byId.has(n2.id)) out.push(byId.get(n2.id));
|
|
7796
7799
|
return out;
|
|
7797
7800
|
}
|
|
7798
7801
|
function createCanvasComponentsController(options) {
|
|
@@ -7803,7 +7806,7 @@ function createCanvasComponentsController(options) {
|
|
|
7803
7806
|
layout: options.layout,
|
|
7804
7807
|
tokens: options.tokens
|
|
7805
7808
|
});
|
|
7806
|
-
const selection = (ids) => ids ? [...ids] : options.getSelectedIds?.() ?? options.getNodes().filter((
|
|
7809
|
+
const selection = (ids) => ids ? [...ids] : options.getSelectedIds?.() ?? options.getNodes().filter((n2) => n2.selected).map((n2) => n2.id);
|
|
7807
7810
|
const target = (id) => id ?? selection()[0];
|
|
7808
7811
|
function set(next) {
|
|
7809
7812
|
synced = next;
|
|
@@ -7837,7 +7840,7 @@ function createCanvasComponentsController(options) {
|
|
|
7837
7840
|
const refused = (why) => ({ ok: false, nodes: nodes(), code: "not-found", reason: why });
|
|
7838
7841
|
const setOf = (id) => {
|
|
7839
7842
|
const at = target(id);
|
|
7840
|
-
const node = at ? nodes().find((
|
|
7843
|
+
const node = at ? nodes().find((n2) => n2.id === at) : void 0;
|
|
7841
7844
|
if (!node) return void 0;
|
|
7842
7845
|
return isCanvasComponentSet(node) ? node.id : getVariantSet(nodes(), node.id);
|
|
7843
7846
|
};
|
|
@@ -7864,22 +7867,22 @@ function createCanvasComponentsController(options) {
|
|
|
7864
7867
|
/** Create Component from `ids` (default: the selection). */
|
|
7865
7868
|
createComponent(ids, createOptions = {}) {
|
|
7866
7869
|
const list = selection(ids);
|
|
7867
|
-
return run("Create Component", (
|
|
7870
|
+
return run("Create Component", (n2) => createCanvasComponent(n2, list, { ...syncOptions(), ...createOptions }));
|
|
7868
7871
|
},
|
|
7869
7872
|
canCreateComponent: (ids) => reason(createCanvasComponent(nodes(), selection(ids), { layout: false })),
|
|
7870
7873
|
/** Combine as Variants: wraps the selected components in a component set. */
|
|
7871
7874
|
combineAsVariants(ids, combineOptions = {}) {
|
|
7872
7875
|
const list = selection(ids);
|
|
7873
|
-
return run("Combine as Variants", (
|
|
7876
|
+
return run("Combine as Variants", (n2) => combineCanvasComponentsAsVariants(n2, list, { ...syncOptions(), ...combineOptions }));
|
|
7874
7877
|
},
|
|
7875
7878
|
canCombineAsVariants: (ids) => reason(combineCanvasComponentsAsVariants(nodes(), selection(ids), { layout: false })),
|
|
7876
7879
|
/** Create Instance of a component or component set. */
|
|
7877
7880
|
createInstance(componentId, createOptions = {}) {
|
|
7878
|
-
return run("Create Instance", (
|
|
7881
|
+
return run("Create Instance", (n2) => createCanvasInstance(n2, componentId, { ...syncOptions(), ...createOptions }));
|
|
7879
7882
|
},
|
|
7880
7883
|
canCreateInstance(componentId, parentId) {
|
|
7881
7884
|
const list = nodes();
|
|
7882
|
-
const target2 = componentId ? list.find((
|
|
7885
|
+
const target2 = componentId ? list.find((n2) => n2.id === componentId) : void 0;
|
|
7883
7886
|
if (!target2 || !isCanvasComponent(target2) && !isCanvasComponentSet(target2)) return "Choose a component or component set.";
|
|
7884
7887
|
if (wouldCreateComponentCycle(list, componentId, parentId)) return "An instance can't be placed inside its own main component.";
|
|
7885
7888
|
if (parentId && getOwningInstance(list, parentId)) return "Instances can't gain layers: place it outside the instance.";
|
|
@@ -7888,11 +7891,11 @@ function createCanvasComponentsController(options) {
|
|
|
7888
7891
|
/** Detach Instance (default: the selected instances). */
|
|
7889
7892
|
detachInstance(ids) {
|
|
7890
7893
|
const list = selection(ids);
|
|
7891
|
-
return run("Detach Instance", (
|
|
7894
|
+
return run("Detach Instance", (n2) => detachCanvasInstance(n2, list, syncOptions()));
|
|
7892
7895
|
},
|
|
7893
7896
|
canDetachInstance(ids) {
|
|
7894
7897
|
const list = nodes();
|
|
7895
|
-
const instances = selection(ids).filter((id) => getInstanceData(list.find((
|
|
7898
|
+
const instances = selection(ids).filter((id) => getInstanceData(list.find((n2) => n2.id === id)));
|
|
7896
7899
|
if (instances.length === 0) return "Select an instance.";
|
|
7897
7900
|
if (instances.some((id) => isInsideInstance(list, id))) return "A nested instance can't be detached on its own: detach the outer instance first.";
|
|
7898
7901
|
return true;
|
|
@@ -7901,21 +7904,21 @@ function createCanvasComponentsController(options) {
|
|
|
7901
7904
|
resetOverrides(id, group) {
|
|
7902
7905
|
const at = target(id);
|
|
7903
7906
|
if (!at) return { ok: false, nodes: nodes(), code: "not-found", reason: "Select an instance or a layer inside one." };
|
|
7904
|
-
return run(group ? "Reset Override" : "Reset All Changes", (
|
|
7907
|
+
return run(group ? "Reset Override" : "Reset All Changes", (n2) => resetCanvasInstanceOverrides(n2, at, group, syncOptions()));
|
|
7905
7908
|
},
|
|
7906
7909
|
canResetOverrides(id) {
|
|
7907
7910
|
const at = target(id);
|
|
7908
7911
|
const info = at ? inspectCanvasInstance(nodes(), at) : void 0;
|
|
7909
7912
|
if (!info) return "Select an instance or a layer inside one.";
|
|
7910
7913
|
const changedProps = !info.nested && info.properties.some((p) => p.value !== p.default);
|
|
7911
|
-
const own = info.id === at ? info.overrides.length > 0 : getNodeOverrides(nodes().find((
|
|
7914
|
+
const own = info.id === at ? info.overrides.length > 0 : getNodeOverrides(nodes().find((n2) => n2.id === at)).length > 0;
|
|
7912
7915
|
return own || info.id === at && changedProps ? true : "No overrides to reset.";
|
|
7913
7916
|
},
|
|
7914
7917
|
/** Push the (outermost) instance's overrides to its main component. */
|
|
7915
7918
|
pushOverrides(id) {
|
|
7916
7919
|
const at = target(id);
|
|
7917
7920
|
if (!at) return { ok: false, nodes: nodes(), code: "not-found", reason: "Select an instance." };
|
|
7918
|
-
return run("Push Changes to Main Component", (
|
|
7921
|
+
return run("Push Changes to Main Component", (n2) => pushCanvasInstanceOverrides(n2, at, syncOptions()));
|
|
7919
7922
|
},
|
|
7920
7923
|
canPushOverrides(id) {
|
|
7921
7924
|
const at = target(id);
|
|
@@ -7924,17 +7927,17 @@ function createCanvasComponentsController(options) {
|
|
|
7924
7927
|
/** Swap the selected instances to another component (or a set's default variant). */
|
|
7925
7928
|
swapInstance(componentId, ids, swapOptions = {}) {
|
|
7926
7929
|
const list = selection(ids);
|
|
7927
|
-
return run("Swap Instance", (
|
|
7930
|
+
return run("Swap Instance", (n2) => swapCanvasInstance(n2, list, componentId, { ...syncOptions(), ...swapOptions }));
|
|
7928
7931
|
},
|
|
7929
7932
|
canSwapInstance(componentId, ids) {
|
|
7930
7933
|
const list = nodes();
|
|
7931
|
-
const instances = selection(ids).filter((id) => getInstanceData(list.find((
|
|
7934
|
+
const instances = selection(ids).filter((id) => getInstanceData(list.find((n2) => n2.id === id)));
|
|
7932
7935
|
if (instances.length === 0) return "Select an instance.";
|
|
7933
7936
|
if (componentId === void 0) return true;
|
|
7934
|
-
const main = list.find((
|
|
7937
|
+
const main = list.find((n2) => n2.id === componentId);
|
|
7935
7938
|
if (!main || !isCanvasComponent(main) && !isCanvasComponentSet(main)) return "Choose a component or component set.";
|
|
7936
7939
|
for (const id of instances) {
|
|
7937
|
-
const node = list.find((
|
|
7940
|
+
const node = list.find((n2) => n2.id === id);
|
|
7938
7941
|
if (wouldCreateComponentCycle(list, componentId, node.parentId)) return "An instance can't show the component it is inside.";
|
|
7939
7942
|
}
|
|
7940
7943
|
return true;
|
|
@@ -7942,18 +7945,18 @@ function createCanvasComponentsController(options) {
|
|
|
7942
7945
|
/** Set variant / component property values on the selected instances (one step). */
|
|
7943
7946
|
setInstanceProperties(properties, ids) {
|
|
7944
7947
|
const list = selection(ids);
|
|
7945
|
-
return run("Set Instance Properties", (
|
|
7948
|
+
return run("Set Instance Properties", (n2) => setCanvasInstanceProperties(n2, list, properties, syncOptions()));
|
|
7946
7949
|
},
|
|
7947
7950
|
canSetInstanceProperties(ids) {
|
|
7948
7951
|
const list = nodes();
|
|
7949
7952
|
const sel = selection(ids);
|
|
7950
|
-
return sel.length > 0 && sel.every((id) => getInstanceData(list.find((
|
|
7953
|
+
return sel.length > 0 && sel.every((id) => getInstanceData(list.find((n2) => n2.id === id))) ? true : "Select instances.";
|
|
7951
7954
|
},
|
|
7952
7955
|
/** Restore Main Component from an instance whose main was deleted. */
|
|
7953
7956
|
restoreMainComponent(id) {
|
|
7954
7957
|
const at = target(id);
|
|
7955
7958
|
if (!at) return { ok: false, nodes: nodes(), code: "not-found", reason: "Select an instance." };
|
|
7956
|
-
return run("Restore Main Component", (
|
|
7959
|
+
return run("Restore Main Component", (n2) => restoreCanvasMainComponent(n2, at, syncOptions()));
|
|
7957
7960
|
},
|
|
7958
7961
|
canRestoreMainComponent(id) {
|
|
7959
7962
|
const at = target(id);
|
|
@@ -7963,7 +7966,7 @@ function createCanvasComponentsController(options) {
|
|
|
7963
7966
|
setComponentProperty(componentId, name, def, propertyOptions = {}) {
|
|
7964
7967
|
return run(
|
|
7965
7968
|
def ? "Edit Component Property" : "Delete Component Property",
|
|
7966
|
-
(
|
|
7969
|
+
(n2) => setCanvasComponentProperty(n2, componentId, name, def, { ...syncOptions(), ...propertyOptions })
|
|
7967
7970
|
);
|
|
7968
7971
|
},
|
|
7969
7972
|
/**
|
|
@@ -7974,7 +7977,7 @@ function createCanvasComponentsController(options) {
|
|
|
7974
7977
|
const set2 = setOf(setId);
|
|
7975
7978
|
if (!set2) return refused(NO_SET);
|
|
7976
7979
|
const opts = addOptions(setId, variantOptions);
|
|
7977
|
-
return run("Add Variant", (
|
|
7980
|
+
return run("Add Variant", (n2) => addCanvasVariant(n2, set2, { ...syncOptions(), ...opts }));
|
|
7978
7981
|
},
|
|
7979
7982
|
canAddVariant(setId, variantOptions = {}) {
|
|
7980
7983
|
const set2 = setOf(setId);
|
|
@@ -7984,7 +7987,7 @@ function createCanvasComponentsController(options) {
|
|
|
7984
7987
|
removeVariant(variantId) {
|
|
7985
7988
|
const v = variantOf(variantId);
|
|
7986
7989
|
if (!v) return refused(NO_VARIANT);
|
|
7987
|
-
return run("Remove Variant", (
|
|
7990
|
+
return run("Remove Variant", (n2) => removeCanvasVariant(n2, v, syncOptions()));
|
|
7988
7991
|
},
|
|
7989
7992
|
canRemoveVariant(variantId) {
|
|
7990
7993
|
const v = variantOf(variantId);
|
|
@@ -7994,7 +7997,7 @@ function createCanvasComponentsController(options) {
|
|
|
7994
7997
|
setVariantProperties(values, variantId, variantOptions = {}) {
|
|
7995
7998
|
const v = variantOf(variantId);
|
|
7996
7999
|
if (!v) return refused(NO_VARIANT);
|
|
7997
|
-
return run("Edit Variant", (
|
|
8000
|
+
return run("Edit Variant", (n2) => setCanvasVariantProperties(n2, v, values, { ...syncOptions(), ...variantOptions }));
|
|
7998
8001
|
},
|
|
7999
8002
|
canSetVariantProperties(values, variantId) {
|
|
8000
8003
|
const v = variantOf(variantId);
|
|
@@ -8005,7 +8008,7 @@ function createCanvasComponentsController(options) {
|
|
|
8005
8008
|
renameVariantProperty(name, newName, setId) {
|
|
8006
8009
|
const set2 = setOf(setId);
|
|
8007
8010
|
if (!set2) return refused(NO_SET);
|
|
8008
|
-
return run("Rename Variant Property", (
|
|
8011
|
+
return run("Rename Variant Property", (n2) => renameCanvasVariantProperty(n2, set2, name, newName, syncOptions()));
|
|
8009
8012
|
},
|
|
8010
8013
|
canRenameVariantProperty(name, newName, setId) {
|
|
8011
8014
|
const set2 = setOf(setId);
|
|
@@ -8016,7 +8019,7 @@ function createCanvasComponentsController(options) {
|
|
|
8016
8019
|
renameVariantValue(property, value, newValue, setId) {
|
|
8017
8020
|
const set2 = setOf(setId);
|
|
8018
8021
|
if (!set2) return refused(NO_SET);
|
|
8019
|
-
return run("Rename Variant Value", (
|
|
8022
|
+
return run("Rename Variant Value", (n2) => renameCanvasVariantValue(n2, set2, property, value, newValue, syncOptions()));
|
|
8020
8023
|
},
|
|
8021
8024
|
canRenameVariantValue(property, value, newValue, setId) {
|
|
8022
8025
|
const set2 = setOf(setId);
|
|
@@ -8025,19 +8028,19 @@ function createCanvasComponentsController(options) {
|
|
|
8025
8028
|
},
|
|
8026
8029
|
/** Binds (or with `null` unbinds) a main layer's field to a component property. */
|
|
8027
8030
|
bindComponentProperty(layerId, field, name) {
|
|
8028
|
-
return run("Bind Component Property", (
|
|
8031
|
+
return run("Bind Component Property", (n2) => bindCanvasComponentProperty(n2, layerId, field, name, syncOptions()));
|
|
8029
8032
|
},
|
|
8030
8033
|
/** Selects the main component of an instance (or of the instance a layer is in). */
|
|
8031
8034
|
goToMainComponent(id) {
|
|
8032
8035
|
const at = target(id);
|
|
8033
8036
|
const list = sync();
|
|
8034
8037
|
const inst = at ? getOwningInstance(list, at) : void 0;
|
|
8035
|
-
const main = inst ? getInstanceData(list.find((
|
|
8036
|
-
const node = main ? list.find((
|
|
8038
|
+
const main = inst ? getInstanceData(list.find((n2) => n2.id === inst))?.componentId : void 0;
|
|
8039
|
+
const node = main ? list.find((n2) => n2.id === main) : void 0;
|
|
8037
8040
|
if (!node) return void 0;
|
|
8038
|
-
const next = list.map((
|
|
8041
|
+
const next = list.map((n2) => !!n2.selected === (n2.id === main) ? n2 : { ...n2, selected: n2.id === main });
|
|
8039
8042
|
set(next);
|
|
8040
|
-
options.onReveal?.(next.find((
|
|
8043
|
+
options.onReveal?.(next.find((n2) => n2.id === main));
|
|
8041
8044
|
return main;
|
|
8042
8045
|
},
|
|
8043
8046
|
canGoToMainComponent(id) {
|
|
@@ -8045,8 +8048,8 @@ function createCanvasComponentsController(options) {
|
|
|
8045
8048
|
const list = nodes();
|
|
8046
8049
|
const inst = at ? getOwningInstance(list, at) : void 0;
|
|
8047
8050
|
if (!inst) return "Select an instance.";
|
|
8048
|
-
const main = getInstanceData(list.find((
|
|
8049
|
-
return list.some((
|
|
8051
|
+
const main = getInstanceData(list.find((n2) => n2.id === inst)).componentId;
|
|
8052
|
+
return list.some((n2) => n2.id === main) ? true : "The main component was deleted.";
|
|
8050
8053
|
},
|
|
8051
8054
|
/** Components and component sets, for a components panel. */
|
|
8052
8055
|
list: () => listCanvasComponents(nodes()),
|
|
@@ -8182,20 +8185,20 @@ function findStrokesAtPoint(point, nodes, radius = 12) {
|
|
|
8182
8185
|
for (const node of nodes) {
|
|
8183
8186
|
const shape = getNodeShape(node);
|
|
8184
8187
|
if (!shape || shape.kind !== "path") continue;
|
|
8185
|
-
const
|
|
8188
|
+
const rect2 = getNodeRect(node);
|
|
8186
8189
|
const strokeWidth = shape.strokeWidth ?? 2;
|
|
8187
8190
|
const effectiveRadius = radius + strokeWidth / 2;
|
|
8188
|
-
if (point[0] <
|
|
8191
|
+
if (point[0] < rect2.x - effectiveRadius || point[0] > rect2.x + rect2.width + effectiveRadius || point[1] < rect2.y - effectiveRadius || point[1] > rect2.y + rect2.height + effectiveRadius) {
|
|
8189
8192
|
continue;
|
|
8190
8193
|
}
|
|
8191
|
-
const localPoint = [point[0] -
|
|
8194
|
+
const localPoint = [point[0] - rect2.x, point[1] - rect2.y];
|
|
8192
8195
|
try {
|
|
8193
8196
|
const dist = distanceToBezierPath(shape.d, localPoint);
|
|
8194
8197
|
if (dist <= effectiveRadius) {
|
|
8195
8198
|
matches2.push(node);
|
|
8196
8199
|
}
|
|
8197
8200
|
} catch {
|
|
8198
|
-
if (point[0] >=
|
|
8201
|
+
if (point[0] >= rect2.x && point[0] <= rect2.x + rect2.width && point[1] >= rect2.y && point[1] <= rect2.y + rect2.height) {
|
|
8199
8202
|
matches2.push(node);
|
|
8200
8203
|
}
|
|
8201
8204
|
}
|
|
@@ -8269,7 +8272,7 @@ function createCanvasDrawController(options) {
|
|
|
8269
8272
|
options.history.execute({
|
|
8270
8273
|
name: "Erase strokes",
|
|
8271
8274
|
execute: () => {
|
|
8272
|
-
const remaining = options.getNodes().filter((
|
|
8275
|
+
const remaining = options.getNodes().filter((n2) => !erasedIds.has(n2.id));
|
|
8273
8276
|
options.setNodes(remaining);
|
|
8274
8277
|
},
|
|
8275
8278
|
undo: () => {
|
|
@@ -8301,7 +8304,7 @@ function createCanvasDrawController(options) {
|
|
|
8301
8304
|
options.setNodes([...options.getNodes(), node]);
|
|
8302
8305
|
},
|
|
8303
8306
|
undo: () => {
|
|
8304
|
-
options.setNodes(options.getNodes().filter((
|
|
8307
|
+
options.setNodes(options.getNodes().filter((n2) => n2.id !== node.id));
|
|
8305
8308
|
}
|
|
8306
8309
|
});
|
|
8307
8310
|
} else {
|
|
@@ -8333,15 +8336,15 @@ function createCanvasDrawController(options) {
|
|
|
8333
8336
|
const newlyErased = [];
|
|
8334
8337
|
for (const candidate of candidates) {
|
|
8335
8338
|
if (erasedInDrag.has(candidate.id) || isLocked(candidate)) continue;
|
|
8336
|
-
const index = nodes.findIndex((
|
|
8339
|
+
const index = nodes.findIndex((n2) => n2.id === candidate.id);
|
|
8337
8340
|
if (index !== -1) {
|
|
8338
8341
|
erasedInDrag.set(candidate.id, { node: candidate, index });
|
|
8339
8342
|
newlyErased.push(candidate);
|
|
8340
8343
|
}
|
|
8341
8344
|
}
|
|
8342
8345
|
if (newlyErased.length > 0) {
|
|
8343
|
-
const erasedSet = new Set(newlyErased.map((
|
|
8344
|
-
const nextNodes = nodes.filter((
|
|
8346
|
+
const erasedSet = new Set(newlyErased.map((n2) => n2.id));
|
|
8347
|
+
const nextNodes = nodes.filter((n2) => !erasedSet.has(n2.id));
|
|
8345
8348
|
options.setNodes(nextNodes);
|
|
8346
8349
|
options.onNodesErase?.(newlyErased);
|
|
8347
8350
|
}
|
|
@@ -8370,6 +8373,753 @@ function createCanvasDrawController(options) {
|
|
|
8370
8373
|
};
|
|
8371
8374
|
}
|
|
8372
8375
|
|
|
8376
|
+
// src/canvas/mermaid/layout.ts
|
|
8377
|
+
import dagre2 from "@dagrejs/dagre";
|
|
8378
|
+
var DEFAULT_DIAGRAM_NODE_WIDTH = 160;
|
|
8379
|
+
var DEFAULT_DIAGRAM_NODE_HEIGHT = 56;
|
|
8380
|
+
function estimateDiagramNodeSize(node) {
|
|
8381
|
+
const lines = String(node.label ?? node.id).split(/<br\s*\/?>|\n/);
|
|
8382
|
+
const longest = Math.max(...lines.map((l) => l.replace(/<[^>]+>/g, "").length), 1);
|
|
8383
|
+
let width = Math.min(360, Math.max(DEFAULT_DIAGRAM_NODE_WIDTH, longest * 8 + 48));
|
|
8384
|
+
let height = Math.max(DEFAULT_DIAGRAM_NODE_HEIGHT, lines.length * 20 + 28);
|
|
8385
|
+
const extra = extraLines(node);
|
|
8386
|
+
if (extra) height += extra * 18 + 12;
|
|
8387
|
+
switch (node.shape) {
|
|
8388
|
+
case "actor":
|
|
8389
|
+
case "c4-person":
|
|
8390
|
+
height = Math.round(height * 1.5);
|
|
8391
|
+
break;
|
|
8392
|
+
case "point":
|
|
8393
|
+
width = Math.max(72, longest * 7 + 36);
|
|
8394
|
+
height = 30;
|
|
8395
|
+
break;
|
|
8396
|
+
case "commit": {
|
|
8397
|
+
const d = Math.max(56, Math.min(120, longest * 7 + 24));
|
|
8398
|
+
width = d;
|
|
8399
|
+
height = d;
|
|
8400
|
+
break;
|
|
8401
|
+
}
|
|
8402
|
+
case "diam":
|
|
8403
|
+
case "hex":
|
|
8404
|
+
case "trap-b":
|
|
8405
|
+
case "trap-t":
|
|
8406
|
+
case "lean-r":
|
|
8407
|
+
case "lean-l":
|
|
8408
|
+
width = Math.round(width * 1.25);
|
|
8409
|
+
height = Math.round(height * 1.4);
|
|
8410
|
+
break;
|
|
8411
|
+
case "circle":
|
|
8412
|
+
case "dbl-circ":
|
|
8413
|
+
case "sm-circ":
|
|
8414
|
+
case "fr-circ":
|
|
8415
|
+
case "f-circ":
|
|
8416
|
+
case "cross-circ": {
|
|
8417
|
+
const d = Math.max(width * 0.75, height * 1.3);
|
|
8418
|
+
width = Math.round(d);
|
|
8419
|
+
height = Math.round(d);
|
|
8420
|
+
break;
|
|
8421
|
+
}
|
|
8422
|
+
case "stateStart":
|
|
8423
|
+
case "stateEnd":
|
|
8424
|
+
width = 28;
|
|
8425
|
+
height = 28;
|
|
8426
|
+
break;
|
|
8427
|
+
case "fork":
|
|
8428
|
+
case "join":
|
|
8429
|
+
width = 120;
|
|
8430
|
+
height = 10;
|
|
8431
|
+
break;
|
|
8432
|
+
case "choice":
|
|
8433
|
+
width = 48;
|
|
8434
|
+
height = 48;
|
|
8435
|
+
break;
|
|
8436
|
+
case "cyl":
|
|
8437
|
+
case "h-cyl":
|
|
8438
|
+
case "lin-cyl":
|
|
8439
|
+
height = Math.round(height * 1.3);
|
|
8440
|
+
break;
|
|
8441
|
+
case "image": {
|
|
8442
|
+
const picture = diagramImageSize(node);
|
|
8443
|
+
const label = String(node.label ?? "").trim() ? IMAGE_LABEL_HEIGHT : 0;
|
|
8444
|
+
width = Math.max(picture.width, label ? Math.min(360, longest * 7 + 16) : 0);
|
|
8445
|
+
height = picture.height + label;
|
|
8446
|
+
break;
|
|
8447
|
+
}
|
|
8448
|
+
default:
|
|
8449
|
+
break;
|
|
8450
|
+
}
|
|
8451
|
+
return { width, height };
|
|
8452
|
+
}
|
|
8453
|
+
var IMAGE_LABEL_HEIGHT = 24;
|
|
8454
|
+
function diagramImageSize(node) {
|
|
8455
|
+
const num2 = (v) => typeof v === "number" && v > 0 ? v : void 0;
|
|
8456
|
+
const w = num2(node.data?.w);
|
|
8457
|
+
const h = num2(node.data?.h);
|
|
8458
|
+
return { width: w ?? h ?? 96, height: h ?? w ?? 96 };
|
|
8459
|
+
}
|
|
8460
|
+
function extraLines(node) {
|
|
8461
|
+
const data = node.data ?? {};
|
|
8462
|
+
const members = Array.isArray(data.members) ? data.members.length : 0;
|
|
8463
|
+
const attributes = Array.isArray(data.attributes) ? data.attributes.length : 0;
|
|
8464
|
+
const descriptions = Array.isArray(data.descriptions) ? data.descriptions.length : 0;
|
|
8465
|
+
const details = Array.isArray(data.details) ? data.details.length : 0;
|
|
8466
|
+
return members + attributes + descriptions + details;
|
|
8467
|
+
}
|
|
8468
|
+
function rankdir(direction) {
|
|
8469
|
+
const d = direction.toUpperCase();
|
|
8470
|
+
if (d === "TD") return "TB";
|
|
8471
|
+
if (d === "TB" || d === "BT" || d === "LR" || d === "RL") return d;
|
|
8472
|
+
return "TB";
|
|
8473
|
+
}
|
|
8474
|
+
function autoLayoutDiagram(graph, options = {}) {
|
|
8475
|
+
const measure = options.measure ?? estimateDiagramNodeSize;
|
|
8476
|
+
const nodeSep = options.nodeSep ?? 48;
|
|
8477
|
+
const rankSep = options.rankSep ?? 72;
|
|
8478
|
+
const pad = options.groupPadding ?? 24;
|
|
8479
|
+
const titleH = options.groupTitleHeight ?? 32;
|
|
8480
|
+
const childrenOf = /* @__PURE__ */ new Map();
|
|
8481
|
+
for (const n2 of graph.nodes) push(childrenOf, n2.parentId, { id: n2.id, isGroup: false });
|
|
8482
|
+
for (const g of graph.groups) push(childrenOf, g.parentId, { id: g.id, isGroup: true });
|
|
8483
|
+
const nodeById = new Map(graph.nodes.map((n2) => [n2.id, n2]));
|
|
8484
|
+
const groupById = new Map(graph.groups.map((g) => [g.id, g]));
|
|
8485
|
+
const sizes = {};
|
|
8486
|
+
const relative = {};
|
|
8487
|
+
const layoutScope = (scope, direction) => {
|
|
8488
|
+
const children = childrenOf.get(scope) ?? [];
|
|
8489
|
+
for (const c of children) {
|
|
8490
|
+
if (c.isGroup) {
|
|
8491
|
+
const g2 = groupById.get(c.id);
|
|
8492
|
+
const inner = layoutScope(c.id, g2.direction ?? direction);
|
|
8493
|
+
sizes[c.id] = { width: inner.width + pad * 2, height: inner.height + pad * 2 + titleH };
|
|
8494
|
+
} else {
|
|
8495
|
+
sizes[c.id] = measure(nodeById.get(c.id));
|
|
8496
|
+
}
|
|
8497
|
+
}
|
|
8498
|
+
if (!children.length) return { width: 120, height: 40 };
|
|
8499
|
+
const g = new dagre2.graphlib.Graph({ multigraph: true });
|
|
8500
|
+
g.setGraph({
|
|
8501
|
+
rankdir: rankdir(direction),
|
|
8502
|
+
nodesep: nodeSep,
|
|
8503
|
+
ranksep: rankSep,
|
|
8504
|
+
marginx: 0,
|
|
8505
|
+
marginy: 0
|
|
8506
|
+
});
|
|
8507
|
+
g.setDefaultEdgeLabel(() => ({}));
|
|
8508
|
+
const ids = new Set(children.map((c) => c.id));
|
|
8509
|
+
for (const c of children)
|
|
8510
|
+
g.setNode(c.id, { width: sizes[c.id].width, height: sizes[c.id].height });
|
|
8511
|
+
const lift = (id) => {
|
|
8512
|
+
let cur = id;
|
|
8513
|
+
const seen = /* @__PURE__ */ new Set();
|
|
8514
|
+
while (cur && !seen.has(cur)) {
|
|
8515
|
+
if (ids.has(cur)) return cur;
|
|
8516
|
+
seen.add(cur);
|
|
8517
|
+
cur = nodeById.get(cur)?.parentId ?? groupById.get(cur)?.parentId;
|
|
8518
|
+
}
|
|
8519
|
+
return null;
|
|
8520
|
+
};
|
|
8521
|
+
graph.edges.forEach((e, i) => {
|
|
8522
|
+
const s = lift(e.source);
|
|
8523
|
+
const t = lift(e.target);
|
|
8524
|
+
if (s && t && s !== t) g.setEdge(s, t, { minlen: Math.max(1, e.length) }, `e${i}`);
|
|
8525
|
+
});
|
|
8526
|
+
dagre2.layout(g);
|
|
8527
|
+
let minX = Infinity;
|
|
8528
|
+
let minY = Infinity;
|
|
8529
|
+
let maxX = -Infinity;
|
|
8530
|
+
let maxY = -Infinity;
|
|
8531
|
+
for (const c of children) {
|
|
8532
|
+
const n2 = g.node(c.id);
|
|
8533
|
+
const w = sizes[c.id].width;
|
|
8534
|
+
const h = sizes[c.id].height;
|
|
8535
|
+
const x = n2.x - w / 2;
|
|
8536
|
+
const y = n2.y - h / 2;
|
|
8537
|
+
relative[c.id] = [x, y];
|
|
8538
|
+
minX = Math.min(minX, x);
|
|
8539
|
+
minY = Math.min(minY, y);
|
|
8540
|
+
maxX = Math.max(maxX, x + w);
|
|
8541
|
+
maxY = Math.max(maxY, y + h);
|
|
8542
|
+
}
|
|
8543
|
+
for (const c of children) {
|
|
8544
|
+
const [x, y] = relative[c.id];
|
|
8545
|
+
relative[c.id] = [x - minX, y - minY];
|
|
8546
|
+
}
|
|
8547
|
+
return { width: maxX - minX, height: maxY - minY };
|
|
8548
|
+
};
|
|
8549
|
+
layoutScope(void 0, graph.direction);
|
|
8550
|
+
const positions = {};
|
|
8551
|
+
const absolute = (id) => {
|
|
8552
|
+
if (positions[id]) return positions[id];
|
|
8553
|
+
const parentId = nodeById.get(id)?.parentId ?? groupById.get(id)?.parentId;
|
|
8554
|
+
const [rx, ry] = relative[id] ?? [0, 0];
|
|
8555
|
+
if (!parentId) {
|
|
8556
|
+
positions[id] = [rx, ry];
|
|
8557
|
+
} else {
|
|
8558
|
+
const [px2, py] = absolute(parentId);
|
|
8559
|
+
positions[id] = [px2 + pad + rx, py + pad + titleH + ry];
|
|
8560
|
+
}
|
|
8561
|
+
return positions[id];
|
|
8562
|
+
};
|
|
8563
|
+
for (const n2 of graph.nodes) absolute(n2.id);
|
|
8564
|
+
for (const g of graph.groups) absolute(g.id);
|
|
8565
|
+
return { positions, sizes };
|
|
8566
|
+
}
|
|
8567
|
+
function push(map, key, value) {
|
|
8568
|
+
const arr = map.get(key);
|
|
8569
|
+
if (arr) arr.push(value);
|
|
8570
|
+
else map.set(key, [value]);
|
|
8571
|
+
}
|
|
8572
|
+
function ensureDiagramLayout(graph, meta, options) {
|
|
8573
|
+
const measure = options?.measure ?? estimateDiagramNodeSize;
|
|
8574
|
+
const stored = meta.layout ?? {};
|
|
8575
|
+
const allIds = [...graph.nodes.map((n2) => n2.id), ...graph.groups.map((g) => g.id)];
|
|
8576
|
+
const missing = allIds.filter((id) => !stored[id]);
|
|
8577
|
+
const sizes = {};
|
|
8578
|
+
for (const n2 of graph.nodes)
|
|
8579
|
+
sizes[n2.id] = meta.sizes?.[n2.id] ? { width: meta.sizes[n2.id][0], height: meta.sizes[n2.id][1] } : measure(n2);
|
|
8580
|
+
if (!missing.length) {
|
|
8581
|
+
const positions2 = {};
|
|
8582
|
+
for (const id of allIds) positions2[id] = stored[id];
|
|
8583
|
+
for (const g of graph.groups) sizes[g.id] = diagramGroupSize(g.id, graph, positions2, sizes, meta);
|
|
8584
|
+
return { positions: positions2, sizes };
|
|
8585
|
+
}
|
|
8586
|
+
const auto = autoLayoutDiagram(graph, options);
|
|
8587
|
+
if (missing.length === allIds.length) return auto;
|
|
8588
|
+
const both = allIds.filter((id) => stored[id] && auto.positions[id]);
|
|
8589
|
+
let dx = 0;
|
|
8590
|
+
let dy = 0;
|
|
8591
|
+
if (both.length) {
|
|
8592
|
+
for (const id of both) {
|
|
8593
|
+
dx += stored[id][0] - auto.positions[id][0];
|
|
8594
|
+
dy += stored[id][1] - auto.positions[id][1];
|
|
8595
|
+
}
|
|
8596
|
+
dx /= both.length;
|
|
8597
|
+
dy /= both.length;
|
|
8598
|
+
}
|
|
8599
|
+
const positions = {};
|
|
8600
|
+
for (const id of allIds) {
|
|
8601
|
+
positions[id] = stored[id] ?? [auto.positions[id][0] + dx, auto.positions[id][1] + dy];
|
|
8602
|
+
}
|
|
8603
|
+
for (const g of graph.groups) sizes[g.id] = diagramGroupSize(g.id, graph, positions, sizes, meta);
|
|
8604
|
+
return { positions, sizes };
|
|
8605
|
+
}
|
|
8606
|
+
function diagramGroupSize(groupId, graph, positions, sizes, meta, pad = 24, titleH = 32) {
|
|
8607
|
+
if (meta.sizes?.[groupId])
|
|
8608
|
+
return { width: meta.sizes[groupId][0], height: meta.sizes[groupId][1] };
|
|
8609
|
+
const members = [
|
|
8610
|
+
...graph.nodes.filter((n2) => n2.parentId === groupId).map((n2) => n2.id),
|
|
8611
|
+
...graph.groups.filter((g) => g.parentId === groupId).map((g) => g.id)
|
|
8612
|
+
];
|
|
8613
|
+
if (!members.length) return { width: 200, height: 100 };
|
|
8614
|
+
const [gx, gy] = positions[groupId] ?? [0, 0];
|
|
8615
|
+
let maxX = 0;
|
|
8616
|
+
let maxY = 0;
|
|
8617
|
+
for (const id of members) {
|
|
8618
|
+
const size = sizes[id] ?? (graph.groups.some((g) => g.id === id) ? diagramGroupSize(id, graph, positions, sizes, meta, pad, titleH) : { width: DEFAULT_DIAGRAM_NODE_WIDTH, height: DEFAULT_DIAGRAM_NODE_HEIGHT });
|
|
8619
|
+
sizes[id] = size;
|
|
8620
|
+
const [x, y] = positions[id] ?? [gx, gy];
|
|
8621
|
+
maxX = Math.max(maxX, x - gx + size.width);
|
|
8622
|
+
maxY = Math.max(maxY, y - gy + size.height);
|
|
8623
|
+
}
|
|
8624
|
+
return { width: maxX + pad, height: maxY + pad };
|
|
8625
|
+
}
|
|
8626
|
+
|
|
8627
|
+
// src/canvas/mermaid/toFlow.ts
|
|
8628
|
+
function parseMermaidStyles(styles) {
|
|
8629
|
+
const out = {};
|
|
8630
|
+
for (const s of styles) {
|
|
8631
|
+
const idx = s.indexOf(":");
|
|
8632
|
+
if (idx === -1) continue;
|
|
8633
|
+
out[s.slice(0, idx).trim()] = s.slice(idx + 1).trim();
|
|
8634
|
+
}
|
|
8635
|
+
return out;
|
|
8636
|
+
}
|
|
8637
|
+
function resolveMermaidStyles(classes, inline, classDefs) {
|
|
8638
|
+
let out = {};
|
|
8639
|
+
if (classDefs.default) out = { ...out, ...parseMermaidStyles(classDefs.default) };
|
|
8640
|
+
for (const cls of classes)
|
|
8641
|
+
if (classDefs[cls]) out = { ...out, ...parseMermaidStyles(classDefs[cls]) };
|
|
8642
|
+
return { ...out, ...parseMermaidStyles(inline) };
|
|
8643
|
+
}
|
|
8644
|
+
function depth(id, parents) {
|
|
8645
|
+
let d = 0;
|
|
8646
|
+
let cur = parents.get(id);
|
|
8647
|
+
const seen = /* @__PURE__ */ new Set();
|
|
8648
|
+
while (cur && !seen.has(cur)) {
|
|
8649
|
+
seen.add(cur);
|
|
8650
|
+
d++;
|
|
8651
|
+
cur = parents.get(cur);
|
|
8652
|
+
}
|
|
8653
|
+
return d;
|
|
8654
|
+
}
|
|
8655
|
+
function mermaidFlowNodes(graph, layout2, options = {}) {
|
|
8656
|
+
const editable = options.editable ?? false;
|
|
8657
|
+
const positions = { ...layout2.positions, ...options.positions ?? {} };
|
|
8658
|
+
const sizes = { ...layout2.sizes, ...options.sizes ?? {} };
|
|
8659
|
+
const parents = /* @__PURE__ */ new Map();
|
|
8660
|
+
for (const n2 of graph.nodes) parents.set(n2.id, n2.parentId);
|
|
8661
|
+
for (const g of graph.groups) parents.set(g.id, g.parentId);
|
|
8662
|
+
const rel = (id, parentId) => {
|
|
8663
|
+
const [x, y] = positions[id] ?? [0, 0];
|
|
8664
|
+
if (!parentId) return { x, y };
|
|
8665
|
+
const [px2, py] = positions[parentId] ?? [0, 0];
|
|
8666
|
+
return { x: x - px2, y: y - py };
|
|
8667
|
+
};
|
|
8668
|
+
const groups = graph.groups.map((g) => {
|
|
8669
|
+
const size = sizes[g.id] ?? { width: 240, height: 160 };
|
|
8670
|
+
return {
|
|
8671
|
+
id: g.id,
|
|
8672
|
+
type: "mermaid-group",
|
|
8673
|
+
position: rel(g.id, g.parentId),
|
|
8674
|
+
parentId: g.parentId,
|
|
8675
|
+
data: {
|
|
8676
|
+
group: g,
|
|
8677
|
+
family: "",
|
|
8678
|
+
resolvedStyles: resolveMermaidStyles(g.classes, g.styles, graph.classDefs),
|
|
8679
|
+
editable
|
|
8680
|
+
},
|
|
8681
|
+
width: size.width,
|
|
8682
|
+
height: size.height,
|
|
8683
|
+
style: { width: size.width, height: size.height },
|
|
8684
|
+
draggable: editable && !g.data?.locked,
|
|
8685
|
+
selectable: editable,
|
|
8686
|
+
connectable: editable && !g.data?.locked,
|
|
8687
|
+
zIndex: depth(g.id, parents)
|
|
8688
|
+
};
|
|
8689
|
+
});
|
|
8690
|
+
const nodes = graph.nodes.map((n2) => {
|
|
8691
|
+
const size = sizes[n2.id] ?? { width: 160, height: 56 };
|
|
8692
|
+
return {
|
|
8693
|
+
id: n2.id,
|
|
8694
|
+
type: "mermaid-node",
|
|
8695
|
+
position: rel(n2.id, n2.parentId),
|
|
8696
|
+
parentId: n2.parentId,
|
|
8697
|
+
data: {
|
|
8698
|
+
node: n2,
|
|
8699
|
+
family: "",
|
|
8700
|
+
resolvedStyles: resolveMermaidStyles(n2.classes, n2.styles, graph.classDefs),
|
|
8701
|
+
editable
|
|
8702
|
+
},
|
|
8703
|
+
width: size.width,
|
|
8704
|
+
height: size.height,
|
|
8705
|
+
style: { width: size.width, height: size.height },
|
|
8706
|
+
draggable: editable && !n2.data?.locked,
|
|
8707
|
+
selectable: editable,
|
|
8708
|
+
connectable: editable && !n2.data?.locked && !n2.data?.synthetic,
|
|
8709
|
+
zIndex: depth(n2.id, parents) + 100
|
|
8710
|
+
};
|
|
8711
|
+
});
|
|
8712
|
+
const order = (a, b) => depth(a.id, parents) - depth(b.id, parents);
|
|
8713
|
+
return [...groups.sort(order), ...nodes.sort(order)];
|
|
8714
|
+
}
|
|
8715
|
+
function mermaidFlowEdges(graph, options = {}) {
|
|
8716
|
+
const editable = options.editable ?? false;
|
|
8717
|
+
return graph.edges.map((e) => ({
|
|
8718
|
+
id: e.id,
|
|
8719
|
+
type: "mermaid-edge",
|
|
8720
|
+
source: e.source,
|
|
8721
|
+
target: e.target,
|
|
8722
|
+
label: e.label,
|
|
8723
|
+
data: {
|
|
8724
|
+
edge: e,
|
|
8725
|
+
family: "",
|
|
8726
|
+
resolvedStyles: resolveMermaidStyles(e.classes, e.styles, graph.classDefs),
|
|
8727
|
+
editable
|
|
8728
|
+
},
|
|
8729
|
+
selectable: editable,
|
|
8730
|
+
reconnectable: editable,
|
|
8731
|
+
zIndex: 1e3
|
|
8732
|
+
}));
|
|
8733
|
+
}
|
|
8734
|
+
function mermaidMarkerId(head, side) {
|
|
8735
|
+
if (head === "none") return void 0;
|
|
8736
|
+
return `pixerate-mermaid-marker-${head}-${side}`;
|
|
8737
|
+
}
|
|
8738
|
+
function mermaidEdgeDash(pattern) {
|
|
8739
|
+
switch (pattern) {
|
|
8740
|
+
case "dotted":
|
|
8741
|
+
return "6 4";
|
|
8742
|
+
case "invisible":
|
|
8743
|
+
return "0 1";
|
|
8744
|
+
default:
|
|
8745
|
+
return void 0;
|
|
8746
|
+
}
|
|
8747
|
+
}
|
|
8748
|
+
function mermaidEdgeWidth(pattern) {
|
|
8749
|
+
return pattern === "thick" ? 3.5 : 1.75;
|
|
8750
|
+
}
|
|
8751
|
+
|
|
8752
|
+
// src/canvas/mermaid/view.ts
|
|
8753
|
+
function diagramLayoutBounds(layout2) {
|
|
8754
|
+
let minX = Infinity;
|
|
8755
|
+
let minY = Infinity;
|
|
8756
|
+
let maxX = -Infinity;
|
|
8757
|
+
let maxY = -Infinity;
|
|
8758
|
+
for (const [id, [x, y]] of Object.entries(layout2.positions)) {
|
|
8759
|
+
const size = layout2.sizes[id] ?? { width: 0, height: 0 };
|
|
8760
|
+
minX = Math.min(minX, x);
|
|
8761
|
+
minY = Math.min(minY, y);
|
|
8762
|
+
maxX = Math.max(maxX, x + size.width);
|
|
8763
|
+
maxY = Math.max(maxY, y + size.height);
|
|
8764
|
+
}
|
|
8765
|
+
if (minX === Infinity) return null;
|
|
8766
|
+
return { x: minX, y: minY, width: maxX - minX, height: maxY - minY };
|
|
8767
|
+
}
|
|
8768
|
+
function clampHeight2(content, options = {}) {
|
|
8769
|
+
const { min = 320, max = 560, padding = 48 } = options;
|
|
8770
|
+
return Math.round(Math.min(max, Math.max(min, content + padding)));
|
|
8771
|
+
}
|
|
8772
|
+
function diagramCanvasHeight(layout2, options) {
|
|
8773
|
+
return clampHeight2(diagramLayoutBounds(layout2)?.height ?? 0, options);
|
|
8774
|
+
}
|
|
8775
|
+
var RANK_HEIGHT = DEFAULT_DIAGRAM_NODE_HEIGHT + 72;
|
|
8776
|
+
var NODES_PER_RANK2 = 2;
|
|
8777
|
+
var GROUP_BAND = 24 * 2 + 32;
|
|
8778
|
+
function estimateDiagramCanvasHeight(graph, options) {
|
|
8779
|
+
const ranks = Math.ceil(graph.nodes.length / NODES_PER_RANK2);
|
|
8780
|
+
return clampHeight2(ranks * RANK_HEIGHT + graph.groups.length * GROUP_BAND, options);
|
|
8781
|
+
}
|
|
8782
|
+
function mix2(a, b, t) {
|
|
8783
|
+
return a + (b - a) * t;
|
|
8784
|
+
}
|
|
8785
|
+
function blendDiagramLayout(from, to, t) {
|
|
8786
|
+
if (t >= 1) return to;
|
|
8787
|
+
const positions = {};
|
|
8788
|
+
for (const [id, [x, y]] of Object.entries(to.positions)) {
|
|
8789
|
+
const origin = from.positions[id];
|
|
8790
|
+
positions[id] = origin ? [mix2(origin[0], x, t), mix2(origin[1], y, t)] : [x, y];
|
|
8791
|
+
}
|
|
8792
|
+
const sizes = {};
|
|
8793
|
+
for (const [id, size] of Object.entries(to.sizes)) {
|
|
8794
|
+
const origin = from.sizes[id];
|
|
8795
|
+
sizes[id] = origin ? { width: mix2(origin.width, size.width, t), height: mix2(origin.height, size.height, t) } : size;
|
|
8796
|
+
}
|
|
8797
|
+
return { positions, sizes };
|
|
8798
|
+
}
|
|
8799
|
+
function connectedDiagramOnly(graph) {
|
|
8800
|
+
const linked = /* @__PURE__ */ new Set();
|
|
8801
|
+
for (const edge of graph.edges) {
|
|
8802
|
+
linked.add(edge.source);
|
|
8803
|
+
linked.add(edge.target);
|
|
8804
|
+
}
|
|
8805
|
+
const nodes = graph.nodes.filter((n2) => linked.has(n2.id));
|
|
8806
|
+
if (nodes.length === graph.nodes.length) return graph;
|
|
8807
|
+
const parentOf = new Map(graph.groups.map((g) => [g.id, g.parentId]));
|
|
8808
|
+
const keep = /* @__PURE__ */ new Set();
|
|
8809
|
+
for (const node of nodes) {
|
|
8810
|
+
let id = node.parentId;
|
|
8811
|
+
while (id && !keep.has(id)) {
|
|
8812
|
+
keep.add(id);
|
|
8813
|
+
id = parentOf.get(id);
|
|
8814
|
+
}
|
|
8815
|
+
}
|
|
8816
|
+
for (const id of linked) if (parentOf.has(id)) keep.add(id);
|
|
8817
|
+
return { ...graph, nodes, groups: graph.groups.filter((g) => keep.has(g.id)) };
|
|
8818
|
+
}
|
|
8819
|
+
|
|
8820
|
+
// src/canvas/mermaid/stream.ts
|
|
8821
|
+
function fingerprint(graph) {
|
|
8822
|
+
return JSON.stringify([
|
|
8823
|
+
graph.direction,
|
|
8824
|
+
graph.nodes.map((n2) => [n2.id, n2.parentId ?? "", n2.shape, String(n2.label).length > 24 ? 1 : 0]),
|
|
8825
|
+
graph.edges.map((e) => [e.source, e.target]),
|
|
8826
|
+
graph.groups.map((g) => [g.id, g.parentId ?? "", g.direction ?? ""])
|
|
8827
|
+
]);
|
|
8828
|
+
}
|
|
8829
|
+
var DiagramStream = class {
|
|
8830
|
+
constructor(options = {}) {
|
|
8831
|
+
this.options = options;
|
|
8832
|
+
}
|
|
8833
|
+
options;
|
|
8834
|
+
lastKey = "";
|
|
8835
|
+
layout = null;
|
|
8836
|
+
/** Reads the source so far. `complete` when nothing more will arrive. */
|
|
8837
|
+
update(source, complete = false) {
|
|
8838
|
+
const text = streamedDiagramText(source);
|
|
8839
|
+
const parsed = parseMermaid(text);
|
|
8840
|
+
const document = !complete ? { ...parsed, graph: connectedDiagramOnly(parsed.graph) } : parsed;
|
|
8841
|
+
if (document.tier !== "editable" || !document.graph.nodes.length) return { document, layout: this.layout && complete ? null : this.layout, relaid: false };
|
|
8842
|
+
const key = fingerprint(document.graph);
|
|
8843
|
+
if (key === this.lastKey && this.layout) return { document, layout: this.layout, relaid: false };
|
|
8844
|
+
this.lastKey = key;
|
|
8845
|
+
this.layout = ensureDiagramLayout(document.graph, document.meta, this.options);
|
|
8846
|
+
return { document, layout: this.layout, relaid: true };
|
|
8847
|
+
}
|
|
8848
|
+
/** Forgets the previous layout (a new source). */
|
|
8849
|
+
reset() {
|
|
8850
|
+
this.lastKey = "";
|
|
8851
|
+
this.layout = null;
|
|
8852
|
+
}
|
|
8853
|
+
};
|
|
8854
|
+
function streamedDiagramText(source) {
|
|
8855
|
+
const open = /(?:^|\n)[ ]{0,3}(`{3,}|~{3,})[ \t]*(mermaid|mmd)?[^\n`]*(?:\n|$)/i.exec(source);
|
|
8856
|
+
if (!open) return source;
|
|
8857
|
+
const rest = source.slice(open.index + open[0].length);
|
|
8858
|
+
const fence = open[1];
|
|
8859
|
+
const close = new RegExp(`(?:^|\\n)[ ]{0,3}${fence[0] === "`" ? "`" : "~"}{${fence.length},}[ \\t]*(?:\\n|$)`).exec(rest);
|
|
8860
|
+
return close ? rest.slice(0, close.index) : rest.replace(/\n[ ]{0,3}[`~]{1,2}$/, "");
|
|
8861
|
+
}
|
|
8862
|
+
var easeDiagramTween = (t) => 1 - Math.pow(1 - Math.max(0, Math.min(1, t)), 3);
|
|
8863
|
+
|
|
8864
|
+
// src/canvas/mermaid/shapes.ts
|
|
8865
|
+
var n = (v) => Math.round(v * 100) / 100;
|
|
8866
|
+
var poly = (points) => `M${points.map(([x, y]) => `${n(x)},${n(y)}`).join(" L")} Z`;
|
|
8867
|
+
var rect = (x, y, w, h, r = 0) => {
|
|
8868
|
+
if (r <= 0) return poly([[x, y], [x + w, y], [x + w, y + h], [x, y + h]]);
|
|
8869
|
+
const rr = Math.min(r, w / 2, h / 2);
|
|
8870
|
+
return `M${n(x + rr)},${n(y)} H${n(x + w - rr)} A${n(rr)},${n(rr)} 0 0 1 ${n(x + w)},${n(y + rr)} V${n(y + h - rr)} A${n(rr)},${n(rr)} 0 0 1 ${n(x + w - rr)},${n(y + h)} H${n(x + rr)} A${n(rr)},${n(rr)} 0 0 1 ${n(x)},${n(y + h - rr)} V${n(y + rr)} A${n(rr)},${n(rr)} 0 0 1 ${n(x + rr)},${n(y)} Z`;
|
|
8871
|
+
};
|
|
8872
|
+
var ellipse = (cx, cy, rx, ry) => `M${n(cx - rx)},${n(cy)} A${n(rx)},${n(ry)} 0 1 0 ${n(cx + rx)},${n(cy)} A${n(rx)},${n(ry)} 0 1 0 ${n(cx - rx)},${n(cy)} Z`;
|
|
8873
|
+
var line2 = (x1, y1, x2, y2) => `M${n(x1)},${n(y1)} L${n(x2)},${n(y2)}`;
|
|
8874
|
+
function mermaidShapePaths(shape, width, height, inset = 1) {
|
|
8875
|
+
const s = inset;
|
|
8876
|
+
const W = Math.max(0, width - 2 * s);
|
|
8877
|
+
const H = Math.max(0, height - 2 * s);
|
|
8878
|
+
const x0 = s;
|
|
8879
|
+
const y0 = s;
|
|
8880
|
+
const x1 = width - s;
|
|
8881
|
+
const y1 = height - s;
|
|
8882
|
+
const cx = width / 2;
|
|
8883
|
+
const cy = height / 2;
|
|
8884
|
+
const fill = (d) => ({ d, paint: "shape" });
|
|
8885
|
+
const stroke = (d) => ({ d, paint: "line" });
|
|
8886
|
+
const solid = (d) => ({ d, paint: "filled" });
|
|
8887
|
+
switch (shape) {
|
|
8888
|
+
case "rounded":
|
|
8889
|
+
case "event":
|
|
8890
|
+
return [fill(rect(x0, y0, W, H, Math.min(10, H / 4)))];
|
|
8891
|
+
case "stadium":
|
|
8892
|
+
return [fill(rect(x0, y0, W, H, H / 2))];
|
|
8893
|
+
case "subproc":
|
|
8894
|
+
case "subroutine": {
|
|
8895
|
+
const i = Math.min(10, W / 8);
|
|
8896
|
+
return [fill(rect(x0, y0, W, H)), stroke(line2(x0 + i, y0, x0 + i, y1)), stroke(line2(x1 - i, y0, x1 - i, y1))];
|
|
8897
|
+
}
|
|
8898
|
+
case "cyl":
|
|
8899
|
+
case "cylinder": {
|
|
8900
|
+
const ry = Math.min(H / 6, 14);
|
|
8901
|
+
return [
|
|
8902
|
+
fill(`M${n(x0)},${n(y0 + ry)} A${n(W / 2)},${n(ry)} 0 0 1 ${n(x1)},${n(y0 + ry)} L${n(x1)},${n(y1 - ry)} A${n(W / 2)},${n(ry)} 0 0 1 ${n(x0)},${n(y1 - ry)} Z`),
|
|
8903
|
+
stroke(`M${n(x0)},${n(y0 + ry)} A${n(W / 2)},${n(ry)} 0 0 0 ${n(x1)},${n(y0 + ry)}`)
|
|
8904
|
+
];
|
|
8905
|
+
}
|
|
8906
|
+
case "h-cyl":
|
|
8907
|
+
case "lin-cyl": {
|
|
8908
|
+
const rx = Math.min(W / 6, 14);
|
|
8909
|
+
const paths = [
|
|
8910
|
+
fill(`M${n(x0 + rx)},${n(y0)} L${n(x1 - rx)},${n(y0)} A${n(rx)},${n(H / 2)} 0 0 1 ${n(x1 - rx)},${n(y1)} L${n(x0 + rx)},${n(y1)} A${n(rx)},${n(H / 2)} 0 0 1 ${n(x0 + rx)},${n(y0)} Z`),
|
|
8911
|
+
stroke(ellipse(x1 - rx, cy, rx, H / 2))
|
|
8912
|
+
];
|
|
8913
|
+
if (shape === "lin-cyl") paths.push(stroke(line2(x0 + rx * 2, y0, x0 + rx * 2, y1)));
|
|
8914
|
+
return paths;
|
|
8915
|
+
}
|
|
8916
|
+
case "circle":
|
|
8917
|
+
case "circ":
|
|
8918
|
+
return [fill(ellipse(cx, cy, W / 2, H / 2))];
|
|
8919
|
+
case "dbl-circ":
|
|
8920
|
+
return [fill(ellipse(cx, cy, W / 2, H / 2)), stroke(ellipse(cx, cy, Math.max(0, W / 2 - 5), Math.max(0, H / 2 - 5)))];
|
|
8921
|
+
case "sm-circ":
|
|
8922
|
+
case "f-circ":
|
|
8923
|
+
case "stateStart":
|
|
8924
|
+
return [solid(ellipse(cx, cy, W / 2, H / 2))];
|
|
8925
|
+
case "fr-circ":
|
|
8926
|
+
case "stateEnd":
|
|
8927
|
+
return [fill(ellipse(cx, cy, W / 2, H / 2)), solid(ellipse(cx, cy, Math.max(0, W / 2 - 5), Math.max(0, H / 2 - 5)))];
|
|
8928
|
+
case "cross-circ":
|
|
8929
|
+
return [
|
|
8930
|
+
fill(ellipse(cx, cy, W / 2, H / 2)),
|
|
8931
|
+
stroke(line2(cx - W / 2.83, cy - H / 2.83, cx + W / 2.83, cy + H / 2.83)),
|
|
8932
|
+
stroke(line2(cx + W / 2.83, cy - H / 2.83, cx - W / 2.83, cy + H / 2.83))
|
|
8933
|
+
];
|
|
8934
|
+
case "odd":
|
|
8935
|
+
case "asymmetric": {
|
|
8936
|
+
const d = Math.min(H / 2, 20);
|
|
8937
|
+
return [fill(poly([[x0 + d, y0], [x1, y0], [x1, y1], [x0 + d, y1], [x0, cy]]))];
|
|
8938
|
+
}
|
|
8939
|
+
case "diam":
|
|
8940
|
+
case "diamond":
|
|
8941
|
+
case "choice":
|
|
8942
|
+
return [fill(poly([[cx, y0], [x1, cy], [cx, y1], [x0, cy]]))];
|
|
8943
|
+
case "hex":
|
|
8944
|
+
case "hexagon": {
|
|
8945
|
+
const d = Math.min(W / 5, H / 2);
|
|
8946
|
+
return [fill(poly([[x0 + d, y0], [x1 - d, y0], [x1, cy], [x1 - d, y1], [x0 + d, y1], [x0, cy]]))];
|
|
8947
|
+
}
|
|
8948
|
+
case "lean-r": {
|
|
8949
|
+
const d = Math.min(W / 5, H / 2);
|
|
8950
|
+
return [fill(poly([[x0 + d, y0], [x1, y0], [x1 - d, y1], [x0, y1]]))];
|
|
8951
|
+
}
|
|
8952
|
+
case "lean-l": {
|
|
8953
|
+
const d = Math.min(W / 5, H / 2);
|
|
8954
|
+
return [fill(poly([[x0, y0], [x1 - d, y0], [x1, y1], [x0 + d, y1]]))];
|
|
8955
|
+
}
|
|
8956
|
+
case "trap-b": {
|
|
8957
|
+
const d = Math.min(W / 5, H / 2);
|
|
8958
|
+
return [fill(poly([[x0 + d, y0], [x1 - d, y0], [x1, y1], [x0, y1]]))];
|
|
8959
|
+
}
|
|
8960
|
+
case "trap-t": {
|
|
8961
|
+
const d = Math.min(W / 5, H / 2);
|
|
8962
|
+
return [fill(poly([[x0, y0], [x1, y0], [x1 - d, y1], [x0 + d, y1]]))];
|
|
8963
|
+
}
|
|
8964
|
+
case "text":
|
|
8965
|
+
case "anchor":
|
|
8966
|
+
return [{ d: rect(x0, y0, W, H), paint: "hidden" }];
|
|
8967
|
+
case "card":
|
|
8968
|
+
case "notch-rect": {
|
|
8969
|
+
const d = Math.min(14, H / 3);
|
|
8970
|
+
return [fill(poly([[x0 + d, y0], [x1, y0], [x1, y1], [x0, y1], [x0, y0 + d]]))];
|
|
8971
|
+
}
|
|
8972
|
+
case "lin-rect":
|
|
8973
|
+
case "shaded-process":
|
|
8974
|
+
return [fill(rect(x0, y0, W, H)), stroke(line2(x0 + 8, y0, x0 + 8, y1))];
|
|
8975
|
+
case "fork":
|
|
8976
|
+
case "join":
|
|
8977
|
+
return [solid(rect(x0, y0, W, H, 2))];
|
|
8978
|
+
case "hourglass":
|
|
8979
|
+
return [fill(poly([[x0, y0], [x1, y0], [x0, y1], [x1, y1]]))];
|
|
8980
|
+
case "bolt":
|
|
8981
|
+
return [fill(poly([[cx + W * 0.1, y0], [x0 + W * 0.25, cy + 4], [cx, cy + 4], [cx - W * 0.1, y1], [x1 - W * 0.25, cy - 4], [cx, cy - 4]]))];
|
|
8982
|
+
case "doc":
|
|
8983
|
+
case "lin-doc":
|
|
8984
|
+
case "tag-doc": {
|
|
8985
|
+
const wave = Math.min(12, H / 5);
|
|
8986
|
+
const paths = [fill(`M${n(x0)},${n(y0)} L${n(x1)},${n(y0)} L${n(x1)},${n(y1 - wave)} Q${n(x1 - W / 4)},${n(y1 - wave * 2.2)} ${n(cx)},${n(y1 - wave)} T${n(x0)},${n(y1 - wave)} Z`)];
|
|
8987
|
+
if (shape === "lin-doc") paths.push(stroke(line2(x0 + 8, y0, x0 + 8, y1 - wave)));
|
|
8988
|
+
if (shape === "tag-doc") paths.push(stroke(line2(x1 - 12, y1 - wave * 1.6, x1, y1 - wave * 2.6)));
|
|
8989
|
+
return paths;
|
|
8990
|
+
}
|
|
8991
|
+
case "docs": {
|
|
8992
|
+
const wave = Math.min(10, H / 6);
|
|
8993
|
+
const page = (dx, dy, inner) => fill(`M${n(x0 + dx)},${n(y0 + dy)} L${n(x1 - inner)},${n(y0 + dy)} L${n(x1 - inner)},${n(y1 - wave - (12 - dy))} Q${n(x1 - W / 4 - inner)},${n(y1 - wave * 2.2 - (12 - dy))} ${n(cx + 6 - dy)},${n(y1 - wave - (12 - dy))} T${n(x0 + dx)},${n(y1 - wave - (12 - dy))} Z`);
|
|
8994
|
+
return [page(12, 0, 0), page(6, 6, 6), page(0, 12, 12)];
|
|
8995
|
+
}
|
|
8996
|
+
case "delay":
|
|
8997
|
+
return [fill(`M${n(x0)},${n(y0)} L${n(x1 - H / 2)},${n(y0)} A${n(H / 2)},${n(H / 2)} 0 0 1 ${n(x1 - H / 2)},${n(y1)} L${n(x0)},${n(y1)} Z`)];
|
|
8998
|
+
case "curv-trap": {
|
|
8999
|
+
const d = Math.min(W / 6, H / 3);
|
|
9000
|
+
return [fill(`M${n(x0 + d)},${n(y0)} L${n(x1 - d)},${n(y0)} Q${n(x1)},${n(y0)} ${n(x1)},${n(cy)} Q${n(x1)},${n(y1)} ${n(x1 - d)},${n(y1)} L${n(x0 + d)},${n(y1)} L${n(x0)},${n(cy)} Z`)];
|
|
9001
|
+
}
|
|
9002
|
+
case "div-rect": {
|
|
9003
|
+
const d = Math.min(24, H / 3);
|
|
9004
|
+
return [fill(rect(x0, y0, W, H)), stroke(line2(x0, y0 + d, x1, y0 + d))];
|
|
9005
|
+
}
|
|
9006
|
+
case "tri":
|
|
9007
|
+
return [fill(poly([[cx, y0], [x1, y1], [x0, y1]]))];
|
|
9008
|
+
case "flip-tri":
|
|
9009
|
+
return [fill(poly([[x0, y0], [x1, y0], [cx, y1]]))];
|
|
9010
|
+
case "win-pane":
|
|
9011
|
+
return [fill(rect(x0, y0, W, H)), stroke(line2(x0 + 10, y0, x0 + 10, y1)), stroke(line2(x0, y0 + 10, x1, y0 + 10))];
|
|
9012
|
+
case "flag": {
|
|
9013
|
+
const wave = Math.min(10, H / 5);
|
|
9014
|
+
return [fill(`M${n(x0)},${n(y0 + wave)} Q${n(x0 + W / 4)},${n(y0 - wave)} ${n(cx)},${n(y0 + wave)} T${n(x1)},${n(y0 + wave)} L${n(x1)},${n(y1 - wave)} Q${n(x1 - W / 4)},${n(y1 + wave)} ${n(cx)},${n(y1 - wave)} T${n(x0)},${n(y1 - wave)} Z`)];
|
|
9015
|
+
}
|
|
9016
|
+
case "st-rect":
|
|
9017
|
+
return [fill(rect(x0 + 8, y0, W - 8, H - 8)), fill(rect(x0 + 4, y0 + 4, W - 8, H - 8)), fill(rect(x0, y0 + 8, W - 8, H - 8))];
|
|
9018
|
+
case "bow-rect": {
|
|
9019
|
+
const d = Math.min(W / 8, 14);
|
|
9020
|
+
return [fill(`M${n(x0)},${n(y0)} Q${n(x0 + d)},${n(cy)} ${n(x0)},${n(y1)} L${n(x1)},${n(y1)} Q${n(x1 - d)},${n(cy)} ${n(x1)},${n(y0)} Z`)];
|
|
9021
|
+
}
|
|
9022
|
+
case "tag-rect":
|
|
9023
|
+
return [fill(rect(x0, y0, W, H)), stroke(line2(x1 - 14, y1, x1, y1 - 14))];
|
|
9024
|
+
case "notch-pent": {
|
|
9025
|
+
const d = Math.min(W / 6, H / 3);
|
|
9026
|
+
return [fill(poly([[x0 + d, y0], [x1 - d, y0], [x1, y0 + d], [x1, y1], [x0, y1], [x0, y0 + d]]))];
|
|
9027
|
+
}
|
|
9028
|
+
case "sl-rect": {
|
|
9029
|
+
const d = Math.min(H / 3, 20);
|
|
9030
|
+
return [fill(poly([[x0, y0 + d], [x1, y0], [x1, y1], [x0, y1]]))];
|
|
9031
|
+
}
|
|
9032
|
+
case "brace":
|
|
9033
|
+
case "brace-l":
|
|
9034
|
+
case "brace-r":
|
|
9035
|
+
case "braces": {
|
|
9036
|
+
const left = `M${n(x0 + 18)},${n(y0)} Q${n(x0 + 6)},${n(y0)} ${n(x0 + 6)},${n(cy - 6)} Q${n(x0 + 6)},${n(cy)} ${n(x0)},${n(cy)} Q${n(x0 + 6)},${n(cy)} ${n(x0 + 6)},${n(cy + 6)} Q${n(x0 + 6)},${n(y1)} ${n(x0 + 18)},${n(y1)}`;
|
|
9037
|
+
const right = `M${n(x1 - 18)},${n(y0)} Q${n(x1 - 6)},${n(y0)} ${n(x1 - 6)},${n(cy - 6)} Q${n(x1 - 6)},${n(cy)} ${n(x1)},${n(cy)} Q${n(x1 - 6)},${n(cy)} ${n(x1 - 6)},${n(cy + 6)} Q${n(x1 - 6)},${n(y1)} ${n(x1 - 18)},${n(y1)}`;
|
|
9038
|
+
const hit = { d: rect(x0, y0, W, H), paint: "hidden" };
|
|
9039
|
+
if (shape === "brace-r") return [hit, stroke(right)];
|
|
9040
|
+
if (shape === "braces") return [hit, stroke(left), stroke(right)];
|
|
9041
|
+
return [hit, stroke(left)];
|
|
9042
|
+
}
|
|
9043
|
+
case "comment":
|
|
9044
|
+
return [{ d: rect(x0, y0, W, H), paint: "hidden" }, stroke(`M${n(x0 + 14)},${n(y0)} Q${n(x0)},${n(y0)} ${n(x0)},${n(y0 + 14)} L${n(x0)},${n(y1 - 14)} Q${n(x0)},${n(y1)} ${n(x0 + 14)},${n(y1)}`)];
|
|
9045
|
+
case "icon":
|
|
9046
|
+
case "image":
|
|
9047
|
+
return [fill(rect(x0, y0, W, H, 6))];
|
|
9048
|
+
case "note":
|
|
9049
|
+
return [fill(poly([[x0, y0], [x1 - 12, y0], [x1, y0 + 12], [x1, y1], [x0, y1]]))];
|
|
9050
|
+
default:
|
|
9051
|
+
return [fill(rect(x0, y0, W, H))];
|
|
9052
|
+
}
|
|
9053
|
+
}
|
|
9054
|
+
function mermaidEdgeMarker(head) {
|
|
9055
|
+
if (head === "none") return null;
|
|
9056
|
+
if (head === "arrow_open" || head === "dependency") return "arrow";
|
|
9057
|
+
return "arrowclosed";
|
|
9058
|
+
}
|
|
9059
|
+
function mermaidNodePaint(styles = {}, selected = false) {
|
|
9060
|
+
const paint = {
|
|
9061
|
+
"--pixerate-diagram-node-bg": styles.fill ?? "var(--card, var(--background, #ffffff))",
|
|
9062
|
+
"--pixerate-diagram-node-border": selected ? "var(--primary, #2563eb)" : styles.stroke ?? "var(--foreground, #0f172a)",
|
|
9063
|
+
color: styles.color ?? "var(--foreground, #0f172a)",
|
|
9064
|
+
"stroke-width": styles["stroke-width"] ?? (selected ? "2px" : "1.25px")
|
|
9065
|
+
};
|
|
9066
|
+
if (styles["stroke-dasharray"]) paint["stroke-dasharray"] = styles["stroke-dasharray"];
|
|
9067
|
+
return paint;
|
|
9068
|
+
}
|
|
9069
|
+
var MERMAID_SHAPE_PAINT = {
|
|
9070
|
+
shape: { fill: "var(--pixerate-diagram-node-bg)", stroke: "var(--pixerate-diagram-node-border)" },
|
|
9071
|
+
line: { fill: "none", stroke: "var(--pixerate-diagram-node-border)" },
|
|
9072
|
+
filled: { fill: "var(--pixerate-diagram-node-border)", stroke: "var(--pixerate-diagram-node-border)" },
|
|
9073
|
+
hidden: { fill: "transparent", stroke: "none" }
|
|
9074
|
+
};
|
|
9075
|
+
function mermaidLabelLines(label) {
|
|
9076
|
+
return String(label).replace(/^"`?|`?"$/g, "").split(/<br\s*\/?>|\n/i).map((line3) => line3.replace(/<[^>]+>/g, ""));
|
|
9077
|
+
}
|
|
9078
|
+
function mermaidNodeMembers(data) {
|
|
9079
|
+
const list = [...data?.members ?? [], ...data?.attributes ?? []];
|
|
9080
|
+
return list.map((m) => m.raw ?? "");
|
|
9081
|
+
}
|
|
9082
|
+
|
|
9083
|
+
// src/canvas/mermaid/index.ts
|
|
9084
|
+
function mermaidToCanvas(doc, options = {}) {
|
|
9085
|
+
const layout2 = options.layout ?? ensureDiagramLayout(doc.graph, doc.meta, options);
|
|
9086
|
+
return {
|
|
9087
|
+
nodes: mermaidFlowNodes(doc.graph, layout2, { editable: options.editable }),
|
|
9088
|
+
edges: mermaidFlowEdges(doc.graph, { editable: options.editable }),
|
|
9089
|
+
layout: layout2
|
|
9090
|
+
};
|
|
9091
|
+
}
|
|
9092
|
+
function mermaidMovesFromCanvas(layout2, moved, all = moved, options = {}) {
|
|
9093
|
+
const byId = new Map([...all, ...moved].map((n2) => [n2.id, n2]));
|
|
9094
|
+
const absolute = (id, seen = /* @__PURE__ */ new Set()) => {
|
|
9095
|
+
const node = byId.get(id);
|
|
9096
|
+
if (!node) return layout2.positions[id] ?? [0, 0];
|
|
9097
|
+
if (!node.parentId || seen.has(id)) return [node.position.x, node.position.y];
|
|
9098
|
+
seen.add(id);
|
|
9099
|
+
const [px2, py] = absolute(node.parentId, seen);
|
|
9100
|
+
return [px2 + node.position.x, py + node.position.y];
|
|
9101
|
+
};
|
|
9102
|
+
const moves = moved.map((n2) => ({ id: n2.id, position: absolute(n2.id) })).filter(({ id, position: [x, y] }) => {
|
|
9103
|
+
const before = layout2.positions[id];
|
|
9104
|
+
return !before || Math.abs(before[0] - x) >= 0.5 || Math.abs(before[1] - y) >= 0.5;
|
|
9105
|
+
});
|
|
9106
|
+
const movedIds = new Set(moves.map((m) => m.id));
|
|
9107
|
+
for (const n2 of all) {
|
|
9108
|
+
if (movedIds.has(n2.id)) continue;
|
|
9109
|
+
let parent = n2.parentId;
|
|
9110
|
+
while (parent && !movedIds.has(parent)) parent = byId.get(parent)?.parentId;
|
|
9111
|
+
if (parent) moves.push({ id: n2.id, position: absolute(n2.id) });
|
|
9112
|
+
}
|
|
9113
|
+
if (!moves.length) return null;
|
|
9114
|
+
if (options.stored) {
|
|
9115
|
+
const taken = new Set(moves.map((m) => m.id));
|
|
9116
|
+
for (const [id, position] of Object.entries(layout2.positions)) {
|
|
9117
|
+
if (!taken.has(id) && !options.stored[id]) moves.push({ id, position });
|
|
9118
|
+
}
|
|
9119
|
+
}
|
|
9120
|
+
return { type: "moveNodes", moves };
|
|
9121
|
+
}
|
|
9122
|
+
|
|
8373
9123
|
// src/canvas/agent-presence.ts
|
|
8374
9124
|
var DEFAULT_CURSOR_INACTIVITY_MS = 12e3;
|
|
8375
9125
|
function hashString(str) {
|
|
@@ -8508,13 +9258,17 @@ export {
|
|
|
8508
9258
|
CanvasScenesStore,
|
|
8509
9259
|
DEFAULT_ARRANGE_SHORTCUTS,
|
|
8510
9260
|
DEFAULT_CURSOR_INACTIVITY_MS,
|
|
9261
|
+
DEFAULT_DIAGRAM_NODE_HEIGHT,
|
|
9262
|
+
DEFAULT_DIAGRAM_NODE_WIDTH,
|
|
8511
9263
|
DEFAULT_NODE_HEIGHT,
|
|
8512
9264
|
DEFAULT_NODE_WIDTH,
|
|
8513
9265
|
DEFAULT_PLACEMENT_GAP,
|
|
9266
|
+
DiagramStream,
|
|
8514
9267
|
INSTANCE_DATA_KEY,
|
|
8515
9268
|
LOCKED_DATA_KEY,
|
|
8516
9269
|
LOCKED_PREVIOUS_FLAGS_KEY,
|
|
8517
9270
|
MAX_KEYFRAME_REFS,
|
|
9271
|
+
MERMAID_SHAPE_PAINT,
|
|
8518
9272
|
ManualClock,
|
|
8519
9273
|
PATHFINDER_OPERATIONS,
|
|
8520
9274
|
PIXERATE_BRAND_GRADIENT,
|
|
@@ -8540,6 +9294,7 @@ export {
|
|
|
8540
9294
|
applyShapeCombination,
|
|
8541
9295
|
applyShapeReplacement,
|
|
8542
9296
|
arcToCubics,
|
|
9297
|
+
autoLayoutDiagram,
|
|
8543
9298
|
bezierPathArea,
|
|
8544
9299
|
bezierPathBounds,
|
|
8545
9300
|
bezierPathLength,
|
|
@@ -8548,6 +9303,7 @@ export {
|
|
|
8548
9303
|
bezierPathToSvg,
|
|
8549
9304
|
bindCanvasComponentProperty,
|
|
8550
9305
|
bindCanvasToken,
|
|
9306
|
+
blendDiagramLayout,
|
|
8551
9307
|
blendLayout,
|
|
8552
9308
|
boundsOf,
|
|
8553
9309
|
calculateCursorArrowRotation,
|
|
@@ -8568,6 +9324,7 @@ export {
|
|
|
8568
9324
|
combineShapeNodes,
|
|
8569
9325
|
computeNodesBoundingBox,
|
|
8570
9326
|
computeSnapGuides,
|
|
9327
|
+
connectedDiagramOnly,
|
|
8571
9328
|
connectedOnly,
|
|
8572
9329
|
contourEnclosesArea,
|
|
8573
9330
|
contourSignedArea,
|
|
@@ -8598,17 +9355,25 @@ export {
|
|
|
8598
9355
|
deleteKeyframes,
|
|
8599
9356
|
detachCanvasInstance,
|
|
8600
9357
|
detachTokenBindings,
|
|
9358
|
+
diagramCanvasHeight,
|
|
9359
|
+
diagramGroupSize,
|
|
9360
|
+
diagramImageSize,
|
|
9361
|
+
diagramLayoutBounds,
|
|
8601
9362
|
diffOverrideGroups,
|
|
8602
9363
|
distanceToBezierPath,
|
|
8603
9364
|
distributeNodes,
|
|
8604
9365
|
dividePaths,
|
|
8605
9366
|
dividePolygons,
|
|
9367
|
+
easeDiagramTween,
|
|
8606
9368
|
easingFromInfluence,
|
|
8607
9369
|
easingLabel,
|
|
8608
9370
|
easingToCss,
|
|
8609
9371
|
elasticAt,
|
|
9372
|
+
ensureDiagramLayout,
|
|
8610
9373
|
ensureLayout,
|
|
8611
9374
|
estimateCanvasHeight,
|
|
9375
|
+
estimateDiagramCanvasHeight,
|
|
9376
|
+
estimateDiagramNodeSize,
|
|
8612
9377
|
estimateNodeSize,
|
|
8613
9378
|
evaluateAnimation,
|
|
8614
9379
|
evaluateEasing,
|
|
@@ -8740,6 +9505,18 @@ export {
|
|
|
8740
9505
|
measureSelection,
|
|
8741
9506
|
measureToLine,
|
|
8742
9507
|
mergeNodeUpdates,
|
|
9508
|
+
mermaidEdgeDash,
|
|
9509
|
+
mermaidEdgeMarker,
|
|
9510
|
+
mermaidEdgeWidth,
|
|
9511
|
+
mermaidFlowEdges,
|
|
9512
|
+
mermaidFlowNodes,
|
|
9513
|
+
mermaidLabelLines,
|
|
9514
|
+
mermaidMarkerId,
|
|
9515
|
+
mermaidMovesFromCanvas,
|
|
9516
|
+
mermaidNodeMembers,
|
|
9517
|
+
mermaidNodePaint,
|
|
9518
|
+
mermaidShapePaths,
|
|
9519
|
+
mermaidToCanvas,
|
|
8743
9520
|
mixColorsOklab,
|
|
8744
9521
|
moveKeyframes,
|
|
8745
9522
|
moveLayoutChild,
|
|
@@ -8761,6 +9538,7 @@ export {
|
|
|
8761
9538
|
parseCssEasing,
|
|
8762
9539
|
parseCssGradient,
|
|
8763
9540
|
parseKeyframeClipboard,
|
|
9541
|
+
parseMermaidStyles,
|
|
8764
9542
|
parseNodeStyleDeclarations,
|
|
8765
9543
|
parseOklab,
|
|
8766
9544
|
parseSvgPath,
|
|
@@ -8801,6 +9579,7 @@ export {
|
|
|
8801
9579
|
resolveCanvasGradient,
|
|
8802
9580
|
resolveCanvasTokens,
|
|
8803
9581
|
resolveEasing,
|
|
9582
|
+
resolveMermaidStyles,
|
|
8804
9583
|
resolvePadding,
|
|
8805
9584
|
restoreCanvasMainComponent,
|
|
8806
9585
|
revertShapeCombination,
|
|
@@ -8842,6 +9621,7 @@ export {
|
|
|
8842
9621
|
snapToGrid,
|
|
8843
9622
|
splitSegment,
|
|
8844
9623
|
springAt,
|
|
9624
|
+
streamedDiagramText,
|
|
8845
9625
|
streamlinePoints,
|
|
8846
9626
|
strokeBoundingBox,
|
|
8847
9627
|
strokeOutlineRings,
|