@pixerate/editor-svelte 0.15.2 → 0.16.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.
Files changed (149) hide show
  1. package/dist/BubbleMenu.svelte.d.ts +14 -0
  2. package/dist/BubbleMenu.svelte.d.ts.map +1 -0
  3. package/{src → dist}/EditableTextNodeEditor.svelte +1 -1
  4. package/dist/EditableTextNodeEditor.svelte.d.ts +26 -0
  5. package/dist/EditableTextNodeEditor.svelte.d.ts.map +1 -0
  6. package/dist/TemplateRenderer.svelte.d.ts +14 -0
  7. package/dist/TemplateRenderer.svelte.d.ts.map +1 -0
  8. package/dist/canvas/AgentPresenceLayer.svelte.d.ts +9 -0
  9. package/dist/canvas/AgentPresenceLayer.svelte.d.ts.map +1 -0
  10. package/dist/canvas/FloatingHorizontalScrollbar.svelte.d.ts +9 -0
  11. package/dist/canvas/FloatingHorizontalScrollbar.svelte.d.ts.map +1 -0
  12. package/dist/canvas/createCanvasClipboard.svelte.d.ts +32 -0
  13. package/dist/canvas/createCanvasClipboard.svelte.d.ts.map +1 -0
  14. package/dist/canvas/createCanvasClipboard.svelte.js +171 -0
  15. package/dist/canvas/createCanvasDisplacement.d.ts +32 -0
  16. package/dist/canvas/createCanvasDisplacement.d.ts.map +1 -0
  17. package/dist/canvas/createCanvasDisplacement.js +170 -0
  18. package/dist/canvas/createCanvasDocking.svelte.d.ts +56 -0
  19. package/dist/canvas/createCanvasDocking.svelte.d.ts.map +1 -0
  20. package/dist/canvas/createCanvasDocking.svelte.js +227 -0
  21. package/dist/canvas/createCanvasExplosion.svelte.d.ts +31 -0
  22. package/dist/canvas/createCanvasExplosion.svelte.d.ts.map +1 -0
  23. package/dist/canvas/createCanvasExplosion.svelte.js +346 -0
  24. package/dist/canvas/createCanvasGraph.svelte.d.ts +62 -0
  25. package/dist/canvas/createCanvasGraph.svelte.d.ts.map +1 -0
  26. package/dist/canvas/createCanvasGraph.svelte.js +223 -0
  27. package/dist/canvas/createCanvasInteractions.svelte.d.ts +28 -0
  28. package/dist/canvas/createCanvasInteractions.svelte.d.ts.map +1 -0
  29. package/dist/canvas/createCanvasInteractions.svelte.js +95 -0
  30. package/dist/canvas/createCanvasLayout.d.ts +22 -0
  31. package/dist/canvas/createCanvasLayout.d.ts.map +1 -0
  32. package/dist/canvas/createCanvasLayout.js +76 -0
  33. package/dist/canvas/createCanvasMultiDrag.svelte.d.ts +61 -0
  34. package/dist/canvas/createCanvasMultiDrag.svelte.d.ts.map +1 -0
  35. package/dist/canvas/createCanvasMultiDrag.svelte.js +105 -0
  36. package/dist/canvas/createCanvasNodeSync.svelte.d.ts +58 -0
  37. package/dist/canvas/createCanvasNodeSync.svelte.d.ts.map +1 -0
  38. package/dist/canvas/createCanvasNodeSync.svelte.js +82 -0
  39. package/dist/canvas/createCanvasSelection.svelte.d.ts +26 -0
  40. package/dist/canvas/createCanvasSelection.svelte.d.ts.map +1 -0
  41. package/dist/canvas/createCanvasSelection.svelte.js +26 -0
  42. package/dist/canvas/createCanvasShortcuts.d.ts +9 -0
  43. package/dist/canvas/createCanvasShortcuts.d.ts.map +1 -0
  44. package/dist/canvas/createCanvasShortcuts.js +97 -0
  45. package/dist/canvas/createCanvasTrajectory.d.ts +31 -0
  46. package/dist/canvas/createCanvasTrajectory.d.ts.map +1 -0
  47. package/dist/canvas/createCanvasTrajectory.js +141 -0
  48. package/dist/canvas/createStreamingCanvas.svelte.d.ts +19 -0
  49. package/dist/canvas/createStreamingCanvas.svelte.d.ts.map +1 -0
  50. package/dist/canvas/createStreamingCanvas.svelte.js +32 -0
  51. package/dist/canvas/index.d.ts +18 -688
  52. package/dist/canvas/index.d.ts.map +1 -0
  53. package/dist/canvas/index.js +34 -1839
  54. package/dist/canvas/types.d.ts +183 -0
  55. package/dist/canvas/types.d.ts.map +1 -0
  56. package/dist/canvas/types.js +1 -0
  57. package/dist/createNavigationGuard.svelte.d.ts +24 -0
  58. package/dist/createNavigationGuard.svelte.d.ts.map +1 -0
  59. package/dist/createNavigationGuard.svelte.js +65 -0
  60. package/dist/editor.svelte.d.ts +23 -0
  61. package/dist/editor.svelte.d.ts.map +1 -0
  62. package/dist/editor.svelte.js +41 -0
  63. package/dist/history/createHistoryShortcuts.d.ts +24 -0
  64. package/dist/history/createHistoryShortcuts.d.ts.map +1 -0
  65. package/dist/history/createHistoryShortcuts.js +57 -0
  66. package/dist/history/history.svelte.d.ts +18 -0
  67. package/dist/history/history.svelte.d.ts.map +1 -0
  68. package/dist/history/history.svelte.js +43 -0
  69. package/dist/history/index.d.ts +3 -0
  70. package/dist/history/index.d.ts.map +1 -0
  71. package/dist/history/index.js +2 -0
  72. package/{src → dist}/image-editor/ImageEditor.svelte +1 -1
  73. package/dist/image-editor/ImageEditor.svelte.d.ts +17 -0
  74. package/dist/image-editor/ImageEditor.svelte.d.ts.map +1 -0
  75. package/dist/image-editor/imageEditorState.svelte.d.ts +50 -0
  76. package/dist/image-editor/imageEditorState.svelte.d.ts.map +1 -0
  77. package/dist/image-editor/imageEditorState.svelte.js +132 -0
  78. package/dist/image-editor/index.d.ts +6 -16
  79. package/dist/image-editor/index.d.ts.map +1 -0
  80. package/dist/image-editor/index.js +2 -9
  81. package/dist/index.d.ts +20 -249
  82. package/dist/index.d.ts.map +1 -0
  83. package/dist/index.js +10 -1119
  84. package/dist/navigationGuard.d.ts +21 -0
  85. package/dist/navigationGuard.d.ts.map +1 -0
  86. package/dist/navigationGuard.js +59 -0
  87. package/{src → dist}/spreadsheet/FormulaBar.svelte +1 -1
  88. package/dist/spreadsheet/FormulaBar.svelte.d.ts +17 -0
  89. package/dist/spreadsheet/FormulaBar.svelte.d.ts.map +1 -0
  90. package/{src → dist}/spreadsheet/SpreadsheetEditor.svelte +1 -1
  91. package/dist/spreadsheet/SpreadsheetEditor.svelte.d.ts +22 -0
  92. package/dist/spreadsheet/SpreadsheetEditor.svelte.d.ts.map +1 -0
  93. package/dist/spreadsheet/index.d.ts +9 -0
  94. package/dist/spreadsheet/index.d.ts.map +1 -0
  95. package/{src/spreadsheet/index.ts → dist/spreadsheet/index.js} +1 -1
  96. package/dist/spreadsheet/spreadsheet.svelte.d.ts +33 -0
  97. package/dist/spreadsheet/spreadsheet.svelte.d.ts.map +1 -0
  98. package/dist/spreadsheet/spreadsheet.svelte.js +160 -0
  99. package/package.json +14 -16
  100. package/dist/canvas/index.js.map +0 -1
  101. package/dist/chunk-HEOI4UNF.js +0 -1191
  102. package/dist/chunk-HEOI4UNF.js.map +0 -1
  103. package/dist/image-editor/index.js.map +0 -1
  104. package/dist/index.css +0 -50
  105. package/dist/index.css.map +0 -1
  106. package/dist/index.js.map +0 -1
  107. package/src/canvas/__tests__/canvas-clipboard.test.ts +0 -154
  108. package/src/canvas/__tests__/canvas-docking.test.ts +0 -288
  109. package/src/canvas/__tests__/canvas-explosion.test.ts +0 -634
  110. package/src/canvas/__tests__/canvas-graph.test.ts +0 -159
  111. package/src/canvas/__tests__/canvas-interactions.test.ts +0 -86
  112. package/src/canvas/__tests__/canvas-layout.test.ts +0 -75
  113. package/src/canvas/__tests__/canvas-multi-drag.test.ts +0 -112
  114. package/src/canvas/__tests__/canvas-node-sync.svelte.test.ts +0 -104
  115. package/src/canvas/__tests__/canvas-shortcuts.test.ts +0 -59
  116. package/src/canvas/createCanvasClipboard.svelte.ts +0 -219
  117. package/src/canvas/createCanvasDisplacement.ts +0 -253
  118. package/src/canvas/createCanvasDocking.svelte.ts +0 -355
  119. package/src/canvas/createCanvasExplosion.svelte.ts +0 -457
  120. package/src/canvas/createCanvasGraph.svelte.ts +0 -330
  121. package/src/canvas/createCanvasInteractions.svelte.ts +0 -112
  122. package/src/canvas/createCanvasLayout.ts +0 -129
  123. package/src/canvas/createCanvasMultiDrag.svelte.ts +0 -175
  124. package/src/canvas/createCanvasNodeSync.svelte.ts +0 -150
  125. package/src/canvas/createCanvasSelection.svelte.ts +0 -51
  126. package/src/canvas/createCanvasShortcuts.ts +0 -99
  127. package/src/canvas/createCanvasTrajectory.ts +0 -207
  128. package/src/canvas/createStreamingCanvas.svelte.ts +0 -56
  129. package/src/canvas/index.d.ts +0 -688
  130. package/src/canvas/index.ts +0 -126
  131. package/src/canvas/types.ts +0 -223
  132. package/src/createNavigationGuard.svelte.ts +0 -97
  133. package/src/editor.svelte.ts +0 -65
  134. package/src/history/createHistoryShortcuts.ts +0 -95
  135. package/src/history/history.svelte.ts +0 -68
  136. package/src/history/index.ts +0 -2
  137. package/src/image-editor/imageEditorState.svelte.ts +0 -151
  138. package/src/image-editor/index.d.ts +0 -16
  139. package/src/image-editor/index.ts +0 -2
  140. package/src/index.d.ts +0 -249
  141. package/src/index.ts +0 -89
  142. package/src/navigationGuard.ts +0 -82
  143. package/src/spreadsheet/spreadsheet.svelte.ts +0 -176
  144. package/src/svelte.d.ts +0 -5
  145. /package/{src → dist}/BubbleMenu.svelte +0 -0
  146. /package/{src → dist}/TemplateRenderer.svelte +0 -0
  147. /package/{src → dist}/canvas/AgentPresenceLayer.svelte +0 -0
  148. /package/{src → dist}/canvas/FloatingHorizontalScrollbar.svelte +0 -0
  149. /package/{src → dist}/canvas/README.md +0 -0
