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