@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,330 +0,0 @@
1
- import { getConnectedEdges, type XYPosition } from '@xyflow/svelte';
2
- import { cubicOut } from 'svelte/easing';
3
- import type { CanvasNode, CanvasEdge, GraphDifferences } from './types.js';
4
-
5
- /**
6
- * Pure calculation of graph differences between a current state and a baseline state.
7
- */
8
- export function calculateGraphDifferences<
9
- TNode extends CanvasNode = CanvasNode,
10
- TEdge extends CanvasEdge = CanvasEdge
11
- >(
12
- currentState: { nodes?: TNode[]; edges?: TEdge[] },
13
- baselineState: { nodes?: TNode[]; edges?: TEdge[] }
14
- ): GraphDifferences<TNode, TEdge> {
15
- const currentNodes = currentState.nodes ?? [];
16
- const currentEdges = currentState.edges ?? [];
17
- const baselineNodes = baselineState.nodes ?? [];
18
- const baselineEdges = baselineState.edges ?? [];
19
-
20
- // Map baseline for fast O(1) lookup
21
- const baselineNodeMap = new Map(baselineNodes.map((n) => [n.id, n]));
22
- const baselineEdgeMap = new Map(baselineEdges.map((e) => [e.id, e]));
23
- const currentNodeMap = new Map(currentNodes.map((n) => [n.id, n]));
24
- const currentEdgeMap = new Map(currentEdges.map((e) => [e.id, e]));
25
-
26
- const removedNodes = baselineNodes.filter((oldNode) => !currentNodeMap.has(oldNode.id));
27
- const removedEdges = baselineEdges.filter((oldEdge) => !currentEdgeMap.has(oldEdge.id));
28
-
29
- const changedNodes = currentNodes.filter((newNode) => {
30
- const oldNode = baselineNodeMap.get(newNode.id);
31
- if (!oldNode) return true;
32
- return JSON.stringify(newNode) !== JSON.stringify(oldNode);
33
- });
34
-
35
- const changedEdges = currentEdges.filter((newEdge) => {
36
- const oldEdge = baselineEdgeMap.get(newEdge.id);
37
- if (!oldEdge) return true;
38
- return JSON.stringify(newEdge) !== JSON.stringify(oldEdge);
39
- });
40
-
41
- return { changedNodes, changedEdges, removedNodes, removedEdges };
42
- }
43
-
44
- /**
45
- * Pure function to replace a node in a graph, optionally preserving its connected edges.
46
- */
47
- export function replaceNodeInGraph<
48
- TNode extends CanvasNode = CanvasNode,
49
- TEdge extends CanvasEdge = CanvasEdge
50
- >(
51
- nodes: TNode[],
52
- edges: TEdge[],
53
- oldNode: TNode,
54
- newNode: TNode,
55
- keepEdges = false
56
- ): { nodes: TNode[]; edges: TEdge[] } {
57
- const updatedNodes = nodes.map((n) => (n.id === oldNode.id ? newNode : n));
58
-
59
- if (!keepEdges) {
60
- return { nodes: updatedNodes, edges };
61
- }
62
-
63
- const updatedEdges = edges.map((edge) => {
64
- if (edge.source === oldNode.id || edge.target === oldNode.id) {
65
- return {
66
- ...edge,
67
- id: crypto.randomUUID(),
68
- source: edge.source === oldNode.id ? newNode.id : edge.source,
69
- target: edge.target === oldNode.id ? newNode.id : edge.target
70
- };
71
- }
72
- return edge;
73
- });
74
-
75
- return {
76
- nodes: updatedNodes,
77
- edges: updatedEdges
78
- };
79
- }
80
-
81
- export interface CreateCanvasGraphOptions<
82
- TNode extends CanvasNode = CanvasNode,
83
- TEdge extends CanvasEdge = CanvasEdge
84
- > {
85
- initialNodes?: TNode[];
86
- initialEdges?: TEdge[];
87
- onNodesChange?: (nodes: TNode[]) => void;
88
- onEdgesChange?: (edges: TEdge[]) => void;
89
- onSave?: () => void;
90
- createEdge?: (
91
- sourceId: string,
92
- targetId: string,
93
- options?: { label?: string; animated?: boolean; data?: any }
94
- ) => TEdge;
95
- }
96
-
97
- /**
98
- * Headless Svelte 5 rune managing canvas graph state and operations.
99
- */
100
- export function createCanvasGraph<
101
- TNode extends CanvasNode = CanvasNode,
102
- TEdge extends CanvasEdge = CanvasEdge
103
- >(options: CreateCanvasGraphOptions<TNode, TEdge> = {}) {
104
- let nodes = $state.raw<TNode[]>(options.initialNodes ?? []);
105
- let edges = $state.raw<TEdge[]>(options.initialEdges ?? []);
106
-
107
- function setNodes(newNodes: TNode[], triggerCallback = true) {
108
- nodes = newNodes;
109
- if (triggerCallback) {
110
- options.onNodesChange?.(nodes);
111
- }
112
- }
113
-
114
- function setEdges(newEdges: TEdge[], triggerCallback = true) {
115
- edges = newEdges;
116
- if (triggerCallback) {
117
- options.onEdgesChange?.(edges);
118
- }
119
- }
120
-
121
- function animateNodePosition(
122
- node: TNode,
123
- targetPosition: XYPosition,
124
- duration = 400,
125
- easing: (t: number) => number = cubicOut
126
- ) {
127
- const delay = (node.data as any)?.animationDelay ?? 0;
128
- const startPosition = { ...node.position };
129
- const startTime = Date.now() + delay;
130
-
131
- function step() {
132
- const currentTime = Date.now();
133
- if (currentTime < startTime) {
134
- if (typeof requestAnimationFrame !== 'undefined') {
135
- requestAnimationFrame(step);
136
- }
137
- return;
138
- }
139
-
140
- const progress = Math.min((currentTime - startTime) / duration, 1);
141
- const eased = easing(progress);
142
-
143
- const currentPos = {
144
- x: startPosition.x + (targetPosition.x - startPosition.x) * eased,
145
- y: startPosition.y + (targetPosition.y - startPosition.y) * eased
146
- };
147
-
148
- // Mutate position in place without recreating the entire array every frame
149
- const targetNode = nodes.find((n) => n.id === node.id);
150
- if (targetNode) {
151
- targetNode.position = currentPos;
152
- }
153
-
154
- if (progress < 1) {
155
- if (typeof requestAnimationFrame !== 'undefined') {
156
- requestAnimationFrame(step);
157
- }
158
- } else {
159
- // Animation completed: trigger final reactive update and change event
160
- setNodes([...nodes]);
161
- }
162
- }
163
-
164
- step();
165
- }
166
-
167
- function addNodeOrNodes(
168
- nodeOrNodesToAdd: TNode | TNode[],
169
- animateFromPosition?: XYPosition,
170
- save = true
171
- ): void {
172
- const toAdd = Array.isArray(nodeOrNodesToAdd) ? nodeOrNodesToAdd : [nodeOrNodesToAdd];
173
- const existingMap = new Map(nodes.map((n) => [n.id, n]));
174
-
175
- toAdd.forEach((node) => {
176
- if (!existingMap.has(node.id)) {
177
- existingMap.set(node.id, node);
178
- }
179
- });
180
-
181
- setNodes(Array.from(existingMap.values()));
182
-
183
- if (animateFromPosition) {
184
- toAdd.forEach((node) => {
185
- const target = { ...node.position };
186
- node.position = { ...animateFromPosition };
187
- animateNodePosition(node, target);
188
- });
189
- }
190
-
191
- if (save) options.onSave?.();
192
- }
193
-
194
- function addEdge(edgeToAdd: TEdge, save = true): void {
195
- setEdges([...edges, edgeToAdd]);
196
- if (save) options.onSave?.();
197
- }
198
-
199
- function addEdges(edgesToAdd: TEdge[], save = true): void {
200
- setEdges([...edges, ...edgesToAdd]);
201
- if (save) options.onSave?.();
202
- }
203
-
204
- function removeNodes(nodesToRemove: TNode[], save = true): void {
205
- const idsToRemove = new Set(nodesToRemove.map((n) => n.id));
206
- setNodes(nodes.filter((n) => !idsToRemove.has(n.id)));
207
- if (save) options.onSave?.();
208
- }
209
-
210
- function removeEdges(edgesToRemove: TEdge[], save = true): void {
211
- const idsToRemove = new Set(edgesToRemove.map((e) => e.id));
212
- setEdges(edges.filter((e) => !idsToRemove.has(e.id)));
213
- if (save) options.onSave?.();
214
- }
215
-
216
- function replaceNode(
217
- oldNode: TNode,
218
- newNode: TNode,
219
- save = true,
220
- keepEdges = false
221
- ): void {
222
- const result = replaceNodeInGraph(nodes, edges, oldNode, newNode, keepEdges);
223
- setNodes(result.nodes);
224
- if (result.edges !== edges) {
225
- setEdges(result.edges);
226
- }
227
- if (save) options.onSave?.();
228
- }
229
-
230
- function addConnectedNodes(params: {
231
- nodesToAdd: TNode[];
232
- inboundNodes?: TNode[];
233
- outboundNodes?: TNode[];
234
- animatedEdges?: boolean;
235
- animateFromPosition?: XYPosition;
236
- inboundEdgeData?: any;
237
- outboundEdgeData?: any;
238
- getEdgeLabel?: (source: TNode, target: TNode) => string;
239
- }): void {
240
- const {
241
- nodesToAdd,
242
- inboundNodes = [],
243
- outboundNodes = [],
244
- animatedEdges = false,
245
- animateFromPosition,
246
- inboundEdgeData = {},
247
- outboundEdgeData = {},
248
- getEdgeLabel
249
- } = params;
250
-
251
- const defaultCreateEdge = (
252
- sourceId: string,
253
- targetId: string,
254
- opt?: { label?: string; animated?: boolean; data?: any }
255
- ): TEdge => {
256
- if (options.createEdge) {
257
- return options.createEdge(sourceId, targetId, opt);
258
- }
259
- return {
260
- id: crypto.randomUUID(),
261
- type: 'default',
262
- source: sourceId,
263
- target: targetId,
264
- label: opt?.label ?? '',
265
- animated: opt?.animated ?? false,
266
- data: opt?.data ?? {}
267
- } as unknown as TEdge;
268
- };
269
-
270
- nodesToAdd.forEach((addedNode) => {
271
- addNodeOrNodes(addedNode, animateFromPosition, false);
272
-
273
- inboundNodes.forEach((sourceNode) => {
274
- const label = getEdgeLabel ? getEdgeLabel(sourceNode, addedNode) : '';
275
- addEdge(
276
- defaultCreateEdge(sourceNode.id, addedNode.id, {
277
- label,
278
- animated: animatedEdges,
279
- data: inboundEdgeData
280
- }),
281
- false
282
- );
283
- });
284
-
285
- outboundNodes.forEach((targetNode) => {
286
- const label = getEdgeLabel ? getEdgeLabel(addedNode, targetNode) : '';
287
- addEdge(
288
- defaultCreateEdge(addedNode.id, targetNode.id, {
289
- label,
290
- animated: animatedEdges,
291
- data: outboundEdgeData
292
- }),
293
- false
294
- );
295
- });
296
- });
297
-
298
- options.onSave?.();
299
- }
300
-
301
- function getDifferences(baseline: { nodes?: TNode[]; edges?: TEdge[] }) {
302
- return calculateGraphDifferences({ nodes, edges }, baseline);
303
- }
304
-
305
- return {
306
- get nodes() {
307
- return nodes;
308
- },
309
- set nodes(val: TNode[]) {
310
- setNodes(val);
311
- },
312
- get edges() {
313
- return edges;
314
- },
315
- set edges(val: TEdge[]) {
316
- setEdges(val);
317
- },
318
- setNodes,
319
- setEdges,
320
- addNodeOrNodes,
321
- addEdge,
322
- addEdges,
323
- removeNodes,
324
- removeEdges,
325
- replaceNode,
326
- addConnectedNodes,
327
- animateNodePosition,
328
- getDifferences
329
- };
330
- }
@@ -1,112 +0,0 @@
1
- import type { ColorMode } from '@xyflow/svelte';
2
- import { isEventFromTextInput } from './createCanvasClipboard.svelte.js';
3
- import type { CanvasInteractionPresetConfig } from './types.js';
4
-
5
- export interface CreateCanvasInteractionsOptions {
6
- targetElement?: HTMLElement | Window;
7
- onPanModeChange?: (active: boolean) => void;
8
- onTrackpadDetected?: () => void;
9
- }
10
-
11
- /**
12
- * Headless Svelte 5 rune managing canvas pan interactions (spacebar panning, trackpad pinch detection).
13
- */
14
- export function createCanvasInteractions(options: CreateCanvasInteractionsOptions = {}) {
15
- let isSpacebarPanning = $state.raw(false);
16
- let trackpadDetected = $state.raw(false);
17
- let toggledPanMode = false;
18
-
19
- function handleKeyDown(event: KeyboardEvent) {
20
- if (event.key === ' ' || event.code === 'Space') {
21
- if (isSpacebarPanning || isEventFromTextInput(event)) return;
22
- isSpacebarPanning = true;
23
- toggledPanMode = true;
24
- options.onPanModeChange?.(true);
25
-
26
- if (typeof document !== 'undefined') {
27
- document.body.classList.add('cursor-grab');
28
- }
29
- }
30
- }
31
-
32
- function handleKeyUp(event: KeyboardEvent) {
33
- if (event.key === ' ' || event.code === 'Space') {
34
- if (!isSpacebarPanning && !toggledPanMode) return;
35
- isSpacebarPanning = false;
36
- toggledPanMode = false;
37
- options.onPanModeChange?.(false);
38
-
39
- if (typeof document !== 'undefined') {
40
- document.body.classList.remove('cursor-grab');
41
- }
42
- }
43
- }
44
-
45
- function handleWheel(event: WheelEvent) {
46
- if (event.ctrlKey && !trackpadDetected) {
47
- trackpadDetected = true;
48
- options.onTrackpadDetected?.();
49
- }
50
- }
51
-
52
- function attachListeners(target?: HTMLElement | Window): () => void {
53
- const el = target ?? options.targetElement ?? (typeof window !== 'undefined' ? window : null);
54
- if (!el) return () => {};
55
-
56
- el.addEventListener('keydown', handleKeyDown as EventListener);
57
- el.addEventListener('keyup', handleKeyUp as EventListener);
58
- el.addEventListener('wheel', handleWheel as EventListener, { passive: true });
59
-
60
- return () => {
61
- el.removeEventListener('keydown', handleKeyDown as EventListener);
62
- el.removeEventListener('keyup', handleKeyUp as EventListener);
63
- el.removeEventListener('wheel', handleWheel as EventListener);
64
- if (typeof document !== 'undefined') {
65
- document.body.classList.remove('cursor-grab');
66
- }
67
- };
68
- }
69
-
70
- return {
71
- get isSpacebarPanning() {
72
- return isSpacebarPanning;
73
- },
74
- get trackpadDetected() {
75
- return trackpadDetected;
76
- },
77
- attachListeners,
78
- destroy: attachListeners()
79
- };
80
- }
81
-
82
- /**
83
- * Default interaction configuration presets for SvelteFlow.
84
- */
85
- export const defaultSvelteFlowPreset: CanvasInteractionPresetConfig = {
86
- snapGrid: [25, 25],
87
- panOnDrag: [0, 1, 2, 3, 4],
88
- panOnScroll: false,
89
- selectionOnDrag: false,
90
- colorMode: 'system' as ColorMode,
91
- multiSelectionKey: ['Shift', 'Meta']
92
- };
93
-
94
- /**
95
- * Miro-compatible interaction preset (middle/right drag to pan, left drag to select).
96
- */
97
- export const miroCompatiblePreset: CanvasInteractionPresetConfig = {
98
- ...defaultSvelteFlowPreset,
99
- panOnDrag: [1, 2],
100
- selectionOnDrag: true
101
- };
102
-
103
- /**
104
- * Helper to ensure panels restore pointer events after selection rectangle releases.
105
- */
106
- export function restorePanelPointerEvents(panelSelector = '.svelte-flow__panel'): void {
107
- if (typeof document === 'undefined') return;
108
- const panels = document.querySelectorAll(panelSelector);
109
- panels.forEach((panel) => {
110
- (panel as HTMLElement).style.pointerEvents = 'auto';
111
- });
112
- }
@@ -1,129 +0,0 @@
1
- import dagre from '@dagrejs/dagre';
2
- import { Position, type XYPosition, type Rect } from '@xyflow/svelte';
3
- import type { CanvasNode, CanvasEdge, CanvasLayoutOptions } from './types.js';
4
-
5
- /**
6
- * Calculates upper-left flow coordinate for an element to be centered in the viewport.
7
- */
8
- export function getCenteredNodePosition(
9
- width = 0,
10
- height = 0,
11
- screenToFlowPosition: (position: XYPosition) => XYPosition,
12
- screenDimensions?: { width: number; height: number }
13
- ): XYPosition {
14
- const rect = screenDimensions ?? (typeof document !== 'undefined'
15
- ? { width: document.documentElement.clientWidth, height: document.documentElement.clientHeight }
16
- : { width: 1920, height: 1080 });
17
-
18
- const flowPos = screenToFlowPosition({ x: rect.width / 2, y: rect.height / 2 });
19
- return {
20
- x: flowPos.x - width / 2,
21
- y: flowPos.y - height / 2
22
- };
23
- }
24
-
25
- /**
26
- * Updates positions of nodes so their collective bounding box is centered in the current viewport.
27
- */
28
- export function centerNodes<TNode extends CanvasNode = CanvasNode>(
29
- nodes: TNode[],
30
- screenToFlowPosition: (position: XYPosition) => XYPosition,
31
- getNodesBounds: (nodes: TNode[]) => Rect,
32
- screenDimensions?: { width: number; height: number }
33
- ): TNode[] {
34
- if (nodes.length === 0) {
35
- return [];
36
- }
37
-
38
- const bounds = getNodesBounds(nodes);
39
- const boundingBoxOrigin = { x: bounds.x, y: bounds.y };
40
-
41
- const centeredPosition = getCenteredNodePosition(
42
- bounds.width,
43
- bounds.height,
44
- screenToFlowPosition,
45
- screenDimensions
46
- );
47
-
48
- const deltaX = centeredPosition.x - boundingBoxOrigin.x;
49
- const deltaY = centeredPosition.y - boundingBoxOrigin.y;
50
-
51
- return nodes.map((node) => ({
52
- ...node,
53
- position: {
54
- x: node.position.x + deltaX,
55
- y: node.position.y + deltaY
56
- }
57
- }));
58
- }
59
-
60
- /**
61
- * Automatically calculates directed hierarchical layout of nodes and edges using Dagre.
62
- */
63
- export function getLayoutedNodes<
64
- TNode extends CanvasNode = CanvasNode,
65
- TEdge extends CanvasEdge = CanvasEdge
66
- >(
67
- nodes: TNode[],
68
- edges: TEdge[],
69
- getNodesBounds: (nodes: TNode[]) => Rect,
70
- options: CanvasLayoutOptions = {}
71
- ): TNode[] {
72
- if (nodes.length === 0) return [];
73
-
74
- const {
75
- direction = 'LR',
76
- ranksep = 100,
77
- nodesep = 25,
78
- defaultNodeWidth = 200,
79
- defaultNodeHeight = 200
80
- } = options;
81
-
82
- const isHorizontal = direction === 'LR' || direction === 'RL';
83
- const bounds = getNodesBounds(nodes);
84
-
85
- const dagreGraph = new dagre.graphlib.Graph();
86
- dagreGraph.setDefaultEdgeLabel(() => ({}));
87
- dagreGraph.setGraph({ rankdir: direction, ranksep, nodesep });
88
-
89
- const nodeIds = new Set(nodes.map((node) => node.id));
90
-
91
- nodes.forEach((node) => {
92
- const nodeWidth = node.measured?.width ?? (node as any).width ?? defaultNodeWidth;
93
- const nodeHeight = node.measured?.height ?? (node as any).height ?? defaultNodeHeight;
94
- dagreGraph.setNode(node.id, { width: nodeWidth, height: nodeHeight });
95
- });
96
-
97
- edges.forEach((edge) => {
98
- if (nodeIds.has(edge.source) && nodeIds.has(edge.target)) {
99
- dagreGraph.setEdge(edge.source, edge.target);
100
- }
101
- });
102
-
103
- dagre.layout(dagreGraph);
104
-
105
- return nodes.map((node) => {
106
- const nodeWithPosition = dagreGraph.node(node.id);
107
- const nodeWidth = node.measured?.width ?? (node as any).width ?? defaultNodeWidth;
108
- const nodeHeight = node.measured?.height ?? (node as any).height ?? defaultNodeHeight;
109
-
110
- return {
111
- ...node,
112
- targetPosition: isHorizontal ? Position.Left : Position.Top,
113
- sourcePosition: isHorizontal ? Position.Right : Position.Bottom,
114
- position: {
115
- x: bounds.x + (nodeWithPosition?.x ?? 0) - nodeWidth / 2,
116
- y: bounds.y + (nodeWithPosition?.y ?? 0) - nodeHeight / 2
117
- }
118
- };
119
- });
120
- }
121
-
122
- // Re-export incremental layout and collision-aware placement from core
123
- export {
124
- ensureLayout,
125
- placeBeside,
126
- estimateNodeSize,
127
- flowSide
128
- } from '@pixerate/editor/canvas';
129
-