@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.
Files changed (125) hide show
  1. package/dist/agent/canvasPlayback.d.cts +15 -0
  2. package/dist/agent/canvasPlayback.d.ts +15 -0
  3. package/dist/agent/index.cjs +173 -33
  4. package/dist/agent/index.d.cts +1 -0
  5. package/dist/agent/index.d.ts +1 -0
  6. package/dist/agent/index.js +147 -7
  7. package/dist/agent/providers.d.cts +12 -1
  8. package/dist/agent/providers.d.ts +12 -1
  9. package/dist/agent/types.d.cts +3 -0
  10. package/dist/agent/types.d.ts +3 -0
  11. package/dist/animation/index.cjs +2 -2
  12. package/dist/animation/index.js +1 -1
  13. package/dist/animation/presence.d.cts +1 -75
  14. package/dist/animation/presence.d.ts +1 -75
  15. package/dist/animation-editor/index.cjs +69 -19
  16. package/dist/animation-editor/index.d.cts +1 -0
  17. package/dist/animation-editor/index.d.ts +1 -0
  18. package/dist/animation-editor/index.js +54 -4
  19. package/dist/animation-editor/playback.d.cts +10 -0
  20. package/dist/animation-editor/playback.d.ts +10 -0
  21. package/dist/bridge/cli.cjs +3 -3
  22. package/dist/bridge/cli.js +2 -2
  23. package/dist/bridge/index.cjs +3 -3
  24. package/dist/bridge/index.js +2 -2
  25. package/dist/canvas/index.cjs +336 -646
  26. package/dist/canvas/index.d.cts +1 -0
  27. package/dist/canvas/index.d.ts +1 -0
  28. package/dist/canvas/index.js +44 -354
  29. package/dist/canvas/playback.d.cts +14 -0
  30. package/dist/canvas/playback.d.ts +14 -0
  31. package/dist/chart/index.cjs +255 -171
  32. package/dist/chart/index.d.cts +1 -0
  33. package/dist/chart/index.d.ts +1 -0
  34. package/dist/chart/index.js +244 -160
  35. package/dist/chart/playback.d.cts +22 -0
  36. package/dist/chart/playback.d.ts +22 -0
  37. package/dist/chunk-54GVEVXS.js +408 -0
  38. package/dist/{chunk-E747F3D5.js → chunk-CC6WKVIH.js} +86 -5
  39. package/dist/chunk-DW4CV5H4.js +591 -0
  40. package/dist/{chunk-UMS6YFA6.js → chunk-EAQ4BGNS.js} +1 -1
  41. package/dist/{chunk-AGCD3EHB.cjs → chunk-ENIZYNEF.cjs} +7 -7
  42. package/dist/{chunk-BSGPXPTW.js → chunk-PEEP2YR7.js} +1 -1
  43. package/dist/{chunk-VTY64I6H.cjs → chunk-QSM3MDDJ.cjs} +85 -85
  44. package/dist/{chunk-2RUNJYOX.cjs → chunk-QZFEX2N4.cjs} +86 -5
  45. package/dist/{chunk-RB62U6MS.js → chunk-RFBFTLVN.js} +27 -5
  46. package/dist/chunk-UBRYHNRU.cjs +591 -0
  47. package/dist/{chunk-GEY73RUW.cjs → chunk-UJGAA6AK.cjs} +1 -1
  48. package/dist/{chunk-LMSFXRAJ.js → chunk-VGJTUCWM.js} +1 -1
  49. package/dist/chunk-X2HQP7DF.cjs +408 -0
  50. package/dist/chunk-XH32BATE.cjs +68 -0
  51. package/dist/{chunk-HDK3T2QS.cjs → chunk-Y4BWZB6J.cjs} +29 -7
  52. package/dist/chunk-Y6SGC6KO.js +68 -0
  53. package/dist/commands/index.cjs +37 -1
  54. package/dist/commands/index.js +36 -0
  55. package/dist/commands/registry.d.cts +11 -0
  56. package/dist/commands/registry.d.ts +11 -0
  57. package/dist/diagram/index.cjs +7 -7
  58. package/dist/diagram/index.js +1 -1
  59. package/dist/image-editor/index.cjs +108 -16
  60. package/dist/image-editor/index.d.cts +1 -0
  61. package/dist/image-editor/index.d.ts +1 -0
  62. package/dist/image-editor/index.js +107 -15
  63. package/dist/image-editor/playback.d.cts +22 -0
  64. package/dist/image-editor/playback.d.ts +22 -0
  65. package/dist/index.cjs +7 -3
  66. package/dist/index.js +6 -2
  67. package/dist/paint-editor/index.cjs +73 -25
  68. package/dist/paint-editor/index.d.cts +1 -0
  69. package/dist/paint-editor/index.d.ts +1 -0
  70. package/dist/paint-editor/index.js +68 -20
  71. package/dist/paint-editor/playback.d.cts +16 -0
  72. package/dist/paint-editor/playback.d.ts +16 -0
  73. package/dist/parameters/index.cjs +32 -8
  74. package/dist/parameters/index.d.cts +1 -0
  75. package/dist/parameters/index.d.ts +1 -0
  76. package/dist/parameters/index.js +28 -4
  77. package/dist/parameters/playback.d.cts +10 -0
  78. package/dist/parameters/playback.d.ts +10 -0
  79. package/dist/spreadsheet/index.cjs +7 -3
  80. package/dist/spreadsheet/index.d.cts +1 -0
  81. package/dist/spreadsheet/index.d.ts +1 -0
  82. package/dist/spreadsheet/index.js +6 -2
  83. package/dist/spreadsheet/playback.d.cts +15 -0
  84. package/dist/spreadsheet/playback.d.ts +15 -0
  85. package/dist/tools/index.cjs +40 -3
  86. package/dist/tools/index.d.cts +3 -0
  87. package/dist/tools/index.d.ts +3 -0
  88. package/dist/tools/index.js +39 -2
  89. package/dist/tools/playback.d.cts +205 -0
  90. package/dist/tools/playback.d.ts +205 -0
  91. package/dist/tools/presence.d.cts +82 -0
  92. package/dist/tools/presence.d.ts +82 -0
  93. package/dist/tools/registry.d.cts +45 -6
  94. package/dist/tools/registry.d.ts +45 -6
  95. package/dist/tools/script.d.cts +77 -0
  96. package/dist/tools/script.d.ts +77 -0
  97. package/dist/tools/view.d.cts +2 -4
  98. package/dist/tools/view.d.ts +2 -4
  99. package/dist/vector/index.cjs +217 -100
  100. package/dist/vector/index.d.cts +1 -0
  101. package/dist/vector/index.d.ts +1 -0
  102. package/dist/vector/index.js +140 -23
  103. package/dist/vector/playback.d.cts +13 -0
  104. package/dist/vector/playback.d.ts +13 -0
  105. package/dist/video-editor/index.cjs +81 -28
  106. package/dist/video-editor/index.d.cts +1 -0
  107. package/dist/video-editor/index.d.ts +1 -0
  108. package/dist/video-editor/index.js +58 -5
  109. package/dist/video-editor/playback.d.cts +20 -0
  110. package/dist/video-editor/playback.d.ts +20 -0
  111. package/package.json +1 -1
  112. package/skills/pixerate-agent-tools/SKILL.md +13 -0
  113. package/skills/pixerate-animation-editor/SKILL.md +1 -0
  114. package/skills/pixerate-canvas/SKILL.md +3 -0
  115. package/skills/pixerate-chart/SKILL.md +1 -0
  116. package/skills/pixerate-image-editor/SKILL.md +2 -2
  117. package/skills/pixerate-paint-editor/SKILL.md +1 -0
  118. package/skills/pixerate-parameters/SKILL.md +1 -0
  119. package/skills/pixerate-spreadsheet/SKILL.md +1 -0
  120. package/skills/pixerate-vector/SKILL.md +5 -0
  121. package/skills/pixerate-video-editor/SKILL.md +1 -0
  122. package/dist/chunk-BTZS3KZY.js +0 -221
  123. package/dist/chunk-K73HMKQP.js +0 -0
  124. package/dist/chunk-LACYURUW.cjs +0 -1
  125. 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
@@ -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
- };
File without changes
@@ -1 +0,0 @@
1
- "use strict";
@@ -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;