@pixerate/editor-svelte 0.3.11 → 0.4.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.
@@ -0,0 +1,345 @@
1
+ import type { Node, Edge, XYPosition, Rect, ColorMode } from '@xyflow/svelte';
2
+
3
+ /**
4
+ * Generic node interface representing an element on the canvas.
5
+ */
6
+ export type CanvasNode<
7
+ TData extends Record<string, any> = Record<string, any>,
8
+ TType extends string | undefined = string | undefined
9
+ > = Node<TData, TType>;
10
+
11
+ /**
12
+ * Generic edge interface representing a connection on the canvas.
13
+ */
14
+ export type CanvasEdge<
15
+ TData extends Record<string, any> = Record<string, any>,
16
+ TType extends string | undefined = string | undefined
17
+ > = Edge<TData, TType>;
18
+
19
+ /**
20
+ * Differences computed between two graph states.
21
+ */
22
+ export interface GraphDifferences<
23
+ TNode extends CanvasNode = CanvasNode,
24
+ TEdge extends CanvasEdge = CanvasEdge
25
+ > {
26
+ changedNodes: TNode[];
27
+ changedEdges: TEdge[];
28
+ removedNodes: TNode[];
29
+ removedEdges: TEdge[];
30
+ }
31
+
32
+ /**
33
+ * Standard serialized clipboard payload for nodes and optional edges.
34
+ */
35
+ export interface CanvasClipboardPayload<
36
+ TNode extends CanvasNode = CanvasNode,
37
+ TEdge extends CanvasEdge = CanvasEdge
38
+ > {
39
+ version?: number;
40
+ nodes: TNode[];
41
+ edges?: TEdge[];
42
+ }
43
+
44
+ /**
45
+ * Options for Dagre graph layout.
46
+ */
47
+ export interface CanvasLayoutOptions {
48
+ direction?: 'LR' | 'TB' | 'RL' | 'BT';
49
+ ranksep?: number;
50
+ nodesep?: number;
51
+ defaultNodeWidth?: number;
52
+ defaultNodeHeight?: number;
53
+ }
54
+
55
+ /**
56
+ * Options for keyboard shortcuts.
57
+ */
58
+ export interface CanvasShortcutsOptions<TNode extends CanvasNode = CanvasNode> {
59
+ targetElement?: HTMLElement | Window;
60
+ onCopy?: () => void;
61
+ onCut?: () => void;
62
+ onPaste?: (event: ClipboardEvent) => void;
63
+ onDelete?: (selectedNodes: TNode[]) => void;
64
+ onDuplicate?: (selectedNodes: TNode[]) => void;
65
+ onSelectAll?: () => void;
66
+ onGroup?: (selectedNodes: TNode[]) => void;
67
+ onUngroup?: (selectedNodes: TNode[]) => void;
68
+ onZoomIn?: () => void;
69
+ onZoomOut?: () => void;
70
+ onFitView?: () => void;
71
+ onSearch?: () => void;
72
+ getSelectedNodes?: () => TNode[];
73
+ }
74
+
75
+ /**
76
+ * Docking and intersection callbacks.
77
+ */
78
+ export interface CanvasDockingCallbacks<TNode extends CanvasNode = CanvasNode> {
79
+ onDockHover?: (dockTarget: TNode, draggedNode: TNode) => void;
80
+ onDockLeave?: (dockTarget: TNode, draggedNode: TNode) => void;
81
+ onDockDrop?: (dockTarget: TNode, draggedNode: TNode) => void;
82
+ }
83
+
84
+ /**
85
+ * Configuration options for SvelteFlow presets.
86
+ */
87
+ export interface CanvasInteractionPresetConfig {
88
+ snapGrid?: [number, number];
89
+ panOnDrag?: number[] | boolean;
90
+ panOnScroll?: boolean;
91
+ selectionOnDrag?: boolean;
92
+ colorMode?: ColorMode;
93
+ multiSelectionKey?: string[];
94
+ minZoom?: number;
95
+ maxZoom?: number;
96
+ }
97
+
98
+ /**
99
+ * Pure calculation of graph differences between a current state and a baseline state.
100
+ */
101
+ export declare function calculateGraphDifferences<
102
+ TNode extends CanvasNode = CanvasNode,
103
+ TEdge extends CanvasEdge = CanvasEdge
104
+ >(
105
+ currentState: { nodes?: TNode[]; edges?: TEdge[] },
106
+ baselineState: { nodes?: TNode[]; edges?: TEdge[] }
107
+ ): GraphDifferences<TNode, TEdge>;
108
+
109
+ /**
110
+ * Pure function to replace a node in a graph, optionally preserving its connected edges.
111
+ */
112
+ export declare function replaceNodeInGraph<
113
+ TNode extends CanvasNode = CanvasNode,
114
+ TEdge extends CanvasEdge = CanvasEdge
115
+ >(
116
+ nodes: TNode[],
117
+ edges: TEdge[],
118
+ oldNode: TNode,
119
+ newNode: TNode,
120
+ keepEdges?: boolean
121
+ ): { nodes: TNode[]; edges: TEdge[] };
122
+
123
+ export interface CreateCanvasGraphOptions<
124
+ TNode extends CanvasNode = CanvasNode,
125
+ TEdge extends CanvasEdge = CanvasEdge
126
+ > {
127
+ initialNodes?: TNode[];
128
+ initialEdges?: TEdge[];
129
+ onNodesChange?: (nodes: TNode[]) => void;
130
+ onEdgesChange?: (edges: TEdge[]) => void;
131
+ onSave?: () => void;
132
+ createEdge?: (
133
+ sourceId: string,
134
+ targetId: string,
135
+ options?: { label?: string; animated?: boolean; data?: any }
136
+ ) => TEdge;
137
+ }
138
+
139
+ /**
140
+ * Headless Svelte 5 rune managing canvas graph state and operations.
141
+ */
142
+ export declare function createCanvasGraph<
143
+ TNode extends CanvasNode = CanvasNode,
144
+ TEdge extends CanvasEdge = CanvasEdge
145
+ >(options?: CreateCanvasGraphOptions<TNode, TEdge>): {
146
+ nodes: TNode[];
147
+ edges: TEdge[];
148
+ setNodes(newNodes: TNode[], triggerCallback?: boolean): void;
149
+ setEdges(newEdges: TEdge[], triggerCallback?: boolean): void;
150
+ addNodeOrNodes(nodeOrNodesToAdd: TNode | TNode[], animateFromPosition?: XYPosition, save?: boolean): void;
151
+ addEdge(edgeToAdd: TEdge, save?: boolean): void;
152
+ addEdges(edgesToAdd: TEdge[], save?: boolean): void;
153
+ removeNodes(nodesToRemove: TNode[], save?: boolean): void;
154
+ removeEdges(edgesToRemove: TEdge[], save?: boolean): void;
155
+ replaceNode(oldNode: TNode, newNode: TNode, save?: boolean, keepEdges?: boolean): void;
156
+ addConnectedNodes(params: {
157
+ nodesToAdd: TNode[];
158
+ inboundNodes?: TNode[];
159
+ outboundNodes?: TNode[];
160
+ animatedEdges?: boolean;
161
+ animateFromPosition?: XYPosition;
162
+ inboundEdgeData?: any;
163
+ outboundEdgeData?: any;
164
+ getEdgeLabel?: (source: TNode, target: TNode) => string;
165
+ }): void;
166
+ animateNodePosition(
167
+ node: TNode,
168
+ targetPosition: XYPosition,
169
+ duration?: number,
170
+ easing?: (t: number) => number
171
+ ): void;
172
+ getDifferences(baseline: { nodes?: TNode[]; edges?: TEdge[] }): GraphDifferences<TNode, TEdge>;
173
+ };
174
+
175
+ /**
176
+ * Calculates upper-left flow coordinate for an element to be centered in the viewport.
177
+ */
178
+ export declare function getCenteredNodePosition(
179
+ width?: number,
180
+ height?: number,
181
+ screenToFlowPosition?: (position: XYPosition) => XYPosition,
182
+ screenDimensions?: { width: number; height: number }
183
+ ): XYPosition;
184
+
185
+ /**
186
+ * Updates positions of nodes so their collective bounding box is centered in the current viewport.
187
+ */
188
+ export declare function centerNodes<TNode extends CanvasNode = CanvasNode>(
189
+ nodes: TNode[],
190
+ screenToFlowPosition: (position: XYPosition) => XYPosition,
191
+ getNodesBounds: (nodes: TNode[]) => Rect,
192
+ screenDimensions?: { width: number; height: number }
193
+ ): TNode[];
194
+
195
+ /**
196
+ * Automatically calculates directed hierarchical layout of nodes and edges using Dagre.
197
+ */
198
+ export declare function getLayoutedNodes<
199
+ TNode extends CanvasNode = CanvasNode,
200
+ TEdge extends CanvasEdge = CanvasEdge
201
+ >(
202
+ nodes: TNode[],
203
+ edges: TEdge[],
204
+ getNodesBounds: (nodes: TNode[]) => Rect,
205
+ options?: CanvasLayoutOptions
206
+ ): TNode[];
207
+
208
+ /**
209
+ * Checks if an event originated from a text input, textarea, contenteditable element, or rich editor.
210
+ */
211
+ export declare function isEventFromTextInput(event: Event | { target: EventTarget | null }): boolean;
212
+
213
+ /**
214
+ * Validates that an object conforms to minimal CanvasNode shape.
215
+ */
216
+ export declare function isValidCanvasNode(obj: unknown): obj is CanvasNode;
217
+
218
+ /**
219
+ * Checks if a string is a valid HTTP/HTTPS URL.
220
+ */
221
+ export declare function isValidUrl(url: string): boolean;
222
+
223
+ export interface CreateCanvasClipboardOptions<
224
+ TNode extends CanvasNode = CanvasNode,
225
+ TEdge extends CanvasEdge = CanvasEdge
226
+ > {
227
+ onPasteNodes?: (nodes: TNode[], edges?: TEdge[]) => void | Promise<void>;
228
+ onPasteUrl?: (url: string, position?: XYPosition) => void;
229
+ onPasteText?: (text: string, position?: XYPosition) => void;
230
+ onPasteImage?: (blob: File) => void | Promise<void>;
231
+ screenToFlowPosition?: (position: XYPosition) => XYPosition;
232
+ }
233
+
234
+ /**
235
+ * Headless Svelte 5 rune managing canvas copy, cut, and paste interactions.
236
+ */
237
+ export declare function createCanvasClipboard<
238
+ TNode extends CanvasNode = CanvasNode,
239
+ TEdge extends CanvasEdge = CanvasEdge
240
+ >(options?: CreateCanvasClipboardOptions<TNode, TEdge>): {
241
+ copySelectedNodes(
242
+ selectedNodes: TNode[],
243
+ connectedEdges?: TEdge[],
244
+ event?: ClipboardEvent
245
+ ): boolean;
246
+ cutSelectedNodes(
247
+ selectedNodes: TNode[],
248
+ connectedEdges?: TEdge[],
249
+ onRemove?: (nodes: TNode[]) => void,
250
+ event?: ClipboardEvent
251
+ ): boolean;
252
+ handlePasteEvent(event: ClipboardEvent): Promise<boolean>;
253
+ };
254
+
255
+ export interface CreateCanvasDockingOptions<TNode extends CanvasNode = CanvasNode>
256
+ extends CanvasDockingCallbacks<TNode> {
257
+ isDockTarget?: (target: TNode) => boolean;
258
+ restorePositionOnDock?: boolean;
259
+ onSave?: () => void;
260
+ }
261
+
262
+ /**
263
+ * Headless Svelte 5 rune managing canvas node dragging, docking intersection, and connection tracking.
264
+ */
265
+ export declare function createCanvasDocking<TNode extends CanvasNode = CanvasNode>(
266
+ options?: CreateCanvasDockingOptions<TNode>
267
+ ): {
268
+ readonly draggedNode: TNode | null;
269
+ readonly draggedInitialPosition: XYPosition | null;
270
+ readonly connectingHandle: string;
271
+ readonly connectingNode: TNode | null;
272
+ readonly isDragging: boolean;
273
+ handleNodeDragStart(params: {
274
+ targetNode: TNode | null;
275
+ event?: MouseEvent | TouchEvent;
276
+ }): void;
277
+ handleNodeDrag(
278
+ params: {
279
+ targetNode: TNode | null;
280
+ event?: MouseEvent | TouchEvent;
281
+ },
282
+ getIntersectingNodes: (node: TNode) => TNode[]
283
+ ): void;
284
+ handleNodeDragStop(
285
+ params: {
286
+ targetNode: TNode | null;
287
+ event?: MouseEvent | TouchEvent;
288
+ },
289
+ getIntersectingNodes: (node: TNode) => TNode[],
290
+ updateNodePosition?: (nodeId: string, position: XYPosition) => void
291
+ ): void;
292
+ handleConnectStart(
293
+ params: {
294
+ nodeId: string | null;
295
+ handleId?: string | null;
296
+ handleType: 'source' | 'target' | null;
297
+ },
298
+ getNode: (id: string) => TNode | undefined
299
+ ): void;
300
+ handleConnectEnd(): void;
301
+ reset(): void;
302
+ };
303
+
304
+ /**
305
+ * Attaches keyboard shortcut handlers for canvas interaction.
306
+ * Automatically ignores shortcuts when the user is typing into text inputs, textareas, or rich editors.
307
+ *
308
+ * @returns A cleanup function to remove event listeners.
309
+ */
310
+ export declare function createCanvasShortcuts<TNode extends CanvasNode = CanvasNode>(
311
+ options: CanvasShortcutsOptions<TNode>
312
+ ): () => void;
313
+
314
+ export interface CreateCanvasInteractionsOptions {
315
+ targetElement?: HTMLElement | Window;
316
+ onPanModeChange?: (active: boolean) => void;
317
+ onTrackpadDetected?: () => void;
318
+ }
319
+
320
+ /**
321
+ * Headless Svelte 5 rune managing canvas pan interactions (spacebar panning, trackpad pinch detection).
322
+ */
323
+ export declare function createCanvasInteractions(
324
+ options?: CreateCanvasInteractionsOptions
325
+ ): {
326
+ readonly isSpacebarPanning: boolean;
327
+ readonly trackpadDetected: boolean;
328
+ attachListeners(target?: HTMLElement | Window): () => void;
329
+ destroy: () => void;
330
+ };
331
+
332
+ /**
333
+ * Default interaction configuration presets for SvelteFlow.
334
+ */
335
+ export declare const defaultSvelteFlowPreset: CanvasInteractionPresetConfig;
336
+
337
+ /**
338
+ * Miro-compatible interaction preset (middle/right drag to pan, left drag to select).
339
+ */
340
+ export declare const miroCompatiblePreset: CanvasInteractionPresetConfig;
341
+
342
+ /**
343
+ * Helper to ensure panels restore pointer events after selection rectangle releases.
344
+ */
345
+ export declare function restorePanelPointerEvents(panelSelector?: string): void;
@@ -0,0 +1,46 @@
1
+ // Types
2
+ export * from './types.js';
3
+
4
+ // Graph management rune & pure functions
5
+ export {
6
+ createCanvasGraph,
7
+ calculateGraphDifferences,
8
+ replaceNodeInGraph,
9
+ type CreateCanvasGraphOptions
10
+ } from './createCanvasGraph.svelte.js';
11
+
12
+ // Layout calculations
13
+ export {
14
+ getLayoutedNodes,
15
+ getCenteredNodePosition,
16
+ centerNodes
17
+ } from './createCanvasLayout.js';
18
+
19
+ // Clipboard rune & helpers
20
+ export {
21
+ createCanvasClipboard,
22
+ isEventFromTextInput,
23
+ isValidCanvasNode,
24
+ isValidUrl,
25
+ type CreateCanvasClipboardOptions
26
+ } from './createCanvasClipboard.svelte.js';
27
+
28
+ // Docking & drag interactions rune
29
+ export {
30
+ createCanvasDocking,
31
+ type CreateCanvasDockingOptions
32
+ } from './createCanvasDocking.svelte.js';
33
+
34
+ // Shortcuts manager
35
+ export {
36
+ createCanvasShortcuts
37
+ } from './createCanvasShortcuts.js';
38
+
39
+ // Interaction modes & presets
40
+ export {
41
+ createCanvasInteractions,
42
+ defaultSvelteFlowPreset,
43
+ miroCompatiblePreset,
44
+ restorePanelPointerEvents,
45
+ type CreateCanvasInteractionsOptions
46
+ } from './createCanvasInteractions.svelte.js';
@@ -0,0 +1,96 @@
1
+ import type { Node, Edge, XYPosition, Rect, ColorMode, Position } from '@xyflow/svelte';
2
+
3
+ /**
4
+ * Generic node interface representing an element on the canvas.
5
+ */
6
+ export type CanvasNode<
7
+ TData extends Record<string, any> = Record<string, any>,
8
+ TType extends string | undefined = string | undefined
9
+ > = Node<TData, TType>;
10
+
11
+ /**
12
+ * Generic edge interface representing a connection on the canvas.
13
+ */
14
+ export type CanvasEdge<
15
+ TData extends Record<string, any> = Record<string, any>,
16
+ TType extends string | undefined = string | undefined
17
+ > = Edge<TData, TType>;
18
+
19
+ /**
20
+ * Differences computed between two graph states.
21
+ */
22
+ export interface GraphDifferences<
23
+ TNode extends CanvasNode = CanvasNode,
24
+ TEdge extends CanvasEdge = CanvasEdge
25
+ > {
26
+ changedNodes: TNode[];
27
+ changedEdges: TEdge[];
28
+ removedNodes: TNode[];
29
+ removedEdges: TEdge[];
30
+ }
31
+
32
+ /**
33
+ * Standard serialized clipboard payload for nodes and optional edges.
34
+ */
35
+ export interface CanvasClipboardPayload<
36
+ TNode extends CanvasNode = CanvasNode,
37
+ TEdge extends CanvasEdge = CanvasEdge
38
+ > {
39
+ version?: number;
40
+ nodes: TNode[];
41
+ edges?: TEdge[];
42
+ }
43
+
44
+ /**
45
+ * Options for Dagre graph layout.
46
+ */
47
+ export interface CanvasLayoutOptions {
48
+ direction?: 'LR' | 'TB' | 'RL' | 'BT';
49
+ ranksep?: number;
50
+ nodesep?: number;
51
+ defaultNodeWidth?: number;
52
+ defaultNodeHeight?: number;
53
+ }
54
+
55
+ /**
56
+ * Options for keyboard shortcuts.
57
+ */
58
+ export interface CanvasShortcutsOptions<TNode extends CanvasNode = CanvasNode> {
59
+ targetElement?: HTMLElement | Window;
60
+ onCopy?: () => void;
61
+ onCut?: () => void;
62
+ onPaste?: (event: ClipboardEvent) => void;
63
+ onDelete?: (selectedNodes: TNode[]) => void;
64
+ onDuplicate?: (selectedNodes: TNode[]) => void;
65
+ onSelectAll?: () => void;
66
+ onGroup?: (selectedNodes: TNode[]) => void;
67
+ onUngroup?: (selectedNodes: TNode[]) => void;
68
+ onZoomIn?: () => void;
69
+ onZoomOut?: () => void;
70
+ onFitView?: () => void;
71
+ onSearch?: () => void;
72
+ getSelectedNodes?: () => TNode[];
73
+ }
74
+
75
+ /**
76
+ * Docking and intersection callbacks.
77
+ */
78
+ export interface CanvasDockingCallbacks<TNode extends CanvasNode = CanvasNode> {
79
+ onDockHover?: (dockTarget: TNode, draggedNode: TNode) => void;
80
+ onDockLeave?: (dockTarget: TNode, draggedNode: TNode) => void;
81
+ onDockDrop?: (dockTarget: TNode, draggedNode: TNode) => void;
82
+ }
83
+
84
+ /**
85
+ * Configuration options for SvelteFlow presets.
86
+ */
87
+ export interface CanvasInteractionPresetConfig {
88
+ snapGrid?: [number, number];
89
+ panOnDrag?: number[] | boolean;
90
+ panOnScroll?: boolean;
91
+ selectionOnDrag?: boolean;
92
+ colorMode?: ColorMode;
93
+ multiSelectionKey?: string[];
94
+ minZoom?: number;
95
+ maxZoom?: number;
96
+ }