@@ -1,1839 +1,34 @@
1
- // src/canvas/createCanvasGraph.svelte.ts
2
- import * as $ from "svelte/internal/client";
3
- import { cubicOut } from "svelte/easing";
4
- function calculateGraphDifferences(currentState, baselineState) {
5
- const currentNodes = currentState.nodes ?? [];
6
- const currentEdges = currentState.edges ?? [];
7
- const baselineNodes = baselineState.nodes ?? [];
8
- const baselineEdges = baselineState.edges ?? [];
9
- const baselineNodeMap = new Map(baselineNodes.map((n) => [n.id, n]));
10
- const baselineEdgeMap = new Map(baselineEdges.map((e) => [e.id, e]));
11
- const currentNodeMap = new Map(currentNodes.map((n) => [n.id, n]));
12
- const currentEdgeMap = new Map(currentEdges.map((e) => [e.id, e]));
13
- const removedNodes = baselineNodes.filter((oldNode) => !currentNodeMap.has(oldNode.id));
14
- const removedEdges = baselineEdges.filter((oldEdge) => !currentEdgeMap.has(oldEdge.id));
15
- const changedNodes = currentNodes.filter((newNode) => {
16
- const oldNode = baselineNodeMap.get(newNode.id);
17
- if (!oldNode) return true;
18
- return JSON.stringify(newNode) !== JSON.stringify(oldNode);
19
- });
20
- const changedEdges = currentEdges.filter((newEdge) => {
21
- const oldEdge = baselineEdgeMap.get(newEdge.id);
22
- if (!oldEdge) return true;
23
- return JSON.stringify(newEdge) !== JSON.stringify(oldEdge);
24
- });
25
- return { changedNodes, changedEdges, removedNodes, removedEdges };
26
- }
27
- function replaceNodeInGraph(nodes, edges, oldNode, newNode, keepEdges = false) {
28
- const updatedNodes = nodes.map((n) => n.id === oldNode.id ? newNode : n);
29
- if (!keepEdges) {
30
- return { nodes: updatedNodes, edges };
31
- }
32
- const updatedEdges = edges.map((edge) => {
33
- if (edge.source === oldNode.id || edge.target === oldNode.id) {
34
- return {
35
- ...edge,
36
- id: crypto.randomUUID(),
37
- source: edge.source === oldNode.id ? newNode.id : edge.source,
38
- target: edge.target === oldNode.id ? newNode.id : edge.target
39
- };
40
- }
41
- return edge;
42
- });
43
- return { nodes: updatedNodes, edges: updatedEdges };
44
- }
45
- function createCanvasGraph(options = {}) {
46
- let nodes = $.state(options.initialNodes ?? []);
47
- let edges = $.state(options.initialEdges ?? []);
48
- function setNodes(newNodes, triggerCallback = true) {
49
- $.set(nodes, newNodes);
50
- if (triggerCallback) {
51
- options.onNodesChange?.($.get(nodes));
52
- }
53
- }
54
- function setEdges(newEdges, triggerCallback = true) {
55
- $.set(edges, newEdges);
56
- if (triggerCallback) {
57
- options.onEdgesChange?.($.get(edges));
58
- }
59
- }
60
- function animateNodePosition(node, targetPosition, duration = 400, easing = cubicOut) {
61
- const delay = node.data?.animationDelay ?? 0;
62
- const startPosition = { ...node.position };
63
- const startTime = Date.now() + delay;
64
- function step() {
65
- const currentTime = Date.now();
66
- if (currentTime < startTime) {
67
- if (typeof requestAnimationFrame !== "undefined") {
68
- requestAnimationFrame(step);
69
- }
70
- return;
71
- }
72
- const progress = Math.min((currentTime - startTime) / duration, 1);
73
- const eased = easing(progress);
74
- const currentPos = {
75
- x: startPosition.x + (targetPosition.x - startPosition.x) * eased,
76
- y: startPosition.y + (targetPosition.y - startPosition.y) * eased
77
- };
78
- const targetNode = $.get(nodes).find((n) => n.id === node.id);
79
- if (targetNode) {
80
- targetNode.position = currentPos;
81
- }
82
- if (progress < 1) {
83
- if (typeof requestAnimationFrame !== "undefined") {
84
- requestAnimationFrame(step);
85
- }
86
- } else {
87
- setNodes([...$.get(nodes)]);
88
- }
89
- }
90
- step();
91
- }
92
- function addNodeOrNodes(nodeOrNodesToAdd, animateFromPosition, save = true) {
93
- const toAdd = Array.isArray(nodeOrNodesToAdd) ? nodeOrNodesToAdd : [nodeOrNodesToAdd];
94
- const existingMap = new Map($.get(nodes).map((n) => [n.id, n]));
95
- toAdd.forEach((node) => {
96
- if (!existingMap.has(node.id)) {
97
- existingMap.set(node.id, node);
98
- }
99
- });
100
- setNodes(Array.from(existingMap.values()));
101
- if (animateFromPosition) {
102
- toAdd.forEach((node) => {
103
- const target = { ...node.position };
104
- node.position = { ...animateFromPosition };
105
- animateNodePosition(node, target);
106
- });
107
- }
108
- if (save) options.onSave?.();
109
- }
110
- function addEdge(edgeToAdd, save = true) {
111
- setEdges([...$.get(edges), edgeToAdd]);
112
- if (save) options.onSave?.();
113
- }
114
- function addEdges(edgesToAdd, save = true) {
115
- setEdges([...$.get(edges), ...edgesToAdd]);
116
- if (save) options.onSave?.();
117
- }
118
- function removeNodes(nodesToRemove, save = true) {
119
- const idsToRemove = new Set(nodesToRemove.map((n) => n.id));
120
- setNodes($.get(nodes).filter((n) => !idsToRemove.has(n.id)));
121
- if (save) options.onSave?.();
122
- }
123
- function removeEdges(edgesToRemove, save = true) {
124
- const idsToRemove = new Set(edgesToRemove.map((e) => e.id));
125
- setEdges($.get(edges).filter((e) => !idsToRemove.has(e.id)));
126
- if (save) options.onSave?.();
127
- }
128
- function replaceNode(oldNode, newNode, save = true, keepEdges = false) {
129
- const result = replaceNodeInGraph($.get(nodes), $.get(edges), oldNode, newNode, keepEdges);
130
- setNodes(result.nodes);
131
- if (result.edges !== $.get(edges)) {
132
- setEdges(result.edges);
133
- }
134
- if (save) options.onSave?.();
135
- }
136
- function addConnectedNodes(params) {
137
- const {
138
- nodesToAdd,
139
- inboundNodes = [],
140
- outboundNodes = [],
141
- animatedEdges = false,
142
- animateFromPosition,
143
- inboundEdgeData = {},
144
- outboundEdgeData = {},
145
- getEdgeLabel
146
- } = params;
147
- const defaultCreateEdge = (sourceId, targetId, opt) => {
148
- if (options.createEdge) {
149
- return options.createEdge(sourceId, targetId, opt);
150
- }
151
- return {
152
- id: crypto.randomUUID(),
153
- type: "default",
154
- source: sourceId,
155
- target: targetId,
156
- label: opt?.label ?? "",
157
- animated: opt?.animated ?? false,
158
- data: opt?.data ?? {}
159
- };
160
- };
161
- nodesToAdd.forEach((addedNode) => {
162
- addNodeOrNodes(addedNode, animateFromPosition, false);
163
- inboundNodes.forEach((sourceNode) => {
164
- const label = getEdgeLabel ? getEdgeLabel(sourceNode, addedNode) : "";
165
- addEdge(defaultCreateEdge(sourceNode.id, addedNode.id, { label, animated: animatedEdges, data: inboundEdgeData }), false);
166
- });
167
- outboundNodes.forEach((targetNode) => {
168
- const label = getEdgeLabel ? getEdgeLabel(addedNode, targetNode) : "";
169
- addEdge(defaultCreateEdge(addedNode.id, targetNode.id, { label, animated: animatedEdges, data: outboundEdgeData }), false);
170
- });
171
- });
172
- options.onSave?.();
173
- }
174
- function getDifferences(baseline) {
175
- return calculateGraphDifferences({ nodes: $.get(nodes), edges: $.get(edges) }, baseline);
176
- }
177
- return {
178
- get nodes() {
179
- return $.get(nodes);
180
- },
181
- set nodes(val) {
182
- setNodes(val);
183
- },
184
- get edges() {
185
- return $.get(edges);
186
- },
187
- set edges(val) {
188
- setEdges(val);
189
- },
190
- setNodes,
191
- setEdges,
192
- addNodeOrNodes,
193
- addEdge,
194
- addEdges,
195
- removeNodes,
196
- removeEdges,
197
- replaceNode,
198
- addConnectedNodes,
199
- animateNodePosition,
200
- getDifferences
201
- };
202
- }
203
-
204
- // src/canvas/createCanvasLayout.ts
205
- import dagre from "@dagrejs/dagre";
206
- import { Position } from "@xyflow/svelte";
207
- import {
208
- ensureLayout,
209
- placeBeside,
210
- estimateNodeSize,
211
- flowSide
212
- } from "@pixerate/editor/canvas";
213
- function getCenteredNodePosition(width = 0, height = 0, screenToFlowPosition, screenDimensions) {
214
- const rect = screenDimensions ?? (typeof document !== "undefined" ? { width: document.documentElement.clientWidth, height: document.documentElement.clientHeight } : { width: 1920, height: 1080 });
215
- const flowPos = screenToFlowPosition({ x: rect.width / 2, y: rect.height / 2 });
216
- return {
217
- x: flowPos.x - width / 2,
218
- y: flowPos.y - height / 2
219
- };
220
- }
221
- function centerNodes(nodes, screenToFlowPosition, getNodesBounds, screenDimensions) {
222
- if (nodes.length === 0) {
223
- return [];
224
- }
225
- const bounds = getNodesBounds(nodes);
226
- const boundingBoxOrigin = { x: bounds.x, y: bounds.y };
227
- const centeredPosition = getCenteredNodePosition(
228
- bounds.width,
229
- bounds.height,
230
- screenToFlowPosition,
231
- screenDimensions
232
- );
233
- const deltaX = centeredPosition.x - boundingBoxOrigin.x;
234
- const deltaY = centeredPosition.y - boundingBoxOrigin.y;
235
- return nodes.map((node) => ({
236
- ...node,
237
- position: {
238
- x: node.position.x + deltaX,
239
- y: node.position.y + deltaY
240
- }
241
- }));
242
- }
243
- function getLayoutedNodes(nodes, edges, getNodesBounds, options = {}) {
244
- if (nodes.length === 0) return [];
245
- const {
246
- direction = "LR",
247
- ranksep = 100,
248
- nodesep = 25,
249
- defaultNodeWidth = 200,
250
- defaultNodeHeight = 200
251
- } = options;
252
- const isHorizontal = direction === "LR" || direction === "RL";
253
- const bounds = getNodesBounds(nodes);
254
- const dagreGraph = new dagre.graphlib.Graph();
255
- dagreGraph.setDefaultEdgeLabel(() => ({}));
256
- dagreGraph.setGraph({ rankdir: direction, ranksep, nodesep });
257
- const nodeIds = new Set(nodes.map((node) => node.id));
258
- nodes.forEach((node) => {
259
- const nodeWidth = node.measured?.width ?? node.width ?? defaultNodeWidth;
260
- const nodeHeight = node.measured?.height ?? node.height ?? defaultNodeHeight;
261
- dagreGraph.setNode(node.id, { width: nodeWidth, height: nodeHeight });
262
- });
263
- edges.forEach((edge) => {
264
- if (nodeIds.has(edge.source) && nodeIds.has(edge.target)) {
265
- dagreGraph.setEdge(edge.source, edge.target);
266
- }
267
- });
268
- dagre.layout(dagreGraph);
269
- return nodes.map((node) => {
270
- const nodeWithPosition = dagreGraph.node(node.id);
271
- const nodeWidth = node.measured?.width ?? node.width ?? defaultNodeWidth;
272
- const nodeHeight = node.measured?.height ?? node.height ?? defaultNodeHeight;
273
- return {
274
- ...node,
275
- targetPosition: isHorizontal ? Position.Left : Position.Top,
276
- sourcePosition: isHorizontal ? Position.Right : Position.Bottom,
277
- position: {
278
- x: bounds.x + (nodeWithPosition?.x ?? 0) - nodeWidth / 2,
279
- y: bounds.y + (nodeWithPosition?.y ?? 0) - nodeHeight / 2
280
- }
281
- };
282
- });
283
- }
284
-
285
- // src/canvas/createCanvasClipboard.svelte.ts
286
- import * as $2 from "svelte/internal/client";
287
- import { tick } from "svelte";
288
- function isEventFromTextInput(event2) {
289
- const target = event2.target;
290
- if (!target) return false;
291
- if (target.tagName === "INPUT" || target.tagName === "TEXTAREA" || target.tagName === "SELECT" || target.isContentEditable || target.closest?.('[contenteditable="true"]') || target.closest?.(".ProseMirror")) {
292
- return true;
293
- }
294
- return false;
295
- }
296
- function isValidCanvasNode(obj) {
297
- return typeof obj === "object" && obj !== null && "id" in obj && typeof obj.id === "string" && "position" in obj && typeof obj.position === "object" && obj.position !== null && "x" in obj.position && "y" in obj.position;
298
- }
299
- function isValidUrl(url) {
300
- try {
301
- const parsed = new URL(url);
302
- return parsed.protocol === "http:" || parsed.protocol === "https:";
303
- } catch {
304
- return false;
305
- }
306
- }
307
- function createCanvasClipboard(options = {}) {
308
- function copySelectedNodes(selectedNodes, connectedEdges, event2) {
309
- if (event2 && isEventFromTextInput(event2)) {
310
- return false;
311
- }
312
- if (selectedNodes.length === 0) return false;
313
- const payload = { version: 1, nodes: selectedNodes, edges: connectedEdges };
314
- const serialized = JSON.stringify(payload);
315
- if (event2?.clipboardData) {
316
- event2.clipboardData.setData("application/json", serialized);
317
- event2.clipboardData.setData("text/plain", serialized);
318
- event2.preventDefault();
319
- } else if (typeof navigator !== "undefined" && navigator.clipboard) {
320
- navigator.clipboard.writeText(serialized).catch(() => {
321
- });
322
- }
323
- return true;
324
- }
325
- function cutSelectedNodes(selectedNodes, connectedEdges, onRemove, event2) {
326
- if (event2 && isEventFromTextInput(event2)) {
327
- return false;
328
- }
329
- const copied = copySelectedNodes(selectedNodes, connectedEdges, event2);
330
- if (copied && onRemove) {
331
- onRemove(selectedNodes);
332
- }
333
- return copied;
334
- }
335
- async function handlePasteEvent(event2) {
336
- if (isEventFromTextInput(event2)) {
337
- return false;
338
- }
339
- const clipboardData = event2.clipboardData;
340
- if (!clipboardData) return false;
341
- const files = clipboardData.files;
342
- if (files && files.length > 0) {
343
- const imageFile = Array.from(files).find((f) => f.type.startsWith("image/"));
344
- if (imageFile && options.onPasteImage) {
345
- event2.preventDefault();
346
- await options.onPasteImage(imageFile);
347
- return true;
348
- }
349
- }
350
- const rawJson = clipboardData.getData("application/json") || clipboardData.getData("text/plain");
351
- if (rawJson) {
352
- try {
353
- const parsed = JSON.parse(rawJson);
354
- let rawNodes;
355
- let rawEdges;
356
- if (Array.isArray(parsed) && parsed.every(isValidCanvasNode)) {
357
- rawNodes = parsed;
358
- } else if (typeof parsed === "object" && parsed !== null && Array.isArray(parsed.nodes) && parsed.nodes.every(isValidCanvasNode)) {
359
- rawNodes = parsed.nodes;
360
- rawEdges = parsed.edges;
361
- }
362
- if (rawNodes && rawNodes.length > 0) {
363
- event2.preventDefault();
364
- const idMap = /* @__PURE__ */ new Map();
365
- const newNodes = rawNodes.map((node) => {
366
- const newId = crypto.randomUUID();
367
- idMap.set(node.id, newId);
368
- return {
369
- ...node,
370
- id: newId,
371
- selected: true,
372
- position: { x: node.position.x + 40, y: node.position.y + 40 }
373
- };
374
- });
375
- const newEdges = rawEdges?.map((edge) => ({
376
- ...edge,
377
- id: crypto.randomUUID(),
378
- source: idMap.get(edge.source) ?? edge.source,
379
- target: idMap.get(edge.target) ?? edge.target
380
- }));
381
- if (options.onPasteNodes) {
382
- await options.onPasteNodes(newNodes, newEdges);
383
- await tick();
384
- }
385
- return true;
386
- }
387
- } catch {
388
- }
389
- }
390
- const text = clipboardData.getData("text/plain")?.trim();
391
- if (text) {
392
- if (isValidUrl(text) && options.onPasteUrl) {
393
- event2.preventDefault();
394
- options.onPasteUrl(text);
395
- return true;
396
- } else if (options.onPasteText) {
397
- event2.preventDefault();
398
- options.onPasteText(text);
399
- return true;
400
- }
401
- }
402
- return false;
403
- }
404
- return { copySelectedNodes, cutSelectedNodes, handlePasteEvent };
405
- }
406
-
407
- // src/canvas/createCanvasDocking.svelte.ts
408
- import * as $3 from "svelte/internal/client";
409
- function getNodeRect(node) {
410
- const x = node.position?.x ?? 0;
411
- const y = node.position?.y ?? 0;
412
- const width = node.measured?.width ?? node.width ?? node.initialWidth ?? 0;
413
- const height = node.measured?.height ?? node.height ?? node.initialHeight ?? 0;
414
- return { x, y, width, height };
415
- }
416
- function getNodeCenter(node) {
417
- const rect = getNodeRect(node);
418
- return { x: rect.x + rect.width / 2, y: rect.y + rect.height / 2 };
419
- }
420
- function getDistanceSq(p1, p2) {
421
- const dx = p1.x - p2.x;
422
- const dy = p1.y - p2.y;
423
- return dx * dx + dy * dy;
424
- }
425
- function getOverlapArea(rectA, rectB) {
426
- const xOverlap = Math.max(0, Math.min(rectA.x + rectA.width, rectB.x + rectB.width) - Math.max(rectA.x, rectB.x));
427
- const yOverlap = Math.max(0, Math.min(rectA.y + rectA.height, rectB.y + rectB.height) - Math.max(rectA.y, rectB.y));
428
- return xOverlap * yOverlap;
429
- }
430
- function resolvePrimaryTarget(targets, draggedNode, strategy, customResolver, event2) {
431
- if (targets.length === 0) return null;
432
- if (targets.length === 1) return targets[0];
433
- if (customResolver) {
434
- const resolved = customResolver(targets, draggedNode, event2);
435
- if (resolved !== void 0) return resolved;
436
- }
437
- if (strategy === "first") {
438
- return targets[0];
439
- }
440
- if (strategy === "pointer" && event2) {
441
- const clientX = "clientX" in event2 ? event2.clientX : event2.touches?.[0]?.clientX;
442
- const clientY = "clientY" in event2 ? event2.clientY : event2.touches?.[0]?.clientY;
443
- if (typeof clientX === "number" && typeof clientY === "number") {
444
- const pointerInside = targets.filter((target) => {
445
- const r = getNodeRect(target);
446
- return r.width > 0 && r.height > 0 && clientX >= r.x && clientX <= r.x + r.width && clientY >= r.y && clientY <= r.y + r.height;
447
- });
448
- if (pointerInside.length === 1) return pointerInside[0];
449
- if (pointerInside.length > 1) {
450
- return pointerInside.reduce((best, cur) => {
451
- const bestDist = getDistanceSq(getNodeCenter(best), { x: clientX, y: clientY });
452
- const curDist = getDistanceSq(getNodeCenter(cur), { x: clientX, y: clientY });
453
- return curDist < bestDist ? cur : best;
454
- });
455
- }
456
- }
457
- }
458
- if (strategy === "max-overlap") {
459
- const draggedRect = getNodeRect(draggedNode);
460
- let maxArea = -1;
461
- let bestTarget = targets[0];
462
- for (const target of targets) {
463
- const targetRect = getNodeRect(target);
464
- const area = getOverlapArea(draggedRect, targetRect);
465
- if (area > maxArea) {
466
- maxArea = area;
467
- bestTarget = target;
468
- }
469
- }
470
- return bestTarget;
471
- }
472
- const draggedCenter = getNodeCenter(draggedNode);
473
- const containing = targets.filter((target) => {
474
- const r = getNodeRect(target);
475
- if (r.width > 0 && r.height > 0) {
476
- return draggedCenter.x >= r.x && draggedCenter.x <= r.x + r.width && draggedCenter.y >= r.y && draggedCenter.y <= r.y + r.height;
477
- }
478
- return false;
479
- });
480
- if (containing.length === 1) return containing[0];
481
- if (containing.length > 1) {
482
- return containing.reduce((best, cur) => {
483
- const bestDist = getDistanceSq(getNodeCenter(best), draggedCenter);
484
- const curDist = getDistanceSq(getNodeCenter(cur), draggedCenter);
485
- return curDist < bestDist ? cur : best;
486
- });
487
- }
488
- return targets.reduce((best, cur) => {
489
- const bestDist = getDistanceSq(getNodeCenter(best), draggedCenter);
490
- const curDist = getDistanceSq(getNodeCenter(cur), draggedCenter);
491
- return curDist < bestDist ? cur : best;
492
- });
493
- }
494
- function createCanvasDocking(options = {}) {
495
- let draggedNode = $3.state(null);
496
- let draggedInitialPosition = $3.state(null);
497
- let connectingHandle = $3.state("");
498
- let connectingNode = $3.state(null);
499
- let currentHoverTargets = $3.state(/* @__PURE__ */ new Set());
500
- const isDockTarget = options.isDockTarget ?? ((target) => target.type === "boardNode");
501
- const dockStrategy = options.dockStrategy ?? "center-point";
502
- const exclusiveHover = options.exclusiveHover ?? true;
503
- function handleNodeDragStart(params) {
504
- $3.set(draggedNode, params.targetNode);
505
- $3.set(draggedInitialPosition, params.targetNode?.position ? { ...params.targetNode.position } : null);
506
- $3.set(currentHoverTargets, /* @__PURE__ */ new Set());
507
- }
508
- function handleNodeDrag(params, getIntersectingNodes) {
509
- $3.set(draggedNode, params.targetNode);
510
- if (!$3.get(draggedNode)) return;
511
- const intersecting = getIntersectingNodes($3.get(draggedNode));
512
- const currentDockTargets = intersecting.filter(isDockTarget);
513
- if (exclusiveHover) {
514
- const primaryTarget = currentDockTargets.length > 0 ? resolvePrimaryTarget(currentDockTargets, $3.get(draggedNode), dockStrategy, options.resolvePrimaryDockTarget, params.event) : null;
515
- const primaryTargetId = primaryTarget ? primaryTarget.id : null;
516
- $3.get(currentHoverTargets).forEach((targetId) => {
517
- if (targetId !== primaryTargetId) {
518
- const leftNode = intersecting.find((n) => n.id === targetId) ?? { id: targetId };
519
- options.onDockLeave?.(leftNode, $3.get(draggedNode));
520
- }
521
- });
522
- if (primaryTarget && !$3.get(currentHoverTargets).has(primaryTarget.id)) {
523
- options.onDockHover?.(primaryTarget, $3.get(draggedNode));
524
- }
525
- $3.set(currentHoverTargets, primaryTargetId ? /* @__PURE__ */ new Set([primaryTargetId]) : /* @__PURE__ */ new Set());
526
- } else {
527
- const newHoverSet = new Set(currentDockTargets.map((t) => t.id));
528
- $3.get(currentHoverTargets).forEach((targetId) => {
529
- if (!newHoverSet.has(targetId)) {
530
- const leftNode = intersecting.find((n) => n.id === targetId) ?? { id: targetId };
531
- options.onDockLeave?.(leftNode, $3.get(draggedNode));
532
- }
533
- });
534
- currentDockTargets.forEach((target) => {
535
- if (!$3.get(currentHoverTargets).has(target.id)) {
536
- options.onDockHover?.(target, $3.get(draggedNode));
537
- }
538
- });
539
- $3.set(currentHoverTargets, newHoverSet);
540
- }
541
- }
542
- function handleNodeDragStop(params, getIntersectingNodes, updateNodePosition) {
543
- $3.set(draggedNode, params.targetNode);
544
- if ($3.get(draggedNode)) {
545
- const intersecting = getIntersectingNodes($3.get(draggedNode));
546
- const dockTargets = intersecting.filter(isDockTarget);
547
- const dockTarget = dockTargets.length > 0 ? resolvePrimaryTarget(dockTargets, $3.get(draggedNode), dockStrategy, options.resolvePrimaryDockTarget, params.event) : null;
548
- if (dockTarget) {
549
- options.onDockDrop?.(dockTarget, $3.get(draggedNode));
550
- if (options.restorePositionOnDock !== false && $3.get(draggedInitialPosition) && updateNodePosition) {
551
- updateNodePosition($3.get(draggedNode).id, $3.get(draggedInitialPosition));
552
- }
553
- }
554
- }
555
- $3.set(draggedNode, null);
556
- $3.set(draggedInitialPosition, null);
557
- $3.set(currentHoverTargets, /* @__PURE__ */ new Set());
558
- options.onSave?.();
559
- }
560
- function handleConnectStart(params, getNode) {
561
- $3.set(connectingHandle, params.handleType ?? "");
562
- $3.set(connectingNode, params.nodeId ? getNode(params.nodeId) ?? null : null);
563
- }
564
- function handleConnectEnd() {
565
- $3.set(connectingHandle, "");
566
- $3.set(connectingNode, null);
567
- }
568
- function reset2() {
569
- $3.set(draggedNode, null);
570
- $3.set(draggedInitialPosition, null);
571
- $3.set(connectingHandle, "");
572
- $3.set(connectingNode, null);
573
- $3.set(currentHoverTargets, /* @__PURE__ */ new Set());
574
- }
575
- return {
576
- get draggedNode() {
577
- return $3.get(draggedNode);
578
- },
579
- get draggedInitialPosition() {
580
- return $3.get(draggedInitialPosition);
581
- },
582
- get connectingHandle() {
583
- return $3.get(connectingHandle);
584
- },
585
- get connectingNode() {
586
- return $3.get(connectingNode);
587
- },
588
- get isDragging() {
589
- return $3.get(draggedNode) !== null;
590
- },
591
- handleNodeDragStart,
592
- handleNodeDrag,
593
- handleNodeDragStop,
594
- handleConnectStart,
595
- handleConnectEnd,
596
- reset: reset2
597
- };
598
- }
599
-
600
- // src/canvas/createCanvasShortcuts.ts
601
- function createCanvasShortcuts(options) {
602
- const target = options.targetElement ?? (typeof window !== "undefined" ? window : null);
603
- if (!target) return () => {
604
- };
605
- function handleKeyDown(event2) {
606
- const keyboardEvent = event2;
607
- if (isEventFromTextInput(keyboardEvent)) {
608
- return;
609
- }
610
- const isMod = keyboardEvent.metaKey || keyboardEvent.ctrlKey;
611
- const isShift = keyboardEvent.shiftKey;
612
- const key = keyboardEvent.key;
613
- const selectedNodes = options.getSelectedNodes ? options.getSelectedNodes() : [];
614
- if (key === "Backspace" || key === "Delete") {
615
- if (options.onDelete && selectedNodes.length > 0) {
616
- keyboardEvent.preventDefault();
617
- options.onDelete(selectedNodes);
618
- }
619
- return;
620
- }
621
- if (isMod) {
622
- const lowerKey = key.toLowerCase();
623
- if (lowerKey === "c" && !isShift) {
624
- if (options.onCopy) {
625
- options.onCopy();
626
- }
627
- } else if (lowerKey === "x" && !isShift) {
628
- if (options.onCut) {
629
- options.onCut();
630
- }
631
- } else if (lowerKey === "d" && !isShift) {
632
- if (options.onDuplicate && selectedNodes.length > 0) {
633
- keyboardEvent.preventDefault();
634
- options.onDuplicate(selectedNodes);
635
- }
636
- } else if (lowerKey === "a" && !isShift) {
637
- if (options.onSelectAll) {
638
- keyboardEvent.preventDefault();
639
- options.onSelectAll();
640
- }
641
- } else if (lowerKey === "g") {
642
- if (isShift) {
643
- if (options.onUngroup && selectedNodes.length > 0) {
644
- keyboardEvent.preventDefault();
645
- options.onUngroup(selectedNodes);
646
- }
647
- } else {
648
- if (options.onGroup && selectedNodes.length > 0) {
649
- keyboardEvent.preventDefault();
650
- options.onGroup(selectedNodes);
651
- }
652
- }
653
- } else if (key === "=" || key === "+") {
654
- if (options.onZoomIn) {
655
- keyboardEvent.preventDefault();
656
- options.onZoomIn();
657
- }
658
- } else if (key === "-") {
659
- if (options.onZoomOut) {
660
- keyboardEvent.preventDefault();
661
- options.onZoomOut();
662
- }
663
- } else if (key === "0") {
664
- if (options.onFitView) {
665
- keyboardEvent.preventDefault();
666
- options.onFitView();
667
- }
668
- } else if (lowerKey === "f") {
669
- if (options.onSearch) {
670
- keyboardEvent.preventDefault();
671
- options.onSearch();
672
- }
673
- }
674
- }
675
- }
676
- target.addEventListener("keydown", handleKeyDown);
677
- return () => {
678
- target.removeEventListener("keydown", handleKeyDown);
679
- };
680
- }
681
-
682
- // src/canvas/createCanvasInteractions.svelte.ts
683
- import * as $4 from "svelte/internal/client";
684
- function createCanvasInteractions(options = {}) {
685
- let isSpacebarPanning = $4.state(false);
686
- let trackpadDetected = $4.state(false);
687
- let toggledPanMode = false;
688
- function handleKeyDown(event2) {
689
- if (event2.key === " " || event2.code === "Space") {
690
- if ($4.get(isSpacebarPanning) || isEventFromTextInput(event2)) return;
691
- $4.set(isSpacebarPanning, true);
692
- toggledPanMode = true;
693
- options.onPanModeChange?.(true);
694
- if (typeof document !== "undefined") {
695
- document.body.classList.add("cursor-grab");
696
- }
697
- }
698
- }
699
- function handleKeyUp(event2) {
700
- if (event2.key === " " || event2.code === "Space") {
701
- if (!$4.get(isSpacebarPanning) && !toggledPanMode) return;
702
- $4.set(isSpacebarPanning, false);
703
- toggledPanMode = false;
704
- options.onPanModeChange?.(false);
705
- if (typeof document !== "undefined") {
706
- document.body.classList.remove("cursor-grab");
707
- }
708
- }
709
- }
710
- function handleWheel(event2) {
711
- if (event2.ctrlKey && !$4.get(trackpadDetected)) {
712
- $4.set(trackpadDetected, true);
713
- options.onTrackpadDetected?.();
714
- }
715
- }
716
- function attachListeners(target) {
717
- const el = target ?? options.targetElement ?? (typeof window !== "undefined" ? window : null);
718
- if (!el) return () => {
719
- };
720
- el.addEventListener("keydown", handleKeyDown);
721
- el.addEventListener("keyup", handleKeyUp);
722
- el.addEventListener("wheel", handleWheel, { passive: true });
723
- return () => {
724
- el.removeEventListener("keydown", handleKeyDown);
725
- el.removeEventListener("keyup", handleKeyUp);
726
- el.removeEventListener("wheel", handleWheel);
727
- if (typeof document !== "undefined") {
728
- document.body.classList.remove("cursor-grab");
729
- }
730
- };
731
- }
732
- return {
733
- get isSpacebarPanning() {
734
- return $4.get(isSpacebarPanning);
735
- },
736
- get trackpadDetected() {
737
- return $4.get(trackpadDetected);
738
- },
739
- attachListeners,
740
- destroy: attachListeners()
741
- };
742
- }
743
- var defaultSvelteFlowPreset = {
744
- snapGrid: [25, 25],
745
- panOnDrag: [0, 1, 2, 3, 4],
746
- panOnScroll: false,
747
- selectionOnDrag: false,
748
- colorMode: "system",
749
- multiSelectionKey: ["Shift", "Meta"]
750
- };
751
- var miroCompatiblePreset = {
752
- ...defaultSvelteFlowPreset,
753
- panOnDrag: [1, 2],
754
- selectionOnDrag: true
755
- };
756
- function restorePanelPointerEvents(panelSelector = ".svelte-flow__panel") {
757
- if (typeof document === "undefined") return;
758
- const panels = document.querySelectorAll(panelSelector);
759
- panels.forEach((panel) => {
760
- panel.style.pointerEvents = "auto";
761
- });
762
- }
763
-
764
- // src/canvas/createCanvasTrajectory.ts
765
- import { cubicOut as cubicOut2 } from "svelte/easing";
766
- var linearTrajectory = (origin, target, progress) => {
767
- return {
768
- position: {
769
- x: origin.x + (target.x - origin.x) * progress,
770
- y: origin.y + (target.y - origin.y) * progress
771
- },
772
- scale: progress,
773
- opacity: Math.min(1, progress * 1.5)
774
- };
775
- };
776
- var linearPositionTrajectory = (origin, target, progress) => {
777
- return {
778
- position: {
779
- x: origin.x + (target.x - origin.x) * progress,
780
- y: origin.y + (target.y - origin.y) * progress
781
- }
782
- };
783
- };
784
- function createFanOutTrajectory(options = {}) {
785
- const {
786
- curvature = 0.4,
787
- startScale = 0,
788
- endScale = 1,
789
- startOpacity = 0,
790
- endOpacity = 1
791
- } = options;
792
- return (origin, target, progress, index, total) => {
793
- const dx = target.x - origin.x;
794
- const dy = target.y - origin.y;
795
- const normIndex = total > 1 ? (index - (total - 1) / 2) / ((total - 1) / 2) : 0;
796
- const midX = origin.x + dx * 0.4;
797
- const midY = origin.y + dy * 0.1 - normIndex * Math.abs(dx) * 0.15 * curvature;
798
- const t = progress;
799
- const oneMinusT = 1 - t;
800
- const x = oneMinusT * oneMinusT * origin.x + 2 * oneMinusT * t * midX + t * t * target.x;
801
- const y = oneMinusT * oneMinusT * origin.y + 2 * oneMinusT * t * midY + t * t * target.y;
802
- const scale = startScale + (endScale - startScale) * progress;
803
- const opacity = startOpacity + (endOpacity - startOpacity) * progress;
804
- return {
805
- position: { x, y },
806
- scale,
807
- opacity
808
- };
809
- };
810
- }
811
- function createBezierTrajectory(getControlPoint) {
812
- return (origin, target, progress) => {
813
- const cp = getControlPoint(origin, target);
814
- const t = progress;
815
- const oneMinusT = 1 - t;
816
- const x = oneMinusT * oneMinusT * origin.x + 2 * oneMinusT * t * cp.x + t * t * target.x;
817
- const y = oneMinusT * oneMinusT * origin.y + 2 * oneMinusT * t * cp.y + t * t * target.y;
818
- return {
819
- position: { x, y },
820
- scale: progress,
821
- opacity: progress
822
- };
823
- };
824
- }
825
- function runMultiNodeTransition(transitions, options = {}) {
826
- if (transitions.length === 0) {
827
- options.onComplete?.();
828
- return () => {
829
- };
830
- }
831
- const { defaultDuration = 400, defaultEasing = cubicOut2, onUpdate, onComplete } = options;
832
- let isCancelled = false;
833
- const startTime = Date.now();
834
- const items = transitions.map((tr, i) => ({
835
- ...tr,
836
- index: tr.index ?? i,
837
- total: tr.total ?? transitions.length,
838
- duration: tr.duration ?? defaultDuration,
839
- easing: tr.easing ?? defaultEasing,
840
- delay: tr.delay ?? 0,
841
- trajectory: tr.trajectory ?? linearTrajectory
842
- }));
843
- function frame() {
844
- if (isCancelled) return;
845
- const now = Date.now();
846
- let allCompleted = true;
847
- for (let i = 0; i < items.length; i++) {
848
- const item = items[i];
849
- const elapsed = now - (startTime + item.delay);
850
- if (elapsed < 0) {
851
- allCompleted = false;
852
- continue;
853
- }
854
- const rawProgress = item.duration <= 0 ? 1 : Math.min(elapsed / item.duration, 1);
855
- const progress = item.duration <= 0 ? 1 : item.easing(rawProgress);
856
- const point = item.trajectory(item.from, item.to, progress, item.index, item.total);
857
- item.node.position = { ...point.position };
858
- if (point.scale !== void 0 || point.opacity !== void 0) {
859
- if (!item.node.data) {
860
- item.node.data = {};
861
- }
862
- if (point.scale !== void 0) {
863
- item.node.data.scale = point.scale;
864
- }
865
- if (point.opacity !== void 0) {
866
- item.node.data.opacity = point.opacity;
867
- const currentStyle = (item.node.style || "").replace(/opacity:\s*[^;]+;?/g, "").trim();
868
- item.node.style = `${currentStyle ? currentStyle + "; " : ""}opacity: ${point.opacity};`;
869
- }
870
- }
871
- if (rawProgress < 1) {
872
- allCompleted = false;
873
- }
874
- }
875
- onUpdate?.();
876
- if (!allCompleted) {
877
- if (typeof requestAnimationFrame !== "undefined") {
878
- requestAnimationFrame(frame);
879
- }
880
- } else {
881
- onComplete?.();
882
- }
883
- }
884
- frame();
885
- return () => {
886
- isCancelled = true;
887
- };
888
- }
889
-
890
- // src/canvas/createCanvasDisplacement.ts
891
- import dagre2 from "@dagrejs/dagre";
892
- function computeNodesBoundingBox(nodes, defaultWidth = 200, defaultHeight = 60) {
893
- if (nodes.length === 0) {
894
- return { x: 0, y: 0, width: 0, height: 0 };
895
- }
896
- let minX = Infinity;
897
- let minY = Infinity;
898
- let maxX = -Infinity;
899
- let maxY = -Infinity;
900
- for (const node of nodes) {
901
- const width = node.measured?.width ?? node.width ?? defaultWidth;
902
- const height = node.measured?.height ?? node.height ?? defaultHeight;
903
- minX = Math.min(minX, node.position.x);
904
- minY = Math.min(minY, node.position.y);
905
- maxX = Math.max(maxX, node.position.x + width);
906
- maxY = Math.max(maxY, node.position.y + height);
907
- }
908
- return {
909
- x: minX,
910
- y: minY,
911
- width: maxX - minX,
912
- height: maxY - minY
913
- };
914
- }
915
- function calculateDirectionalDisplacement(params) {
916
- const {
917
- existingNodes,
918
- originNode,
919
- childNodes,
920
- getNodesBounds,
921
- options = {}
922
- } = params;
923
- const {
924
- direction = "right",
925
- gap = 40,
926
- spreadSiblingLanes = false,
927
- siblingTolerance = 50,
928
- minY
929
- } = options;
930
- const displacedMap = /* @__PURE__ */ new Map();
931
- if (childNodes.length === 0 || existingNodes.length === 0) {
932
- return displacedMap;
933
- }
934
- const childBounds = getNodesBounds ? getNodesBounds(childNodes) : computeNodesBoundingBox(childNodes);
935
- const originWidth = originNode.measured?.width ?? originNode.width ?? 200;
936
- const originHeight = originNode.measured?.height ?? originNode.height ?? 60;
937
- const deltaPrimary = direction === "right" || direction === "left" ? childBounds.width + gap : childBounds.height + gap;
938
- const deltaUp = Math.max(0, originNode.position.y - childBounds.y + gap);
939
- const deltaDown = Math.max(
940
- 0,
941
- childBounds.y + childBounds.height - (originNode.position.y + originHeight) + gap
942
- );
943
- const equalDelta = Math.max(deltaUp, deltaDown);
944
- for (const node of existingNodes) {
945
- if (node.id === originNode.id) continue;
946
- let newX = node.position.x;
947
- let newY = node.position.y;
948
- let moved = false;
949
- if (direction === "right") {
950
- if (node.position.x >= originNode.position.x + originWidth * 0.5) {
951
- newX += deltaPrimary;
952
- moved = true;
953
- } else if (spreadSiblingLanes) {
954
- const isVerticallyOverlapping = node.position.y + (node.height ?? 60) >= childBounds.y - gap && node.position.y <= childBounds.y + childBounds.height + gap;
955
- if (isVerticallyOverlapping && Math.abs(node.position.x - originNode.position.x) <= siblingTolerance) {
956
- const pushDirection = node.position.y >= originNode.position.y ? 1 : -1;
957
- newY += pushDirection * (childBounds.height * 0.5 + gap);
958
- moved = true;
959
- }
960
- }
961
- } else if (direction === "left") {
962
- if (node.position.x <= originNode.position.x) {
963
- newX -= deltaPrimary;
964
- moved = true;
965
- }
966
- } else if (direction === "down") {
967
- if (node.position.y >= originNode.position.y + originHeight * 0.5) {
968
- newY += deltaPrimary;
969
- moved = true;
970
- }
971
- } else if (direction === "up") {
972
- if (node.position.y <= originNode.position.y) {
973
- newY -= deltaPrimary;
974
- moved = true;
975
- }
976
- } else if (direction === "vertical") {
977
- if (node.position.y < originNode.position.y) {
978
- if (equalDelta > 0) {
979
- newY -= equalDelta;
980
- moved = true;
981
- }
982
- } else if (node.position.y >= originNode.position.y + originHeight * 0.5) {
983
- if (equalDelta > 0) {
984
- newY += equalDelta;
985
- moved = true;
986
- }
987
- }
988
- }
989
- if (moved) {
990
- displacedMap.set(node.id, { x: newX, y: newY });
991
- }
992
- }
993
- return displacedMap;
994
- }
995
- function calculateReflowDisplacement(params) {
996
- const {
997
- existingNodes,
998
- existingEdges,
999
- originNode,
1000
- childNodes,
1001
- childEdges = [],
1002
- options = {}
1003
- } = params;
1004
- const {
1005
- direction = "LR",
1006
- ranksep = 80,
1007
- nodesep = 30,
1008
- defaultNodeWidth = 200,
1009
- defaultNodeHeight = 60
1010
- } = options;
1011
- const displacedMap = /* @__PURE__ */ new Map();
1012
- if (existingNodes.length === 0) return displacedMap;
1013
- const allNodes = [...existingNodes, ...childNodes];
1014
- const allEdges = [...existingEdges, ...childEdges];
1015
- const dagreGraph = new dagre2.graphlib.Graph();
1016
- dagreGraph.setDefaultEdgeLabel(() => ({}));
1017
- dagreGraph.setGraph({ rankdir: direction, ranksep, nodesep });
1018
- const allNodeIds = new Set(allNodes.map((n) => n.id));
1019
- allNodes.forEach((node) => {
1020
- const nodeWidth = node.measured?.width ?? node.width ?? defaultNodeWidth;
1021
- const nodeHeight = node.measured?.height ?? node.height ?? defaultNodeHeight;
1022
- dagreGraph.setNode(node.id, { width: nodeWidth, height: nodeHeight });
1023
- });
1024
- allEdges.forEach((edge) => {
1025
- if (allNodeIds.has(edge.source) && allNodeIds.has(edge.target)) {
1026
- dagreGraph.setEdge(edge.source, edge.target);
1027
- }
1028
- });
1029
- dagre2.layout(dagreGraph);
1030
- const dagreOrigin = dagreGraph.node(originNode.id);
1031
- if (!dagreOrigin) return displacedMap;
1032
- const originWidth = originNode.measured?.width ?? originNode.width ?? defaultNodeWidth;
1033
- const originHeight = originNode.measured?.height ?? originNode.height ?? defaultNodeHeight;
1034
- const anchorOffsetX = originNode.position.x - (dagreOrigin.x - originWidth / 2);
1035
- const anchorOffsetY = originNode.position.y - (dagreOrigin.y - originHeight / 2);
1036
- existingNodes.forEach((node) => {
1037
- if (node.id === originNode.id) return;
1038
- const dagreNode = dagreGraph.node(node.id);
1039
- if (!dagreNode) return;
1040
- const nodeWidth = node.measured?.width ?? node.width ?? defaultNodeWidth;
1041
- const nodeHeight = node.measured?.height ?? node.height ?? defaultNodeHeight;
1042
- const targetX = dagreNode.x - nodeWidth / 2 + anchorOffsetX;
1043
- const targetY = dagreNode.y - nodeHeight / 2 + anchorOffsetY;
1044
- if (Math.abs(targetX - node.position.x) > 0.5 || Math.abs(targetY - node.position.y) > 0.5) {
1045
- displacedMap.set(node.id, { x: targetX, y: targetY });
1046
- }
1047
- });
1048
- return displacedMap;
1049
- }
1050
-
1051
- // src/canvas/createCanvasExplosion.svelte.ts
1052
- import * as $5 from "svelte/internal/client";
1053
- import { cubicOut as cubicOut3 } from "svelte/easing";
1054
- function createCanvasExplosion(graph, options = {}) {
1055
- let explodedNodeIds = $5.state($5.proxy([]));
1056
- const snapshots = /* @__PURE__ */ new Map();
1057
- let activeAnimationCancel = null;
1058
- function isExploded(nodeId) {
1059
- return $5.get(explodedNodeIds).includes(nodeId);
1060
- }
1061
- function explodeNode(parentId, explodeOptions) {
1062
- if (isExploded(parentId)) {
1063
- return false;
1064
- }
1065
- const parentNode = graph.nodes.find((n) => n.id === parentId);
1066
- if (!parentNode) {
1067
- return false;
1068
- }
1069
- const {
1070
- childNodes,
1071
- childEdges = [],
1072
- connectParentToChildren = "all",
1073
- displacementStrategy = "directional",
1074
- directionalOptions = {},
1075
- reflowOptions = {},
1076
- trajectory,
1077
- duration = 500,
1078
- staggerDelay = 20,
1079
- easing = cubicOut3,
1080
- onComplete
1081
- } = explodeOptions;
1082
- if (childNodes.length === 0) {
1083
- return false;
1084
- }
1085
- let displacementMap;
1086
- if (displacementStrategy === "dagre") {
1087
- displacementMap = calculateReflowDisplacement({
1088
- existingNodes: graph.nodes,
1089
- existingEdges: graph.edges,
1090
- originNode: parentNode,
1091
- childNodes,
1092
- childEdges,
1093
- getNodesBounds: options.getNodesBounds,
1094
- options: { ...reflowOptions, direction: reflowOptions.direction ?? "LR" }
1095
- });
1096
- } else if (displacementStrategy === "none") {
1097
- displacementMap = /* @__PURE__ */ new Map();
1098
- } else {
1099
- displacementMap = calculateDirectionalDisplacement({
1100
- existingNodes: graph.nodes,
1101
- originNode: parentNode,
1102
- childNodes,
1103
- getNodesBounds: options.getNodesBounds,
1104
- options: directionalOptions
1105
- });
1106
- }
1107
- const displacedNodesSnapshot = Array.from(displacementMap.entries()).map(([id]) => {
1108
- const node = graph.nodes.find((n) => n.id === id);
1109
- return {
1110
- id,
1111
- originalPosition: { ...node?.position ?? { x: 0, y: 0 } }
1112
- };
1113
- });
1114
- const edgesToAdd = [...childEdges];
1115
- const defaultCreateEdge = (sourceId, targetId) => {
1116
- if (graph.createEdge) {
1117
- return graph.createEdge(sourceId, targetId);
1118
- }
1119
- return {
1120
- id: crypto.randomUUID(),
1121
- type: "default",
1122
- source: sourceId,
1123
- target: targetId
1124
- };
1125
- };
1126
- if (connectParentToChildren === "all" || connectParentToChildren === true) {
1127
- childNodes.forEach((child2) => {
1128
- const exists = edgesToAdd.some((e) => e.source === parentId && e.target === child2.id);
1129
- if (!exists) {
1130
- edgesToAdd.push(defaultCreateEdge(parentId, child2.id));
1131
- }
1132
- });
1133
- } else if (connectParentToChildren === "first" && childNodes.length > 0) {
1134
- const firstChild = childNodes[0];
1135
- const exists = edgesToAdd.some((e) => e.source === parentId && e.target === firstChild.id);
1136
- if (!exists) {
1137
- edgesToAdd.push(defaultCreateEdge(parentId, firstChild.id));
1138
- }
1139
- }
1140
- const snapshot = {
1141
- parentId,
1142
- childNodeIds: childNodes.map((n) => n.id),
1143
- childEdgeIds: edgesToAdd.map((e) => e.id),
1144
- displacedNodes: displacedNodesSnapshot,
1145
- timestamp: Date.now()
1146
- };
1147
- snapshots.set(parentId, snapshot);
1148
- const originPos = { ...parentNode.position };
1149
- const targetPositions = childNodes.map((child2) => ({ ...child2.position }));
1150
- childNodes.forEach((child2) => {
1151
- child2.position = { ...originPos };
1152
- if (!child2.data) child2.data = {};
1153
- child2.data.scale = 0;
1154
- child2.data.opacity = 0;
1155
- const currentStyle = (child2.style || "").replace(/opacity:\s*[^;]+;?/g, "").trim();
1156
- child2.style = `${currentStyle ? currentStyle + "; " : ""}opacity: 0;`;
1157
- });
1158
- edgesToAdd.forEach((edge) => {
1159
- const currentStyle = (edge.style || "").replace(/opacity:\s*[^;]+;?/g, "").trim();
1160
- edge.style = `${currentStyle ? currentStyle + "; " : ""}opacity: 0;`;
1161
- });
1162
- graph.addNodeOrNodes(childNodes, void 0, false);
1163
- if (edgesToAdd.length > 0) {
1164
- graph.addEdges(edgesToAdd, false);
1165
- }
1166
- const chosenTrajectory = trajectory ?? createFanOutTrajectory({ curvature: 0.35 });
1167
- const transitions = [];
1168
- const effectiveStagger = duration === 0 ? 0 : staggerDelay;
1169
- childNodes.forEach((child2, i) => {
1170
- transitions.push({
1171
- node: child2,
1172
- from: originPos,
1173
- to: targetPositions[i],
1174
- trajectory: chosenTrajectory,
1175
- delay: i * effectiveStagger,
1176
- duration,
1177
- easing,
1178
- index: i,
1179
- total: childNodes.length
1180
- });
1181
- });
1182
- displacementMap.forEach((targetPos, nodeId) => {
1183
- const node = graph.nodes.find((n) => n.id === nodeId);
1184
- if (node) {
1185
- transitions.push({
1186
- node,
1187
- from: { ...node.position },
1188
- to: targetPos,
1189
- trajectory: linearPositionTrajectory,
1190
- duration,
1191
- easing
1192
- });
1193
- }
1194
- });
1195
- if (activeAnimationCancel) {
1196
- activeAnimationCancel();
1197
- }
1198
- activeAnimationCancel = runMultiNodeTransition(transitions, {
1199
- defaultDuration: duration,
1200
- defaultEasing: easing,
1201
- onUpdate: () => {
1202
- if (edgesToAdd.length > 0) {
1203
- const childIdSet = new Set(childNodes.map((c) => c.id));
1204
- const childEdgesInGraph = graph.edges.filter((e) => childIdSet.has(e.target));
1205
- if (childEdgesInGraph.length > 0) {
1206
- childEdgesInGraph.forEach((edge) => {
1207
- const child2 = childNodes.find((c) => c.id === edge.target);
1208
- const childOpacity = child2?.data?.opacity ?? 1;
1209
- const currentStyle = (edge.style || "").replace(/opacity:\s*[^;]+;?/g, "").trim();
1210
- edge.style = `${currentStyle ? currentStyle + "; " : ""}opacity: ${childOpacity};`;
1211
- });
1212
- graph.setEdges([...graph.edges]);
1213
- }
1214
- }
1215
- transitions.forEach((t) => {
1216
- const graphNode = graph.nodes.find((n) => n.id === t.node.id);
1217
- if (graphNode && graphNode !== t.node) {
1218
- graphNode.position = { ...t.node.position };
1219
- graphNode.style = t.node.style;
1220
- if (t.node.data) {
1221
- graphNode.data = { ...graphNode.data, ...t.node.data };
1222
- }
1223
- }
1224
- });
1225
- graph.setNodes([...graph.nodes]);
1226
- },
1227
- onComplete: () => {
1228
- childNodes.forEach((child2, i) => {
1229
- const node = graph.nodes.find((n) => n.id === child2.id);
1230
- if (node) {
1231
- node.position = { ...targetPositions[i] };
1232
- node.style = (node.style || "").replace(/opacity:\s*[^;]+;?/g, "").trim() || void 0;
1233
- if (node.data) {
1234
- node.data.opacity = 1;
1235
- }
1236
- }
1237
- });
1238
- displacementMap.forEach((targetPos, nodeId) => {
1239
- const graphNode = graph.nodes.find((n) => n.id === nodeId);
1240
- if (graphNode) {
1241
- graphNode.position = { ...targetPos };
1242
- }
1243
- });
1244
- edgesToAdd.forEach((edge) => {
1245
- const graphEdge = graph.edges.find((e) => e.id === edge.id);
1246
- if (graphEdge) {
1247
- graphEdge.style = (graphEdge.style || "").replace(/opacity:\s*[^;]+;?/g, "").trim() || void 0;
1248
- }
1249
- });
1250
- graph.setNodes([...graph.nodes]);
1251
- graph.setEdges([...graph.edges]);
1252
- $5.set(explodedNodeIds, [...$5.get(explodedNodeIds), parentId], true);
1253
- activeAnimationCancel = null;
1254
- options.onSave?.();
1255
- graph.onSave?.();
1256
- onComplete?.();
1257
- }
1258
- });
1259
- return true;
1260
- }
1261
- function collapseNode(parentId, collapseOptions = {}) {
1262
- const snapshot = snapshots.get(parentId);
1263
- if (!snapshot) {
1264
- return false;
1265
- }
1266
- const parentNode = graph.nodes.find((n) => n.id === parentId);
1267
- if (!parentNode) {
1268
- return false;
1269
- }
1270
- const {
1271
- duration = 400,
1272
- staggerDelay = 15,
1273
- easing = cubicOut3,
1274
- trajectory,
1275
- onComplete
1276
- } = collapseOptions;
1277
- const childIdSet = new Set(snapshot.childNodeIds);
1278
- const activeChildNodes = graph.nodes.filter((n) => childIdSet.has(n.id));
1279
- const originPos = { ...parentNode.position };
1280
- const reverseTrajectory = trajectory ?? createFanOutTrajectory({
1281
- curvature: 0.2,
1282
- startScale: 1,
1283
- endScale: 0,
1284
- startOpacity: 1,
1285
- endOpacity: 0
1286
- });
1287
- const transitions = [];
1288
- const effectiveStagger = duration === 0 ? 0 : staggerDelay;
1289
- activeChildNodes.forEach((child2, i) => {
1290
- transitions.push({
1291
- node: child2,
1292
- from: { ...child2.position },
1293
- to: originPos,
1294
- trajectory: reverseTrajectory,
1295
- delay: (activeChildNodes.length - 1 - i) * effectiveStagger,
1296
- duration,
1297
- easing,
1298
- index: i,
1299
- total: activeChildNodes.length
1300
- });
1301
- });
1302
- snapshot.displacedNodes.forEach(({ id, originalPosition }) => {
1303
- const node = graph.nodes.find((n) => n.id === id);
1304
- if (node) {
1305
- transitions.push({
1306
- node,
1307
- from: { ...node.position },
1308
- to: originalPosition,
1309
- trajectory: linearPositionTrajectory,
1310
- duration,
1311
- easing
1312
- });
1313
- }
1314
- });
1315
- if (activeAnimationCancel) {
1316
- activeAnimationCancel();
1317
- }
1318
- activeAnimationCancel = runMultiNodeTransition(transitions, {
1319
- defaultDuration: duration,
1320
- defaultEasing: easing,
1321
- onUpdate: () => {
1322
- const edgeIdSet = new Set(snapshot.childEdgeIds);
1323
- const childEdgesInGraph = graph.edges.filter((e) => edgeIdSet.has(e.id));
1324
- if (childEdgesInGraph.length > 0) {
1325
- childEdgesInGraph.forEach((edge) => {
1326
- const child2 = activeChildNodes.find((c) => c.id === edge.target);
1327
- const childOpacity = child2?.data?.opacity ?? 0;
1328
- const currentStyle = (edge.style || "").replace(/opacity:\s*[^;]+;?/g, "").trim();
1329
- edge.style = `${currentStyle ? currentStyle + "; " : ""}opacity: ${childOpacity};`;
1330
- });
1331
- graph.setEdges([...graph.edges]);
1332
- }
1333
- transitions.forEach((t) => {
1334
- const graphNode = graph.nodes.find((n) => n.id === t.node.id);
1335
- if (graphNode && graphNode !== t.node) {
1336
- graphNode.position = { ...t.node.position };
1337
- graphNode.style = t.node.style;
1338
- if (t.node.data) {
1339
- graphNode.data = { ...graphNode.data, ...t.node.data };
1340
- }
1341
- }
1342
- });
1343
- graph.setNodes([...graph.nodes]);
1344
- },
1345
- onComplete: () => {
1346
- graph.removeNodes(activeChildNodes, false);
1347
- const edgeIdSet = new Set(snapshot.childEdgeIds);
1348
- const edgesToRemove = graph.edges.filter((e) => edgeIdSet.has(e.id));
1349
- if (edgesToRemove.length > 0) {
1350
- graph.removeEdges(edgesToRemove, false);
1351
- }
1352
- snapshot.displacedNodes.forEach(({ id, originalPosition }) => {
1353
- const graphNode = graph.nodes.find((n) => n.id === id);
1354
- if (graphNode) {
1355
- graphNode.position = { ...originalPosition };
1356
- }
1357
- });
1358
- graph.setNodes([...graph.nodes]);
1359
- snapshots.delete(parentId);
1360
- $5.set(explodedNodeIds, $5.get(explodedNodeIds).filter((id) => id !== parentId), true);
1361
- activeAnimationCancel = null;
1362
- options.onSave?.();
1363
- graph.onSave?.();
1364
- onComplete?.();
1365
- }
1366
- });
1367
- return true;
1368
- }
1369
- function toggleExplode(parentId, explodeOptions, collapseOptions) {
1370
- if (isExploded(parentId)) {
1371
- return collapseNode(parentId, collapseOptions);
1372
- }
1373
- return explodeNode(parentId, explodeOptions);
1374
- }
1375
- function getSnapshot(parentId) {
1376
- return snapshots.get(parentId);
1377
- }
1378
- return {
1379
- get explodedNodeIds() {
1380
- return $5.get(explodedNodeIds);
1381
- },
1382
- isExploded,
1383
- explodeNode,
1384
- collapseNode,
1385
- toggleExplode,
1386
- getSnapshot
1387
- };
1388
- }
1389
-
1390
- // src/canvas/createCanvasNodeSync.svelte.ts
1391
- import * as $6 from "svelte/internal/client";
1392
- import { untrack } from "svelte";
1393
- function preserveNodeMeasurements(newNodes, existingNodes) {
1394
- const map = existingNodes instanceof Map ? existingNodes : new Map(existingNodes.map((n) => [n.id, n]));
1395
- for (const node of newNodes) {
1396
- const prev = map.get(node.id);
1397
- if (prev && prev.measured) {
1398
- node.measured = { ...prev.measured };
1399
- }
1400
- }
1401
- return newNodes;
1402
- }
1403
- function normalizeNodeHandles(node, handles = []) {
1404
- node.handles = handles;
1405
- return node;
1406
- }
1407
- function createCanvasNodeSync(options) {
1408
- let nodes = $6.state($6.proxy([]));
1409
- let edges = $6.state($6.proxy([]));
1410
- $6.user_pre_effect(() => {
1411
- const rawItems = options.items();
1412
- const existingNodesMap = untrack(() => new Map($6.get(nodes).map((n) => [n.id, n])));
1413
- const newNodes = rawItems.map((item, index) => {
1414
- const existing = existingNodesMap.get(item?.id);
1415
- const node = options.toNode(item, index, { existingNode: existing, prevNodesMap: existingNodesMap });
1416
- if (existing && existing.measured && !node.measured) {
1417
- node.measured = { ...existing.measured };
1418
- }
1419
- if (options.defaultHandles && !node.handles) {
1420
- const handles = options.defaultHandles(node);
1421
- if (handles) {
1422
- node.handles = handles;
1423
- }
1424
- }
1425
- return node;
1426
- });
1427
- const newEdges = options.toEdges ? options.toEdges(rawItems, newNodes) : [];
1428
- $6.set(nodes, newNodes, true);
1429
- $6.set(edges, newEdges, true);
1430
- });
1431
- return {
1432
- get nodes() {
1433
- return $6.get(nodes);
1434
- },
1435
- set nodes(value) {
1436
- $6.set(nodes, value, true);
1437
- },
1438
- get edges() {
1439
- return $6.get(edges);
1440
- },
1441
- set edges(value) {
1442
- $6.set(edges, value, true);
1443
- },
1444
- updateNodeMeasurements(id, width, height) {
1445
- const node = $6.get(nodes).find((n) => n.id === id);
1446
- if (node) {
1447
- node.measured = { width, height };
1448
- }
1449
- }
1450
- };
1451
- }
1452
-
1453
- // src/canvas/createCanvasMultiDrag.svelte.ts
1454
- import * as $7 from "svelte/internal/client";
1455
- function createCanvasMultiDrag(options = {}) {
1456
- const stepX = options.stackOffsetStepX ?? 4;
1457
- const stepY = options.stackOffsetStepY ?? 4;
1458
- const angles = options.rotationAngles ?? [-2, 2.5, -3, 3];
1459
- const baseZIndex = options.baseZIndex ?? 50;
1460
- let dragState = $7.state(null);
1461
- function startMultiDrag(leadNodeId, selectedNodeIds, nodes) {
1462
- const selectedSet = selectedNodeIds instanceof Set ? selectedNodeIds : new Set(selectedNodeIds);
1463
- if (selectedSet.size <= 1 || !selectedSet.has(leadNodeId)) {
1464
- $7.set(dragState, null);
1465
- return null;
1466
- }
1467
- const nodeMap = nodes instanceof Map ? nodes : new Map(nodes.map((n) => [n.id, n]));
1468
- const leadNode = nodeMap.get(leadNodeId);
1469
- if (!leadNode) {
1470
- $7.set(dragState, null);
1471
- return null;
1472
- }
1473
- const leadPos = leadNode.position ?? { x: 0, y: 0 };
1474
- const offsets = {};
1475
- let followerIndex = 0;
1476
- for (const id of selectedSet) {
1477
- if (id === leadNodeId) continue;
1478
- const follower = nodeMap.get(id);
1479
- const fPos = follower?.position ?? { x: 0, y: 0 };
1480
- const angle = angles[followerIndex % angles.length];
1481
- offsets[id] = {
1482
- deltaX: fPos.x - leadPos.x,
1483
- deltaY: fPos.y - leadPos.y,
1484
- originalPosition: { ...fPos },
1485
- stackOffsetX: (followerIndex + 1) * stepX,
1486
- stackOffsetY: (followerIndex + 1) * stepY,
1487
- rotationDeg: angle
1488
- };
1489
- followerIndex++;
1490
- }
1491
- const state9 = { leadId: leadNodeId, offsets, count: selectedSet.size };
1492
- $7.set(dragState, state9, true);
1493
- return state9;
1494
- }
1495
- function getFollowerTransform(nodeId) {
1496
- if (!$7.get(dragState) || !(nodeId in $7.get(dragState).offsets)) {
1497
- return {
1498
- isFollower: false,
1499
- stackOffsetX: 0,
1500
- stackOffsetY: 0,
1501
- rotationDeg: 0,
1502
- zIndex: 0
1503
- };
1504
- }
1505
- const offset = $7.get(dragState).offsets[nodeId];
1506
- const followerKeys = Object.keys($7.get(dragState).offsets);
1507
- const index = followerKeys.indexOf(nodeId);
1508
- return {
1509
- isFollower: true,
1510
- stackOffsetX: offset.stackOffsetX,
1511
- stackOffsetY: offset.stackOffsetY,
1512
- rotationDeg: offset.rotationDeg,
1513
- zIndex: baseZIndex - (index + 1)
1514
- };
1515
- }
1516
- function cancelMultiDrag(applyRestore) {
1517
- if (!$7.get(dragState)) return [];
1518
- const restores = Object.entries($7.get(dragState).offsets).map(([id, offset]) => ({ id, originalPosition: { ...offset.originalPosition } }));
1519
- if (applyRestore) {
1520
- applyRestore(restores);
1521
- }
1522
- $7.set(dragState, null);
1523
- return restores;
1524
- }
1525
- function commitMultiDrag() {
1526
- $7.set(dragState, null);
1527
- }
1528
- return {
1529
- get dragState() {
1530
- return $7.get(dragState);
1531
- },
1532
- get isMultiDrag() {
1533
- return Boolean($7.get(dragState) && $7.get(dragState).count > 1);
1534
- },
1535
- get count() {
1536
- return $7.get(dragState) ? $7.get(dragState).count : 0;
1537
- },
1538
- get leadId() {
1539
- return $7.get(dragState)?.leadId ?? null;
1540
- },
1541
- startMultiDrag,
1542
- getFollowerTransform,
1543
- cancelMultiDrag,
1544
- commitMultiDrag
1545
- };
1546
- }
1547
-
1548
- // src/canvas/createCanvasSelection.svelte.ts
1549
- import * as $8 from "svelte/internal/client";
1550
- function getMarqueeSelectionPreset(options = {}) {
1551
- const isSpacebarPanning = options.isSpacebarPanning ?? false;
1552
- return {
1553
- snapGrid: [25, 25],
1554
- panOnDrag: isSpacebarPanning ? [0, 1, 2] : [1, 2],
1555
- panOnScroll: false,
1556
- selectionOnDrag: !isSpacebarPanning,
1557
- colorMode: "system",
1558
- multiSelectionKey: options.multiSelectionKey ?? ["Shift", "Meta"],
1559
- selectionMode: options.selectionMode ?? "partial"
1560
- };
1561
- }
1562
- function handleDeselectOnEscape(event2, onDeselect) {
1563
- if (event2.key === "Escape" || event2.code === "Escape") {
1564
- onDeselect();
1565
- return true;
1566
- }
1567
- return false;
1568
- }
1569
-
1570
- // src/canvas/FloatingHorizontalScrollbar.svelte
1571
- import "svelte/internal/disclose-version";
1572
- import * as $9 from "svelte/internal/client";
1573
- import { onMount } from "svelte";
1574
- var root = $9.from_html(`<div class="fixed bottom-0 z-50 overflow-x-auto overflow-y-hidden border-t border-border/40 bg-background/80 shadow-md backdrop-blur-sm transition-opacity duration-150" role="scrollbar" aria-orientation="horizontal"><div></div></div>`);
1575
- function FloatingHorizontalScrollbar($$anchor, $$props) {
1576
- $9.push($$props, true);
1577
- let targetElement = $9.prop($$props, "targetElement", 7, null), totalWidth = $9.prop($$props, "totalWidth", 3, 1e3), minHeightAboveFold = $9.prop($$props, "minHeightAboveFold", 3, 80);
1578
- let scrollbarRef = $9.state(null);
1579
- let isVisible = $9.state(false);
1580
- let barLeft = $9.state(0);
1581
- let barWidth = $9.state(0);
1582
- let isSyncing = false;
1583
- function updateMetrics() {
1584
- if (!targetElement()) {
1585
- $9.set(isVisible, false);
1586
- return;
1587
- }
1588
- const rect = targetElement().getBoundingClientRect();
1589
- const hasHorizontalOverflow = targetElement().scrollWidth > targetElement().clientWidth;
1590
- const isTopInView = rect.top < window.innerHeight;
1591
- const isBottomBelowViewport = rect.bottom > window.innerHeight;
1592
- const isBottomAboveTop = rect.bottom > minHeightAboveFold();
1593
- const shouldShow = hasHorizontalOverflow && isTopInView && isBottomBelowViewport && isBottomAboveTop;
1594
- $9.set(isVisible, shouldShow, true);
1595
- if (shouldShow) {
1596
- const left = Math.max(0, rect.left);
1597
- const right = Math.min(window.innerWidth, rect.right);
1598
- $9.set(barLeft, left, true);
1599
- $9.set(barWidth, Math.max(0, right - left), true);
1600
- if ($9.get(scrollbarRef) && Math.abs($9.get(scrollbarRef).scrollLeft - targetElement().scrollLeft) > 1) {
1601
- isSyncing = true;
1602
- $9.get(scrollbarRef).scrollLeft = targetElement().scrollLeft;
1603
- requestAnimationFrame(() => {
1604
- isSyncing = false;
1605
- });
1606
- }
1607
- }
1608
- }
1609
- function handleFloatingScroll() {
1610
- if (!$9.get(scrollbarRef) || !targetElement() || isSyncing) return;
1611
- isSyncing = true;
1612
- targetElement().scrollLeft = $9.get(scrollbarRef).scrollLeft;
1613
- requestAnimationFrame(() => {
1614
- isSyncing = false;
1615
- });
1616
- }
1617
- onMount(() => {
1618
- updateMetrics();
1619
- const onScrollOrResize = () => {
1620
- updateMetrics();
1621
- };
1622
- window.addEventListener("scroll", onScrollOrResize, { passive: true });
1623
- window.addEventListener("resize", onScrollOrResize, { passive: true });
1624
- const target = targetElement();
1625
- if (target) {
1626
- target.addEventListener("scroll", onScrollOrResize, { passive: true });
1627
- }
1628
- return () => {
1629
- window.removeEventListener("scroll", onScrollOrResize);
1630
- window.removeEventListener("resize", onScrollOrResize);
1631
- if (target) {
1632
- target.removeEventListener("scroll", onScrollOrResize);
1633
- }
1634
- };
1635
- });
1636
- $9.user_effect(() => {
1637
- if (targetElement()) {
1638
- updateMetrics();
1639
- }
1640
- });
1641
- var fragment = $9.comment();
1642
- var node = $9.first_child(fragment);
1643
- {
1644
- var consequent = ($$anchor2) => {
1645
- var div = root();
1646
- $9.set_attribute(div, "aria-valuemin", 0);
1647
- var div_1 = $9.only_child(div);
1648
- $9.bind_this(div, ($$value) => $9.set(scrollbarRef, $$value), () => $9.get(scrollbarRef));
1649
- $9.template_effect(
1650
- ($0) => {
1651
- $9.set_style(div, `left: ${$9.get(barLeft) ?? ""}px; width: ${$9.get(barWidth) ?? ""}px; height: 14px;`);
1652
- $9.set_attribute(div, "aria-controls", targetElement()?.id);
1653
- $9.set_attribute(div, "aria-valuenow", targetElement()?.scrollLeft ?? 0);
1654
- $9.set_attribute(div, "aria-valuemax", (targetElement()?.scrollWidth ?? totalWidth()) - (targetElement()?.clientWidth ?? 0));
1655
- $9.set_style(div_1, `width: ${$0 ?? ""}px; height: 1px;`);
1656
- },
1657
- [
1658
- () => Math.max(totalWidth(), targetElement()?.scrollWidth ?? 0)
1659
- ]
1660
- );
1661
- $9.event("scroll", div, handleFloatingScroll);
1662
- $9.append($$anchor2, div);
1663
- };
1664
- $9.if(node, ($$render) => {
1665
- if ($9.get(isVisible)) $$render(consequent);
1666
- });
1667
- }
1668
- $9.append($$anchor, fragment);
1669
- $9.pop();
1670
- }
1671
-
1672
- // src/canvas/AgentPresenceLayer.svelte
1673
- import "svelte/internal/disclose-version";
1674
- import * as $10 from "svelte/internal/client";
1675
- var root2 = $10.from_html(`<span class="opacity-80 text-[10px]"> </span>`);
1676
- var root_1 = $10.from_html(`<div class="mt-1 max-w-xs rounded-lg bg-white/95 backdrop-blur-sm border border-slate-200 px-2.5 py-1.5 text-xs text-slate-800 shadow-lg dark:bg-slate-900/95 dark:border-slate-700 dark:text-slate-100"> </div>`);
1677
- var root_2 = $10.from_html(`<div class="absolute transition-transform duration-75 ease-out"><svg class="h-5 w-5 drop-shadow-md" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M5.65376 12.3673H5.46026L5.31717 12.4976L0.500002 16.8829L0.500002 1.19841L11.7841 12.3673H5.65376Z" stroke="white" stroke-width="1"></path></svg> <div class="mt-1 flex items-center gap-1 rounded-full px-2 py-0.5 text-xs font-medium text-white shadow-md whitespace-nowrap"><span> </span> <!></div> <!></div>`);
1678
- var root_3 = $10.from_html(`<div aria-hidden="true"></div>`);
1679
- function AgentPresenceLayer($$anchor, $$props) {
1680
- $10.push($$props, true);
1681
- let presences = $10.prop($$props, "presences", 19, () => []), className = $10.prop($$props, "class", 3, "");
1682
- var fragment = $10.comment();
1683
- var node = $10.first_child(fragment);
1684
- {
1685
- var consequent_3 = ($$anchor2) => {
1686
- var div = root_3();
1687
- $10.each(div, 21, presences, (agent) => agent.agentId, ($$anchor3, agent) => {
1688
- var fragment_1 = $10.comment();
1689
- var node_1 = $10.first_child(fragment_1);
1690
- {
1691
- var consequent_2 = ($$anchor4) => {
1692
- var div_1 = root_2();
1693
- var svg = $10.child(div_1);
1694
- var path = $10.only_child(svg);
1695
- var div_2 = $10.sibling(svg, 2);
1696
- var span = $10.child(div_2);
1697
- var text = $10.only_child(span, true);
1698
- var node_2 = $10.sibling(span, 2);
1699
- {
1700
- var consequent = ($$anchor5) => {
1701
- var span_1 = root2();
1702
- var text_1 = $10.only_child(span_1);
1703
- $10.template_effect(() => $10.set_text(text_1, `(${$10.get(agent).statusMessage ?? ""})`));
1704
- $10.append($$anchor5, span_1);
1705
- };
1706
- $10.if(node_2, ($$render) => {
1707
- if ($10.get(agent).statusMessage) $$render(consequent);
1708
- });
1709
- }
1710
- $10.reset(div_2);
1711
- var node_3 = $10.sibling(div_2, 2);
1712
- {
1713
- var consequent_1 = ($$anchor5) => {
1714
- var div_3 = root_1();
1715
- var text_2 = $10.only_child(div_3, true);
1716
- $10.template_effect(() => $10.set_text(text_2, $10.get(agent).note));
1717
- $10.append($$anchor5, div_3);
1718
- };
1719
- $10.if(node_3, ($$render) => {
1720
- if ($10.get(agent).note) $$render(consequent_1);
1721
- });
1722
- }
1723
- $10.reset(div_1);
1724
- $10.template_effect(() => {
1725
- $10.set_style(div_1, `transform: translate3d(${$10.get(agent).cursorPosition.x ?? ""}px, ${$10.get(agent).cursorPosition.y ?? ""}px, 0);`);
1726
- $10.set_attribute(path, "fill", $10.get(agent).color || "#3b82f6");
1727
- $10.set_style(div_2, `background-color: ${($10.get(agent).color || "#3b82f6") ?? ""};`);
1728
- $10.set_text(text, $10.get(agent).name);
1729
- });
1730
- $10.append($$anchor4, div_1);
1731
- };
1732
- $10.if(node_1, ($$render) => {
1733
- if ($10.get(agent).cursorPosition) $$render(consequent_2);
1734
- });
1735
- }
1736
- $10.append($$anchor3, fragment_1);
1737
- });
1738
- $10.reset(div);
1739
- $10.template_effect(() => $10.set_class(div, 1, `pixerate-presence agent-presence pixerate-agent-presence-layer pointer-events-none absolute inset-0 z-50 overflow-hidden ${className() ?? ""}`));
1740
- $10.append($$anchor2, div);
1741
- };
1742
- $10.if(node, ($$render) => {
1743
- if (presences().length > 0) $$render(consequent_3);
1744
- });
1745
- }
1746
- $10.append($$anchor, fragment);
1747
- $10.pop();
1748
- }
1749
-
1750
- // src/canvas/createStreamingCanvas.svelte.ts
1751
- import * as $11 from "svelte/internal/client";
1752
- import { StreamingLayoutManager } from "@pixerate/editor/canvas";
1753
- function createStreamingCanvas(options = {}) {
1754
- let positions = $11.state($11.proxy(/* @__PURE__ */ new Map()));
1755
- const manager = new StreamingLayoutManager({
1756
- throttleMs: options.throttleMs,
1757
- glideDurationMs: options.glideDurationMs,
1758
- connectedOnly: options.connectedOnly,
1759
- clock: options.clock,
1760
- layoutOptions: options.layoutOptions,
1761
- onLayoutUpdated: (updated) => {
1762
- $11.set(positions, updated, true);
1763
- options.onPositionsChange?.(updated);
1764
- }
1765
- });
1766
- return {
1767
- get positions() {
1768
- return $11.get(positions);
1769
- },
1770
- pushStreamUpdate(nodes, edges, currentPositions) {
1771
- manager.pushStreamUpdate(nodes, edges, currentPositions);
1772
- },
1773
- flush(nodes, edges, currentPositions) {
1774
- manager.flush(nodes, edges, currentPositions);
1775
- },
1776
- destroy() {
1777
- manager.destroy();
1778
- }
1779
- };
1780
- }
1781
-
1782
- // src/canvas/index.ts
1783
- import {
1784
- realClock,
1785
- ManualClock,
1786
- layoutBounds,
1787
- canvasHeight,
1788
- estimateCanvasHeight,
1789
- blendLayout,
1790
- connectedOnly
1791
- } from "@pixerate/editor/canvas";
1792
- export {
1793
- AgentPresenceLayer,
1794
- FloatingHorizontalScrollbar,
1795
- ManualClock,
1796
- blendLayout,
1797
- calculateDirectionalDisplacement,
1798
- calculateGraphDifferences,
1799
- calculateReflowDisplacement,
1800
- canvasHeight,
1801
- centerNodes,
1802
- computeNodesBoundingBox,
1803
- connectedOnly,
1804
- createBezierTrajectory,
1805
- createCanvasClipboard,
1806
- createCanvasDocking,
1807
- createCanvasExplosion,
1808
- createCanvasGraph,
1809
- createCanvasInteractions,
1810
- createCanvasMultiDrag,
1811
- createCanvasNodeSync,
1812
- createCanvasShortcuts,
1813
- createFanOutTrajectory,
1814
- createStreamingCanvas,
1815
- defaultSvelteFlowPreset,
1816
- ensureLayout,
1817
- estimateCanvasHeight,
1818
- estimateNodeSize,
1819
- flowSide,
1820
- getCenteredNodePosition,
1821
- getLayoutedNodes,
1822
- getMarqueeSelectionPreset,
1823
- handleDeselectOnEscape,
1824
- isEventFromTextInput,
1825
- isValidCanvasNode,
1826
- isValidUrl,
1827
- layoutBounds,
1828
- linearPositionTrajectory,
1829
- linearTrajectory,
1830
- miroCompatiblePreset,
1831
- normalizeNodeHandles,
1832
- placeBeside,
1833
- preserveNodeMeasurements,
1834
- realClock,
1835
- replaceNodeInGraph,
1836
- restorePanelPointerEvents,
1837
- runMultiNodeTransition
1838
- };
1839
- //# sourceMappingURL=index.js.map
1
+ // Types
2
+ export * from './types.js';
3
+ // Graph management rune & pure functions
4
+ export { createCanvasGraph, calculateGraphDifferences, replaceNodeInGraph } from './createCanvasGraph.svelte.js';
5
+ // Layout calculations
6
+ export { getLayoutedNodes, getCenteredNodePosition, centerNodes, ensureLayout, placeBeside, estimateNodeSize, flowSide } from './createCanvasLayout.js';
7
+ // Clipboard rune & helpers
8
+ export { createCanvasClipboard, isEventFromTextInput, isValidCanvasNode, isValidUrl } from './createCanvasClipboard.svelte.js';
9
+ // Docking & drag interactions rune
10
+ export { createCanvasDocking } from './createCanvasDocking.svelte.js';
11
+ // Shortcuts manager
12
+ export { createCanvasShortcuts } from './createCanvasShortcuts.js';
13
+ // Interaction modes & presets
14
+ export { createCanvasInteractions, defaultSvelteFlowPreset, miroCompatiblePreset, restorePanelPointerEvents } from './createCanvasInteractions.svelte.js';
15
+ // Trajectory calculation & multi-node transitions
16
+ export { linearTrajectory, linearPositionTrajectory, createFanOutTrajectory, createBezierTrajectory, runMultiNodeTransition } from './createCanvasTrajectory.js';
17
+ // Spatial layout displacement
18
+ export { computeNodesBoundingBox, calculateDirectionalDisplacement, calculateReflowDisplacement } from './createCanvasDisplacement.js';
19
+ // Node explosion & collapse rune
20
+ export { createCanvasExplosion } from './createCanvasExplosion.svelte.js';
21
+ // Node synchronization & handle normalization
22
+ export { createCanvasNodeSync, preserveNodeMeasurements, normalizeNodeHandles } from './createCanvasNodeSync.svelte.js';
23
+ // Multi-node drag coordination rune
24
+ export { createCanvasMultiDrag } from './createCanvasMultiDrag.svelte.js';
25
+ // Drag selection helpers & presets
26
+ export { getMarqueeSelectionPreset, handleDeselectOnEscape } from './createCanvasSelection.svelte.js';
27
+ // Viewport floating scrollbar component
28
+ export { default as FloatingHorizontalScrollbar } from './FloatingHorizontalScrollbar.svelte';
29
+ // Agent presence visual layer
30
+ export { default as AgentPresenceLayer } from './AgentPresenceLayer.svelte';
31
+ // Streaming canvas rune
32
+ export { createStreamingCanvas } from './createStreamingCanvas.svelte.js';
33
+ // Clock and view helpers from core
34
+ export { realClock, ManualClock, layoutBounds, canvasHeight, estimateCanvasHeight, blendLayout, connectedOnly } from '@pixerate/editor/canvas';