@pixerate/editor 0.140.4 → 0.142.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agent/canvasPlayback.d.cts +15 -0
- package/dist/agent/canvasPlayback.d.ts +15 -0
- package/dist/agent/index.cjs +173 -33
- package/dist/agent/index.d.cts +1 -0
- package/dist/agent/index.d.ts +1 -0
- package/dist/agent/index.js +147 -7
- package/dist/agent/providers.d.cts +12 -1
- package/dist/agent/providers.d.ts +12 -1
- package/dist/agent/types.d.cts +3 -0
- package/dist/agent/types.d.ts +3 -0
- package/dist/animation/index.cjs +2 -2
- package/dist/animation/index.js +1 -1
- package/dist/animation/presence.d.cts +1 -75
- package/dist/animation/presence.d.ts +1 -75
- package/dist/animation-editor/index.cjs +69 -19
- package/dist/animation-editor/index.d.cts +1 -0
- package/dist/animation-editor/index.d.ts +1 -0
- package/dist/animation-editor/index.js +54 -4
- package/dist/animation-editor/playback.d.cts +10 -0
- package/dist/animation-editor/playback.d.ts +10 -0
- package/dist/bridge/cli.cjs +3 -3
- package/dist/bridge/cli.js +2 -2
- package/dist/bridge/index.cjs +3 -3
- package/dist/bridge/index.js +2 -2
- package/dist/canvas/index.cjs +336 -646
- package/dist/canvas/index.d.cts +1 -0
- package/dist/canvas/index.d.ts +1 -0
- package/dist/canvas/index.js +44 -354
- package/dist/canvas/playback.d.cts +14 -0
- package/dist/canvas/playback.d.ts +14 -0
- package/dist/chart/index.cjs +255 -171
- package/dist/chart/index.d.cts +1 -0
- package/dist/chart/index.d.ts +1 -0
- package/dist/chart/index.js +244 -160
- package/dist/chart/playback.d.cts +22 -0
- package/dist/chart/playback.d.ts +22 -0
- package/dist/chunk-54GVEVXS.js +408 -0
- package/dist/{chunk-E747F3D5.js → chunk-CC6WKVIH.js} +86 -5
- package/dist/chunk-DW4CV5H4.js +591 -0
- package/dist/{chunk-UMS6YFA6.js → chunk-EAQ4BGNS.js} +1 -1
- package/dist/{chunk-AGCD3EHB.cjs → chunk-ENIZYNEF.cjs} +7 -7
- package/dist/{chunk-BSGPXPTW.js → chunk-PEEP2YR7.js} +1 -1
- package/dist/{chunk-VTY64I6H.cjs → chunk-QSM3MDDJ.cjs} +85 -85
- package/dist/{chunk-2RUNJYOX.cjs → chunk-QZFEX2N4.cjs} +86 -5
- package/dist/{chunk-RB62U6MS.js → chunk-RFBFTLVN.js} +27 -5
- package/dist/chunk-UBRYHNRU.cjs +591 -0
- package/dist/{chunk-GEY73RUW.cjs → chunk-UJGAA6AK.cjs} +1 -1
- package/dist/{chunk-LMSFXRAJ.js → chunk-VGJTUCWM.js} +1 -1
- package/dist/chunk-X2HQP7DF.cjs +408 -0
- package/dist/chunk-XH32BATE.cjs +68 -0
- package/dist/{chunk-HDK3T2QS.cjs → chunk-Y4BWZB6J.cjs} +29 -7
- package/dist/chunk-Y6SGC6KO.js +68 -0
- package/dist/commands/index.cjs +37 -1
- package/dist/commands/index.js +36 -0
- package/dist/commands/registry.d.cts +11 -0
- package/dist/commands/registry.d.ts +11 -0
- package/dist/diagram/index.cjs +7 -7
- package/dist/diagram/index.js +1 -1
- package/dist/image-editor/index.cjs +108 -16
- package/dist/image-editor/index.d.cts +1 -0
- package/dist/image-editor/index.d.ts +1 -0
- package/dist/image-editor/index.js +107 -15
- package/dist/image-editor/playback.d.cts +22 -0
- package/dist/image-editor/playback.d.ts +22 -0
- package/dist/index.cjs +7 -3
- package/dist/index.js +6 -2
- package/dist/paint-editor/index.cjs +73 -25
- package/dist/paint-editor/index.d.cts +1 -0
- package/dist/paint-editor/index.d.ts +1 -0
- package/dist/paint-editor/index.js +68 -20
- package/dist/paint-editor/playback.d.cts +16 -0
- package/dist/paint-editor/playback.d.ts +16 -0
- package/dist/parameters/index.cjs +32 -8
- package/dist/parameters/index.d.cts +1 -0
- package/dist/parameters/index.d.ts +1 -0
- package/dist/parameters/index.js +28 -4
- package/dist/parameters/playback.d.cts +10 -0
- package/dist/parameters/playback.d.ts +10 -0
- package/dist/spreadsheet/index.cjs +7 -3
- package/dist/spreadsheet/index.d.cts +1 -0
- package/dist/spreadsheet/index.d.ts +1 -0
- package/dist/spreadsheet/index.js +6 -2
- package/dist/spreadsheet/playback.d.cts +15 -0
- package/dist/spreadsheet/playback.d.ts +15 -0
- package/dist/tools/index.cjs +40 -3
- package/dist/tools/index.d.cts +3 -0
- package/dist/tools/index.d.ts +3 -0
- package/dist/tools/index.js +39 -2
- package/dist/tools/playback.d.cts +205 -0
- package/dist/tools/playback.d.ts +205 -0
- package/dist/tools/presence.d.cts +82 -0
- package/dist/tools/presence.d.ts +82 -0
- package/dist/tools/registry.d.cts +45 -6
- package/dist/tools/registry.d.ts +45 -6
- package/dist/tools/script.d.cts +77 -0
- package/dist/tools/script.d.ts +77 -0
- package/dist/tools/view.d.cts +2 -4
- package/dist/tools/view.d.ts +2 -4
- package/dist/vector/index.cjs +217 -100
- package/dist/vector/index.d.cts +1 -0
- package/dist/vector/index.d.ts +1 -0
- package/dist/vector/index.js +140 -23
- package/dist/vector/playback.d.cts +13 -0
- package/dist/vector/playback.d.ts +13 -0
- package/dist/video-editor/index.cjs +81 -28
- package/dist/video-editor/index.d.cts +1 -0
- package/dist/video-editor/index.d.ts +1 -0
- package/dist/video-editor/index.js +58 -5
- package/dist/video-editor/playback.d.cts +20 -0
- package/dist/video-editor/playback.d.ts +20 -0
- package/package.json +1 -1
- package/skills/pixerate-agent-tools/SKILL.md +13 -0
- package/skills/pixerate-animation-editor/SKILL.md +1 -0
- package/skills/pixerate-canvas/SKILL.md +3 -0
- package/skills/pixerate-chart/SKILL.md +1 -0
- package/skills/pixerate-image-editor/SKILL.md +2 -2
- package/skills/pixerate-paint-editor/SKILL.md +1 -0
- package/skills/pixerate-parameters/SKILL.md +1 -0
- package/skills/pixerate-spreadsheet/SKILL.md +1 -0
- package/skills/pixerate-vector/SKILL.md +5 -0
- package/skills/pixerate-video-editor/SKILL.md +1 -0
- package/dist/chunk-BTZS3KZY.js +0 -221
- package/dist/chunk-K73HMKQP.js +0 -0
- package/dist/chunk-LACYURUW.cjs +0 -1
- package/dist/chunk-MRD3NXKR.cjs +0 -221
|
@@ -459,6 +459,11 @@ the animation editor.
|
|
|
459
459
|
|
|
460
460
|
The most common ones are below. Read [references/pitfalls.md](references/pitfalls.md) before working with connectors, frames, masks, filters, text, symbols, constraints, blends, gradient meshes or live corners.
|
|
461
461
|
|
|
462
|
+
- With agent playback on, `vector.addShape` is dragged out from (x, y) to (x + width, y + height),
|
|
463
|
+
`vector.addPath` is traced through its anchors, and text is clicked in and typed out. So give
|
|
464
|
+
shapes their real place and size in the first call rather than adding them at 0, 0 and moving
|
|
465
|
+
them after: the user watches the cursor go where the shape lands. Commands with `ids` visit those
|
|
466
|
+
nodes; nothing else about the calls changes.
|
|
462
467
|
- `d` and anchor positions are in the node's own space; `bounds` are in document space. For
|
|
463
468
|
rotated nodes (`rotation` not 0), `vector.moveAnchor` and `vector.bendSegment` take document
|
|
464
469
|
coordinates, so compute them from the drawn position, not from `d`.
|
|
@@ -256,6 +256,7 @@ and every write tool is refused with the reason.
|
|
|
256
256
|
|
|
257
257
|
## Pitfalls
|
|
258
258
|
|
|
259
|
+
- With agent playback on, the cursor drags a moved or trimmed clip to its new time, clicks a track where a clip goes in, and clicks the ruler where a split, seek or marker lands. Give real `start` / `at` times in ms; results are unchanged.
|
|
259
260
|
- **Effects need rendered frames to export.** ffmpeg cannot draw provider effects, so
|
|
260
261
|
`export_video_ffmpeg` refuses a project with enabled effects unless the host renders the
|
|
261
262
|
picture frame by frame (`renderVideoFrameExact`) and passes `frames`. Tell the user, or turn
|
package/dist/chunk-BTZS3KZY.js
DELETED
|
@@ -1,221 +0,0 @@
|
|
|
1
|
-
// src/canvas/layout.ts
|
|
2
|
-
import dagre from "@dagrejs/dagre";
|
|
3
|
-
var DEFAULT_NODE_WIDTH = 200;
|
|
4
|
-
var DEFAULT_NODE_HEIGHT = 60;
|
|
5
|
-
var DEFAULT_PLACEMENT_GAP = 48;
|
|
6
|
-
function getCenteredNodePosition(width = 0, height = 0, screenToFlowPosition, screenDimensions) {
|
|
7
|
-
const rect = screenDimensions ?? (typeof document !== "undefined" ? { width: document.documentElement.clientWidth, height: document.documentElement.clientHeight } : { width: 1920, height: 1080 });
|
|
8
|
-
const flowPos = screenToFlowPosition({ x: rect.width / 2, y: rect.height / 2 });
|
|
9
|
-
return {
|
|
10
|
-
x: flowPos.x - width / 2,
|
|
11
|
-
y: flowPos.y - height / 2
|
|
12
|
-
};
|
|
13
|
-
}
|
|
14
|
-
function centerNodes(nodes, screenToFlowPosition, getNodesBounds, screenDimensions) {
|
|
15
|
-
if (nodes.length === 0) {
|
|
16
|
-
return [];
|
|
17
|
-
}
|
|
18
|
-
const bounds = getNodesBounds(nodes);
|
|
19
|
-
const boundingBoxOrigin = { x: bounds.x, y: bounds.y };
|
|
20
|
-
const centeredPosition = getCenteredNodePosition(
|
|
21
|
-
bounds.width,
|
|
22
|
-
bounds.height,
|
|
23
|
-
screenToFlowPosition,
|
|
24
|
-
screenDimensions
|
|
25
|
-
);
|
|
26
|
-
const deltaX = centeredPosition.x - boundingBoxOrigin.x;
|
|
27
|
-
const deltaY = centeredPosition.y - boundingBoxOrigin.y;
|
|
28
|
-
return nodes.map((node) => ({
|
|
29
|
-
...node,
|
|
30
|
-
position: {
|
|
31
|
-
x: node.position.x + deltaX,
|
|
32
|
-
y: node.position.y + deltaY
|
|
33
|
-
}
|
|
34
|
-
}));
|
|
35
|
-
}
|
|
36
|
-
function getLayoutedNodes(nodes, edges, getNodesBounds, options = {}) {
|
|
37
|
-
if (nodes.length === 0) return [];
|
|
38
|
-
const {
|
|
39
|
-
direction = "LR",
|
|
40
|
-
ranksep = 100,
|
|
41
|
-
nodesep = 25,
|
|
42
|
-
defaultNodeWidth = DEFAULT_NODE_WIDTH,
|
|
43
|
-
defaultNodeHeight = DEFAULT_NODE_HEIGHT
|
|
44
|
-
} = options;
|
|
45
|
-
const dagreGraph = new dagre.graphlib.Graph();
|
|
46
|
-
dagreGraph.setDefaultEdgeLabel(() => ({}));
|
|
47
|
-
dagreGraph.setGraph({ rankdir: direction, ranksep, nodesep });
|
|
48
|
-
const nodeIds = new Set(nodes.map((node) => node.id));
|
|
49
|
-
nodes.forEach((node) => {
|
|
50
|
-
const nodeWidth = node.measured?.width ?? node.width ?? defaultNodeWidth;
|
|
51
|
-
const nodeHeight = node.measured?.height ?? node.height ?? defaultNodeHeight;
|
|
52
|
-
dagreGraph.setNode(node.id, { width: nodeWidth, height: nodeHeight });
|
|
53
|
-
});
|
|
54
|
-
edges.forEach((edge) => {
|
|
55
|
-
if (nodeIds.has(edge.source) && nodeIds.has(edge.target)) {
|
|
56
|
-
dagreGraph.setEdge(edge.source, edge.target);
|
|
57
|
-
}
|
|
58
|
-
});
|
|
59
|
-
dagre.layout(dagreGraph);
|
|
60
|
-
return nodes.map((node) => {
|
|
61
|
-
const nodeWithPosition = dagreGraph.node(node.id);
|
|
62
|
-
const nodeWidth = node.measured?.width ?? node.width ?? defaultNodeWidth;
|
|
63
|
-
const nodeHeight = node.measured?.height ?? node.height ?? defaultNodeHeight;
|
|
64
|
-
return {
|
|
65
|
-
...node,
|
|
66
|
-
position: {
|
|
67
|
-
x: nodeWithPosition.x - nodeWidth / 2,
|
|
68
|
-
y: nodeWithPosition.y - nodeHeight / 2
|
|
69
|
-
}
|
|
70
|
-
};
|
|
71
|
-
});
|
|
72
|
-
}
|
|
73
|
-
function estimateNodeSize(node, defaultWidth = DEFAULT_NODE_WIDTH, defaultHeight = DEFAULT_NODE_HEIGHT) {
|
|
74
|
-
const label = String(node.data?.label ?? node.data?.title ?? node.id ?? "");
|
|
75
|
-
const lines = label.split(/\n|<br\s*\/?>/);
|
|
76
|
-
const longest = Math.max(...lines.map((l) => l.replace(/<[^>]+>/g, "").length), 1);
|
|
77
|
-
const width = Math.min(480, Math.max(defaultWidth, longest * 8 + 48));
|
|
78
|
-
const height = Math.max(defaultHeight, lines.length * 20 + 24);
|
|
79
|
-
return { width, height };
|
|
80
|
-
}
|
|
81
|
-
function boundsOf(rects) {
|
|
82
|
-
if (!rects.length) return null;
|
|
83
|
-
const minX = Math.min(...rects.map((r) => r.x));
|
|
84
|
-
const minY = Math.min(...rects.map((r) => r.y));
|
|
85
|
-
const maxX = Math.max(...rects.map((r) => r.x + r.width));
|
|
86
|
-
const maxY = Math.max(...rects.map((r) => r.y + r.height));
|
|
87
|
-
return { x: minX, y: minY, width: maxX - minX, height: maxY - minY };
|
|
88
|
-
}
|
|
89
|
-
function centre(r) {
|
|
90
|
-
return { x: r.x + r.width / 2, y: r.y + r.height / 2 };
|
|
91
|
-
}
|
|
92
|
-
function overlaps(a, b, pad = 16) {
|
|
93
|
-
return a.x < b.x + b.width + pad && a.x + a.width + pad > b.x && a.y < b.y + b.height + pad && a.y + a.height + pad > b.y;
|
|
94
|
-
}
|
|
95
|
-
function flowSide(direction = "LR") {
|
|
96
|
-
switch (direction) {
|
|
97
|
-
case "LR":
|
|
98
|
-
return "right";
|
|
99
|
-
case "RL":
|
|
100
|
-
return "left";
|
|
101
|
-
case "BT":
|
|
102
|
-
return "above";
|
|
103
|
-
case "TB":
|
|
104
|
-
default:
|
|
105
|
-
return "below";
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
function ensureLayout(nodes, edges, options = {}) {
|
|
109
|
-
if (nodes.length === 0) return [];
|
|
110
|
-
const stored = options.storedPositions ?? {};
|
|
111
|
-
const missing = nodes.filter((n) => !stored[n.id]);
|
|
112
|
-
if (missing.length === 0) {
|
|
113
|
-
return nodes.map((n) => ({
|
|
114
|
-
...n,
|
|
115
|
-
position: { ...stored[n.id] }
|
|
116
|
-
}));
|
|
117
|
-
}
|
|
118
|
-
const autoLayouted = getLayoutedNodes(nodes, edges, void 0, options);
|
|
119
|
-
const autoMap = new Map(
|
|
120
|
-
autoLayouted.map((n) => [n.id, n.position])
|
|
121
|
-
);
|
|
122
|
-
const both = nodes.filter((n) => stored[n.id] && autoMap.has(n.id));
|
|
123
|
-
if (both.length === 0) {
|
|
124
|
-
return autoLayouted;
|
|
125
|
-
}
|
|
126
|
-
let dx = 0;
|
|
127
|
-
let dy = 0;
|
|
128
|
-
for (const n of both) {
|
|
129
|
-
const s = stored[n.id];
|
|
130
|
-
const a = autoMap.get(n.id);
|
|
131
|
-
dx += s.x - a.x;
|
|
132
|
-
dy += s.y - a.y;
|
|
133
|
-
}
|
|
134
|
-
dx /= both.length;
|
|
135
|
-
dy /= both.length;
|
|
136
|
-
return nodes.map((node) => {
|
|
137
|
-
if (stored[node.id]) {
|
|
138
|
-
return {
|
|
139
|
-
...node,
|
|
140
|
-
position: { ...stored[node.id] }
|
|
141
|
-
};
|
|
142
|
-
}
|
|
143
|
-
const autoPos = autoMap.get(node.id) ?? { x: 0, y: 0 };
|
|
144
|
-
return {
|
|
145
|
-
...node,
|
|
146
|
-
position: {
|
|
147
|
-
x: Math.round(autoPos.x + dx),
|
|
148
|
-
y: Math.round(autoPos.y + dy)
|
|
149
|
-
}
|
|
150
|
-
};
|
|
151
|
-
});
|
|
152
|
-
}
|
|
153
|
-
function placeBeside(rects, size, side, nearNodeId, options = {}) {
|
|
154
|
-
const {
|
|
155
|
-
gap = DEFAULT_PLACEMENT_GAP,
|
|
156
|
-
ignore = [],
|
|
157
|
-
maxAttempts = 32
|
|
158
|
-
} = options;
|
|
159
|
-
const skip = new Set([nearNodeId, ...ignore].filter(Boolean));
|
|
160
|
-
const obstacles = Object.entries(rects).filter(([id]) => !skip.has(id)).map(([, r]) => r);
|
|
161
|
-
const anchor = nearNodeId && rects[nearNodeId] || boundsOf(Object.values(rects)) || { x: 0, y: 0, width: 0, height: 0 };
|
|
162
|
-
const anchorCenter = centre(anchor);
|
|
163
|
-
let baseX;
|
|
164
|
-
let baseY;
|
|
165
|
-
switch (side) {
|
|
166
|
-
case "right":
|
|
167
|
-
baseX = anchor.x + anchor.width + gap;
|
|
168
|
-
baseY = anchorCenter.y - size.height / 2;
|
|
169
|
-
break;
|
|
170
|
-
case "left":
|
|
171
|
-
baseX = anchor.x - gap - size.width;
|
|
172
|
-
baseY = anchorCenter.y - size.height / 2;
|
|
173
|
-
break;
|
|
174
|
-
case "above":
|
|
175
|
-
baseX = anchorCenter.x - size.width / 2;
|
|
176
|
-
baseY = anchor.y - gap - size.height;
|
|
177
|
-
break;
|
|
178
|
-
case "below":
|
|
179
|
-
default:
|
|
180
|
-
baseX = anchorCenter.x - size.width / 2;
|
|
181
|
-
baseY = anchor.y + anchor.height + gap;
|
|
182
|
-
break;
|
|
183
|
-
}
|
|
184
|
-
const isHorizontal = side === "right" || side === "left";
|
|
185
|
-
const step = (isHorizontal ? size.height : size.width) + 20;
|
|
186
|
-
for (let i = 0; i < maxAttempts; i++) {
|
|
187
|
-
const offset = i === 0 ? 0 : Math.ceil(i / 2) * step * (i % 2 === 1 ? 1 : -1);
|
|
188
|
-
const candidateBox = {
|
|
189
|
-
x: isHorizontal ? baseX : baseX + offset,
|
|
190
|
-
y: isHorizontal ? baseY + offset : baseY,
|
|
191
|
-
width: size.width,
|
|
192
|
-
height: size.height
|
|
193
|
-
};
|
|
194
|
-
if (!obstacles.some((obstacle) => overlaps(candidateBox, obstacle, 8))) {
|
|
195
|
-
return {
|
|
196
|
-
x: Math.round(candidateBox.x),
|
|
197
|
-
y: Math.round(candidateBox.y)
|
|
198
|
-
};
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
return {
|
|
202
|
-
x: Math.round(baseX),
|
|
203
|
-
y: Math.round(baseY)
|
|
204
|
-
};
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
export {
|
|
208
|
-
DEFAULT_NODE_WIDTH,
|
|
209
|
-
DEFAULT_NODE_HEIGHT,
|
|
210
|
-
DEFAULT_PLACEMENT_GAP,
|
|
211
|
-
getCenteredNodePosition,
|
|
212
|
-
centerNodes,
|
|
213
|
-
getLayoutedNodes,
|
|
214
|
-
estimateNodeSize,
|
|
215
|
-
boundsOf,
|
|
216
|
-
centre,
|
|
217
|
-
overlaps,
|
|
218
|
-
flowSide,
|
|
219
|
-
ensureLayout,
|
|
220
|
-
placeBeside
|
|
221
|
-
};
|
package/dist/chunk-K73HMKQP.js
DELETED
|
File without changes
|
package/dist/chunk-LACYURUW.cjs
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
"use strict";
|
package/dist/chunk-MRD3NXKR.cjs
DELETED
|
@@ -1,221 +0,0 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }// src/canvas/layout.ts
|
|
2
|
-
var _dagre = require('@dagrejs/dagre'); var _dagre2 = _interopRequireDefault(_dagre);
|
|
3
|
-
var DEFAULT_NODE_WIDTH = 200;
|
|
4
|
-
var DEFAULT_NODE_HEIGHT = 60;
|
|
5
|
-
var DEFAULT_PLACEMENT_GAP = 48;
|
|
6
|
-
function getCenteredNodePosition(width = 0, height = 0, screenToFlowPosition, screenDimensions) {
|
|
7
|
-
const rect = _nullishCoalesce(screenDimensions, () => ( (typeof document !== "undefined" ? { width: document.documentElement.clientWidth, height: document.documentElement.clientHeight } : { width: 1920, height: 1080 })));
|
|
8
|
-
const flowPos = screenToFlowPosition({ x: rect.width / 2, y: rect.height / 2 });
|
|
9
|
-
return {
|
|
10
|
-
x: flowPos.x - width / 2,
|
|
11
|
-
y: flowPos.y - height / 2
|
|
12
|
-
};
|
|
13
|
-
}
|
|
14
|
-
function centerNodes(nodes, screenToFlowPosition, getNodesBounds, screenDimensions) {
|
|
15
|
-
if (nodes.length === 0) {
|
|
16
|
-
return [];
|
|
17
|
-
}
|
|
18
|
-
const bounds = getNodesBounds(nodes);
|
|
19
|
-
const boundingBoxOrigin = { x: bounds.x, y: bounds.y };
|
|
20
|
-
const centeredPosition = getCenteredNodePosition(
|
|
21
|
-
bounds.width,
|
|
22
|
-
bounds.height,
|
|
23
|
-
screenToFlowPosition,
|
|
24
|
-
screenDimensions
|
|
25
|
-
);
|
|
26
|
-
const deltaX = centeredPosition.x - boundingBoxOrigin.x;
|
|
27
|
-
const deltaY = centeredPosition.y - boundingBoxOrigin.y;
|
|
28
|
-
return nodes.map((node) => ({
|
|
29
|
-
...node,
|
|
30
|
-
position: {
|
|
31
|
-
x: node.position.x + deltaX,
|
|
32
|
-
y: node.position.y + deltaY
|
|
33
|
-
}
|
|
34
|
-
}));
|
|
35
|
-
}
|
|
36
|
-
function getLayoutedNodes(nodes, edges, getNodesBounds, options = {}) {
|
|
37
|
-
if (nodes.length === 0) return [];
|
|
38
|
-
const {
|
|
39
|
-
direction = "LR",
|
|
40
|
-
ranksep = 100,
|
|
41
|
-
nodesep = 25,
|
|
42
|
-
defaultNodeWidth = DEFAULT_NODE_WIDTH,
|
|
43
|
-
defaultNodeHeight = DEFAULT_NODE_HEIGHT
|
|
44
|
-
} = options;
|
|
45
|
-
const dagreGraph = new _dagre2.default.graphlib.Graph();
|
|
46
|
-
dagreGraph.setDefaultEdgeLabel(() => ({}));
|
|
47
|
-
dagreGraph.setGraph({ rankdir: direction, ranksep, nodesep });
|
|
48
|
-
const nodeIds = new Set(nodes.map((node) => node.id));
|
|
49
|
-
nodes.forEach((node) => {
|
|
50
|
-
const nodeWidth = _nullishCoalesce(_nullishCoalesce(_optionalChain([node, 'access', _ => _.measured, 'optionalAccess', _2 => _2.width]), () => ( node.width)), () => ( defaultNodeWidth));
|
|
51
|
-
const nodeHeight = _nullishCoalesce(_nullishCoalesce(_optionalChain([node, 'access', _3 => _3.measured, 'optionalAccess', _4 => _4.height]), () => ( node.height)), () => ( defaultNodeHeight));
|
|
52
|
-
dagreGraph.setNode(node.id, { width: nodeWidth, height: nodeHeight });
|
|
53
|
-
});
|
|
54
|
-
edges.forEach((edge) => {
|
|
55
|
-
if (nodeIds.has(edge.source) && nodeIds.has(edge.target)) {
|
|
56
|
-
dagreGraph.setEdge(edge.source, edge.target);
|
|
57
|
-
}
|
|
58
|
-
});
|
|
59
|
-
_dagre2.default.layout(dagreGraph);
|
|
60
|
-
return nodes.map((node) => {
|
|
61
|
-
const nodeWithPosition = dagreGraph.node(node.id);
|
|
62
|
-
const nodeWidth = _nullishCoalesce(_nullishCoalesce(_optionalChain([node, 'access', _5 => _5.measured, 'optionalAccess', _6 => _6.width]), () => ( node.width)), () => ( defaultNodeWidth));
|
|
63
|
-
const nodeHeight = _nullishCoalesce(_nullishCoalesce(_optionalChain([node, 'access', _7 => _7.measured, 'optionalAccess', _8 => _8.height]), () => ( node.height)), () => ( defaultNodeHeight));
|
|
64
|
-
return {
|
|
65
|
-
...node,
|
|
66
|
-
position: {
|
|
67
|
-
x: nodeWithPosition.x - nodeWidth / 2,
|
|
68
|
-
y: nodeWithPosition.y - nodeHeight / 2
|
|
69
|
-
}
|
|
70
|
-
};
|
|
71
|
-
});
|
|
72
|
-
}
|
|
73
|
-
function estimateNodeSize(node, defaultWidth = DEFAULT_NODE_WIDTH, defaultHeight = DEFAULT_NODE_HEIGHT) {
|
|
74
|
-
const label = String(_nullishCoalesce(_nullishCoalesce(_nullishCoalesce(_optionalChain([node, 'access', _9 => _9.data, 'optionalAccess', _10 => _10.label]), () => ( _optionalChain([node, 'access', _11 => _11.data, 'optionalAccess', _12 => _12.title]))), () => ( node.id)), () => ( "")));
|
|
75
|
-
const lines = label.split(/\n|<br\s*\/?>/);
|
|
76
|
-
const longest = Math.max(...lines.map((l) => l.replace(/<[^>]+>/g, "").length), 1);
|
|
77
|
-
const width = Math.min(480, Math.max(defaultWidth, longest * 8 + 48));
|
|
78
|
-
const height = Math.max(defaultHeight, lines.length * 20 + 24);
|
|
79
|
-
return { width, height };
|
|
80
|
-
}
|
|
81
|
-
function boundsOf(rects) {
|
|
82
|
-
if (!rects.length) return null;
|
|
83
|
-
const minX = Math.min(...rects.map((r) => r.x));
|
|
84
|
-
const minY = Math.min(...rects.map((r) => r.y));
|
|
85
|
-
const maxX = Math.max(...rects.map((r) => r.x + r.width));
|
|
86
|
-
const maxY = Math.max(...rects.map((r) => r.y + r.height));
|
|
87
|
-
return { x: minX, y: minY, width: maxX - minX, height: maxY - minY };
|
|
88
|
-
}
|
|
89
|
-
function centre(r) {
|
|
90
|
-
return { x: r.x + r.width / 2, y: r.y + r.height / 2 };
|
|
91
|
-
}
|
|
92
|
-
function overlaps(a, b, pad = 16) {
|
|
93
|
-
return a.x < b.x + b.width + pad && a.x + a.width + pad > b.x && a.y < b.y + b.height + pad && a.y + a.height + pad > b.y;
|
|
94
|
-
}
|
|
95
|
-
function flowSide(direction = "LR") {
|
|
96
|
-
switch (direction) {
|
|
97
|
-
case "LR":
|
|
98
|
-
return "right";
|
|
99
|
-
case "RL":
|
|
100
|
-
return "left";
|
|
101
|
-
case "BT":
|
|
102
|
-
return "above";
|
|
103
|
-
case "TB":
|
|
104
|
-
default:
|
|
105
|
-
return "below";
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
function ensureLayout(nodes, edges, options = {}) {
|
|
109
|
-
if (nodes.length === 0) return [];
|
|
110
|
-
const stored = _nullishCoalesce(options.storedPositions, () => ( {}));
|
|
111
|
-
const missing = nodes.filter((n) => !stored[n.id]);
|
|
112
|
-
if (missing.length === 0) {
|
|
113
|
-
return nodes.map((n) => ({
|
|
114
|
-
...n,
|
|
115
|
-
position: { ...stored[n.id] }
|
|
116
|
-
}));
|
|
117
|
-
}
|
|
118
|
-
const autoLayouted = getLayoutedNodes(nodes, edges, void 0, options);
|
|
119
|
-
const autoMap = new Map(
|
|
120
|
-
autoLayouted.map((n) => [n.id, n.position])
|
|
121
|
-
);
|
|
122
|
-
const both = nodes.filter((n) => stored[n.id] && autoMap.has(n.id));
|
|
123
|
-
if (both.length === 0) {
|
|
124
|
-
return autoLayouted;
|
|
125
|
-
}
|
|
126
|
-
let dx = 0;
|
|
127
|
-
let dy = 0;
|
|
128
|
-
for (const n of both) {
|
|
129
|
-
const s = stored[n.id];
|
|
130
|
-
const a = autoMap.get(n.id);
|
|
131
|
-
dx += s.x - a.x;
|
|
132
|
-
dy += s.y - a.y;
|
|
133
|
-
}
|
|
134
|
-
dx /= both.length;
|
|
135
|
-
dy /= both.length;
|
|
136
|
-
return nodes.map((node) => {
|
|
137
|
-
if (stored[node.id]) {
|
|
138
|
-
return {
|
|
139
|
-
...node,
|
|
140
|
-
position: { ...stored[node.id] }
|
|
141
|
-
};
|
|
142
|
-
}
|
|
143
|
-
const autoPos = _nullishCoalesce(autoMap.get(node.id), () => ( { x: 0, y: 0 }));
|
|
144
|
-
return {
|
|
145
|
-
...node,
|
|
146
|
-
position: {
|
|
147
|
-
x: Math.round(autoPos.x + dx),
|
|
148
|
-
y: Math.round(autoPos.y + dy)
|
|
149
|
-
}
|
|
150
|
-
};
|
|
151
|
-
});
|
|
152
|
-
}
|
|
153
|
-
function placeBeside(rects, size, side, nearNodeId, options = {}) {
|
|
154
|
-
const {
|
|
155
|
-
gap = DEFAULT_PLACEMENT_GAP,
|
|
156
|
-
ignore = [],
|
|
157
|
-
maxAttempts = 32
|
|
158
|
-
} = options;
|
|
159
|
-
const skip = new Set([nearNodeId, ...ignore].filter(Boolean));
|
|
160
|
-
const obstacles = Object.entries(rects).filter(([id]) => !skip.has(id)).map(([, r]) => r);
|
|
161
|
-
const anchor = nearNodeId && rects[nearNodeId] || boundsOf(Object.values(rects)) || { x: 0, y: 0, width: 0, height: 0 };
|
|
162
|
-
const anchorCenter = centre(anchor);
|
|
163
|
-
let baseX;
|
|
164
|
-
let baseY;
|
|
165
|
-
switch (side) {
|
|
166
|
-
case "right":
|
|
167
|
-
baseX = anchor.x + anchor.width + gap;
|
|
168
|
-
baseY = anchorCenter.y - size.height / 2;
|
|
169
|
-
break;
|
|
170
|
-
case "left":
|
|
171
|
-
baseX = anchor.x - gap - size.width;
|
|
172
|
-
baseY = anchorCenter.y - size.height / 2;
|
|
173
|
-
break;
|
|
174
|
-
case "above":
|
|
175
|
-
baseX = anchorCenter.x - size.width / 2;
|
|
176
|
-
baseY = anchor.y - gap - size.height;
|
|
177
|
-
break;
|
|
178
|
-
case "below":
|
|
179
|
-
default:
|
|
180
|
-
baseX = anchorCenter.x - size.width / 2;
|
|
181
|
-
baseY = anchor.y + anchor.height + gap;
|
|
182
|
-
break;
|
|
183
|
-
}
|
|
184
|
-
const isHorizontal = side === "right" || side === "left";
|
|
185
|
-
const step = (isHorizontal ? size.height : size.width) + 20;
|
|
186
|
-
for (let i = 0; i < maxAttempts; i++) {
|
|
187
|
-
const offset = i === 0 ? 0 : Math.ceil(i / 2) * step * (i % 2 === 1 ? 1 : -1);
|
|
188
|
-
const candidateBox = {
|
|
189
|
-
x: isHorizontal ? baseX : baseX + offset,
|
|
190
|
-
y: isHorizontal ? baseY + offset : baseY,
|
|
191
|
-
width: size.width,
|
|
192
|
-
height: size.height
|
|
193
|
-
};
|
|
194
|
-
if (!obstacles.some((obstacle) => overlaps(candidateBox, obstacle, 8))) {
|
|
195
|
-
return {
|
|
196
|
-
x: Math.round(candidateBox.x),
|
|
197
|
-
y: Math.round(candidateBox.y)
|
|
198
|
-
};
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
return {
|
|
202
|
-
x: Math.round(baseX),
|
|
203
|
-
y: Math.round(baseY)
|
|
204
|
-
};
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
exports.DEFAULT_NODE_WIDTH = DEFAULT_NODE_WIDTH; exports.DEFAULT_NODE_HEIGHT = DEFAULT_NODE_HEIGHT; exports.DEFAULT_PLACEMENT_GAP = DEFAULT_PLACEMENT_GAP; exports.getCenteredNodePosition = getCenteredNodePosition; exports.centerNodes = centerNodes; exports.getLayoutedNodes = getLayoutedNodes; exports.estimateNodeSize = estimateNodeSize; exports.boundsOf = boundsOf; exports.centre = centre; exports.overlaps = overlaps; exports.flowSide = flowSide; exports.ensureLayout = ensureLayout; exports.placeBeside = placeBeside;
|