@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.
- package/dist/BubbleMenu.svelte.d.ts +14 -0
- package/dist/BubbleMenu.svelte.d.ts.map +1 -0
- package/{src → dist}/EditableTextNodeEditor.svelte +1 -1
- package/dist/EditableTextNodeEditor.svelte.d.ts +26 -0
- package/dist/EditableTextNodeEditor.svelte.d.ts.map +1 -0
- package/dist/TemplateRenderer.svelte.d.ts +14 -0
- package/dist/TemplateRenderer.svelte.d.ts.map +1 -0
- package/dist/canvas/AgentPresenceLayer.svelte.d.ts +9 -0
- package/dist/canvas/AgentPresenceLayer.svelte.d.ts.map +1 -0
- package/dist/canvas/FloatingHorizontalScrollbar.svelte.d.ts +9 -0
- package/dist/canvas/FloatingHorizontalScrollbar.svelte.d.ts.map +1 -0
- package/dist/canvas/createCanvasClipboard.svelte.d.ts +32 -0
- package/dist/canvas/createCanvasClipboard.svelte.d.ts.map +1 -0
- package/dist/canvas/createCanvasClipboard.svelte.js +171 -0
- package/dist/canvas/createCanvasDisplacement.d.ts +32 -0
- package/dist/canvas/createCanvasDisplacement.d.ts.map +1 -0
- package/dist/canvas/createCanvasDisplacement.js +170 -0
- package/dist/canvas/createCanvasDocking.svelte.d.ts +56 -0
- package/dist/canvas/createCanvasDocking.svelte.d.ts.map +1 -0
- package/dist/canvas/createCanvasDocking.svelte.js +227 -0
- package/dist/canvas/createCanvasExplosion.svelte.d.ts +31 -0
- package/dist/canvas/createCanvasExplosion.svelte.d.ts.map +1 -0
- package/dist/canvas/createCanvasExplosion.svelte.js +346 -0
- package/dist/canvas/createCanvasGraph.svelte.d.ts +62 -0
- package/dist/canvas/createCanvasGraph.svelte.d.ts.map +1 -0
- package/dist/canvas/createCanvasGraph.svelte.js +223 -0
- package/dist/canvas/createCanvasInteractions.svelte.d.ts +28 -0
- package/dist/canvas/createCanvasInteractions.svelte.d.ts.map +1 -0
- package/dist/canvas/createCanvasInteractions.svelte.js +95 -0
- package/dist/canvas/createCanvasLayout.d.ts +22 -0
- package/dist/canvas/createCanvasLayout.d.ts.map +1 -0
- package/dist/canvas/createCanvasLayout.js +76 -0
- package/dist/canvas/createCanvasMultiDrag.svelte.d.ts +61 -0
- package/dist/canvas/createCanvasMultiDrag.svelte.d.ts.map +1 -0
- package/dist/canvas/createCanvasMultiDrag.svelte.js +105 -0
- package/dist/canvas/createCanvasNodeSync.svelte.d.ts +58 -0
- package/dist/canvas/createCanvasNodeSync.svelte.d.ts.map +1 -0
- package/dist/canvas/createCanvasNodeSync.svelte.js +82 -0
- package/dist/canvas/createCanvasSelection.svelte.d.ts +26 -0
- package/dist/canvas/createCanvasSelection.svelte.d.ts.map +1 -0
- package/dist/canvas/createCanvasSelection.svelte.js +26 -0
- package/dist/canvas/createCanvasShortcuts.d.ts +9 -0
- package/dist/canvas/createCanvasShortcuts.d.ts.map +1 -0
- package/dist/canvas/createCanvasShortcuts.js +97 -0
- package/dist/canvas/createCanvasTrajectory.d.ts +31 -0
- package/dist/canvas/createCanvasTrajectory.d.ts.map +1 -0
- package/dist/canvas/createCanvasTrajectory.js +141 -0
- package/dist/canvas/createStreamingCanvas.svelte.d.ts +19 -0
- package/dist/canvas/createStreamingCanvas.svelte.d.ts.map +1 -0
- package/dist/canvas/createStreamingCanvas.svelte.js +32 -0
- package/dist/canvas/index.d.ts +18 -688
- package/dist/canvas/index.d.ts.map +1 -0
- package/dist/canvas/index.js +34 -1839
- package/dist/canvas/types.d.ts +183 -0
- package/dist/canvas/types.d.ts.map +1 -0
- package/dist/canvas/types.js +1 -0
- package/dist/createNavigationGuard.svelte.d.ts +24 -0
- package/dist/createNavigationGuard.svelte.d.ts.map +1 -0
- package/dist/createNavigationGuard.svelte.js +65 -0
- package/dist/editor.svelte.d.ts +23 -0
- package/dist/editor.svelte.d.ts.map +1 -0
- package/dist/editor.svelte.js +41 -0
- package/dist/history/createHistoryShortcuts.d.ts +24 -0
- package/dist/history/createHistoryShortcuts.d.ts.map +1 -0
- package/dist/history/createHistoryShortcuts.js +57 -0
- package/dist/history/history.svelte.d.ts +18 -0
- package/dist/history/history.svelte.d.ts.map +1 -0
- package/dist/history/history.svelte.js +43 -0
- package/dist/history/index.d.ts +3 -0
- package/dist/history/index.d.ts.map +1 -0
- package/dist/history/index.js +2 -0
- package/{src → dist}/image-editor/ImageEditor.svelte +1 -1
- package/dist/image-editor/ImageEditor.svelte.d.ts +17 -0
- package/dist/image-editor/ImageEditor.svelte.d.ts.map +1 -0
- package/dist/image-editor/imageEditorState.svelte.d.ts +50 -0
- package/dist/image-editor/imageEditorState.svelte.d.ts.map +1 -0
- package/dist/image-editor/imageEditorState.svelte.js +132 -0
- package/dist/image-editor/index.d.ts +6 -16
- package/dist/image-editor/index.d.ts.map +1 -0
- package/dist/image-editor/index.js +2 -9
- package/dist/index.d.ts +20 -249
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +10 -1119
- package/dist/navigationGuard.d.ts +21 -0
- package/dist/navigationGuard.d.ts.map +1 -0
- package/dist/navigationGuard.js +59 -0
- package/{src → dist}/spreadsheet/FormulaBar.svelte +1 -1
- package/dist/spreadsheet/FormulaBar.svelte.d.ts +17 -0
- package/dist/spreadsheet/FormulaBar.svelte.d.ts.map +1 -0
- package/{src → dist}/spreadsheet/SpreadsheetEditor.svelte +1 -1
- package/dist/spreadsheet/SpreadsheetEditor.svelte.d.ts +22 -0
- package/dist/spreadsheet/SpreadsheetEditor.svelte.d.ts.map +1 -0
- package/dist/spreadsheet/index.d.ts +9 -0
- package/dist/spreadsheet/index.d.ts.map +1 -0
- package/{src/spreadsheet/index.ts → dist/spreadsheet/index.js} +1 -1
- package/dist/spreadsheet/spreadsheet.svelte.d.ts +33 -0
- package/dist/spreadsheet/spreadsheet.svelte.d.ts.map +1 -0
- package/dist/spreadsheet/spreadsheet.svelte.js +160 -0
- package/package.json +14 -16
- package/dist/canvas/index.js.map +0 -1
- package/dist/chunk-HEOI4UNF.js +0 -1191
- package/dist/chunk-HEOI4UNF.js.map +0 -1
- package/dist/image-editor/index.js.map +0 -1
- package/dist/index.css +0 -50
- package/dist/index.css.map +0 -1
- package/dist/index.js.map +0 -1
- package/src/canvas/__tests__/canvas-clipboard.test.ts +0 -154
- package/src/canvas/__tests__/canvas-docking.test.ts +0 -288
- package/src/canvas/__tests__/canvas-explosion.test.ts +0 -634
- package/src/canvas/__tests__/canvas-graph.test.ts +0 -159
- package/src/canvas/__tests__/canvas-interactions.test.ts +0 -86
- package/src/canvas/__tests__/canvas-layout.test.ts +0 -75
- package/src/canvas/__tests__/canvas-multi-drag.test.ts +0 -112
- package/src/canvas/__tests__/canvas-node-sync.svelte.test.ts +0 -104
- package/src/canvas/__tests__/canvas-shortcuts.test.ts +0 -59
- package/src/canvas/createCanvasClipboard.svelte.ts +0 -219
- package/src/canvas/createCanvasDisplacement.ts +0 -253
- package/src/canvas/createCanvasDocking.svelte.ts +0 -355
- package/src/canvas/createCanvasExplosion.svelte.ts +0 -457
- package/src/canvas/createCanvasGraph.svelte.ts +0 -330
- package/src/canvas/createCanvasInteractions.svelte.ts +0 -112
- package/src/canvas/createCanvasLayout.ts +0 -129
- package/src/canvas/createCanvasMultiDrag.svelte.ts +0 -175
- package/src/canvas/createCanvasNodeSync.svelte.ts +0 -150
- package/src/canvas/createCanvasSelection.svelte.ts +0 -51
- package/src/canvas/createCanvasShortcuts.ts +0 -99
- package/src/canvas/createCanvasTrajectory.ts +0 -207
- package/src/canvas/createStreamingCanvas.svelte.ts +0 -56
- package/src/canvas/index.d.ts +0 -688
- package/src/canvas/index.ts +0 -126
- package/src/canvas/types.ts +0 -223
- package/src/createNavigationGuard.svelte.ts +0 -97
- package/src/editor.svelte.ts +0 -65
- package/src/history/createHistoryShortcuts.ts +0 -95
- package/src/history/history.svelte.ts +0 -68
- package/src/history/index.ts +0 -2
- package/src/image-editor/imageEditorState.svelte.ts +0 -151
- package/src/image-editor/index.d.ts +0 -16
- package/src/image-editor/index.ts +0 -2
- package/src/index.d.ts +0 -249
- package/src/index.ts +0 -89
- package/src/navigationGuard.ts +0 -82
- package/src/spreadsheet/spreadsheet.svelte.ts +0 -176
- package/src/svelte.d.ts +0 -5
- /package/{src → dist}/BubbleMenu.svelte +0 -0
- /package/{src → dist}/TemplateRenderer.svelte +0 -0
- /package/{src → dist}/canvas/AgentPresenceLayer.svelte +0 -0
- /package/{src → dist}/canvas/FloatingHorizontalScrollbar.svelte +0 -0
- /package/{src → dist}/canvas/README.md +0 -0
|
@@ -1,457 +0,0 @@
|
|
|
1
|
-
import { cubicOut } from 'svelte/easing';
|
|
2
|
-
import type { Rect, XYPosition } from '@xyflow/svelte';
|
|
3
|
-
import type {
|
|
4
|
-
CanvasEdge,
|
|
5
|
-
CanvasNode,
|
|
6
|
-
CollapseNodeOptions,
|
|
7
|
-
ExplodeNodeOptions,
|
|
8
|
-
ExplosionSnapshot,
|
|
9
|
-
NodeTransition
|
|
10
|
-
} from './types.js';
|
|
11
|
-
import {
|
|
12
|
-
calculateDirectionalDisplacement,
|
|
13
|
-
calculateReflowDisplacement
|
|
14
|
-
} from './createCanvasDisplacement.js';
|
|
15
|
-
import {
|
|
16
|
-
createFanOutTrajectory,
|
|
17
|
-
linearPositionTrajectory,
|
|
18
|
-
linearTrajectory,
|
|
19
|
-
runMultiNodeTransition
|
|
20
|
-
} from './createCanvasTrajectory.js';
|
|
21
|
-
|
|
22
|
-
export interface CanvasGraphTarget<
|
|
23
|
-
TNode extends CanvasNode = CanvasNode,
|
|
24
|
-
TEdge extends CanvasEdge = CanvasEdge
|
|
25
|
-
> {
|
|
26
|
-
nodes: TNode[];
|
|
27
|
-
edges: TEdge[];
|
|
28
|
-
setNodes: (nodes: TNode[], triggerCallback?: boolean) => void;
|
|
29
|
-
setEdges: (edges: TEdge[], triggerCallback?: boolean) => void;
|
|
30
|
-
addNodeOrNodes: (nodes: TNode | TNode[], animateFrom?: XYPosition, save?: boolean) => void;
|
|
31
|
-
addEdges: (edges: TEdge[], save?: boolean) => void;
|
|
32
|
-
removeNodes: (nodes: TNode[], save?: boolean) => void;
|
|
33
|
-
removeEdges: (edges: TEdge[], save?: boolean) => void;
|
|
34
|
-
createEdge?: (sourceId: string, targetId: string, options?: any) => TEdge;
|
|
35
|
-
onSave?: () => void;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
export interface CreateCanvasExplosionOptions<TNode extends CanvasNode = CanvasNode> {
|
|
39
|
-
getNodesBounds?: (nodes: TNode[]) => Rect;
|
|
40
|
-
onSave?: () => void;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
* Headless Svelte 5 rune managing canvas node explosion, spatial layout displacement,
|
|
45
|
-
* coordinated multi-node animation paths, and reversible collapsing.
|
|
46
|
-
*/
|
|
47
|
-
export function createCanvasExplosion<
|
|
48
|
-
TNode extends CanvasNode = CanvasNode,
|
|
49
|
-
TEdge extends CanvasEdge = CanvasEdge
|
|
50
|
-
>(
|
|
51
|
-
graph: CanvasGraphTarget<TNode, TEdge>,
|
|
52
|
-
options: CreateCanvasExplosionOptions<TNode> = {}
|
|
53
|
-
) {
|
|
54
|
-
let explodedNodeIds = $state<string[]>([]);
|
|
55
|
-
const snapshots = new Map<string, ExplosionSnapshot<TNode, TEdge>>();
|
|
56
|
-
let activeAnimationCancel: (() => void) | null = null;
|
|
57
|
-
|
|
58
|
-
function isExploded(nodeId: string): boolean {
|
|
59
|
-
return explodedNodeIds.includes(nodeId);
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
function explodeNode(
|
|
63
|
-
parentId: string,
|
|
64
|
-
explodeOptions: ExplodeNodeOptions<TNode, TEdge>
|
|
65
|
-
): boolean {
|
|
66
|
-
if (isExploded(parentId)) {
|
|
67
|
-
return false;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
const parentNode = graph.nodes.find((n) => n.id === parentId);
|
|
71
|
-
if (!parentNode) {
|
|
72
|
-
return false;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
const {
|
|
76
|
-
childNodes,
|
|
77
|
-
childEdges = [],
|
|
78
|
-
connectParentToChildren = 'all',
|
|
79
|
-
displacementStrategy = 'directional',
|
|
80
|
-
directionalOptions = {},
|
|
81
|
-
reflowOptions = {},
|
|
82
|
-
trajectory,
|
|
83
|
-
duration = 500,
|
|
84
|
-
staggerDelay = 20,
|
|
85
|
-
easing = cubicOut,
|
|
86
|
-
onComplete
|
|
87
|
-
} = explodeOptions;
|
|
88
|
-
|
|
89
|
-
if (childNodes.length === 0) {
|
|
90
|
-
return false;
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
// 1. Calculate displacement for existing nodes
|
|
94
|
-
let displacementMap: Map<string, XYPosition>;
|
|
95
|
-
if (displacementStrategy === 'dagre') {
|
|
96
|
-
displacementMap = calculateReflowDisplacement({
|
|
97
|
-
existingNodes: graph.nodes,
|
|
98
|
-
existingEdges: graph.edges,
|
|
99
|
-
originNode: parentNode,
|
|
100
|
-
childNodes,
|
|
101
|
-
childEdges,
|
|
102
|
-
getNodesBounds: options.getNodesBounds,
|
|
103
|
-
options: {
|
|
104
|
-
...reflowOptions,
|
|
105
|
-
direction: (reflowOptions.direction as any) ?? 'LR'
|
|
106
|
-
}
|
|
107
|
-
});
|
|
108
|
-
} else if (displacementStrategy === 'none') {
|
|
109
|
-
displacementMap = new Map();
|
|
110
|
-
} else {
|
|
111
|
-
displacementMap = calculateDirectionalDisplacement({
|
|
112
|
-
existingNodes: graph.nodes,
|
|
113
|
-
originNode: parentNode,
|
|
114
|
-
childNodes,
|
|
115
|
-
getNodesBounds: options.getNodesBounds,
|
|
116
|
-
options: directionalOptions
|
|
117
|
-
});
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
// 2. Build snapshot of displaced nodes before mutating positions
|
|
121
|
-
const displacedNodesSnapshot = Array.from(displacementMap.entries()).map(([id]) => {
|
|
122
|
-
const node = graph.nodes.find((n) => n.id === id);
|
|
123
|
-
return {
|
|
124
|
-
id,
|
|
125
|
-
originalPosition: { ...(node?.position ?? { x: 0, y: 0 }) }
|
|
126
|
-
};
|
|
127
|
-
});
|
|
128
|
-
|
|
129
|
-
// 3. Prepare child edges & parent connection edges
|
|
130
|
-
const edgesToAdd: TEdge[] = [...childEdges];
|
|
131
|
-
const defaultCreateEdge = (sourceId: string, targetId: string): TEdge => {
|
|
132
|
-
if (graph.createEdge) {
|
|
133
|
-
return graph.createEdge(sourceId, targetId);
|
|
134
|
-
}
|
|
135
|
-
return {
|
|
136
|
-
id: crypto.randomUUID(),
|
|
137
|
-
type: 'default',
|
|
138
|
-
source: sourceId,
|
|
139
|
-
target: targetId
|
|
140
|
-
} as unknown as TEdge;
|
|
141
|
-
};
|
|
142
|
-
|
|
143
|
-
if (connectParentToChildren === 'all' || connectParentToChildren === true) {
|
|
144
|
-
childNodes.forEach((child) => {
|
|
145
|
-
const exists = edgesToAdd.some((e) => e.source === parentId && e.target === child.id);
|
|
146
|
-
if (!exists) {
|
|
147
|
-
edgesToAdd.push(defaultCreateEdge(parentId, child.id));
|
|
148
|
-
}
|
|
149
|
-
});
|
|
150
|
-
} else if (connectParentToChildren === 'first' && childNodes.length > 0) {
|
|
151
|
-
const firstChild = childNodes[0];
|
|
152
|
-
const exists = edgesToAdd.some((e) => e.source === parentId && e.target === firstChild.id);
|
|
153
|
-
if (!exists) {
|
|
154
|
-
edgesToAdd.push(defaultCreateEdge(parentId, firstChild.id));
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
const snapshot: ExplosionSnapshot<TNode, TEdge> = {
|
|
159
|
-
parentId,
|
|
160
|
-
childNodeIds: childNodes.map((n) => n.id),
|
|
161
|
-
childEdgeIds: edgesToAdd.map((e) => e.id),
|
|
162
|
-
displacedNodes: displacedNodesSnapshot,
|
|
163
|
-
timestamp: Date.now()
|
|
164
|
-
};
|
|
165
|
-
snapshots.set(parentId, snapshot);
|
|
166
|
-
|
|
167
|
-
// 4. Position child nodes initially at origin node coordinate
|
|
168
|
-
const originPos = { ...parentNode.position };
|
|
169
|
-
const targetPositions = childNodes.map((child) => ({ ...child.position }));
|
|
170
|
-
|
|
171
|
-
childNodes.forEach((child) => {
|
|
172
|
-
child.position = { ...originPos };
|
|
173
|
-
if (!child.data) child.data = {} as any;
|
|
174
|
-
(child.data as any).scale = 0;
|
|
175
|
-
(child.data as any).opacity = 0;
|
|
176
|
-
const currentStyle = (child.style || '').replace(/opacity:\s*[^;]+;?/g, '').trim();
|
|
177
|
-
child.style = `${currentStyle ? currentStyle + '; ' : ''}opacity: 0;`;
|
|
178
|
-
});
|
|
179
|
-
|
|
180
|
-
edgesToAdd.forEach((edge) => {
|
|
181
|
-
const currentStyle = (edge.style || '').replace(/opacity:\s*[^;]+;?/g, '').trim();
|
|
182
|
-
edge.style = `${currentStyle ? currentStyle + '; ' : ''}opacity: 0;`;
|
|
183
|
-
});
|
|
184
|
-
|
|
185
|
-
// Add nodes and edges to graph without saving yet
|
|
186
|
-
graph.addNodeOrNodes(childNodes, undefined, false);
|
|
187
|
-
if (edgesToAdd.length > 0) {
|
|
188
|
-
graph.addEdges(edgesToAdd, false);
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
// 5. Build transition list
|
|
192
|
-
const chosenTrajectory = trajectory ?? createFanOutTrajectory({ curvature: 0.35 });
|
|
193
|
-
const transitions: NodeTransition<TNode>[] = [];
|
|
194
|
-
const effectiveStagger = duration === 0 ? 0 : staggerDelay;
|
|
195
|
-
|
|
196
|
-
// Expanding child transitions
|
|
197
|
-
childNodes.forEach((child, i) => {
|
|
198
|
-
transitions.push({
|
|
199
|
-
node: child,
|
|
200
|
-
from: originPos,
|
|
201
|
-
to: targetPositions[i],
|
|
202
|
-
trajectory: chosenTrajectory,
|
|
203
|
-
delay: i * effectiveStagger,
|
|
204
|
-
duration,
|
|
205
|
-
easing,
|
|
206
|
-
index: i,
|
|
207
|
-
total: childNodes.length
|
|
208
|
-
});
|
|
209
|
-
});
|
|
210
|
-
|
|
211
|
-
// Displaced node transitions
|
|
212
|
-
displacementMap.forEach((targetPos, nodeId) => {
|
|
213
|
-
const node = graph.nodes.find((n) => n.id === nodeId);
|
|
214
|
-
if (node) {
|
|
215
|
-
transitions.push({
|
|
216
|
-
node,
|
|
217
|
-
from: { ...node.position },
|
|
218
|
-
to: targetPos,
|
|
219
|
-
trajectory: linearPositionTrajectory,
|
|
220
|
-
duration,
|
|
221
|
-
easing
|
|
222
|
-
});
|
|
223
|
-
}
|
|
224
|
-
});
|
|
225
|
-
|
|
226
|
-
// 6. Run coordinated animation
|
|
227
|
-
if (activeAnimationCancel) {
|
|
228
|
-
activeAnimationCancel();
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
activeAnimationCancel = runMultiNodeTransition(transitions, {
|
|
232
|
-
defaultDuration: duration,
|
|
233
|
-
defaultEasing: easing,
|
|
234
|
-
onUpdate: () => {
|
|
235
|
-
if (edgesToAdd.length > 0) {
|
|
236
|
-
const childIdSet = new Set(childNodes.map((c) => c.id));
|
|
237
|
-
const childEdgesInGraph = graph.edges.filter((e) => childIdSet.has(e.target));
|
|
238
|
-
if (childEdgesInGraph.length > 0) {
|
|
239
|
-
childEdgesInGraph.forEach((edge) => {
|
|
240
|
-
const child = childNodes.find((c) => c.id === edge.target);
|
|
241
|
-
const childOpacity = (child?.data as any)?.opacity ?? 1;
|
|
242
|
-
const currentStyle = (edge.style || '').replace(/opacity:\s*[^;]+;?/g, '').trim();
|
|
243
|
-
edge.style = `${currentStyle ? currentStyle + '; ' : ''}opacity: ${childOpacity};`;
|
|
244
|
-
});
|
|
245
|
-
graph.setEdges([...graph.edges]);
|
|
246
|
-
}
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
// Sync any mismatched node references in graph.nodes from transitions
|
|
250
|
-
transitions.forEach((t) => {
|
|
251
|
-
const graphNode = graph.nodes.find((n) => n.id === t.node.id);
|
|
252
|
-
if (graphNode && graphNode !== t.node) {
|
|
253
|
-
graphNode.position = { ...t.node.position };
|
|
254
|
-
graphNode.style = t.node.style;
|
|
255
|
-
if (t.node.data) {
|
|
256
|
-
graphNode.data = { ...graphNode.data, ...t.node.data };
|
|
257
|
-
}
|
|
258
|
-
}
|
|
259
|
-
});
|
|
260
|
-
|
|
261
|
-
graph.setNodes([...graph.nodes]);
|
|
262
|
-
},
|
|
263
|
-
onComplete: () => {
|
|
264
|
-
childNodes.forEach((child, i) => {
|
|
265
|
-
const node = graph.nodes.find((n) => n.id === child.id);
|
|
266
|
-
if (node) {
|
|
267
|
-
node.position = { ...targetPositions[i] };
|
|
268
|
-
node.style = (node.style || '').replace(/opacity:\s*[^;]+;?/g, '').trim() || undefined;
|
|
269
|
-
if (node.data) {
|
|
270
|
-
(node.data as any).opacity = 1;
|
|
271
|
-
}
|
|
272
|
-
}
|
|
273
|
-
});
|
|
274
|
-
displacementMap.forEach((targetPos, nodeId) => {
|
|
275
|
-
const graphNode = graph.nodes.find((n) => n.id === nodeId);
|
|
276
|
-
if (graphNode) {
|
|
277
|
-
graphNode.position = { ...targetPos };
|
|
278
|
-
}
|
|
279
|
-
});
|
|
280
|
-
edgesToAdd.forEach((edge) => {
|
|
281
|
-
const graphEdge = graph.edges.find((e) => e.id === edge.id);
|
|
282
|
-
if (graphEdge) {
|
|
283
|
-
graphEdge.style = (graphEdge.style || '').replace(/opacity:\s*[^;]+;?/g, '').trim() || undefined;
|
|
284
|
-
}
|
|
285
|
-
});
|
|
286
|
-
graph.setNodes([...graph.nodes]);
|
|
287
|
-
graph.setEdges([...graph.edges]);
|
|
288
|
-
explodedNodeIds = [...explodedNodeIds, parentId];
|
|
289
|
-
activeAnimationCancel = null;
|
|
290
|
-
options.onSave?.();
|
|
291
|
-
graph.onSave?.();
|
|
292
|
-
onComplete?.();
|
|
293
|
-
}
|
|
294
|
-
});
|
|
295
|
-
|
|
296
|
-
return true;
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
function collapseNode(
|
|
300
|
-
parentId: string,
|
|
301
|
-
collapseOptions: CollapseNodeOptions = {}
|
|
302
|
-
): boolean {
|
|
303
|
-
const snapshot = snapshots.get(parentId);
|
|
304
|
-
if (!snapshot) {
|
|
305
|
-
return false;
|
|
306
|
-
}
|
|
307
|
-
|
|
308
|
-
const parentNode = graph.nodes.find((n) => n.id === parentId);
|
|
309
|
-
if (!parentNode) {
|
|
310
|
-
return false;
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
const {
|
|
314
|
-
duration = 400,
|
|
315
|
-
staggerDelay = 15,
|
|
316
|
-
easing = cubicOut,
|
|
317
|
-
trajectory,
|
|
318
|
-
onComplete
|
|
319
|
-
} = collapseOptions;
|
|
320
|
-
|
|
321
|
-
const childIdSet = new Set(snapshot.childNodeIds);
|
|
322
|
-
const activeChildNodes = graph.nodes.filter((n) => childIdSet.has(n.id));
|
|
323
|
-
const originPos = { ...parentNode.position };
|
|
324
|
-
|
|
325
|
-
// Reverse trajectory pulls nodes back toward parent while collapsing scale
|
|
326
|
-
const reverseTrajectory = trajectory ?? createFanOutTrajectory({
|
|
327
|
-
curvature: 0.2,
|
|
328
|
-
startScale: 1,
|
|
329
|
-
endScale: 0,
|
|
330
|
-
startOpacity: 1,
|
|
331
|
-
endOpacity: 0
|
|
332
|
-
});
|
|
333
|
-
|
|
334
|
-
const transitions: NodeTransition<TNode>[] = [];
|
|
335
|
-
const effectiveStagger = duration === 0 ? 0 : staggerDelay;
|
|
336
|
-
|
|
337
|
-
// Collapsing child transitions back into origin
|
|
338
|
-
activeChildNodes.forEach((child, i) => {
|
|
339
|
-
transitions.push({
|
|
340
|
-
node: child,
|
|
341
|
-
from: { ...child.position },
|
|
342
|
-
to: originPos,
|
|
343
|
-
trajectory: reverseTrajectory,
|
|
344
|
-
delay: (activeChildNodes.length - 1 - i) * effectiveStagger,
|
|
345
|
-
duration,
|
|
346
|
-
easing,
|
|
347
|
-
index: i,
|
|
348
|
-
total: activeChildNodes.length
|
|
349
|
-
});
|
|
350
|
-
});
|
|
351
|
-
|
|
352
|
-
// Displaced node restore transitions
|
|
353
|
-
snapshot.displacedNodes.forEach(({ id, originalPosition }) => {
|
|
354
|
-
const node = graph.nodes.find((n) => n.id === id);
|
|
355
|
-
if (node) {
|
|
356
|
-
transitions.push({
|
|
357
|
-
node,
|
|
358
|
-
from: { ...node.position },
|
|
359
|
-
to: originalPosition,
|
|
360
|
-
trajectory: linearPositionTrajectory,
|
|
361
|
-
duration,
|
|
362
|
-
easing
|
|
363
|
-
});
|
|
364
|
-
}
|
|
365
|
-
});
|
|
366
|
-
|
|
367
|
-
if (activeAnimationCancel) {
|
|
368
|
-
activeAnimationCancel();
|
|
369
|
-
}
|
|
370
|
-
|
|
371
|
-
activeAnimationCancel = runMultiNodeTransition(transitions, {
|
|
372
|
-
defaultDuration: duration,
|
|
373
|
-
defaultEasing: easing,
|
|
374
|
-
onUpdate: () => {
|
|
375
|
-
const edgeIdSet = new Set(snapshot.childEdgeIds);
|
|
376
|
-
const childEdgesInGraph = graph.edges.filter((e) => edgeIdSet.has(e.id));
|
|
377
|
-
if (childEdgesInGraph.length > 0) {
|
|
378
|
-
childEdgesInGraph.forEach((edge) => {
|
|
379
|
-
const child = activeChildNodes.find((c) => c.id === edge.target);
|
|
380
|
-
const childOpacity = (child?.data as any)?.opacity ?? 0;
|
|
381
|
-
const currentStyle = (edge.style || '').replace(/opacity:\s*[^;]+;?/g, '').trim();
|
|
382
|
-
edge.style = `${currentStyle ? currentStyle + '; ' : ''}opacity: ${childOpacity};`;
|
|
383
|
-
});
|
|
384
|
-
graph.setEdges([...graph.edges]);
|
|
385
|
-
}
|
|
386
|
-
|
|
387
|
-
// Sync any mismatched node references in graph.nodes from transitions
|
|
388
|
-
transitions.forEach((t) => {
|
|
389
|
-
const graphNode = graph.nodes.find((n) => n.id === t.node.id);
|
|
390
|
-
if (graphNode && graphNode !== t.node) {
|
|
391
|
-
graphNode.position = { ...t.node.position };
|
|
392
|
-
graphNode.style = t.node.style;
|
|
393
|
-
if (t.node.data) {
|
|
394
|
-
graphNode.data = { ...graphNode.data, ...t.node.data };
|
|
395
|
-
}
|
|
396
|
-
}
|
|
397
|
-
});
|
|
398
|
-
|
|
399
|
-
graph.setNodes([...graph.nodes]);
|
|
400
|
-
},
|
|
401
|
-
onComplete: () => {
|
|
402
|
-
// Animation completed: prune child nodes and edges
|
|
403
|
-
graph.removeNodes(activeChildNodes, false);
|
|
404
|
-
|
|
405
|
-
const edgeIdSet = new Set(snapshot.childEdgeIds);
|
|
406
|
-
const edgesToRemove = graph.edges.filter((e) => edgeIdSet.has(e.id));
|
|
407
|
-
if (edgesToRemove.length > 0) {
|
|
408
|
-
graph.removeEdges(edgesToRemove, false);
|
|
409
|
-
}
|
|
410
|
-
|
|
411
|
-
snapshot.displacedNodes.forEach(({ id, originalPosition }) => {
|
|
412
|
-
const graphNode = graph.nodes.find((n) => n.id === id);
|
|
413
|
-
if (graphNode) {
|
|
414
|
-
graphNode.position = { ...originalPosition };
|
|
415
|
-
}
|
|
416
|
-
});
|
|
417
|
-
graph.setNodes([...graph.nodes]);
|
|
418
|
-
|
|
419
|
-
snapshots.delete(parentId);
|
|
420
|
-
explodedNodeIds = explodedNodeIds.filter((id) => id !== parentId);
|
|
421
|
-
activeAnimationCancel = null;
|
|
422
|
-
|
|
423
|
-
options.onSave?.();
|
|
424
|
-
graph.onSave?.();
|
|
425
|
-
onComplete?.();
|
|
426
|
-
}
|
|
427
|
-
});
|
|
428
|
-
|
|
429
|
-
return true;
|
|
430
|
-
}
|
|
431
|
-
|
|
432
|
-
function toggleExplode(
|
|
433
|
-
parentId: string,
|
|
434
|
-
explodeOptions: ExplodeNodeOptions<TNode, TEdge>,
|
|
435
|
-
collapseOptions?: CollapseNodeOptions
|
|
436
|
-
): boolean {
|
|
437
|
-
if (isExploded(parentId)) {
|
|
438
|
-
return collapseNode(parentId, collapseOptions);
|
|
439
|
-
}
|
|
440
|
-
return explodeNode(parentId, explodeOptions);
|
|
441
|
-
}
|
|
442
|
-
|
|
443
|
-
function getSnapshot(parentId: string) {
|
|
444
|
-
return snapshots.get(parentId);
|
|
445
|
-
}
|
|
446
|
-
|
|
447
|
-
return {
|
|
448
|
-
get explodedNodeIds() {
|
|
449
|
-
return explodedNodeIds;
|
|
450
|
-
},
|
|
451
|
-
isExploded,
|
|
452
|
-
explodeNode,
|
|
453
|
-
collapseNode,
|
|
454
|
-
toggleExplode,
|
|
455
|
-
getSnapshot
|
|
456
|
-
};
|
|
457
|
-
}
|