@pixerate/editor-svelte 0.17.4 → 0.17.5
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/canvas/createCanvasClipboard.svelte.d.ts +2 -1
- package/dist/canvas/createCanvasClipboard.svelte.d.ts.map +1 -1
- package/dist/canvas/createCanvasClipboard.svelte.js +36 -13
- package/dist/canvas/createCanvasExplosion.svelte.d.ts.map +1 -1
- package/dist/canvas/createCanvasExplosion.svelte.js +33 -28
- package/dist/canvas/createCanvasTrajectory.d.ts +8 -4
- package/dist/canvas/createCanvasTrajectory.d.ts.map +1 -1
- package/dist/canvas/createCanvasTrajectory.js +19 -14
- package/package.json +2 -2
|
@@ -7,7 +7,8 @@ export declare function isEventFromTextInput(event: Event | {
|
|
|
7
7
|
target: EventTarget | null;
|
|
8
8
|
}): boolean;
|
|
9
9
|
/**
|
|
10
|
-
* Validates that an object conforms to minimal CanvasNode shape
|
|
10
|
+
* Validates that an object conforms to minimal CanvasNode shape:
|
|
11
|
+
* a string `id` and a `position` whose `x` / `y` are finite numbers.
|
|
11
12
|
*/
|
|
12
13
|
export declare function isValidCanvasNode(obj: unknown): obj is CanvasNode;
|
|
13
14
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createCanvasClipboard.svelte.d.ts","sourceRoot":"","sources":["../../src/canvas/createCanvasClipboard.svelte.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,KAAK,EAAE,UAAU,EAAE,UAAU,EAA0B,MAAM,YAAY,CAAC;AAEjF;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,KAAK,GAAG;IAAE,MAAM,EAAE,WAAW,GAAG,IAAI,CAAA;CAAE,GAAG,OAAO,CAc3F;AAED
|
|
1
|
+
{"version":3,"file":"createCanvasClipboard.svelte.d.ts","sourceRoot":"","sources":["../../src/canvas/createCanvasClipboard.svelte.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,KAAK,EAAE,UAAU,EAAE,UAAU,EAA0B,MAAM,YAAY,CAAC;AAEjF;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,KAAK,GAAG;IAAE,MAAM,EAAE,WAAW,GAAG,IAAI,CAAA;CAAE,GAAG,OAAO,CAc3F;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,OAAO,GAAG,GAAG,IAAI,UAAU,CAajE;AAWD;;GAEG;AACH,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAO/C;AAED,MAAM,WAAW,4BAA4B,CAC5C,KAAK,SAAS,UAAU,GAAG,UAAU,EACrC,KAAK,SAAS,UAAU,GAAG,UAAU;IAErC,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,KAAK,CAAC,EAAE,KAAK,EAAE,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACzE,UAAU,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,UAAU,KAAK,IAAI,CAAC;IAC1D,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,UAAU,KAAK,IAAI,CAAC;IAC5D,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACpD,oBAAoB,CAAC,EAAE,CAAC,QAAQ,EAAE,UAAU,KAAK,UAAU,CAAC;CAC5D;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CACpC,KAAK,SAAS,UAAU,GAAG,UAAU,EACrC,KAAK,SAAS,UAAU,GAAG,UAAU,EACpC,OAAO,GAAE,4BAA4B,CAAC,KAAK,EAAE,KAAK,CAAM;uCAEzC,KAAK,EAAE,mBACL,KAAK,EAAE,UAChB,cAAc,KACpB,OAAO;sCA2BM,KAAK,EAAE,mBACL,KAAK,EAAE,aACb,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,IAAI,UAC3B,cAAc,KACpB,OAAO;8BAY6B,cAAc,KAAG,OAAO,CAAC,OAAO,CAAC;EAkHxE"}
|
|
@@ -17,18 +17,28 @@ export function isEventFromTextInput(event) {
|
|
|
17
17
|
return false;
|
|
18
18
|
}
|
|
19
19
|
/**
|
|
20
|
-
* Validates that an object conforms to minimal CanvasNode shape
|
|
20
|
+
* Validates that an object conforms to minimal CanvasNode shape:
|
|
21
|
+
* a string `id` and a `position` whose `x` / `y` are finite numbers.
|
|
21
22
|
*/
|
|
22
23
|
export function isValidCanvasNode(obj) {
|
|
24
|
+
if (typeof obj !== 'object' || obj === null)
|
|
25
|
+
return false;
|
|
26
|
+
const candidate = obj;
|
|
27
|
+
if (typeof candidate.id !== 'string')
|
|
28
|
+
return false;
|
|
29
|
+
const position = candidate.position;
|
|
30
|
+
return (typeof position === 'object' &&
|
|
31
|
+
position !== null &&
|
|
32
|
+
typeof position.x === 'number' &&
|
|
33
|
+
Number.isFinite(position.x) &&
|
|
34
|
+
typeof position.y === 'number' &&
|
|
35
|
+
Number.isFinite(position.y));
|
|
36
|
+
}
|
|
37
|
+
function isValidCanvasEdgeShape(obj) {
|
|
23
38
|
return (typeof obj === 'object' &&
|
|
24
39
|
obj !== null &&
|
|
25
|
-
'
|
|
26
|
-
typeof obj.
|
|
27
|
-
'position' in obj &&
|
|
28
|
-
typeof obj.position === 'object' &&
|
|
29
|
-
obj.position !== null &&
|
|
30
|
-
'x' in obj.position &&
|
|
31
|
-
'y' in obj.position);
|
|
40
|
+
typeof obj.source === 'string' &&
|
|
41
|
+
typeof obj.target === 'string');
|
|
32
42
|
}
|
|
33
43
|
/**
|
|
34
44
|
* Checks if a string is a valid HTTP/HTTPS URL.
|
|
@@ -110,24 +120,37 @@ export function createCanvasClipboard(options = {}) {
|
|
|
110
120
|
Array.isArray(parsed.nodes) &&
|
|
111
121
|
parsed.nodes.every(isValidCanvasNode)) {
|
|
112
122
|
rawNodes = parsed.nodes;
|
|
113
|
-
|
|
123
|
+
const edgesField = parsed.edges;
|
|
124
|
+
// Untrusted input: ignore a non-array `edges` and malformed edge entries.
|
|
125
|
+
rawEdges = Array.isArray(edgesField)
|
|
126
|
+
? edgesField.filter(isValidCanvasEdgeShape)
|
|
127
|
+
: undefined;
|
|
114
128
|
}
|
|
115
129
|
if (rawNodes && rawNodes.length > 0) {
|
|
116
130
|
event.preventDefault();
|
|
117
131
|
// Create ID mapping for cloned nodes
|
|
118
132
|
const idMap = new Map();
|
|
133
|
+
for (const node of rawNodes) {
|
|
134
|
+
idMap.set(node.id, crypto.randomUUID());
|
|
135
|
+
}
|
|
119
136
|
const newNodes = rawNodes.map((node) => {
|
|
120
|
-
const
|
|
121
|
-
idMap.set(node.id, newId);
|
|
122
|
-
return {
|
|
137
|
+
const next = {
|
|
123
138
|
...node,
|
|
124
|
-
id:
|
|
139
|
+
id: idMap.get(node.id),
|
|
125
140
|
selected: true,
|
|
126
141
|
position: {
|
|
127
142
|
x: node.position.x + 40,
|
|
128
143
|
y: node.position.y + 40
|
|
129
144
|
}
|
|
130
145
|
};
|
|
146
|
+
// Children of a pasted parent point at the new parent and keep their
|
|
147
|
+
// parent-relative position; other parent references are left unchanged.
|
|
148
|
+
const parentId = node.parentId;
|
|
149
|
+
if (typeof parentId === 'string' && idMap.has(parentId)) {
|
|
150
|
+
next.parentId = idMap.get(parentId);
|
|
151
|
+
next.position = { x: node.position.x, y: node.position.y };
|
|
152
|
+
}
|
|
153
|
+
return next;
|
|
131
154
|
});
|
|
132
155
|
// Clone edges mapping them to the newly generated node IDs
|
|
133
156
|
const newEdges = rawEdges?.map((edge) => ({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createCanvasExplosion.svelte.d.ts","sourceRoot":"","sources":["../../src/canvas/createCanvasExplosion.svelte.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AACvD,OAAO,KAAK,EACX,UAAU,EACV,UAAU,EACV,mBAAmB,EACnB,kBAAkB,EAClB,iBAAiB,EAEjB,MAAM,YAAY,CAAC;AAYpB,MAAM,WAAW,iBAAiB,CACjC,KAAK,SAAS,UAAU,GAAG,UAAU,EACrC,KAAK,SAAS,UAAU,GAAG,UAAU;IAErC,KAAK,EAAE,KAAK,EAAE,CAAC;IACf,KAAK,EAAE,KAAK,EAAE,CAAC;IACf,QAAQ,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,eAAe,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;IAC9D,QAAQ,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,eAAe,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;IAC9D,cAAc,EAAE,CAAC,KAAK,EAAE,KAAK,GAAG,KAAK,EAAE,EAAE,WAAW,CAAC,EAAE,UAAU,EAAE,IAAI,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;IAC3F,QAAQ,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,IAAI,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;IACnD,WAAW,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,IAAI,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;IACtD,WAAW,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,IAAI,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;IACtD,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,KAAK,KAAK,CAAC;IAC1E,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;CACpB;AAED,MAAM,WAAW,4BAA4B,CAAC,KAAK,SAAS,UAAU,GAAG,UAAU;IAClF,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,IAAI,CAAC;IAC1C,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;CACpB;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CACpC,KAAK,SAAS,UAAU,GAAG,UAAU,EACrC,KAAK,SAAS,UAAU,GAAG,UAAU,EAErC,KAAK,EAAE,iBAAiB,CAAC,KAAK,EAAE,KAAK,CAAC,EACtC,OAAO,GAAE,4BAA4B,CAAC,KAAK,CAAM;;
|
|
1
|
+
{"version":3,"file":"createCanvasExplosion.svelte.d.ts","sourceRoot":"","sources":["../../src/canvas/createCanvasExplosion.svelte.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AACvD,OAAO,KAAK,EACX,UAAU,EACV,UAAU,EACV,mBAAmB,EACnB,kBAAkB,EAClB,iBAAiB,EAEjB,MAAM,YAAY,CAAC;AAYpB,MAAM,WAAW,iBAAiB,CACjC,KAAK,SAAS,UAAU,GAAG,UAAU,EACrC,KAAK,SAAS,UAAU,GAAG,UAAU;IAErC,KAAK,EAAE,KAAK,EAAE,CAAC;IACf,KAAK,EAAE,KAAK,EAAE,CAAC;IACf,QAAQ,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,eAAe,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;IAC9D,QAAQ,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,eAAe,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;IAC9D,cAAc,EAAE,CAAC,KAAK,EAAE,KAAK,GAAG,KAAK,EAAE,EAAE,WAAW,CAAC,EAAE,UAAU,EAAE,IAAI,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;IAC3F,QAAQ,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,IAAI,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;IACnD,WAAW,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,IAAI,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;IACtD,WAAW,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,IAAI,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;IACtD,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,KAAK,KAAK,CAAC;IAC1E,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;CACpB;AAED,MAAM,WAAW,4BAA4B,CAAC,KAAK,SAAS,UAAU,GAAG,UAAU;IAClF,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,IAAI,CAAC;IAC1C,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;CACpB;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CACpC,KAAK,SAAS,UAAU,GAAG,UAAU,EACrC,KAAK,SAAS,UAAU,GAAG,UAAU,EAErC,KAAK,EAAE,iBAAiB,CAAC,KAAK,EAAE,KAAK,CAAC,EACtC,OAAO,GAAE,4BAA4B,CAAC,KAAK,CAAM;;yBA2BrB,MAAM,KAAG,OAAO;4BAKjC,MAAM,kBACA,kBAAkB,CAAC,KAAK,EAAE,KAAK,CAAC,KAC9C,OAAO;6BAiOC,MAAM,oBACC,mBAAmB,KAClC,OAAO;8BAyHC,MAAM,kBACA,kBAAkB,CAAC,KAAK,EAAE,KAAK,CAAC,oBAC9B,mBAAmB,KACnC,OAAO;4BAOqB,MAAM;EAcrC"}
|
|
@@ -9,6 +9,29 @@ export function createCanvasExplosion(graph, options = {}) {
|
|
|
9
9
|
let explodedNodeIds = $state([]);
|
|
10
10
|
const snapshots = new Map();
|
|
11
11
|
let activeAnimationCancel = null;
|
|
12
|
+
/**
|
|
13
|
+
* Applies one animation frame (node copies emitted by runMultiNodeTransition) onto the
|
|
14
|
+
* graph's live node objects and publishes the new node array.
|
|
15
|
+
*/
|
|
16
|
+
function syncTransitionFrame(byId) {
|
|
17
|
+
for (const graphNode of graph.nodes) {
|
|
18
|
+
const frameNode = byId.get(graphNode.id);
|
|
19
|
+
if (!frameNode || frameNode === graphNode)
|
|
20
|
+
continue;
|
|
21
|
+
graphNode.position = { ...frameNode.position };
|
|
22
|
+
graphNode.style = frameNode.style;
|
|
23
|
+
const frameData = frameNode.data;
|
|
24
|
+
if (frameData && ('scale' in frameData || 'opacity' in frameData)) {
|
|
25
|
+
const data = { ...(graphNode.data ?? {}) };
|
|
26
|
+
if ('scale' in frameData)
|
|
27
|
+
data.scale = frameData.scale;
|
|
28
|
+
if ('opacity' in frameData)
|
|
29
|
+
data.opacity = frameData.opacity;
|
|
30
|
+
graphNode.data = data;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
graph.setNodes([...graph.nodes]);
|
|
34
|
+
}
|
|
12
35
|
function isExploded(nodeId) {
|
|
13
36
|
return explodedNodeIds.includes(nodeId);
|
|
14
37
|
}
|
|
@@ -156,13 +179,15 @@ export function createCanvasExplosion(graph, options = {}) {
|
|
|
156
179
|
activeAnimationCancel = runMultiNodeTransition(transitions, {
|
|
157
180
|
defaultDuration: duration,
|
|
158
181
|
defaultEasing: easing,
|
|
159
|
-
onUpdate: () => {
|
|
182
|
+
onUpdate: (updated) => {
|
|
183
|
+
// runMultiNodeTransition never mutates inputs; it hands us per-frame copies.
|
|
184
|
+
const byId = new Map(updated.map((n) => [n.id, n]));
|
|
160
185
|
if (edgesToAdd.length > 0) {
|
|
161
186
|
const childIdSet = new Set(childNodes.map((c) => c.id));
|
|
162
187
|
const childEdgesInGraph = graph.edges.filter((e) => childIdSet.has(e.target));
|
|
163
188
|
if (childEdgesInGraph.length > 0) {
|
|
164
189
|
childEdgesInGraph.forEach((edge) => {
|
|
165
|
-
const child =
|
|
190
|
+
const child = byId.get(edge.target);
|
|
166
191
|
const childOpacity = child?.data?.opacity ?? 1;
|
|
167
192
|
const currentStyle = (edge.style || '').replace(/opacity:\s*[^;]+;?/g, '').trim();
|
|
168
193
|
edge.style = `${currentStyle ? currentStyle + '; ' : ''}opacity: ${childOpacity};`;
|
|
@@ -170,18 +195,7 @@ export function createCanvasExplosion(graph, options = {}) {
|
|
|
170
195
|
graph.setEdges([...graph.edges]);
|
|
171
196
|
}
|
|
172
197
|
}
|
|
173
|
-
|
|
174
|
-
transitions.forEach((t) => {
|
|
175
|
-
const graphNode = graph.nodes.find((n) => n.id === t.node.id);
|
|
176
|
-
if (graphNode && graphNode !== t.node) {
|
|
177
|
-
graphNode.position = { ...t.node.position };
|
|
178
|
-
graphNode.style = t.node.style;
|
|
179
|
-
if (t.node.data) {
|
|
180
|
-
graphNode.data = { ...graphNode.data, ...t.node.data };
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
});
|
|
184
|
-
graph.setNodes([...graph.nodes]);
|
|
198
|
+
syncTransitionFrame(byId);
|
|
185
199
|
},
|
|
186
200
|
onComplete: () => {
|
|
187
201
|
childNodes.forEach((child, i) => {
|
|
@@ -274,30 +288,21 @@ export function createCanvasExplosion(graph, options = {}) {
|
|
|
274
288
|
activeAnimationCancel = runMultiNodeTransition(transitions, {
|
|
275
289
|
defaultDuration: duration,
|
|
276
290
|
defaultEasing: easing,
|
|
277
|
-
onUpdate: () => {
|
|
291
|
+
onUpdate: (updated) => {
|
|
292
|
+
// runMultiNodeTransition never mutates inputs; it hands us per-frame copies.
|
|
293
|
+
const byId = new Map(updated.map((n) => [n.id, n]));
|
|
278
294
|
const edgeIdSet = new Set(snapshot.childEdgeIds);
|
|
279
295
|
const childEdgesInGraph = graph.edges.filter((e) => edgeIdSet.has(e.id));
|
|
280
296
|
if (childEdgesInGraph.length > 0) {
|
|
281
297
|
childEdgesInGraph.forEach((edge) => {
|
|
282
|
-
const child =
|
|
298
|
+
const child = byId.get(edge.target);
|
|
283
299
|
const childOpacity = child?.data?.opacity ?? 0;
|
|
284
300
|
const currentStyle = (edge.style || '').replace(/opacity:\s*[^;]+;?/g, '').trim();
|
|
285
301
|
edge.style = `${currentStyle ? currentStyle + '; ' : ''}opacity: ${childOpacity};`;
|
|
286
302
|
});
|
|
287
303
|
graph.setEdges([...graph.edges]);
|
|
288
304
|
}
|
|
289
|
-
|
|
290
|
-
transitions.forEach((t) => {
|
|
291
|
-
const graphNode = graph.nodes.find((n) => n.id === t.node.id);
|
|
292
|
-
if (graphNode && graphNode !== t.node) {
|
|
293
|
-
graphNode.position = { ...t.node.position };
|
|
294
|
-
graphNode.style = t.node.style;
|
|
295
|
-
if (t.node.data) {
|
|
296
|
-
graphNode.data = { ...graphNode.data, ...t.node.data };
|
|
297
|
-
}
|
|
298
|
-
}
|
|
299
|
-
});
|
|
300
|
-
graph.setNodes([...graph.nodes]);
|
|
305
|
+
syncTransitionFrame(byId);
|
|
301
306
|
},
|
|
302
307
|
onComplete: () => {
|
|
303
308
|
// Animation completed: prune child nodes and edges
|
|
@@ -19,13 +19,17 @@ export declare function createFanOutTrajectory(options?: FanOutTrajectoryOptions
|
|
|
19
19
|
*/
|
|
20
20
|
export declare function createBezierTrajectory(getControlPoint: (origin: XYPosition, target: XYPosition) => XYPosition): TrajectoryFunction;
|
|
21
21
|
/**
|
|
22
|
-
* Coordinates and animates multiple node transitions simultaneously
|
|
23
|
-
*
|
|
22
|
+
* Coordinates and animates multiple node transitions simultaneously.
|
|
23
|
+
*
|
|
24
|
+
* Input nodes are never mutated: every frame produces updated copies (position,
|
|
25
|
+
* `data.scale` / `data.opacity`, `style` opacity) which are passed to `onUpdate`
|
|
26
|
+
* (and finally `onComplete`) in the same order as `transitions`. Both CSS-string and
|
|
27
|
+
* object styles are supported. Merge the copies into your graph state by `id`.
|
|
24
28
|
*/
|
|
25
29
|
export declare function runMultiNodeTransition<TNode extends CanvasNode = CanvasNode>(transitions: NodeTransition<TNode>[], options?: {
|
|
26
30
|
defaultDuration?: number;
|
|
27
31
|
defaultEasing?: (t: number) => number;
|
|
28
|
-
onUpdate?: () => void;
|
|
29
|
-
onComplete?: () => void;
|
|
32
|
+
onUpdate?: (nodes: TNode[]) => void;
|
|
33
|
+
onComplete?: (nodes: TNode[]) => void;
|
|
30
34
|
}): () => void;
|
|
31
35
|
//# sourceMappingURL=createCanvasTrajectory.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createCanvasTrajectory.d.ts","sourceRoot":"","sources":["../../src/canvas/createCanvasTrajectory.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"createCanvasTrajectory.d.ts","sourceRoot":"","sources":["../../src/canvas/createCanvasTrajectory.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,KAAK,EACX,UAAU,EACV,uBAAuB,EACvB,cAAc,EACd,kBAAkB,EAElB,MAAM,YAAY,CAAC;AAEpB;;GAEG;AACH,eAAO,MAAM,gBAAgB,EAAE,kBAa9B,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,wBAAwB,EAAE,kBAWtC,CAAC;AAEF;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,GAAE,uBAA4B,GAAG,kBAAkB,CA0ChG;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CACrC,eAAe,EAAE,CAAC,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,UAAU,KAAK,UAAU,GACrE,kBAAkB,CAepB;AAED;;;;;;;GAOG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,SAAS,UAAU,GAAG,UAAU,EAC3E,WAAW,EAAE,cAAc,CAAC,KAAK,CAAC,EAAE,EACpC,OAAO,GAAE;IACR,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,aAAa,CAAC,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,CAAC;IACtC,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,IAAI,CAAC;IACpC,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,IAAI,CAAC;CACjC,GACJ,MAAM,IAAI,CAiFZ"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { cubicOut } from 'svelte/easing';
|
|
2
|
+
import { withStyleOpacity } from '@pixerate/editor/canvas';
|
|
2
3
|
/**
|
|
3
4
|
* Standard linear trajectory: straight line interpolation with linear scale & opacity progression.
|
|
4
5
|
*/
|
|
@@ -70,12 +71,16 @@ export function createBezierTrajectory(getControlPoint) {
|
|
|
70
71
|
};
|
|
71
72
|
}
|
|
72
73
|
/**
|
|
73
|
-
* Coordinates and animates multiple node transitions simultaneously
|
|
74
|
-
*
|
|
74
|
+
* Coordinates and animates multiple node transitions simultaneously.
|
|
75
|
+
*
|
|
76
|
+
* Input nodes are never mutated: every frame produces updated copies (position,
|
|
77
|
+
* `data.scale` / `data.opacity`, `style` opacity) which are passed to `onUpdate`
|
|
78
|
+
* (and finally `onComplete`) in the same order as `transitions`. Both CSS-string and
|
|
79
|
+
* object styles are supported. Merge the copies into your graph state by `id`.
|
|
75
80
|
*/
|
|
76
81
|
export function runMultiNodeTransition(transitions, options = {}) {
|
|
77
82
|
if (transitions.length === 0) {
|
|
78
|
-
options.onComplete?.();
|
|
83
|
+
options.onComplete?.([]);
|
|
79
84
|
return () => { };
|
|
80
85
|
}
|
|
81
86
|
const { defaultDuration = 400, defaultEasing = cubicOut, onUpdate, onComplete } = options;
|
|
@@ -90,6 +95,8 @@ export function runMultiNodeTransition(transitions, options = {}) {
|
|
|
90
95
|
delay: tr.delay ?? 0,
|
|
91
96
|
trajectory: tr.trajectory ?? linearTrajectory
|
|
92
97
|
}));
|
|
98
|
+
// Latest copy of every node; starts out as the untouched inputs.
|
|
99
|
+
const current = items.map((item) => item.node);
|
|
93
100
|
function frame() {
|
|
94
101
|
if (isCancelled)
|
|
95
102
|
return;
|
|
@@ -105,33 +112,31 @@ export function runMultiNodeTransition(transitions, options = {}) {
|
|
|
105
112
|
const rawProgress = item.duration <= 0 ? 1 : Math.min(elapsed / item.duration, 1);
|
|
106
113
|
const progress = item.duration <= 0 ? 1 : item.easing(rawProgress);
|
|
107
114
|
const point = item.trajectory(item.from, item.to, progress, item.index, item.total);
|
|
108
|
-
|
|
109
|
-
item.node.position = { ...point.position };
|
|
115
|
+
const next = { ...item.node, position: { ...point.position } };
|
|
110
116
|
if (point.scale !== undefined || point.opacity !== undefined) {
|
|
111
|
-
|
|
112
|
-
item.node.data = {};
|
|
113
|
-
}
|
|
117
|
+
const data = { ...(item.node.data ?? {}) };
|
|
114
118
|
if (point.scale !== undefined) {
|
|
115
|
-
|
|
119
|
+
data.scale = point.scale;
|
|
116
120
|
}
|
|
117
121
|
if (point.opacity !== undefined) {
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
item.node.style = `${currentStyle ? currentStyle + '; ' : ''}opacity: ${point.opacity};`;
|
|
122
|
+
data.opacity = point.opacity;
|
|
123
|
+
next.style = withStyleOpacity(item.node.style, point.opacity);
|
|
121
124
|
}
|
|
125
|
+
next.data = data;
|
|
122
126
|
}
|
|
127
|
+
current[i] = next;
|
|
123
128
|
if (rawProgress < 1) {
|
|
124
129
|
allCompleted = false;
|
|
125
130
|
}
|
|
126
131
|
}
|
|
127
|
-
onUpdate?.();
|
|
132
|
+
onUpdate?.(current.slice());
|
|
128
133
|
if (!allCompleted) {
|
|
129
134
|
if (typeof requestAnimationFrame !== 'undefined') {
|
|
130
135
|
requestAnimationFrame(frame);
|
|
131
136
|
}
|
|
132
137
|
}
|
|
133
138
|
else {
|
|
134
|
-
onComplete?.();
|
|
139
|
+
onComplete?.(current.slice());
|
|
135
140
|
}
|
|
136
141
|
}
|
|
137
142
|
frame();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pixerate/editor-svelte",
|
|
3
|
-
"version": "0.17.
|
|
3
|
+
"version": "0.17.5",
|
|
4
4
|
"description": "Svelte bindings and prompt/rich-text components for @pixerate/editor",
|
|
5
5
|
"author": "Pixerate",
|
|
6
6
|
"license": "MIT",
|
|
@@ -52,7 +52,7 @@
|
|
|
52
52
|
"@tiptap/extension-bubble-menu": "^2.11.5",
|
|
53
53
|
"@tiptap/extension-placeholder": "^2.11.5",
|
|
54
54
|
"@tiptap/starter-kit": "^2.11.5",
|
|
55
|
-
"@pixerate/editor": "0.
|
|
55
|
+
"@pixerate/editor": "0.18.0"
|
|
56
56
|
},
|
|
57
57
|
"peerDependencies": {
|
|
58
58
|
"@tiptap/core": "^2.11.5",
|