@pixodesk/svg-animator-web 1.0.10 → 1.0.16
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/index.cjs +3694 -691
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +4928 -198
- package/dist/index.d.ts +4928 -198
- package/dist/index.js +3638 -687
- package/dist/index.js.map +1 -1
- package/dist/index.min.cjs +1 -1
- package/dist/index.min.js +1 -1
- package/dist/index.umd.js +3641 -690
- package/dist/index.umd.js.map +1 -1
- package/dist/index.umd.min.js +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -30,281 +30,1070 @@ var __objRest = (source, exclude) => {
|
|
|
30
30
|
return target;
|
|
31
31
|
};
|
|
32
32
|
|
|
33
|
-
// src/
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
"
|
|
44
|
-
"
|
|
45
|
-
"
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
if (!(fileJson && typeof fileJson === "object" && !Array.isArray(fileJson))) {
|
|
52
|
-
return false;
|
|
33
|
+
// src/effects/transformParts.ts
|
|
34
|
+
function partsRecord(part, value, origin) {
|
|
35
|
+
const rec = {};
|
|
36
|
+
if (part === "translate" /* Translate */) rec.translate = value;
|
|
37
|
+
else if (part === "rotate" /* Rotate */) rec.rotate = value;
|
|
38
|
+
else rec.scale = value;
|
|
39
|
+
if (origin && part !== "translate" /* Translate */) rec.origin = origin;
|
|
40
|
+
return rec;
|
|
41
|
+
}
|
|
42
|
+
function readAnimatable(raw) {
|
|
43
|
+
if (raw === void 0) return { kind: "absent" /* Absent */ };
|
|
44
|
+
if (Array.isArray(raw)) return { kind: "static" /* Static */, value: raw };
|
|
45
|
+
if (typeof raw === "object") {
|
|
46
|
+
const obj = raw;
|
|
47
|
+
if (obj.keyframes) {
|
|
48
|
+
return { kind: "animated" /* Animated */, keyframes: obj.keyframes, autoOrient: obj.autoOrient };
|
|
49
|
+
}
|
|
50
|
+
if (obj.value !== void 0) return { kind: "static" /* Static */, value: obj.value };
|
|
53
51
|
}
|
|
54
|
-
return
|
|
52
|
+
return { kind: "static" /* Static */, value: raw };
|
|
55
53
|
}
|
|
56
|
-
function
|
|
57
|
-
|
|
54
|
+
function readStaticOrigin(raw, ctx) {
|
|
55
|
+
var _a;
|
|
56
|
+
const o = readAnimatable(raw);
|
|
57
|
+
if (o.kind === "absent" /* Absent */) return void 0;
|
|
58
|
+
if (o.kind === "static" /* Static */) return o.value;
|
|
59
|
+
ctx.warnings.push("transformation.origin: animated origin approximated by its first keyframe");
|
|
60
|
+
return (_a = o.keyframes[0]) == null ? void 0 : _a.value;
|
|
58
61
|
}
|
|
59
|
-
function
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
62
|
+
function keyframeWith(kf, value) {
|
|
63
|
+
const out = { value };
|
|
64
|
+
if (kf.time !== void 0) out.time = kf.time;
|
|
65
|
+
if (kf.easing !== void 0) out.easing = kf.easing;
|
|
66
|
+
if (kf.tangentOut !== void 0) out.tangentOut = kf.tangentOut;
|
|
67
|
+
if (kf.tangentIn !== void 0) out.tangentIn = kf.tangentIn;
|
|
68
|
+
return out;
|
|
63
69
|
}
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
return
|
|
70
|
+
|
|
71
|
+
// src/effects/transformationEffect.ts
|
|
72
|
+
function applyTransformationEffect(node, fx, ctx) {
|
|
73
|
+
if (!fx) return node;
|
|
74
|
+
delete node.transform;
|
|
75
|
+
let n = node;
|
|
76
|
+
n = wrapTransformPart(n, "skew" /* Skew */, fx.skew, ctx);
|
|
77
|
+
n = wrapOrigin(
|
|
78
|
+
n,
|
|
79
|
+
fx.origin,
|
|
80
|
+
/*invert=*/
|
|
81
|
+
true
|
|
82
|
+
);
|
|
83
|
+
n = wrapTransformPart(n, "scale" /* Scale */, normalizeScale(fx.scale), ctx);
|
|
84
|
+
n = wrapTransformPart(n, "rotate" /* Rotate */, fx.rotate, ctx);
|
|
85
|
+
n = wrapOrigin(
|
|
86
|
+
n,
|
|
87
|
+
fx.origin,
|
|
88
|
+
/*invert=*/
|
|
89
|
+
false
|
|
90
|
+
);
|
|
91
|
+
if (translateHasAutoOrient(fx.translate)) {
|
|
92
|
+
n = wrapOrigin(
|
|
93
|
+
n,
|
|
94
|
+
fx.origin,
|
|
95
|
+
/*invert=*/
|
|
96
|
+
true
|
|
97
|
+
);
|
|
98
|
+
n = wrapTransformPart(n, "translate" /* Translate */, fx.translate, ctx);
|
|
99
|
+
n = wrapOrigin(
|
|
100
|
+
n,
|
|
101
|
+
fx.origin,
|
|
102
|
+
/*invert=*/
|
|
103
|
+
false
|
|
104
|
+
);
|
|
105
|
+
} else {
|
|
106
|
+
n = wrapTransformPart(n, "translate" /* Translate */, fx.translate, ctx);
|
|
107
|
+
}
|
|
108
|
+
return n;
|
|
68
109
|
}
|
|
69
|
-
function
|
|
70
|
-
if (typeof
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
return
|
|
110
|
+
function translateHasAutoOrient(translate) {
|
|
111
|
+
if (!translate || typeof translate !== "object") return false;
|
|
112
|
+
const obj = translate;
|
|
113
|
+
if (obj.autoOrient) return true;
|
|
114
|
+
return Array.isArray(obj.keyframes) && obj.keyframes.some((kf) => kf.tangentOut || kf.tangentIn);
|
|
74
115
|
}
|
|
75
|
-
function
|
|
76
|
-
if (
|
|
77
|
-
|
|
78
|
-
|
|
116
|
+
function normalizeScale(raw) {
|
|
117
|
+
if (raw === void 0) return void 0;
|
|
118
|
+
if (Array.isArray(raw)) return [raw[0] / 100, raw[1] / 100];
|
|
119
|
+
return raw;
|
|
120
|
+
}
|
|
121
|
+
function wrapTransformPart(inner, part, raw, ctx) {
|
|
122
|
+
if (raw === void 0) return inner;
|
|
123
|
+
if (part === "skew" /* Skew */) {
|
|
124
|
+
const skew = readAnimatable(raw);
|
|
125
|
+
if (skew.kind !== "static" /* Static */) {
|
|
126
|
+
ctx.warnings.push("transformation.skew: only static skew is supported");
|
|
127
|
+
return inner;
|
|
128
|
+
}
|
|
129
|
+
return { type: "g", transform: "skewX(" + skew.value[0] + ")skewY(" + skew.value[1] + ")", children: [inner] };
|
|
79
130
|
}
|
|
80
|
-
|
|
81
|
-
if (v.
|
|
82
|
-
|
|
83
|
-
valid = false;
|
|
131
|
+
const v = readAnimatable(raw);
|
|
132
|
+
if (v.kind === "static" /* Static */) {
|
|
133
|
+
return { type: "g", transform: { value: partsRecord(part, v.value, void 0) }, children: [inner] };
|
|
84
134
|
}
|
|
85
|
-
if (v.
|
|
86
|
-
|
|
87
|
-
|
|
135
|
+
if (v.kind === "animated" /* Animated */) {
|
|
136
|
+
const animTr = { keyframes: v.keyframes.map((kf) => keyframeWith(kf, partsRecord(part, kf.value, void 0))) };
|
|
137
|
+
if (v.autoOrient) animTr.autoOrient = true;
|
|
138
|
+
return {
|
|
139
|
+
type: "g",
|
|
140
|
+
animate: { transform: animTr },
|
|
141
|
+
children: [inner]
|
|
142
|
+
};
|
|
88
143
|
}
|
|
89
|
-
|
|
90
|
-
if (v.e !== void 0 && !validatePxEasingOrRef(v.e, path + ".e", errors)) valid = false;
|
|
91
|
-
return valid;
|
|
144
|
+
return inner;
|
|
92
145
|
}
|
|
93
|
-
function
|
|
94
|
-
if (
|
|
95
|
-
|
|
96
|
-
|
|
146
|
+
function wrapOrigin(inner, raw, invert) {
|
|
147
|
+
if (raw === void 0) return inner;
|
|
148
|
+
const v = readAnimatable(raw);
|
|
149
|
+
const sign = (value) => invert ? [-value[0], -value[1]] : value;
|
|
150
|
+
if (v.kind === "absent" /* Absent */) return inner;
|
|
151
|
+
if (v.kind === "static" /* Static */) {
|
|
152
|
+
if (v.value[0] === 0 && v.value[1] === 0) return inner;
|
|
153
|
+
return { type: "g", transform: { value: { translate: sign(v.value) } }, children: [inner] };
|
|
97
154
|
}
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
155
|
+
if (v.kind === "animated" /* Animated */) {
|
|
156
|
+
return {
|
|
157
|
+
type: "g",
|
|
158
|
+
animate: { transform: { keyframes: v.keyframes.map((kf) => keyframeWith(kf, { translate: sign(kf.value) })) } },
|
|
159
|
+
children: [inner]
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
return inner;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
// src/effects/contentRefSplit.ts
|
|
166
|
+
function identifyContentRefTargets(node, ctx, allocator) {
|
|
167
|
+
var _a, _b, _c;
|
|
168
|
+
if (node.type === "use" && ((_b = (_a = node.effects) == null ? void 0 : _a.ref) == null ? void 0 : _b.type) === "content") {
|
|
169
|
+
const baseId = node.effects.ref.baseId;
|
|
170
|
+
if (typeof baseId === "string" && baseId && !ctx.contentRefInnerIds.has(baseId)) {
|
|
171
|
+
ctx.contentRefInnerIds.set(baseId, allocator(baseId));
|
|
107
172
|
}
|
|
108
173
|
}
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
174
|
+
(_c = node.children) == null ? void 0 : _c.forEach((c) => identifyContentRefTargets(c, ctx, allocator));
|
|
175
|
+
}
|
|
176
|
+
function splitForContentRef(node, transformation, originalId, innerId, ctx) {
|
|
177
|
+
const outerBody = liftBodyTranslate(node, transformation);
|
|
178
|
+
if (typeof node.id === "string") delete node.id;
|
|
179
|
+
const { outer: outerTr, inner: innerTr } = splitTransformationEffect(transformation);
|
|
180
|
+
let innerNode = node;
|
|
181
|
+
innerNode = applyTransformationEffect(innerNode, innerTr, ctx);
|
|
182
|
+
const innerWrapper = { type: "g", id: innerId, children: [innerNode] };
|
|
183
|
+
let outerWrapper = { type: "g", id: originalId, children: [innerWrapper] };
|
|
184
|
+
if (outerBody.transform !== void 0) outerWrapper.transform = outerBody.transform;
|
|
185
|
+
if (outerBody.animate !== void 0) outerWrapper.animate = outerBody.animate;
|
|
186
|
+
if (outerTr) {
|
|
187
|
+
delete outerWrapper.id;
|
|
188
|
+
outerWrapper = applyTransformationEffect(outerWrapper, outerTr, ctx);
|
|
189
|
+
outerWrapper.id = originalId;
|
|
190
|
+
}
|
|
191
|
+
return outerWrapper;
|
|
192
|
+
}
|
|
193
|
+
function liftBodyTranslate(node, transformation) {
|
|
194
|
+
var _a, _b, _c;
|
|
195
|
+
const out = {};
|
|
196
|
+
let didLiftAnimate = false;
|
|
197
|
+
const animTr = (_a = node.animate) == null ? void 0 : _a.transform;
|
|
198
|
+
if (animTr && typeof animTr === "object" && Array.isArray(animTr.keyframes)) {
|
|
199
|
+
const kfs = animTr.keyframes;
|
|
200
|
+
const hasTranslate = kfs.some((kf) => kf.value && kf.value.translate);
|
|
201
|
+
if (hasTranslate) {
|
|
202
|
+
const outerHasOrigin = needsOriginOnOuter(animTr);
|
|
203
|
+
const outerKfs = kfs.map((kf) => {
|
|
204
|
+
const v = kf.value || {};
|
|
205
|
+
const newValue = {};
|
|
206
|
+
if (v.translate !== void 0) newValue.translate = v.translate;
|
|
207
|
+
if (outerHasOrigin && v.origin !== void 0) newValue.origin = v.origin;
|
|
208
|
+
const outerKf = { value: newValue };
|
|
209
|
+
if (kf.time !== void 0) outerKf.time = kf.time;
|
|
210
|
+
if (kf.easing !== void 0) outerKf.easing = kf.easing;
|
|
211
|
+
if (kf.tangentOut !== void 0) outerKf.tangentOut = kf.tangentOut;
|
|
212
|
+
if (kf.tangentIn !== void 0) outerKf.tangentIn = kf.tangentIn;
|
|
213
|
+
return outerKf;
|
|
214
|
+
});
|
|
215
|
+
const outerAnimTr = { keyframes: outerKfs };
|
|
216
|
+
if (animTr.autoOrient) outerAnimTr.autoOrient = true;
|
|
217
|
+
out.animate = { transform: outerAnimTr };
|
|
218
|
+
const innerHasPivotedPart = kfs.some((kf) => {
|
|
219
|
+
const v = kf.value || {};
|
|
220
|
+
return v.rotate !== void 0 || v.scale !== void 0;
|
|
116
221
|
});
|
|
222
|
+
const innerKfs = kfs.map((kf) => {
|
|
223
|
+
const v = kf.value || {};
|
|
224
|
+
const newValue = {};
|
|
225
|
+
if (v.rotate !== void 0) newValue.rotate = v.rotate;
|
|
226
|
+
if (v.scale !== void 0) newValue.scale = v.scale;
|
|
227
|
+
if (v.origin !== void 0 && (!outerHasOrigin || innerHasPivotedPart)) newValue.origin = v.origin;
|
|
228
|
+
const innerKf = { value: newValue };
|
|
229
|
+
if (kf.time !== void 0) innerKf.time = kf.time;
|
|
230
|
+
if (kf.easing !== void 0) innerKf.easing = kf.easing;
|
|
231
|
+
return innerKf;
|
|
232
|
+
});
|
|
233
|
+
const allInnerEmpty = innerKfs.every((kf) => Object.keys(kf.value).length === 0);
|
|
234
|
+
if (allInnerEmpty) {
|
|
235
|
+
delete node.animate.transform;
|
|
236
|
+
if (node.animate && Object.keys(node.animate).length === 0) delete node.animate;
|
|
237
|
+
} else {
|
|
238
|
+
node.animate.transform = { keyframes: innerKfs };
|
|
239
|
+
}
|
|
240
|
+
didLiftAnimate = true;
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
const transformationHasTranslate = (transformation == null ? void 0 : transformation.translate) !== void 0;
|
|
244
|
+
const stripBodyTranslateOnly = didLiftAnimate || transformationHasTranslate;
|
|
245
|
+
const liftedAnimateIsAutoOriented = didLiftAnimate && needsOriginOnOuter(((_b = node.animate) == null ? void 0 : _b.transform) || void 0) || didLiftAnimate && needsOriginOnOuter(((_c = out.animate) == null ? void 0 : _c.transform) || void 0);
|
|
246
|
+
if (typeof node.transform === "string") {
|
|
247
|
+
const split = splitTransformString(node.transform);
|
|
248
|
+
if (stripBodyTranslateOnly) {
|
|
249
|
+
if (split.translate !== void 0) {
|
|
250
|
+
if (split.rest) node.transform = split.rest;
|
|
251
|
+
else delete node.transform;
|
|
252
|
+
} else if (isPureTranslateBody(node.transform)) {
|
|
253
|
+
delete node.transform;
|
|
254
|
+
} else if (liftedAnimateIsAutoOriented && isSingleMatrixBody(node.transform)) {
|
|
255
|
+
delete node.transform;
|
|
256
|
+
}
|
|
257
|
+
} else if (split.translate) {
|
|
258
|
+
out.transform = split.translate;
|
|
259
|
+
if (split.rest) node.transform = split.rest;
|
|
260
|
+
else delete node.transform;
|
|
117
261
|
}
|
|
118
262
|
}
|
|
119
|
-
return
|
|
263
|
+
return out;
|
|
120
264
|
}
|
|
121
|
-
function
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
265
|
+
function isSingleMatrixBody(s) {
|
|
266
|
+
const re = /(translate|rotate|scale|matrix|skewX|skewY)\(([^)]*)\)/g;
|
|
267
|
+
let count = 0;
|
|
268
|
+
let isMatrix = false;
|
|
269
|
+
let m;
|
|
270
|
+
while (m = re.exec(s)) {
|
|
271
|
+
count++;
|
|
272
|
+
if (m[1] === "matrix") isMatrix = true;
|
|
273
|
+
}
|
|
274
|
+
return count === 1 && isMatrix;
|
|
275
|
+
}
|
|
276
|
+
function isPureTranslateBody(s) {
|
|
277
|
+
const re = /(translate|rotate|scale|matrix|skewX|skewY)\(([^)]*)\)/g;
|
|
278
|
+
const ops = [];
|
|
279
|
+
let m;
|
|
280
|
+
while (m = re.exec(s)) ops.push({ name: m[1], full: m[0] });
|
|
281
|
+
if (ops.length !== 1) return false;
|
|
282
|
+
if (ops[0].name === "translate") return true;
|
|
283
|
+
if (ops[0].name !== "matrix") return false;
|
|
284
|
+
const args = /matrix\(([^)]*)\)/.exec(ops[0].full);
|
|
285
|
+
if (!args) return false;
|
|
286
|
+
const nums = args[1].split(/[\s,]+/).filter(Boolean).map(Number);
|
|
287
|
+
return nums.length >= 4 && nums[0] === 1 && nums[1] === 0 && nums[2] === 0 && nums[3] === 1;
|
|
288
|
+
}
|
|
289
|
+
function splitTransformString(s) {
|
|
290
|
+
const ops = [];
|
|
291
|
+
const re = /(translate|rotate|scale|matrix|skewX|skewY)\(([^)]*)\)/g;
|
|
292
|
+
let m;
|
|
293
|
+
while (m = re.exec(s)) ops.push({ name: m[1], full: m[0] });
|
|
294
|
+
if (!ops.length) return { rest: s || void 0 };
|
|
295
|
+
if (ops.every((o) => o.name === "translate")) {
|
|
296
|
+
return { translate: ops.map((o) => o.full).join("") };
|
|
125
297
|
}
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
298
|
+
const leading = ops[0];
|
|
299
|
+
const trailing = ops[ops.length - 1];
|
|
300
|
+
if (trailing.name === "translate" && leading.name === "translate") {
|
|
301
|
+
const trailingVec = parseTranslateArgs(trailing.full);
|
|
302
|
+
const leadingVec = parseTranslateArgs(leading.full);
|
|
303
|
+
const ox = -trailingVec[0];
|
|
304
|
+
const oy = -trailingVec[1];
|
|
305
|
+
const userTx = leadingVec[0] - ox;
|
|
306
|
+
const userTy = leadingVec[1] - oy;
|
|
307
|
+
if (userTx === 0 && userTy === 0) return { rest: s };
|
|
308
|
+
const middleAndTrailing = "translate(" + ox + "," + oy + ")" + ops.slice(1).map((o) => o.full).join("");
|
|
309
|
+
return { translate: "translate(" + userTx + "," + userTy + ")", rest: middleAndTrailing };
|
|
129
310
|
}
|
|
130
|
-
return
|
|
311
|
+
if (trailing.name === "translate") return { rest: s };
|
|
312
|
+
const lifted = [];
|
|
313
|
+
let i = 0;
|
|
314
|
+
while (i < ops.length && ops[i].name === "translate") {
|
|
315
|
+
lifted.push(ops[i].full);
|
|
316
|
+
i++;
|
|
317
|
+
}
|
|
318
|
+
if (!lifted.length) return { rest: s };
|
|
319
|
+
const rest = ops.slice(i).map((o) => o.full).join("");
|
|
320
|
+
return {
|
|
321
|
+
translate: lifted.join(""),
|
|
322
|
+
rest: rest || void 0
|
|
323
|
+
};
|
|
131
324
|
}
|
|
132
|
-
function
|
|
133
|
-
|
|
134
|
-
if (
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
325
|
+
function parseTranslateArgs(translateOp) {
|
|
326
|
+
const m = /translate\(([^)]*)\)/.exec(translateOp);
|
|
327
|
+
if (!m) return [0, 0];
|
|
328
|
+
const nums = m[1].split(/[\s,]+/).filter(Boolean).map(Number);
|
|
329
|
+
return [nums[0] || 0, nums[1] || 0];
|
|
330
|
+
}
|
|
331
|
+
function splitTransformationEffect(fx) {
|
|
332
|
+
if (!fx) return {};
|
|
333
|
+
const originOnOuter = needsOriginOnOuter(fx.translate);
|
|
334
|
+
const innerHasPivotedPart = fx.rotate !== void 0 || fx.scale !== void 0;
|
|
335
|
+
const outer = {};
|
|
336
|
+
const inner = {};
|
|
337
|
+
if (fx.translate !== void 0) outer.translate = fx.translate;
|
|
338
|
+
if (originOnOuter && fx.origin !== void 0) outer.origin = fx.origin;
|
|
339
|
+
if (fx.rotate !== void 0) inner.rotate = fx.rotate;
|
|
340
|
+
if (fx.scale !== void 0) inner.scale = fx.scale;
|
|
341
|
+
if (fx.skew !== void 0) inner.skew = fx.skew;
|
|
342
|
+
if (fx.origin !== void 0 && (!originOnOuter || innerHasPivotedPart)) inner.origin = fx.origin;
|
|
343
|
+
return {
|
|
344
|
+
outer: Object.keys(outer).length ? outer : void 0,
|
|
345
|
+
inner: Object.keys(inner).length ? inner : void 0
|
|
346
|
+
};
|
|
347
|
+
}
|
|
348
|
+
function needsOriginOnOuter(translateAnim) {
|
|
349
|
+
if (!translateAnim || typeof translateAnim !== "object") return false;
|
|
350
|
+
const obj = translateAnim;
|
|
351
|
+
if (obj.autoOrient) return true;
|
|
352
|
+
if (Array.isArray(obj.keyframes)) {
|
|
353
|
+
return obj.keyframes.some((kf) => kf.tangentOut || kf.tangentIn);
|
|
142
354
|
}
|
|
143
|
-
if (isObject(v)) return validatePxAnimationDefinition(v, path, errors);
|
|
144
|
-
errors.push(path + ": expected string, array, or PxAnimationDefinition object");
|
|
145
355
|
return false;
|
|
146
356
|
}
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
357
|
+
|
|
358
|
+
// src/PxSchema.ts
|
|
359
|
+
function pathStr(path) {
|
|
360
|
+
if (!path.length) return ".";
|
|
361
|
+
let result = "";
|
|
362
|
+
for (const seg of path) {
|
|
363
|
+
if (seg.startsWith("[")) result += seg;
|
|
364
|
+
else result += (result ? "." : "") + seg;
|
|
365
|
+
}
|
|
366
|
+
return result;
|
|
367
|
+
}
|
|
368
|
+
var Base = class {
|
|
369
|
+
_canSanitize(raw) {
|
|
370
|
+
return this.isValid(raw);
|
|
371
|
+
}
|
|
372
|
+
optional() {
|
|
373
|
+
return new Optional(this);
|
|
374
|
+
}
|
|
375
|
+
};
|
|
376
|
+
var Optional = class extends Base {
|
|
377
|
+
constructor(inner) {
|
|
378
|
+
super();
|
|
379
|
+
this.inner = inner;
|
|
380
|
+
this._default = void 0;
|
|
381
|
+
}
|
|
382
|
+
sanitize(raw) {
|
|
383
|
+
if (raw === void 0 || raw === null) return void 0;
|
|
384
|
+
return this.inner._canSanitize(raw) ? this.inner.sanitize(raw) : void 0;
|
|
385
|
+
}
|
|
386
|
+
isValid(raw, ctx, path) {
|
|
387
|
+
if (raw === void 0 || raw === null) return true;
|
|
388
|
+
return this.inner.isValid(raw, ctx, path);
|
|
389
|
+
}
|
|
390
|
+
_canSanitize(raw) {
|
|
391
|
+
return raw === void 0 || raw === null || this.inner._canSanitize(raw);
|
|
392
|
+
}
|
|
393
|
+
};
|
|
394
|
+
var Str = class extends Base {
|
|
395
|
+
constructor(_default = "") {
|
|
396
|
+
super();
|
|
397
|
+
this._default = _default;
|
|
398
|
+
}
|
|
399
|
+
sanitize(raw) {
|
|
400
|
+
return typeof raw === "string" ? raw : this._default;
|
|
401
|
+
}
|
|
402
|
+
isValid(raw, ctx, path) {
|
|
403
|
+
if (typeof raw === "string") return true;
|
|
404
|
+
ctx == null ? void 0 : ctx.errors.push(pathStr(path != null ? path : []) + ": expected string, got " + typeof raw);
|
|
150
405
|
return false;
|
|
151
406
|
}
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
407
|
+
};
|
|
408
|
+
var Num = class extends Base {
|
|
409
|
+
constructor(_default = 0) {
|
|
410
|
+
super();
|
|
411
|
+
this._default = _default;
|
|
412
|
+
}
|
|
413
|
+
sanitize(raw) {
|
|
414
|
+
return typeof raw === "number" && isFinite(raw) ? raw : this._default;
|
|
157
415
|
}
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
416
|
+
isValid(raw, ctx, path) {
|
|
417
|
+
if (typeof raw === "number" && isFinite(raw)) return true;
|
|
418
|
+
ctx == null ? void 0 : ctx.errors.push(pathStr(path != null ? path : []) + ": expected finite number, got " + JSON.stringify(raw));
|
|
419
|
+
return false;
|
|
420
|
+
}
|
|
421
|
+
};
|
|
422
|
+
var Bool = class extends Base {
|
|
423
|
+
constructor(_default = false) {
|
|
424
|
+
super();
|
|
425
|
+
this._default = _default;
|
|
164
426
|
}
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
valid = false;
|
|
427
|
+
sanitize(raw) {
|
|
428
|
+
return typeof raw === "boolean" ? raw : this._default;
|
|
168
429
|
}
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
if (!isObject(v)) {
|
|
173
|
-
errors.push(path + ": expected object");
|
|
430
|
+
isValid(raw, ctx, path) {
|
|
431
|
+
if (typeof raw === "boolean") return true;
|
|
432
|
+
ctx == null ? void 0 : ctx.errors.push(pathStr(path != null ? path : []) + ": expected boolean, got " + typeof raw);
|
|
174
433
|
return false;
|
|
175
434
|
}
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
435
|
+
};
|
|
436
|
+
var Literal = class extends Base {
|
|
437
|
+
constructor(value) {
|
|
438
|
+
super();
|
|
439
|
+
this.value = value;
|
|
440
|
+
this._default = value;
|
|
180
441
|
}
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
valid = false;
|
|
442
|
+
sanitize(raw) {
|
|
443
|
+
return raw === this.value ? this.value : this._default;
|
|
184
444
|
}
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
445
|
+
isValid(raw, ctx, path) {
|
|
446
|
+
if (raw === this.value) return true;
|
|
447
|
+
ctx == null ? void 0 : ctx.errors.push(pathStr(path != null ? path : []) + ": expected " + JSON.stringify(this.value) + ", got " + JSON.stringify(raw));
|
|
448
|
+
return false;
|
|
188
449
|
}
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
450
|
+
};
|
|
451
|
+
var Enum = class extends Base {
|
|
452
|
+
constructor(values, defaultVal) {
|
|
453
|
+
super();
|
|
454
|
+
this.values = values;
|
|
455
|
+
this._default = defaultVal != null ? defaultVal : values[0];
|
|
192
456
|
}
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
if (v.frameRate !== void 0 && typeof v.frameRate !== "number") {
|
|
196
|
-
errors.push(path + ".frameRate: expected number, got " + typeof v.frameRate);
|
|
197
|
-
valid = false;
|
|
457
|
+
sanitize(raw) {
|
|
458
|
+
return this.values.includes(raw) ? raw : this._default;
|
|
198
459
|
}
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
function validatePxDefs(v, path, errors) {
|
|
203
|
-
if (!isObject(v)) {
|
|
204
|
-
errors.push(path + ": expected object");
|
|
460
|
+
isValid(raw, ctx, path) {
|
|
461
|
+
if (this.values.includes(raw)) return true;
|
|
462
|
+
ctx == null ? void 0 : ctx.errors.push(pathStr(path != null ? path : []) + ": expected one of " + this.values.map((v) => JSON.stringify(v)).join(" | ") + ", got " + JSON.stringify(raw));
|
|
205
463
|
return false;
|
|
206
464
|
}
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
465
|
+
};
|
|
466
|
+
var Union = class extends Base {
|
|
467
|
+
constructor(schemas, defaultVal) {
|
|
468
|
+
super();
|
|
469
|
+
this.schemas = schemas;
|
|
470
|
+
this._default = defaultVal != null ? defaultVal : schemas[0]._default;
|
|
471
|
+
}
|
|
472
|
+
sanitize(raw) {
|
|
473
|
+
for (const s of this.schemas) {
|
|
474
|
+
if (s.isValid(raw)) return s.sanitize(raw);
|
|
475
|
+
}
|
|
476
|
+
return this._default;
|
|
477
|
+
}
|
|
478
|
+
isValid(raw, ctx, path) {
|
|
479
|
+
var _a;
|
|
480
|
+
if (this.schemas.some((s) => s.isValid(raw))) return true;
|
|
481
|
+
ctx == null ? void 0 : ctx.errors.push(pathStr(path != null ? path : []) + ": no union member matched for value " + ((_a = JSON.stringify(raw)) != null ? _a : "").slice(0, 60));
|
|
482
|
+
return false;
|
|
483
|
+
}
|
|
484
|
+
_canSanitize(raw) {
|
|
485
|
+
return this.schemas.some((s) => s._canSanitize(raw));
|
|
486
|
+
}
|
|
487
|
+
};
|
|
488
|
+
var DiscriminatedUnion = class extends Base {
|
|
489
|
+
constructor(_key, _schemas, defaultVal) {
|
|
490
|
+
super();
|
|
491
|
+
this._key = _key;
|
|
492
|
+
this._schemas = _schemas;
|
|
493
|
+
this._default = defaultVal != null ? defaultVal : _schemas[0]._default;
|
|
494
|
+
this._map = /* @__PURE__ */ new Map();
|
|
495
|
+
for (const s of _schemas) {
|
|
496
|
+
const keySchema = s._shape[_key];
|
|
497
|
+
if (keySchema) this._map.set(keySchema._default, s);
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
_findSchema(raw) {
|
|
501
|
+
if (raw === null || typeof raw !== "object" || Array.isArray(raw)) return void 0;
|
|
502
|
+
const val = raw[this._key];
|
|
503
|
+
if (val === void 0 || val === null) return void 0;
|
|
504
|
+
return this._map.get(val);
|
|
505
|
+
}
|
|
506
|
+
sanitize(raw) {
|
|
507
|
+
var _a;
|
|
508
|
+
return ((_a = this._findSchema(raw)) != null ? _a : this._schemas[0]).sanitize(raw);
|
|
509
|
+
}
|
|
510
|
+
isValid(raw, ctx, path) {
|
|
511
|
+
const schema = this._findSchema(raw);
|
|
512
|
+
if (!schema) {
|
|
513
|
+
const val = raw !== null && typeof raw === "object" && !Array.isArray(raw) ? raw[this._key] : void 0;
|
|
514
|
+
ctx == null ? void 0 : ctx.errors.push(pathStr(path != null ? path : []) + ": no discriminated union member matched " + this._key + "=" + JSON.stringify(val));
|
|
515
|
+
return false;
|
|
516
|
+
}
|
|
517
|
+
return schema.isValid(raw, ctx, path);
|
|
518
|
+
}
|
|
519
|
+
_canSanitize(raw) {
|
|
520
|
+
if (raw === null || typeof raw !== "object" || Array.isArray(raw)) return false;
|
|
521
|
+
const schema = this._findSchema(raw);
|
|
522
|
+
return schema ? schema._canSanitize(raw) : this._schemas[0]._canSanitize(raw);
|
|
523
|
+
}
|
|
524
|
+
};
|
|
525
|
+
var Obj = class extends Base {
|
|
526
|
+
constructor(_shape) {
|
|
527
|
+
super();
|
|
528
|
+
this._shape = _shape;
|
|
529
|
+
const d = {};
|
|
530
|
+
for (const key of Object.keys(_shape)) d[key] = _shape[key]._default;
|
|
531
|
+
this._default = d;
|
|
532
|
+
}
|
|
533
|
+
sanitize(raw) {
|
|
534
|
+
const src = raw && typeof raw === "object" && !Array.isArray(raw) ? raw : {};
|
|
535
|
+
const out = {};
|
|
536
|
+
for (const key of Object.keys(this._shape)) {
|
|
537
|
+
out[key] = this._shape[key].sanitize(src[key]);
|
|
538
|
+
}
|
|
539
|
+
return out;
|
|
540
|
+
}
|
|
541
|
+
isValid(raw, ctx, path) {
|
|
542
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw)) {
|
|
543
|
+
ctx == null ? void 0 : ctx.errors.push(pathStr(path != null ? path : []) + ": expected object, got " + (Array.isArray(raw) ? "array" : typeof raw));
|
|
544
|
+
return false;
|
|
545
|
+
}
|
|
546
|
+
const obj = raw;
|
|
547
|
+
const p = path != null ? path : [];
|
|
548
|
+
let ok = true;
|
|
549
|
+
for (const key of Object.keys(this._shape)) {
|
|
550
|
+
p.push(key);
|
|
551
|
+
if (!this._shape[key].isValid(obj[key], ctx, p)) ok = false;
|
|
552
|
+
p.pop();
|
|
553
|
+
}
|
|
554
|
+
if (ctx == null ? void 0 : ctx.strict) {
|
|
555
|
+
for (const key of Object.keys(obj)) {
|
|
556
|
+
if (key in this._shape) continue;
|
|
557
|
+
p.push(key);
|
|
558
|
+
ctx.errors.push(pathStr(p) + ": unexpected extra key");
|
|
559
|
+
p.pop();
|
|
560
|
+
ok = false;
|
|
215
561
|
}
|
|
216
562
|
}
|
|
563
|
+
return ok;
|
|
217
564
|
}
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
565
|
+
_canSanitize(raw) {
|
|
566
|
+
return !!raw && typeof raw === "object" && !Array.isArray(raw);
|
|
567
|
+
}
|
|
568
|
+
};
|
|
569
|
+
var OpenObj = class extends Base {
|
|
570
|
+
constructor(_shape, _openSchema) {
|
|
571
|
+
super();
|
|
572
|
+
this._shape = _shape;
|
|
573
|
+
this._openSchema = _openSchema;
|
|
574
|
+
const d = {};
|
|
575
|
+
for (const key of Object.keys(_shape)) d[key] = _shape[key]._default;
|
|
576
|
+
this._default = d;
|
|
577
|
+
}
|
|
578
|
+
sanitize(raw) {
|
|
579
|
+
const src = raw && typeof raw === "object" && !Array.isArray(raw) ? raw : {};
|
|
580
|
+
const out = __spreadValues({}, src);
|
|
581
|
+
for (const key of Object.keys(this._shape)) {
|
|
582
|
+
out[key] = this._shape[key].sanitize(src[key]);
|
|
583
|
+
}
|
|
584
|
+
if (this._openSchema) {
|
|
585
|
+
for (const key of Object.keys(src)) {
|
|
586
|
+
if (!(key in this._shape)) out[key] = this._openSchema.sanitize(src[key]);
|
|
587
|
+
}
|
|
588
|
+
}
|
|
589
|
+
return out;
|
|
590
|
+
}
|
|
591
|
+
isValid(raw, ctx, path) {
|
|
592
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw)) {
|
|
593
|
+
ctx == null ? void 0 : ctx.errors.push(pathStr(path != null ? path : []) + ": expected object, got " + (Array.isArray(raw) ? "array" : typeof raw));
|
|
594
|
+
return false;
|
|
595
|
+
}
|
|
596
|
+
const obj = raw;
|
|
597
|
+
const p = path != null ? path : [];
|
|
598
|
+
let ok = true;
|
|
599
|
+
for (const key of Object.keys(this._shape)) {
|
|
600
|
+
p.push(key);
|
|
601
|
+
if (!this._shape[key].isValid(obj[key], ctx, p)) ok = false;
|
|
602
|
+
p.pop();
|
|
603
|
+
}
|
|
604
|
+
if (this._openSchema) {
|
|
605
|
+
for (const key of Object.keys(obj)) {
|
|
606
|
+
if (key in this._shape) continue;
|
|
607
|
+
p.push(key);
|
|
608
|
+
if (!this._openSchema.isValid(obj[key], ctx, p)) ok = false;
|
|
609
|
+
p.pop();
|
|
225
610
|
}
|
|
226
611
|
}
|
|
612
|
+
return ok;
|
|
227
613
|
}
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
valid = false;
|
|
614
|
+
_canSanitize(raw) {
|
|
615
|
+
return !!raw && typeof raw === "object" && !Array.isArray(raw);
|
|
231
616
|
}
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
617
|
+
};
|
|
618
|
+
var Arr = class extends Base {
|
|
619
|
+
constructor(item) {
|
|
620
|
+
super();
|
|
621
|
+
this.item = item;
|
|
622
|
+
this._default = [];
|
|
238
623
|
}
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
624
|
+
sanitize(raw) {
|
|
625
|
+
if (!Array.isArray(raw)) return [];
|
|
626
|
+
const out = [];
|
|
627
|
+
for (const el of raw) {
|
|
628
|
+
if (this.item._canSanitize(el)) out.push(this.item.sanitize(el));
|
|
629
|
+
}
|
|
630
|
+
return out;
|
|
243
631
|
}
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
632
|
+
isValid(raw, ctx, path) {
|
|
633
|
+
if (!Array.isArray(raw)) {
|
|
634
|
+
ctx == null ? void 0 : ctx.errors.push(pathStr(path != null ? path : []) + ": expected array, got " + typeof raw);
|
|
635
|
+
return false;
|
|
636
|
+
}
|
|
637
|
+
const p = path != null ? path : [];
|
|
638
|
+
let ok = true;
|
|
639
|
+
for (let i = 0; i < raw.length; i++) {
|
|
640
|
+
p.push("[" + i + "]");
|
|
641
|
+
if (!this.item.isValid(raw[i], ctx, p)) ok = false;
|
|
642
|
+
p.pop();
|
|
643
|
+
}
|
|
644
|
+
return ok;
|
|
251
645
|
}
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
errors.push(path + ".type: expected string, got " + typeof v.type);
|
|
255
|
-
valid = false;
|
|
646
|
+
_canSanitize(raw) {
|
|
647
|
+
return Array.isArray(raw);
|
|
256
648
|
}
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
649
|
+
};
|
|
650
|
+
var Rec = class extends Base {
|
|
651
|
+
constructor(value) {
|
|
652
|
+
super();
|
|
653
|
+
this.value = value;
|
|
654
|
+
this._default = {};
|
|
655
|
+
}
|
|
656
|
+
sanitize(raw) {
|
|
657
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw)) return {};
|
|
658
|
+
const out = {};
|
|
659
|
+
for (const [k, v] of Object.entries(raw)) {
|
|
660
|
+
if (this.value._canSanitize(v)) out[k] = this.value.sanitize(v);
|
|
265
661
|
}
|
|
662
|
+
return out;
|
|
266
663
|
}
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
664
|
+
isValid(raw, ctx, path) {
|
|
665
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw)) {
|
|
666
|
+
ctx == null ? void 0 : ctx.errors.push(pathStr(path != null ? path : []) + ": expected object/record, got " + (Array.isArray(raw) ? "array" : typeof raw));
|
|
667
|
+
return false;
|
|
668
|
+
}
|
|
669
|
+
const p = path != null ? path : [];
|
|
670
|
+
let ok = true;
|
|
671
|
+
for (const [k, v] of Object.entries(raw)) {
|
|
672
|
+
p.push(k);
|
|
673
|
+
if (!this.value.isValid(v, ctx, p)) ok = false;
|
|
674
|
+
p.pop();
|
|
675
|
+
}
|
|
676
|
+
return ok;
|
|
276
677
|
}
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
valid = false;
|
|
678
|
+
_canSanitize(raw) {
|
|
679
|
+
return !!raw && typeof raw === "object" && !Array.isArray(raw);
|
|
280
680
|
}
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
681
|
+
};
|
|
682
|
+
var Any = class extends Base {
|
|
683
|
+
constructor() {
|
|
684
|
+
super(...arguments);
|
|
685
|
+
this._default = void 0;
|
|
284
686
|
}
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
valid = false;
|
|
687
|
+
sanitize(raw) {
|
|
688
|
+
return raw;
|
|
288
689
|
}
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
690
|
+
isValid(_raw, _ctx, _path) {
|
|
691
|
+
return true;
|
|
692
|
+
}
|
|
693
|
+
_canSanitize(_raw) {
|
|
694
|
+
return true;
|
|
695
|
+
}
|
|
696
|
+
};
|
|
697
|
+
var Lazy = class extends Base {
|
|
698
|
+
constructor(fn, _default) {
|
|
699
|
+
super();
|
|
700
|
+
this.fn = fn;
|
|
701
|
+
this._default = _default;
|
|
702
|
+
this.resolved = null;
|
|
703
|
+
}
|
|
704
|
+
get schema() {
|
|
705
|
+
var _a;
|
|
706
|
+
return (_a = this.resolved) != null ? _a : this.resolved = this.fn();
|
|
707
|
+
}
|
|
708
|
+
sanitize(raw) {
|
|
709
|
+
return this.schema.sanitize(raw);
|
|
710
|
+
}
|
|
711
|
+
isValid(raw, ctx, path) {
|
|
712
|
+
return this.schema.isValid(raw, ctx, path);
|
|
713
|
+
}
|
|
714
|
+
_canSanitize(raw) {
|
|
715
|
+
return this.schema._canSanitize(raw);
|
|
716
|
+
}
|
|
717
|
+
};
|
|
718
|
+
var Tuple = class extends Base {
|
|
719
|
+
constructor(schemas) {
|
|
720
|
+
super();
|
|
721
|
+
this.schemas = schemas;
|
|
722
|
+
this._default = schemas.map((s) => s._default);
|
|
723
|
+
}
|
|
724
|
+
sanitize(raw) {
|
|
725
|
+
if (!Array.isArray(raw) || raw.length !== this.schemas.length) return this._default;
|
|
726
|
+
return this.schemas.map((s, i) => s.sanitize(raw[i]));
|
|
727
|
+
}
|
|
728
|
+
isValid(raw, ctx, path) {
|
|
729
|
+
if (!Array.isArray(raw) || raw.length !== this.schemas.length) {
|
|
730
|
+
ctx == null ? void 0 : ctx.errors.push(pathStr(path != null ? path : []) + ": expected tuple of length " + this.schemas.length + ", got " + (Array.isArray(raw) ? "array[" + raw.length + "]" : typeof raw));
|
|
731
|
+
return false;
|
|
732
|
+
}
|
|
733
|
+
const p = path != null ? path : [];
|
|
734
|
+
let ok = true;
|
|
735
|
+
for (let i = 0; i < this.schemas.length; i++) {
|
|
736
|
+
p.push("[" + i + "]");
|
|
737
|
+
if (!this.schemas[i].isValid(raw[i], ctx, p)) ok = false;
|
|
738
|
+
p.pop();
|
|
739
|
+
}
|
|
740
|
+
return ok;
|
|
741
|
+
}
|
|
742
|
+
// Require exact length so wrong-length arrays are dropped rather than repaired to default.
|
|
743
|
+
_canSanitize(raw) {
|
|
744
|
+
return Array.isArray(raw) && raw.length === this.schemas.length;
|
|
745
|
+
}
|
|
746
|
+
};
|
|
747
|
+
function implementsInterface() {
|
|
748
|
+
return (schema) => schema;
|
|
749
|
+
}
|
|
750
|
+
function schemaKeys(schema) {
|
|
751
|
+
return Object.fromEntries(
|
|
752
|
+
Object.keys(schema["_shape"]).map((k) => [k, k])
|
|
753
|
+
);
|
|
754
|
+
}
|
|
755
|
+
function describeSchema(schema) {
|
|
756
|
+
var _a;
|
|
757
|
+
const s = schema;
|
|
758
|
+
if ("_shape" in s) return { kind: "shape", shape: s._shape };
|
|
759
|
+
if ("item" in s) return { kind: "array", item: s.item };
|
|
760
|
+
if ("inner" in s) return { kind: "optional", inner: s.inner };
|
|
761
|
+
if ("fn" in s) return { kind: "lazy", resolved: (_a = s.resolved) != null ? _a : s.fn() };
|
|
762
|
+
return { kind: "leaf" };
|
|
763
|
+
}
|
|
764
|
+
var px = {
|
|
765
|
+
/** Matches a string. Default: '' or provided value. */
|
|
766
|
+
string: (defaultVal = "") => new Str(defaultVal),
|
|
767
|
+
/** Matches a finite number. Default: 0 or provided value. */
|
|
768
|
+
number: (defaultVal = 0) => new Num(defaultVal),
|
|
769
|
+
/** Matches a boolean. Default: false or provided value. */
|
|
770
|
+
boolean: (defaultVal = false) => new Bool(defaultVal),
|
|
771
|
+
/** Matches one exact primitive value; its default is the value itself. */
|
|
772
|
+
literal: (value) => new Literal(value),
|
|
773
|
+
/** Matches one of a fixed set of string/number values. Default: first value. */
|
|
774
|
+
enum: (values, defaultVal) => new Enum(values, defaultVal),
|
|
775
|
+
/**
|
|
776
|
+
* Returns the first schema whose isValid passes.
|
|
777
|
+
* TypeScript infers the union of all member types automatically.
|
|
778
|
+
*/
|
|
779
|
+
union: (schemas, defaultVal) => new Union(schemas, defaultVal),
|
|
780
|
+
/**
|
|
781
|
+
* Discriminated union — reads `raw[key]`, finds the member schema whose
|
|
782
|
+
* literal at `key` matches, then delegates sanitize/isValid to that member.
|
|
783
|
+
* Each member must be an object schema with a `px.literal(...)` at `key`.
|
|
784
|
+
* TypeScript infers the union of all member types automatically.
|
|
785
|
+
*/
|
|
786
|
+
discriminatedUnion: (key, schemas) => new DiscriminatedUnion(key, schemas),
|
|
787
|
+
/** Typed object — unknown keys are stripped. Required fields fall back to their default. */
|
|
788
|
+
object: (shape) => new Obj(shape),
|
|
789
|
+
/**
|
|
790
|
+
* Open object — validates known keys; passes unknown keys through as-is,
|
|
791
|
+
* or validates/sanitizes them against `openSchema` when provided.
|
|
792
|
+
*/
|
|
793
|
+
openObject: (shape, openSchema) => new OpenObj(shape, openSchema),
|
|
794
|
+
/**
|
|
795
|
+
* Creates a new closed object schema by merging a base schema's shape with additional fields.
|
|
796
|
+
* The base can be the result of px.object() or px.openObject() — anything with a _shape property.
|
|
797
|
+
*
|
|
798
|
+
* @example
|
|
799
|
+
* const PxSvgNodeSchema = px.extendedObject(PxNodeBase, { width: px.number().optional() });
|
|
800
|
+
*/
|
|
801
|
+
extendedObject: (base, extra) => new Obj(__spreadValues(__spreadValues({}, base._shape), extra)),
|
|
802
|
+
/** Array whose unrecoverable items are filtered out. Default: []. */
|
|
803
|
+
array: (item) => new Arr(item),
|
|
804
|
+
/** String-keyed record whose unrecoverable values are dropped. Default: {}. */
|
|
805
|
+
record: (value) => new Rec(value),
|
|
806
|
+
/** Passes anything through unchanged — always valid. */
|
|
807
|
+
any: () => new Any(),
|
|
808
|
+
/** Fixed-length tuple — validates element count and each position individually. */
|
|
809
|
+
tuple: (schemas) => new Tuple(schemas),
|
|
810
|
+
/** Defers schema creation — required for recursive types. Must supply a default value. */
|
|
811
|
+
lazy: (fn, defaultVal) => new Lazy(fn, defaultVal)
|
|
812
|
+
};
|
|
813
|
+
|
|
814
|
+
// src/PxAnimatorTypes.ts
|
|
815
|
+
var PX_ANIM_SRC_ATTR_NAME = "data-px-animation-src";
|
|
816
|
+
var PX_ANIM_ATTR_NAME = "_px_animator";
|
|
817
|
+
var PxAnimatorMode = {
|
|
818
|
+
auto: "auto",
|
|
819
|
+
webapi: "webapi",
|
|
820
|
+
frames: "frames"
|
|
821
|
+
};
|
|
822
|
+
var PxAnimatorEngine = {
|
|
823
|
+
webapi: PxAnimatorMode.webapi,
|
|
824
|
+
frames: PxAnimatorMode.frames
|
|
825
|
+
};
|
|
826
|
+
var TEXT_ATTR = "text";
|
|
827
|
+
var TEXT_CONTENT_ATTR = "textContent";
|
|
828
|
+
var INTERNAL_ATTRS = /* @__PURE__ */ new Set([
|
|
829
|
+
"type",
|
|
830
|
+
"children",
|
|
831
|
+
"animator",
|
|
832
|
+
"meta",
|
|
833
|
+
"animate",
|
|
834
|
+
TEXT_ATTR,
|
|
835
|
+
TEXT_CONTENT_ATTR
|
|
836
|
+
]);
|
|
837
|
+
var PxEasingOrRefSchema = px.union([
|
|
838
|
+
px.string(),
|
|
839
|
+
px.tuple([px.number(), px.number(), px.number(), px.number()])
|
|
840
|
+
]);
|
|
841
|
+
var PxKeyframeValueSchema = implementsInterface()(px.union([
|
|
842
|
+
px.string(),
|
|
843
|
+
// e.g. for colors
|
|
844
|
+
px.number(),
|
|
845
|
+
px.array(px.number()),
|
|
846
|
+
px.lazy(() => PxTransformPartsSchema, {}),
|
|
847
|
+
px.object({ path: px.string() }),
|
|
848
|
+
px.lazy(() => px.object({ paths: px.array(PxBezierPathSchema) }), { paths: [] })
|
|
849
|
+
]));
|
|
850
|
+
var PxKeyframeSchema = implementsInterface()(px.object({
|
|
851
|
+
time: px.number().optional(),
|
|
852
|
+
t: px.number().optional(),
|
|
853
|
+
value: px.any().optional(),
|
|
854
|
+
v: px.any().optional(),
|
|
855
|
+
easing: PxEasingOrRefSchema.optional(),
|
|
856
|
+
e: PxEasingOrRefSchema.optional(),
|
|
857
|
+
tangentOut: px.tuple([px.number(), px.number()]).optional(),
|
|
858
|
+
to: px.tuple([px.number(), px.number()]).optional(),
|
|
859
|
+
// short alias
|
|
860
|
+
tangentIn: px.tuple([px.number(), px.number()]).optional(),
|
|
861
|
+
ti: px.tuple([px.number(), px.number()]).optional(),
|
|
862
|
+
// short alias
|
|
863
|
+
selected: px.boolean().optional()
|
|
864
|
+
// editor-side UI state (Player ignores it)
|
|
865
|
+
}));
|
|
866
|
+
var PxLoopSchema = implementsInterface()(px.object({
|
|
867
|
+
segmentCount: px.number().optional(),
|
|
868
|
+
before: px.boolean().optional(),
|
|
869
|
+
alternate: px.boolean().optional()
|
|
870
|
+
}));
|
|
871
|
+
var PxPropertyAnimationSchema = implementsInterface()(px.object({
|
|
872
|
+
keyframes: px.array(PxKeyframeSchema).optional(),
|
|
873
|
+
kfs: px.array(PxKeyframeSchema).optional(),
|
|
874
|
+
loop: px.union([PxLoopSchema, px.boolean()]).optional(),
|
|
875
|
+
autoOrient: px.boolean().optional()
|
|
876
|
+
}));
|
|
877
|
+
var PX_TRANSFORM_PART_KEYS = ["translate", "rotate", "scale", "origin"];
|
|
878
|
+
var PxTransformPartsSchema = implementsInterface()(px.object({
|
|
879
|
+
translate: px.tuple([px.number(), px.number()]).optional(),
|
|
880
|
+
rotate: px.number().optional(),
|
|
881
|
+
scale: px.tuple([px.number(), px.number()]).optional(),
|
|
882
|
+
origin: px.tuple([px.number(), px.number()]).optional()
|
|
883
|
+
}));
|
|
884
|
+
var PxTransformValueSchema = px.union([
|
|
885
|
+
px.string(),
|
|
886
|
+
px.object({ value: PxTransformPartsSchema }),
|
|
887
|
+
PxPropertyAnimationSchema
|
|
888
|
+
]);
|
|
889
|
+
var PxAnimationDefinitionSchema = implementsInterface()(
|
|
890
|
+
px.record(PxPropertyAnimationSchema)
|
|
891
|
+
);
|
|
892
|
+
var PxElementAnimationSchema = implementsInterface()(px.union([
|
|
893
|
+
px.string(),
|
|
894
|
+
px.array(px.union([px.string(), PxAnimationDefinitionSchema])),
|
|
895
|
+
PxAnimationDefinitionSchema
|
|
896
|
+
]));
|
|
897
|
+
var PxTriggerSchema = implementsInterface()(px.object({
|
|
898
|
+
startOn: px.enum(["load", "mouseOver", "click", "scrollIntoView", "programmatic"]).optional(),
|
|
899
|
+
outAction: px.enum(["continue", "pause", "reset", "reverse"]).optional(),
|
|
900
|
+
scrollIntoViewThreshold: px.number().optional()
|
|
901
|
+
}));
|
|
902
|
+
var PxDefsSchema = implementsInterface()(px.object({
|
|
903
|
+
easings: px.record(px.tuple([px.number(), px.number(), px.number(), px.number()])).optional(),
|
|
904
|
+
animations: px.record(PxAnimationDefinitionSchema).optional(),
|
|
905
|
+
styles: px.record(px.any()).optional()
|
|
906
|
+
}));
|
|
907
|
+
var PxAnimatorConfigSchema = implementsInterface()(px.object({
|
|
908
|
+
mode: px.enum([PxAnimatorMode.auto, PxAnimatorMode.webapi, PxAnimatorMode.frames]).optional(),
|
|
909
|
+
duration: px.number().optional(),
|
|
910
|
+
delay: px.number().optional(),
|
|
911
|
+
iterations: px.union([px.number(), px.literal("infinite")]).optional(),
|
|
912
|
+
fill: px.enum(["forwards", "backwards", "both", "none"]).optional(),
|
|
913
|
+
direction: px.enum(["normal", "reverse", "alternate", "alternate-reverse"]).optional(),
|
|
914
|
+
frameRate: px.number().optional(),
|
|
915
|
+
trigger: PxTriggerSchema.optional(),
|
|
916
|
+
definitions: PxDefsSchema.optional(),
|
|
917
|
+
animate: px.record(PxElementAnimationSchema).optional(),
|
|
918
|
+
debug: px.boolean().optional(),
|
|
919
|
+
debugInstName: px.string().optional()
|
|
920
|
+
}));
|
|
921
|
+
var PxBindingSchema = implementsInterface()(px.object({
|
|
922
|
+
id: px.string(),
|
|
923
|
+
animate: PxElementAnimationSchema
|
|
924
|
+
}));
|
|
925
|
+
var PxAttrValueSchema = px.union([
|
|
926
|
+
px.string(),
|
|
927
|
+
px.number(),
|
|
928
|
+
px.object({ value: px.any() }),
|
|
929
|
+
PxPropertyAnimationSchema
|
|
930
|
+
]);
|
|
931
|
+
var PxAnimatableNumberSchema = px.union([
|
|
932
|
+
px.number(),
|
|
933
|
+
px.object({ value: px.number() }),
|
|
934
|
+
px.object({
|
|
935
|
+
keyframes: px.array(PxKeyframeSchema),
|
|
936
|
+
autoOrient: px.boolean().optional()
|
|
937
|
+
})
|
|
938
|
+
]);
|
|
939
|
+
var PxAnimatableVec2Schema = px.union([
|
|
940
|
+
px.tuple([px.number(), px.number()]),
|
|
941
|
+
px.object({ value: px.tuple([px.number(), px.number()]) }),
|
|
942
|
+
px.object({
|
|
943
|
+
keyframes: px.array(PxKeyframeSchema),
|
|
944
|
+
autoOrient: px.boolean().optional()
|
|
945
|
+
})
|
|
946
|
+
]);
|
|
947
|
+
var PxTransformationEffectSchema = implementsInterface()(px.object({
|
|
948
|
+
translate: PxAnimatableVec2Schema.optional(),
|
|
949
|
+
rotate: PxAnimatableNumberSchema.optional(),
|
|
950
|
+
scale: PxAnimatableVec2Schema.optional(),
|
|
951
|
+
skew: PxAnimatableVec2Schema.optional(),
|
|
952
|
+
origin: PxAnimatableVec2Schema.optional()
|
|
953
|
+
}));
|
|
954
|
+
var PxRepeaterEffectSchema = implementsInterface()(px.object({
|
|
955
|
+
copies: px.number().optional(),
|
|
956
|
+
translate: PxAnimatableVec2Schema.optional(),
|
|
957
|
+
rotate: PxAnimatableNumberSchema.optional(),
|
|
958
|
+
scale: PxAnimatableVec2Schema.optional(),
|
|
959
|
+
origin: PxAnimatableVec2Schema.optional()
|
|
960
|
+
}));
|
|
961
|
+
var PxMaskedByEffectSchema = implementsInterface()(px.object({
|
|
962
|
+
href: px.string().optional(),
|
|
963
|
+
maskType: px.string().optional(),
|
|
964
|
+
maskUnits: px.string().optional(),
|
|
965
|
+
maskContentUnits: px.string().optional()
|
|
966
|
+
}));
|
|
967
|
+
var PxTrimPathEffectSchema = implementsInterface()(px.object({
|
|
968
|
+
offset: PxAnimatableNumberSchema.optional(),
|
|
969
|
+
range: PxAnimatableVec2Schema.optional(),
|
|
970
|
+
trimAllAsOne: px.boolean().optional()
|
|
971
|
+
}));
|
|
972
|
+
var PxRetimeEffectSchema = implementsInterface()(px.object({
|
|
973
|
+
baseId: px.string().optional(),
|
|
974
|
+
start: px.number().optional(),
|
|
975
|
+
stretch: px.number().optional(),
|
|
976
|
+
timeCrop: px.tuple([px.number(), px.number()]).optional()
|
|
977
|
+
}));
|
|
978
|
+
var PxRefEffectSchema = implementsInterface()(px.object({
|
|
979
|
+
baseId: px.string().optional(),
|
|
980
|
+
type: px.string().optional()
|
|
981
|
+
}));
|
|
982
|
+
var PxGradientUnits = {
|
|
983
|
+
userSpaceOnUse: "userSpaceOnUse",
|
|
984
|
+
objectBoundingBox: "objectBoundingBox"
|
|
985
|
+
};
|
|
986
|
+
var PxGradientSpreadMethod = {
|
|
987
|
+
pad: "pad",
|
|
988
|
+
reflect: "reflect",
|
|
989
|
+
repeat: "repeat"
|
|
990
|
+
};
|
|
991
|
+
var PxGradientType = {
|
|
992
|
+
linear: "linear",
|
|
993
|
+
radial: "radial"
|
|
994
|
+
};
|
|
995
|
+
var PxGradientStopSchema = implementsInterface()(px.object({
|
|
996
|
+
offset: px.number(),
|
|
997
|
+
color: px.string()
|
|
998
|
+
}));
|
|
999
|
+
var PxAnimatableGradientStopsSchema = px.union([
|
|
1000
|
+
px.array(PxGradientStopSchema),
|
|
1001
|
+
px.object({ value: px.array(PxGradientStopSchema) }),
|
|
1002
|
+
px.object({ keyframes: px.array(PxKeyframeSchema) })
|
|
1003
|
+
]);
|
|
1004
|
+
var PxFillGradientEffectSchema = implementsInterface()(px.object({
|
|
1005
|
+
type: px.enum([PxGradientType.linear, PxGradientType.radial]),
|
|
1006
|
+
p1: px.tuple([px.number(), px.number()]).optional(),
|
|
1007
|
+
p2: px.tuple([px.number(), px.number()]).optional(),
|
|
1008
|
+
c: px.tuple([px.number(), px.number()]).optional(),
|
|
1009
|
+
r: px.number().optional(),
|
|
1010
|
+
fp: px.tuple([px.number(), px.number()]).optional(),
|
|
1011
|
+
stops: PxAnimatableGradientStopsSchema.optional(),
|
|
1012
|
+
gradientUnits: px.string().optional(),
|
|
1013
|
+
spreadMethod: px.string().optional(),
|
|
1014
|
+
gradientTransform: px.string().optional()
|
|
1015
|
+
}));
|
|
1016
|
+
var PxStrokeGradientEffectSchema = PxFillGradientEffectSchema;
|
|
1017
|
+
var PxTextAlongPathEffectSchema = implementsInterface()(px.object({
|
|
1018
|
+
href: px.string(),
|
|
1019
|
+
lengthAdjust: px.string().optional(),
|
|
1020
|
+
method: px.string().optional(),
|
|
1021
|
+
spacing: px.string().optional(),
|
|
1022
|
+
startOffset: PxAnimatableNumberSchema.optional(),
|
|
1023
|
+
textLength: PxAnimatableNumberSchema.optional()
|
|
1024
|
+
}));
|
|
1025
|
+
var PxEffectsSchema = implementsInterface()(px.object({
|
|
1026
|
+
transformation: PxTransformationEffectSchema.optional(),
|
|
1027
|
+
repeater: PxRepeaterEffectSchema.optional(),
|
|
1028
|
+
maskedBy: PxMaskedByEffectSchema.optional(),
|
|
1029
|
+
trimPath: PxTrimPathEffectSchema.optional(),
|
|
1030
|
+
retime: PxRetimeEffectSchema.optional(),
|
|
1031
|
+
isCombinedShape: px.boolean().optional(),
|
|
1032
|
+
ref: PxRefEffectSchema.optional(),
|
|
1033
|
+
fillGradient: PxFillGradientEffectSchema.optional(),
|
|
1034
|
+
strokeGradient: PxStrokeGradientEffectSchema.optional(),
|
|
1035
|
+
textAlongPath: PxTextAlongPathEffectSchema.optional()
|
|
1036
|
+
}));
|
|
1037
|
+
function validateNodeEffects(root, opts) {
|
|
1038
|
+
const warnings = [];
|
|
1039
|
+
const walk = (node, path) => {
|
|
1040
|
+
if (node && node.effects) {
|
|
1041
|
+
const ctx = { errors: [], warnings: [], strict: !!(opts == null ? void 0 : opts.strict) };
|
|
1042
|
+
const ok = PxEffectsSchema.isValid(node.effects, ctx, [path + ".effects"]);
|
|
1043
|
+
if (!ok) {
|
|
1044
|
+
for (const err of ctx.errors) warnings.push(err);
|
|
1045
|
+
}
|
|
1046
|
+
}
|
|
1047
|
+
if (node && Array.isArray(node.children)) {
|
|
1048
|
+
node.children.forEach((c, i) => walk(c, path + ".children[" + i + "]"));
|
|
299
1049
|
}
|
|
1050
|
+
};
|
|
1051
|
+
walk(root, "root");
|
|
1052
|
+
return warnings;
|
|
1053
|
+
}
|
|
1054
|
+
var PxNodeBase = px.openObject({
|
|
1055
|
+
type: px.string(),
|
|
1056
|
+
id: px.string().optional(),
|
|
1057
|
+
meta: px.any().optional(),
|
|
1058
|
+
// Player-effects bucket emitted by the Editor's lightweight design format.
|
|
1059
|
+
// Consumed and removed by `applyPlayerEffects` before any other normalisation
|
|
1060
|
+
// (see `createAnimatorImpl`), so downstream code never sees it.
|
|
1061
|
+
effects: PxEffectsSchema.optional(),
|
|
1062
|
+
// `PxElementAnimation` (not just `PxAnimationDefinition`) — accepts
|
|
1063
|
+
// string ref / array of refs / inline definition / mixed array; mirrors
|
|
1064
|
+
// `animator.animate` map values and what `processNode` resolves at runtime.
|
|
1065
|
+
animate: PxElementAnimationSchema.optional(),
|
|
1066
|
+
style: px.union([px.string(), px.record(px.union([px.string(), px.number()]))]).optional()
|
|
1067
|
+
}, PxAttrValueSchema);
|
|
1068
|
+
var PxNodeSchema = px.openObject(__spreadProps(__spreadValues({}, PxNodeBase._shape), {
|
|
1069
|
+
children: px.lazy(() => px.array(PxNodeSchema), []).optional()
|
|
1070
|
+
}), PxAttrValueSchema);
|
|
1071
|
+
var PxSvgNodeExtra = px.object({
|
|
1072
|
+
width: px.number().optional(),
|
|
1073
|
+
height: px.number().optional(),
|
|
1074
|
+
viewBox: px.string().optional(),
|
|
1075
|
+
animator: PxAnimatorConfigSchema.optional()
|
|
1076
|
+
});
|
|
1077
|
+
var PxAnimatedSvgDocumentSchema = px.openObject(__spreadProps(__spreadValues(__spreadValues({}, PxNodeBase._shape), PxSvgNodeExtra._shape), {
|
|
1078
|
+
type: px.literal("svg"),
|
|
1079
|
+
// override string → literal to require 'svg'
|
|
1080
|
+
children: px.array(PxNodeSchema).optional()
|
|
1081
|
+
}), PxAttrValueSchema);
|
|
1082
|
+
var PxBezierPathSchema = implementsInterface()(px.object({
|
|
1083
|
+
v: px.array(px.array(px.number())),
|
|
1084
|
+
i: px.array(px.array(px.number())).optional(),
|
|
1085
|
+
o: px.array(px.array(px.number())).optional(),
|
|
1086
|
+
c: px.boolean().optional()
|
|
1087
|
+
}));
|
|
1088
|
+
function isPxElementFileFormat(fileJson) {
|
|
1089
|
+
if (!(fileJson && typeof fileJson === "object" && !Array.isArray(fileJson))) {
|
|
1090
|
+
return false;
|
|
300
1091
|
}
|
|
301
|
-
|
|
302
|
-
return valid;
|
|
1092
|
+
return fileJson["type"] === "svg" || fileJson["tagName"] === "svg";
|
|
303
1093
|
}
|
|
304
1094
|
function isPxElementFileFormatDeep(fileJson) {
|
|
305
|
-
const
|
|
306
|
-
|
|
307
|
-
return { valid, errors };
|
|
1095
|
+
const valid = PxAnimatedSvgDocumentSchema.isValid(fileJson);
|
|
1096
|
+
return { valid, errors: valid ? [] : ["Document failed schema validation"] };
|
|
308
1097
|
}
|
|
309
1098
|
function getAnimatorConfig(doc) {
|
|
310
1099
|
var _a, _b;
|
|
@@ -313,55 +1102,842 @@ function getAnimatorConfig(doc) {
|
|
|
313
1102
|
function getDefs(doc) {
|
|
314
1103
|
var _a;
|
|
315
1104
|
if (!doc) return void 0;
|
|
316
|
-
return
|
|
1105
|
+
return (_a = getAnimatorConfig(doc)) == null ? void 0 : _a.definitions;
|
|
317
1106
|
}
|
|
318
1107
|
function getBindings(doc) {
|
|
319
1108
|
var _a;
|
|
320
1109
|
if (!doc) return void 0;
|
|
321
|
-
|
|
1110
|
+
const animate = (_a = getAnimatorConfig(doc)) == null ? void 0 : _a.animate;
|
|
1111
|
+
if (!animate) return void 0;
|
|
1112
|
+
return Object.entries(animate).map(([id, anim]) => ({ id, animate: anim }));
|
|
322
1113
|
}
|
|
323
1114
|
function getChildren(doc) {
|
|
324
1115
|
return doc == null ? void 0 : doc.children;
|
|
325
1116
|
}
|
|
326
1117
|
|
|
327
|
-
// src/
|
|
328
|
-
function
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
const
|
|
332
|
-
const
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
const
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
const isLine = prevO[0] === prevV[0] && prevO[1] === prevV[1] && (currI[0] === currV[0] && currI[1] === currV[1]);
|
|
344
|
-
if (isLine) {
|
|
345
|
-
d.push("L" + currV[0] + "," + currV[1]);
|
|
346
|
-
} else {
|
|
347
|
-
d.push("C" + prevO[0] + "," + prevO[1] + "," + currI[0] + "," + currI[1] + "," + currV[0] + "," + currV[1]);
|
|
1118
|
+
// src/PxNodeCloneUtil.ts
|
|
1119
|
+
function deepClonePxNode(value) {
|
|
1120
|
+
if (value === null || typeof value !== "object") return value;
|
|
1121
|
+
if (Array.isArray(value)) return value.map(deepClonePxNode);
|
|
1122
|
+
const out = {};
|
|
1123
|
+
for (const k of Object.keys(value)) out[k] = deepClonePxNode(value[k]);
|
|
1124
|
+
return out;
|
|
1125
|
+
}
|
|
1126
|
+
function regenerateIdsAndRewriteRefs(root, genId3) {
|
|
1127
|
+
const oldToNew = /* @__PURE__ */ new Map();
|
|
1128
|
+
const walkAssign = (n) => {
|
|
1129
|
+
var _a;
|
|
1130
|
+
if (typeof n.id === "string") {
|
|
1131
|
+
const newId = genId3();
|
|
1132
|
+
oldToNew.set(n.id, newId);
|
|
1133
|
+
n.id = newId;
|
|
348
1134
|
}
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
const
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
1135
|
+
(_a = n.children) == null ? void 0 : _a.forEach(walkAssign);
|
|
1136
|
+
};
|
|
1137
|
+
walkAssign(root);
|
|
1138
|
+
const rewriteUrl = (s) => s.replace(/url\(#([^)]+)\)/g, (m, oldId) => {
|
|
1139
|
+
const newId = oldToNew.get(oldId);
|
|
1140
|
+
return newId ? "url(#" + newId + ")" : m;
|
|
1141
|
+
});
|
|
1142
|
+
const walkRewrite = (n) => {
|
|
1143
|
+
var _a;
|
|
1144
|
+
if (typeof n.href === "string" && n.href.startsWith("#")) {
|
|
1145
|
+
const newId = oldToNew.get(n.href.slice(1));
|
|
1146
|
+
if (newId) n.href = "#" + newId;
|
|
358
1147
|
}
|
|
359
|
-
|
|
1148
|
+
for (const k of Object.keys(n)) {
|
|
1149
|
+
if (k === "children" || k === "effects" || k === "meta" || k === "animate" || k === "href" || k === "id") continue;
|
|
1150
|
+
const v = n[k];
|
|
1151
|
+
if (typeof v === "string" && v.indexOf("url(#") !== -1) {
|
|
1152
|
+
n[k] = rewriteUrl(v);
|
|
1153
|
+
}
|
|
1154
|
+
}
|
|
1155
|
+
(_a = n.children) == null ? void 0 : _a.forEach(walkRewrite);
|
|
1156
|
+
};
|
|
1157
|
+
walkRewrite(root);
|
|
1158
|
+
return oldToNew;
|
|
1159
|
+
}
|
|
1160
|
+
function toFiniteNum(v) {
|
|
1161
|
+
const n = typeof v === "number" ? v : typeof v === "string" ? parseFloat(v) : NaN;
|
|
1162
|
+
return Number.isFinite(n) ? n : 0;
|
|
1163
|
+
}
|
|
1164
|
+
function applyUseOffsetToG(gNode) {
|
|
1165
|
+
var _a;
|
|
1166
|
+
const x = toFiniteNum(gNode.x);
|
|
1167
|
+
const y = toFiniteNum(gNode.y);
|
|
1168
|
+
delete gNode.x;
|
|
1169
|
+
delete gNode.y;
|
|
1170
|
+
if (!x && !y) return gNode;
|
|
1171
|
+
const offset = "translate(" + x + "," + y + ")";
|
|
1172
|
+
const carriesTransform = gNode.transform !== void 0 || gNode.animate !== void 0;
|
|
1173
|
+
if (carriesTransform) {
|
|
1174
|
+
const inner = { type: "g", transform: offset, children: (_a = gNode.children) != null ? _a : [] };
|
|
1175
|
+
gNode.children = [inner];
|
|
1176
|
+
} else {
|
|
1177
|
+
gNode.transform = offset;
|
|
360
1178
|
}
|
|
361
|
-
return
|
|
1179
|
+
return gNode;
|
|
362
1180
|
}
|
|
363
|
-
|
|
364
|
-
|
|
1181
|
+
|
|
1182
|
+
// src/effects/util.ts
|
|
1183
|
+
function genId(ctx, prefix) {
|
|
1184
|
+
return "_lw_" + prefix + "_" + ctx.nextId++;
|
|
1185
|
+
}
|
|
1186
|
+
function stripHash(href) {
|
|
1187
|
+
return typeof href === "string" ? href.replace(/^#/, "") : void 0;
|
|
1188
|
+
}
|
|
1189
|
+
function indexById(node, map) {
|
|
1190
|
+
var _a;
|
|
1191
|
+
if (typeof node.id === "string") map.set(node.id, node);
|
|
1192
|
+
(_a = node.children) == null ? void 0 : _a.forEach((child) => indexById(child, map));
|
|
1193
|
+
}
|
|
1194
|
+
function spliceDefs(root, defs) {
|
|
1195
|
+
if (!defs.length) return;
|
|
1196
|
+
const existing = root.children || (root.children = []);
|
|
1197
|
+
existing.unshift({ type: "defs", children: defs });
|
|
1198
|
+
}
|
|
1199
|
+
var clone = deepClonePxNode;
|
|
1200
|
+
function regenerateIdsInClone(root, ctx) {
|
|
1201
|
+
return regenerateIdsAndRewriteRefs(root, () => genId(ctx, "retimed"));
|
|
1202
|
+
}
|
|
1203
|
+
|
|
1204
|
+
// src/effects/gradientEffect.ts
|
|
1205
|
+
function applyFillGradientEffect(node, fx, ctx) {
|
|
1206
|
+
return applyGradient(node, fx, ctx, "fill");
|
|
1207
|
+
}
|
|
1208
|
+
function applyStrokeGradientEffect(node, fx, ctx) {
|
|
1209
|
+
return applyGradient(node, fx, ctx, "stroke");
|
|
1210
|
+
}
|
|
1211
|
+
function applyGradient(node, fx, ctx, attr) {
|
|
1212
|
+
if (!fx) return node;
|
|
1213
|
+
const id = genId(ctx, "grad");
|
|
1214
|
+
const def = synthesiseGradientDef(fx, id, ctx);
|
|
1215
|
+
ctx.defs.push(def);
|
|
1216
|
+
node[attr] = "url(#" + id + ")";
|
|
1217
|
+
return node;
|
|
1218
|
+
}
|
|
1219
|
+
function synthesiseGradientDef(fx, id, ctx) {
|
|
1220
|
+
const out = {
|
|
1221
|
+
type: fx.type === PxGradientType.radial ? "radialGradient" : "linearGradient",
|
|
1222
|
+
id
|
|
1223
|
+
};
|
|
1224
|
+
if (fx.type === PxGradientType.linear) {
|
|
1225
|
+
if (fx.p1) {
|
|
1226
|
+
out.x1 = String(fx.p1[0]);
|
|
1227
|
+
out.y1 = String(fx.p1[1]);
|
|
1228
|
+
}
|
|
1229
|
+
if (fx.p2) {
|
|
1230
|
+
out.x2 = String(fx.p2[0]);
|
|
1231
|
+
out.y2 = String(fx.p2[1]);
|
|
1232
|
+
}
|
|
1233
|
+
} else {
|
|
1234
|
+
if (fx.c) {
|
|
1235
|
+
out.cx = String(fx.c[0]);
|
|
1236
|
+
out.cy = String(fx.c[1]);
|
|
1237
|
+
}
|
|
1238
|
+
if (fx.r !== void 0) out.r = String(fx.r);
|
|
1239
|
+
if (fx.fp) {
|
|
1240
|
+
out.fx = String(fx.fp[0]);
|
|
1241
|
+
out.fy = String(fx.fp[1]);
|
|
1242
|
+
}
|
|
1243
|
+
}
|
|
1244
|
+
if (fx.gradientUnits) out.gradientUnits = fx.gradientUnits;
|
|
1245
|
+
if (fx.spreadMethod) out.spreadMethod = fx.spreadMethod;
|
|
1246
|
+
if (fx.gradientTransform) out.gradientTransform = fx.gradientTransform;
|
|
1247
|
+
out.children = buildStopChildren(fx.stops, ctx);
|
|
1248
|
+
return out;
|
|
1249
|
+
}
|
|
1250
|
+
function buildStopChildren(stops, ctx) {
|
|
1251
|
+
var _a, _b, _c, _d;
|
|
1252
|
+
if (!stops) return [];
|
|
1253
|
+
if (Array.isArray(stops)) return stops.map(staticStopNode);
|
|
1254
|
+
if (typeof stops === "object" && Array.isArray(stops.value)) {
|
|
1255
|
+
return stops.value.map(staticStopNode);
|
|
1256
|
+
}
|
|
1257
|
+
const animBlock = stops;
|
|
1258
|
+
const kfs = animBlock.keyframes;
|
|
1259
|
+
if (!Array.isArray(kfs) || !kfs.length) return [];
|
|
1260
|
+
let stopCount = 0;
|
|
1261
|
+
for (const kf of kfs) {
|
|
1262
|
+
const v = (_a = kf.value) != null ? _a : kf.v;
|
|
1263
|
+
if (Array.isArray(v) && v.length > stopCount) stopCount = v.length;
|
|
1264
|
+
}
|
|
1265
|
+
if (!stopCount) return [];
|
|
1266
|
+
const firstKfValue = (_b = kfs[0].value) != null ? _b : kfs[0].v;
|
|
1267
|
+
const baselineStops = [];
|
|
1268
|
+
for (let i = 0; i < stopCount; i++) {
|
|
1269
|
+
const s = (_d = (_c = firstKfValue == null ? void 0 : firstKfValue[i]) != null ? _c : prevDefinedStop(kfs, 0, i)) != null ? _d : { offset: i / Math.max(1, stopCount - 1), color: "#000000" };
|
|
1270
|
+
baselineStops.push({ offset: s.offset, color: s.color });
|
|
1271
|
+
}
|
|
1272
|
+
return baselineStops.map((bs, i) => animatedStopNode(bs, kfs, i, ctx));
|
|
1273
|
+
}
|
|
1274
|
+
function staticStopNode(s) {
|
|
1275
|
+
return {
|
|
1276
|
+
type: "stop",
|
|
1277
|
+
offset: formatOffset(s.offset),
|
|
1278
|
+
stopColor: s.color
|
|
1279
|
+
};
|
|
1280
|
+
}
|
|
1281
|
+
function animatedStopNode(baseline, kfs, stopIdx, _ctx) {
|
|
1282
|
+
var _a, _b, _c, _d, _e;
|
|
1283
|
+
const colorKfs = [];
|
|
1284
|
+
const offsetKfs = [];
|
|
1285
|
+
let offsetVaries = false;
|
|
1286
|
+
for (const kf of kfs) {
|
|
1287
|
+
const t = (_b = (_a = kf.time) != null ? _a : kf.t) != null ? _b : 0;
|
|
1288
|
+
const arr = (_c = kf.value) != null ? _c : kf.v;
|
|
1289
|
+
const sliced = (_d = arr == null ? void 0 : arr[stopIdx]) != null ? _d : prevDefinedStop(kfs, kfs.indexOf(kf), stopIdx);
|
|
1290
|
+
if (!sliced) continue;
|
|
1291
|
+
const easing = (_e = kf.easing) != null ? _e : kf.e;
|
|
1292
|
+
const colorOut = { time: t, value: sliced.color };
|
|
1293
|
+
if (easing !== void 0) colorOut.easing = easing;
|
|
1294
|
+
colorKfs.push(colorOut);
|
|
1295
|
+
const offsetOut = { time: t, value: sliced.offset };
|
|
1296
|
+
if (easing !== void 0) offsetOut.easing = easing;
|
|
1297
|
+
offsetKfs.push(offsetOut);
|
|
1298
|
+
if (sliced.offset !== baseline.offset) offsetVaries = true;
|
|
1299
|
+
}
|
|
1300
|
+
const stop = {
|
|
1301
|
+
type: "stop",
|
|
1302
|
+
offset: formatOffset(baseline.offset),
|
|
1303
|
+
stopColor: baseline.color
|
|
1304
|
+
};
|
|
1305
|
+
const animate = {};
|
|
1306
|
+
if (colorKfs.length) animate.stopColor = { keyframes: colorKfs };
|
|
1307
|
+
if (offsetVaries && offsetKfs.length) animate.offset = { keyframes: offsetKfs };
|
|
1308
|
+
if (Object.keys(animate).length) stop.animate = animate;
|
|
1309
|
+
return stop;
|
|
1310
|
+
}
|
|
1311
|
+
function prevDefinedStop(kfs, fromIdx, stopIdx) {
|
|
1312
|
+
var _a, _b;
|
|
1313
|
+
for (let i = fromIdx; i >= 0; i--) {
|
|
1314
|
+
const arr = (_a = kfs[i].value) != null ? _a : kfs[i].v;
|
|
1315
|
+
if (arr == null ? void 0 : arr[stopIdx]) return arr[stopIdx];
|
|
1316
|
+
}
|
|
1317
|
+
for (let i = fromIdx + 1; i < kfs.length; i++) {
|
|
1318
|
+
const arr = (_b = kfs[i].value) != null ? _b : kfs[i].v;
|
|
1319
|
+
if (arr == null ? void 0 : arr[stopIdx]) return arr[stopIdx];
|
|
1320
|
+
}
|
|
1321
|
+
return void 0;
|
|
1322
|
+
}
|
|
1323
|
+
function formatOffset(o) {
|
|
1324
|
+
const pct = Math.round(o * 1e3) / 10;
|
|
1325
|
+
return pct + "%";
|
|
1326
|
+
}
|
|
1327
|
+
|
|
1328
|
+
// src/effects/maskedByEffect.ts
|
|
1329
|
+
function applyMaskedByEffect(node, fx, transformation, ctx) {
|
|
1330
|
+
if (!fx) return node;
|
|
1331
|
+
if (!fx.href) {
|
|
1332
|
+
ctx.errors.push("maskedBy.href missing \u2014 cannot build mask");
|
|
1333
|
+
return node;
|
|
1334
|
+
}
|
|
1335
|
+
const maskId = genId(ctx, "mask");
|
|
1336
|
+
let content = { type: "use", href: "#" + fx.href };
|
|
1337
|
+
if (transformation) {
|
|
1338
|
+
content = wrapInverseTransform(content, transformation, ctx);
|
|
1339
|
+
} else if (hasAnimateTransform(node)) {
|
|
1340
|
+
content = wrapInverseAnimatedBodyTransform(content, node, ctx);
|
|
1341
|
+
} else {
|
|
1342
|
+
const bodyStatic = readTransformationFromBody(node);
|
|
1343
|
+
if (bodyStatic) content = wrapInverseTransform(content, bodyStatic, ctx);
|
|
1344
|
+
}
|
|
1345
|
+
const includeTargetOwn = transformation === void 0 && !nodeHasBodyTransform(node);
|
|
1346
|
+
content = wrapAncestorChainCompensation(content, node, fx.href, ctx, includeTargetOwn);
|
|
1347
|
+
const mask = { type: "mask", id: maskId, children: [content] };
|
|
1348
|
+
if (fx.maskType) mask.maskType = fx.maskType;
|
|
1349
|
+
if (fx.maskUnits) mask.maskUnits = fx.maskUnits;
|
|
1350
|
+
if (fx.maskContentUnits) mask.maskContentUnits = fx.maskContentUnits;
|
|
1351
|
+
ctx.defs.push(mask);
|
|
1352
|
+
node.mask = "url(#" + maskId + ")";
|
|
1353
|
+
return node;
|
|
1354
|
+
}
|
|
1355
|
+
function wrapInverseTransform(inner, fx, ctx) {
|
|
1356
|
+
if (!fx) return inner;
|
|
1357
|
+
const origin = readStaticOrigin(fx.origin, ctx);
|
|
1358
|
+
let n = inner;
|
|
1359
|
+
n = wrapInversePart(n, "translate" /* Translate */, fx.translate, void 0, ctx);
|
|
1360
|
+
n = wrapInversePart(n, "rotate" /* Rotate */, fx.rotate, origin, ctx);
|
|
1361
|
+
n = wrapInversePart(n, "scale" /* Scale */, fx.scale, origin, ctx);
|
|
1362
|
+
return n;
|
|
1363
|
+
}
|
|
1364
|
+
function wrapInversePart(inner, part, raw, origin, ctx) {
|
|
1365
|
+
if (raw === void 0) return inner;
|
|
1366
|
+
const normalisedRaw = part === "scale" /* Scale */ && Array.isArray(raw) ? [raw[0] / 100, raw[1] / 100] : raw;
|
|
1367
|
+
const v = readAnimatable(normalisedRaw);
|
|
1368
|
+
if (v.kind === "static" /* Static */) {
|
|
1369
|
+
return { type: "g", transform: { value: partsRecord(part, invertPartValue(part, v.value), origin) }, children: [inner] };
|
|
1370
|
+
}
|
|
1371
|
+
if (v.kind === "animated" /* Animated */) {
|
|
1372
|
+
return {
|
|
1373
|
+
type: "g",
|
|
1374
|
+
animate: { transform: { keyframes: v.keyframes.map((kf) => keyframeWith(kf, partsRecord(part, invertPartValue(part, kf.value), origin))) } },
|
|
1375
|
+
children: [inner]
|
|
1376
|
+
};
|
|
1377
|
+
}
|
|
1378
|
+
return inner;
|
|
1379
|
+
}
|
|
1380
|
+
function invertPartValue(part, value) {
|
|
1381
|
+
if (part === "translate" /* Translate */) return [-value[0], -value[1]];
|
|
1382
|
+
if (part === "rotate" /* Rotate */) return -value;
|
|
1383
|
+
return [1 / value[0], 1 / value[1]];
|
|
1384
|
+
}
|
|
1385
|
+
function wrapInverseAnimatedBodyTransform(inner, node, _ctx) {
|
|
1386
|
+
var _a;
|
|
1387
|
+
const animate = node.animate && typeof node.animate === "object" && !Array.isArray(node.animate) ? node.animate : void 0;
|
|
1388
|
+
const animTr = animate == null ? void 0 : animate.transform;
|
|
1389
|
+
const kfs = animTr && typeof animTr === "object" && Array.isArray(animTr.keyframes) ? animTr.keyframes : void 0;
|
|
1390
|
+
if (!kfs || !kfs.length) return inner;
|
|
1391
|
+
const translateKfs = [];
|
|
1392
|
+
const rotateKfs = [];
|
|
1393
|
+
const scaleKfs = [];
|
|
1394
|
+
for (const kf of kfs) {
|
|
1395
|
+
const v = ((_a = kf.value) != null ? _a : kf.v) || {};
|
|
1396
|
+
const baseKf = keyframeWith(kf, void 0);
|
|
1397
|
+
if (Array.isArray(v.translate)) {
|
|
1398
|
+
translateKfs.push(__spreadProps(__spreadValues({}, baseKf), { value: { translate: [-v.translate[0], -v.translate[1]] } }));
|
|
1399
|
+
}
|
|
1400
|
+
if (typeof v.rotate === "number") {
|
|
1401
|
+
const rec = { rotate: -v.rotate };
|
|
1402
|
+
if (Array.isArray(v.origin)) rec.origin = [v.origin[0], v.origin[1]];
|
|
1403
|
+
rotateKfs.push(__spreadProps(__spreadValues({}, baseKf), { value: rec }));
|
|
1404
|
+
}
|
|
1405
|
+
if (Array.isArray(v.scale)) {
|
|
1406
|
+
const rec = { scale: [1 / v.scale[0], 1 / v.scale[1]] };
|
|
1407
|
+
if (Array.isArray(v.origin)) rec.origin = [v.origin[0], v.origin[1]];
|
|
1408
|
+
scaleKfs.push(__spreadProps(__spreadValues({}, baseKf), { value: rec }));
|
|
1409
|
+
}
|
|
1410
|
+
}
|
|
1411
|
+
let n = inner;
|
|
1412
|
+
if (translateKfs.length) n = { type: "g", animate: { transform: { keyframes: translateKfs } }, children: [n] };
|
|
1413
|
+
if (rotateKfs.length) n = { type: "g", animate: { transform: { keyframes: rotateKfs } }, children: [n] };
|
|
1414
|
+
if (scaleKfs.length) n = { type: "g", animate: { transform: { keyframes: scaleKfs } }, children: [n] };
|
|
1415
|
+
return n;
|
|
1416
|
+
}
|
|
1417
|
+
function nodeHasBodyTransform(node) {
|
|
1418
|
+
if (typeof node.transform === "string") return true;
|
|
1419
|
+
if (node.transform && typeof node.transform === "object") return true;
|
|
1420
|
+
return hasAnimateTransform(node);
|
|
1421
|
+
}
|
|
1422
|
+
function hasAnimateTransform(node) {
|
|
1423
|
+
const animate = node.animate && typeof node.animate === "object" && !Array.isArray(node.animate) ? node.animate : void 0;
|
|
1424
|
+
return !!(animate && animate.transform);
|
|
1425
|
+
}
|
|
1426
|
+
function readTransformationFromBody(node) {
|
|
1427
|
+
if (typeof node.transform === "string") {
|
|
1428
|
+
const parts = parseTransformStringToParts(node.transform);
|
|
1429
|
+
if (!parts) return void 0;
|
|
1430
|
+
const out = {};
|
|
1431
|
+
if (parts.translate) out.translate = parts.translate;
|
|
1432
|
+
if (parts.rotate !== void 0) out.rotate = parts.rotate;
|
|
1433
|
+
if (parts.scale) out.scale = { value: parts.scale };
|
|
1434
|
+
if (parts.origin) out.origin = parts.origin;
|
|
1435
|
+
return Object.keys(out).length ? out : void 0;
|
|
1436
|
+
}
|
|
1437
|
+
return void 0;
|
|
1438
|
+
}
|
|
1439
|
+
function parseTransformStringToParts(s) {
|
|
1440
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m;
|
|
1441
|
+
const re = /([a-zA-Z]+)\s*\(([^)]*)\)/g;
|
|
1442
|
+
let m;
|
|
1443
|
+
const ops = [];
|
|
1444
|
+
while ((m = re.exec(s)) !== null) {
|
|
1445
|
+
const args = m[2].split(/[\s,]+/).filter((a) => a.length > 0).map(Number);
|
|
1446
|
+
ops.push({ name: m[1], args });
|
|
1447
|
+
}
|
|
1448
|
+
if (!ops.length) return void 0;
|
|
1449
|
+
const last = ops[ops.length - 1];
|
|
1450
|
+
if (last.name === "translate") {
|
|
1451
|
+
for (let j = ops.length - 2; j >= 0; j--) {
|
|
1452
|
+
const cand = ops[j];
|
|
1453
|
+
if (cand.name !== "translate") continue;
|
|
1454
|
+
const ox = (_a = cand.args[0]) != null ? _a : 0;
|
|
1455
|
+
const oy = (_b = cand.args[1]) != null ? _b : 0;
|
|
1456
|
+
const lx = (_c = last.args[0]) != null ? _c : 0;
|
|
1457
|
+
const ly = (_d = last.args[1]) != null ? _d : 0;
|
|
1458
|
+
if (lx !== -ox || ly !== -oy) continue;
|
|
1459
|
+
const out2 = {};
|
|
1460
|
+
out2.origin = [ox, oy];
|
|
1461
|
+
for (let k = 0; k < j; k++) {
|
|
1462
|
+
if (ops[k].name === "translate") {
|
|
1463
|
+
const tx = (_e = ops[k].args[0]) != null ? _e : 0;
|
|
1464
|
+
const ty = (_f = ops[k].args[1]) != null ? _f : 0;
|
|
1465
|
+
out2.translate = out2.translate ? [out2.translate[0] + tx, out2.translate[1] + ty] : [tx, ty];
|
|
1466
|
+
}
|
|
1467
|
+
}
|
|
1468
|
+
for (let k = j + 1; k < ops.length - 1; k++) {
|
|
1469
|
+
const op = ops[k];
|
|
1470
|
+
if (op.name === "rotate") out2.rotate = ((_g = out2.rotate) != null ? _g : 0) + ((_h = op.args[0]) != null ? _h : 0);
|
|
1471
|
+
else if (op.name === "scale") {
|
|
1472
|
+
const sx = (_i = op.args[0]) != null ? _i : 1;
|
|
1473
|
+
const sy = op.args.length > 1 ? op.args[1] : sx;
|
|
1474
|
+
out2.scale = out2.scale ? [out2.scale[0] * sx, out2.scale[1] * sy] : [sx, sy];
|
|
1475
|
+
}
|
|
1476
|
+
}
|
|
1477
|
+
return out2;
|
|
1478
|
+
}
|
|
1479
|
+
}
|
|
1480
|
+
let translate;
|
|
1481
|
+
let rotate;
|
|
1482
|
+
let scale;
|
|
1483
|
+
for (const op of ops) {
|
|
1484
|
+
if (op.name === "translate") {
|
|
1485
|
+
const dx = (_j = op.args[0]) != null ? _j : 0;
|
|
1486
|
+
const dy = (_k = op.args[1]) != null ? _k : 0;
|
|
1487
|
+
translate = translate ? [translate[0] + dx, translate[1] + dy] : [dx, dy];
|
|
1488
|
+
} else if (op.name === "rotate") {
|
|
1489
|
+
rotate = (rotate != null ? rotate : 0) + ((_l = op.args[0]) != null ? _l : 0);
|
|
1490
|
+
} else if (op.name === "scale") {
|
|
1491
|
+
const sx = (_m = op.args[0]) != null ? _m : 1;
|
|
1492
|
+
const sy = op.args.length > 1 ? op.args[1] : sx;
|
|
1493
|
+
scale = scale ? [scale[0] * sx, scale[1] * sy] : [sx, sy];
|
|
1494
|
+
}
|
|
1495
|
+
}
|
|
1496
|
+
const out = {};
|
|
1497
|
+
if (translate) out.translate = translate;
|
|
1498
|
+
if (rotate !== void 0) out.rotate = rotate;
|
|
1499
|
+
if (scale) out.scale = scale;
|
|
1500
|
+
return Object.keys(out).length ? out : void 0;
|
|
1501
|
+
}
|
|
1502
|
+
function wrapAncestorChainCompensation(inner, maskedNode, sourceId, ctx, includeTargetOwn) {
|
|
1503
|
+
const sourceNode = ctx.idMap.get(sourceId);
|
|
1504
|
+
const targetAncestors = ctx.maskAncestorChains.get(maskedNode) || [];
|
|
1505
|
+
const targetOwn = includeTargetOwn ? extractTranslateOnly(maskedNode, ctx) : void 0;
|
|
1506
|
+
const targetChain = targetOwn ? [...targetAncestors, targetOwn] : targetAncestors;
|
|
1507
|
+
const sourceChain = sourceNode && ctx.maskAncestorChains.get(sourceNode) || [];
|
|
1508
|
+
if (!targetChain.length && !sourceChain.length) return inner;
|
|
1509
|
+
const times = /* @__PURE__ */ new Set();
|
|
1510
|
+
for (const a of targetChain) if (a.translateKeyframes) for (const kf of a.translateKeyframes) times.add(kf.time);
|
|
1511
|
+
for (const a of sourceChain) if (a.translateKeyframes) for (const kf of a.translateKeyframes) times.add(kf.time);
|
|
1512
|
+
const animated = times.size > 0;
|
|
1513
|
+
if (!animated) {
|
|
1514
|
+
const tgt = sumStaticTranslate(targetChain);
|
|
1515
|
+
const src = sumStaticTranslate(sourceChain);
|
|
1516
|
+
const dx = src[0] - tgt[0];
|
|
1517
|
+
const dy = src[1] - tgt[1];
|
|
1518
|
+
if (dx === 0 && dy === 0) return inner;
|
|
1519
|
+
return { type: "g", transform: "translate(" + dx + "," + dy + ")", children: [inner] };
|
|
1520
|
+
}
|
|
1521
|
+
const sortedTimes = Array.from(times).sort((a, b) => a - b);
|
|
1522
|
+
const keyframes = sortedTimes.map((t) => {
|
|
1523
|
+
const tgt = sumTranslateAt(targetChain, t);
|
|
1524
|
+
const src = sumTranslateAt(sourceChain, t);
|
|
1525
|
+
return { time: t, value: { translate: [src[0] - tgt[0], src[1] - tgt[1]] } };
|
|
1526
|
+
});
|
|
1527
|
+
return { type: "g", animate: { transform: { keyframes } }, children: [inner] };
|
|
1528
|
+
}
|
|
1529
|
+
function sumStaticTranslate(chain) {
|
|
1530
|
+
let x = 0, y = 0;
|
|
1531
|
+
for (const a of chain) {
|
|
1532
|
+
if (a.translate) {
|
|
1533
|
+
x += a.translate[0];
|
|
1534
|
+
y += a.translate[1];
|
|
1535
|
+
}
|
|
1536
|
+
}
|
|
1537
|
+
return [x, y];
|
|
1538
|
+
}
|
|
1539
|
+
function sumTranslateAt(chain, t) {
|
|
1540
|
+
let x = 0, y = 0;
|
|
1541
|
+
for (const a of chain) {
|
|
1542
|
+
if (a.translateKeyframes && a.translateKeyframes.length) {
|
|
1543
|
+
const v = interpKfs(a.translateKeyframes, t);
|
|
1544
|
+
x += v[0];
|
|
1545
|
+
y += v[1];
|
|
1546
|
+
} else if (a.translate) {
|
|
1547
|
+
x += a.translate[0];
|
|
1548
|
+
y += a.translate[1];
|
|
1549
|
+
}
|
|
1550
|
+
}
|
|
1551
|
+
return [x, y];
|
|
1552
|
+
}
|
|
1553
|
+
function interpKfs(kfs, t) {
|
|
1554
|
+
if (t <= kfs[0].time) return kfs[0].value;
|
|
1555
|
+
if (t >= kfs[kfs.length - 1].time) return kfs[kfs.length - 1].value;
|
|
1556
|
+
for (let i = 1; i < kfs.length; i++) {
|
|
1557
|
+
if (t <= kfs[i].time) {
|
|
1558
|
+
const prev = kfs[i - 1];
|
|
1559
|
+
const cur = kfs[i];
|
|
1560
|
+
const a = (t - prev.time) / (cur.time - prev.time);
|
|
1561
|
+
return [prev.value[0] + (cur.value[0] - prev.value[0]) * a, prev.value[1] + (cur.value[1] - prev.value[1]) * a];
|
|
1562
|
+
}
|
|
1563
|
+
}
|
|
1564
|
+
return kfs[kfs.length - 1].value;
|
|
1565
|
+
}
|
|
1566
|
+
function collectMaskAncestorChains(root, ctx) {
|
|
1567
|
+
const interestingNodes = /* @__PURE__ */ new Set();
|
|
1568
|
+
const collectInterestingNodes = (n) => {
|
|
1569
|
+
var _a, _b;
|
|
1570
|
+
const href = (_b = (_a = n.effects) == null ? void 0 : _a.maskedBy) == null ? void 0 : _b.href;
|
|
1571
|
+
if (typeof href === "string") {
|
|
1572
|
+
interestingNodes.add(n);
|
|
1573
|
+
const sourceNode = ctx.idMap.get(href);
|
|
1574
|
+
if (sourceNode) interestingNodes.add(sourceNode);
|
|
1575
|
+
}
|
|
1576
|
+
if (Array.isArray(n.children)) for (const ch of n.children) collectInterestingNodes(ch);
|
|
1577
|
+
};
|
|
1578
|
+
collectInterestingNodes(root);
|
|
1579
|
+
if (interestingNodes.size === 0) return;
|
|
1580
|
+
const walk = (node, chain) => {
|
|
1581
|
+
if (interestingNodes.has(node)) ctx.maskAncestorChains.set(node, chain);
|
|
1582
|
+
if (Array.isArray(node.children)) {
|
|
1583
|
+
const own = extractTranslateOnly(node, ctx);
|
|
1584
|
+
const next = own ? [...chain, own] : chain;
|
|
1585
|
+
for (const ch of node.children) walk(ch, next);
|
|
1586
|
+
}
|
|
1587
|
+
};
|
|
1588
|
+
walk(root, []);
|
|
1589
|
+
}
|
|
1590
|
+
function extractTranslateOnly(node, ctx) {
|
|
1591
|
+
var _a, _b, _c;
|
|
1592
|
+
const tr = node.transform;
|
|
1593
|
+
const animateBlock = node.animate && typeof node.animate === "object" && !Array.isArray(node.animate) ? node.animate.transform : void 0;
|
|
1594
|
+
if (tr === void 0 && !animateBlock) return void 0;
|
|
1595
|
+
const out = {};
|
|
1596
|
+
if (typeof tr === "string") {
|
|
1597
|
+
const parts = parseTranslateOnlyFromString(tr, ctx);
|
|
1598
|
+
if (parts) out.translate = parts;
|
|
1599
|
+
} else if (tr && typeof tr === "object") {
|
|
1600
|
+
const value = tr.value;
|
|
1601
|
+
if (value && typeof value === "object" && Array.isArray(value.translate)) {
|
|
1602
|
+
out.translate = [value.translate[0] || 0, value.translate[1] || 0];
|
|
1603
|
+
}
|
|
1604
|
+
if (value && (value.rotate !== void 0 || value.scale !== void 0 || value.skew !== void 0)) {
|
|
1605
|
+
ctx.warnings.push("maskedBy ancestor: non-translate transform parts ignored (rotate/scale not yet supported)");
|
|
1606
|
+
}
|
|
1607
|
+
}
|
|
1608
|
+
if (animateBlock && Array.isArray(animateBlock.keyframes)) {
|
|
1609
|
+
const kfs = animateBlock.keyframes;
|
|
1610
|
+
const translateKfs = [];
|
|
1611
|
+
for (const kf of kfs) {
|
|
1612
|
+
const v = (_a = kf.value) != null ? _a : kf.v;
|
|
1613
|
+
const t = (_c = (_b = kf.time) != null ? _b : kf.t) != null ? _c : 0;
|
|
1614
|
+
if (v && typeof v === "object" && Array.isArray(v.translate)) {
|
|
1615
|
+
translateKfs.push({ time: t, value: [v.translate[0] || 0, v.translate[1] || 0] });
|
|
1616
|
+
if (v.rotate !== void 0 || v.scale !== void 0 || v.skew !== void 0) {
|
|
1617
|
+
ctx.warnings.push("maskedBy ancestor: animated non-translate parts ignored");
|
|
1618
|
+
}
|
|
1619
|
+
}
|
|
1620
|
+
}
|
|
1621
|
+
if (translateKfs.length) out.translateKeyframes = translateKfs;
|
|
1622
|
+
}
|
|
1623
|
+
return out.translate || out.translateKeyframes ? out : void 0;
|
|
1624
|
+
}
|
|
1625
|
+
function parseTranslateOnlyFromString(s, ctx) {
|
|
1626
|
+
const re = /([a-zA-Z]+)\s*\(([^)]*)\)/g;
|
|
1627
|
+
let m;
|
|
1628
|
+
let x = 0, y = 0;
|
|
1629
|
+
let seen = false;
|
|
1630
|
+
let droppedNonTranslate = false;
|
|
1631
|
+
while ((m = re.exec(s)) !== null) {
|
|
1632
|
+
const name = m[1];
|
|
1633
|
+
const args = m[2].split(/[\s,]+/).filter((a) => a.length > 0).map(Number);
|
|
1634
|
+
if (name === "translate") {
|
|
1635
|
+
x += args[0] || 0;
|
|
1636
|
+
y += args[1] || 0;
|
|
1637
|
+
seen = true;
|
|
1638
|
+
} else {
|
|
1639
|
+
droppedNonTranslate = true;
|
|
1640
|
+
}
|
|
1641
|
+
}
|
|
1642
|
+
if (droppedNonTranslate) ctx.warnings.push("maskedBy ancestor: non-translate transform in string ignored: " + s);
|
|
1643
|
+
return seen ? [x, y] : void 0;
|
|
1644
|
+
}
|
|
1645
|
+
|
|
1646
|
+
// src/effects/refEffect.ts
|
|
1647
|
+
var CONTENT_SUBREF = "content";
|
|
1648
|
+
function applyRefAndTransformationEffect(node, ref, transformation, ctx) {
|
|
1649
|
+
if (ref) {
|
|
1650
|
+
const baseId = ref.baseId;
|
|
1651
|
+
if (!baseId) {
|
|
1652
|
+
ctx.errors.push("ref: missing baseId");
|
|
1653
|
+
} else {
|
|
1654
|
+
const targetId = ref.type === CONTENT_SUBREF ? ctx.contentRefInnerIds.get(baseId) || baseId : baseId;
|
|
1655
|
+
node.href = "#" + targetId;
|
|
1656
|
+
}
|
|
1657
|
+
}
|
|
1658
|
+
return applyTransformationEffect(node, transformation, ctx);
|
|
1659
|
+
}
|
|
1660
|
+
|
|
1661
|
+
// src/effects/repeaterEffect.ts
|
|
1662
|
+
function applyRepeaterEffect(node, fx, ctx) {
|
|
1663
|
+
var _a, _b;
|
|
1664
|
+
if (!fx) return node;
|
|
1665
|
+
const copies = (_a = fx.copies) != null ? _a : 1;
|
|
1666
|
+
if (copies < 1) {
|
|
1667
|
+
ctx.errors.push("repeater.copies invalid: " + fx.copies);
|
|
1668
|
+
return node;
|
|
1669
|
+
}
|
|
1670
|
+
const sharedTransform = node.transform;
|
|
1671
|
+
const sharedAnimTransform = (_b = node.animate) == null ? void 0 : _b.transform;
|
|
1672
|
+
const base = clone(node);
|
|
1673
|
+
delete base.transform;
|
|
1674
|
+
if (base.animate) {
|
|
1675
|
+
delete base.animate.transform;
|
|
1676
|
+
if (Object.keys(base.animate).length === 0) delete base.animate;
|
|
1677
|
+
}
|
|
1678
|
+
const children = [base];
|
|
1679
|
+
for (let i = 1; i < copies; i++) {
|
|
1680
|
+
const baseClone = clone(base);
|
|
1681
|
+
const synthFx = synthesisePerCopyFx(fx, i);
|
|
1682
|
+
const wrapped = synthFx ? applyTransformationEffect(baseClone, synthFx, ctx) : baseClone;
|
|
1683
|
+
children.push(wrapped);
|
|
1684
|
+
}
|
|
1685
|
+
const wrapper = { type: "g", children };
|
|
1686
|
+
if (sharedTransform !== void 0) wrapper.transform = sharedTransform;
|
|
1687
|
+
if (sharedAnimTransform !== void 0) wrapper.animate = { transform: sharedAnimTransform };
|
|
1688
|
+
return wrapper;
|
|
1689
|
+
}
|
|
1690
|
+
function synthesisePerCopyFx(fx, i) {
|
|
1691
|
+
const out = {};
|
|
1692
|
+
if (fx.translate !== void 0) {
|
|
1693
|
+
out.translate = mapAnimatableVec2(fx.translate, (v) => [v[0] * i, v[1] * i]);
|
|
1694
|
+
}
|
|
1695
|
+
if (fx.rotate !== void 0) {
|
|
1696
|
+
out.rotate = mapAnimatableNumber(fx.rotate, (v) => v * i);
|
|
1697
|
+
}
|
|
1698
|
+
if (fx.scale !== void 0) {
|
|
1699
|
+
out.scale = synthesiseScale(fx.scale, i);
|
|
1700
|
+
}
|
|
1701
|
+
if (fx.origin !== void 0) {
|
|
1702
|
+
out.origin = fx.origin;
|
|
1703
|
+
}
|
|
1704
|
+
return Object.keys(out).length ? out : void 0;
|
|
1705
|
+
}
|
|
1706
|
+
function mapAnimatableVec2(raw, fn) {
|
|
1707
|
+
if (Array.isArray(raw)) return fn(raw);
|
|
1708
|
+
if (raw && typeof raw === "object") {
|
|
1709
|
+
const obj = raw;
|
|
1710
|
+
if (Array.isArray(obj.keyframes)) {
|
|
1711
|
+
return __spreadProps(__spreadValues({}, obj), {
|
|
1712
|
+
keyframes: obj.keyframes.map((kf) => kf && kf.value !== void 0 ? __spreadProps(__spreadValues({}, kf), { value: fn(kf.value) }) : kf)
|
|
1713
|
+
});
|
|
1714
|
+
}
|
|
1715
|
+
if (obj.value !== void 0) {
|
|
1716
|
+
return __spreadProps(__spreadValues({}, obj), { value: fn(obj.value) });
|
|
1717
|
+
}
|
|
1718
|
+
}
|
|
1719
|
+
return raw;
|
|
1720
|
+
}
|
|
1721
|
+
function mapAnimatableNumber(raw, fn) {
|
|
1722
|
+
if (typeof raw === "number") return fn(raw);
|
|
1723
|
+
if (raw && typeof raw === "object") {
|
|
1724
|
+
const obj = raw;
|
|
1725
|
+
if (Array.isArray(obj.keyframes)) {
|
|
1726
|
+
return __spreadProps(__spreadValues({}, obj), {
|
|
1727
|
+
keyframes: obj.keyframes.map((kf) => kf && kf.value !== void 0 ? __spreadProps(__spreadValues({}, kf), { value: fn(kf.value) }) : kf)
|
|
1728
|
+
});
|
|
1729
|
+
}
|
|
1730
|
+
if (obj.value !== void 0) {
|
|
1731
|
+
return __spreadProps(__spreadValues({}, obj), { value: fn(obj.value) });
|
|
1732
|
+
}
|
|
1733
|
+
}
|
|
1734
|
+
return raw;
|
|
1735
|
+
}
|
|
1736
|
+
function synthesiseScale(raw, i) {
|
|
1737
|
+
const scalePowerFromPercent = (v) => [Math.pow(v[0] / 100, i), Math.pow(v[1] / 100, i)];
|
|
1738
|
+
const scalePowerFromUnits = (v) => [Math.pow(v[0], i), Math.pow(v[1], i)];
|
|
1739
|
+
if (Array.isArray(raw)) {
|
|
1740
|
+
return { value: scalePowerFromPercent(raw) };
|
|
1741
|
+
}
|
|
1742
|
+
if (raw && typeof raw === "object") {
|
|
1743
|
+
const obj = raw;
|
|
1744
|
+
if (Array.isArray(obj.keyframes)) {
|
|
1745
|
+
return __spreadProps(__spreadValues({}, obj), {
|
|
1746
|
+
keyframes: obj.keyframes.map((kf) => kf && kf.value !== void 0 ? __spreadProps(__spreadValues({}, kf), { value: scalePowerFromUnits(kf.value) }) : kf)
|
|
1747
|
+
});
|
|
1748
|
+
}
|
|
1749
|
+
if (obj.value !== void 0) {
|
|
1750
|
+
return __spreadProps(__spreadValues({}, obj), { value: scalePowerFromPercent(obj.value) });
|
|
1751
|
+
}
|
|
1752
|
+
}
|
|
1753
|
+
return raw;
|
|
1754
|
+
}
|
|
1755
|
+
|
|
1756
|
+
// src/effects/retimeEffect.ts
|
|
1757
|
+
var RETIME_MATERIALISATION_MODE_INLINE_G = false;
|
|
1758
|
+
function asRetime(r) {
|
|
1759
|
+
var _a, _b;
|
|
1760
|
+
return { start: (_a = r.start) != null ? _a : 0, stretch: (_b = r.stretch) != null ? _b : 1 };
|
|
1761
|
+
}
|
|
1762
|
+
function concatRetime(child, parent) {
|
|
1763
|
+
return {
|
|
1764
|
+
start: parent.start + parent.stretch * child.start,
|
|
1765
|
+
stretch: parent.stretch * child.stretch
|
|
1766
|
+
};
|
|
1767
|
+
}
|
|
1768
|
+
function applyAllRetimeEffects(root, ctx) {
|
|
1769
|
+
var _a;
|
|
1770
|
+
ctx.idMap.clear();
|
|
1771
|
+
indexById(root, ctx.idMap);
|
|
1772
|
+
const sites = [];
|
|
1773
|
+
const collect = (n) => {
|
|
1774
|
+
var _a2, _b;
|
|
1775
|
+
if ((_a2 = n.effects) == null ? void 0 : _a2.retime) sites.push(n);
|
|
1776
|
+
(_b = n.children) == null ? void 0 : _b.forEach(collect);
|
|
1777
|
+
};
|
|
1778
|
+
collect(root);
|
|
1779
|
+
for (const useNode of sites) {
|
|
1780
|
+
const retime = (_a = useNode.effects) == null ? void 0 : _a.retime;
|
|
1781
|
+
if (!retime) continue;
|
|
1782
|
+
delete useNode.effects.retime;
|
|
1783
|
+
if (Object.keys(useNode.effects).length === 0) delete useNode.effects;
|
|
1784
|
+
materialiseRetime(useNode, asRetime(retime), ctx);
|
|
1785
|
+
}
|
|
1786
|
+
}
|
|
1787
|
+
function materialiseRetime(useNode, retime, ctx) {
|
|
1788
|
+
const targetId = stripHash(useNode.href);
|
|
1789
|
+
if (!targetId) {
|
|
1790
|
+
ctx.errors.push("retime: <use> has no href to follow");
|
|
1791
|
+
return;
|
|
1792
|
+
}
|
|
1793
|
+
const chainRootId = buildChainClone(targetId, retime, ctx, /* @__PURE__ */ new Set());
|
|
1794
|
+
if (!chainRootId) return;
|
|
1795
|
+
if (RETIME_MATERIALISATION_MODE_INLINE_G) {
|
|
1796
|
+
const cloneNode = ctx.idMap.get(chainRootId);
|
|
1797
|
+
useNode.type = "g";
|
|
1798
|
+
delete useNode.href;
|
|
1799
|
+
useNode.children = [cloneNode];
|
|
1800
|
+
applyUseOffsetToG(useNode);
|
|
1801
|
+
ctx.defs = ctx.defs.filter((d) => d !== cloneNode);
|
|
1802
|
+
} else {
|
|
1803
|
+
useNode.href = "#" + chainRootId;
|
|
1804
|
+
}
|
|
1805
|
+
}
|
|
1806
|
+
function buildChainClone(targetId, accum, ctx, chain) {
|
|
1807
|
+
var _a, _b;
|
|
1808
|
+
if (chain.has(targetId)) {
|
|
1809
|
+
ctx.errors.push('retime: loop via "' + targetId + '"');
|
|
1810
|
+
return void 0;
|
|
1811
|
+
}
|
|
1812
|
+
const target = ctx.idMap.get(targetId);
|
|
1813
|
+
if (!target) {
|
|
1814
|
+
ctx.warnings.push('retime: target "' + targetId + '" not found');
|
|
1815
|
+
return void 0;
|
|
1816
|
+
}
|
|
1817
|
+
const cloneNode = clone(target);
|
|
1818
|
+
regenerateIdsInClone(cloneNode, ctx);
|
|
1819
|
+
if (target.type === "use") {
|
|
1820
|
+
remapKeyframeTimesOnly(cloneNode, accum.start, accum.stretch);
|
|
1821
|
+
} else {
|
|
1822
|
+
remapKeyframeTimes(cloneNode, accum.start, accum.stretch);
|
|
1823
|
+
}
|
|
1824
|
+
if ((_a = cloneNode.effects) == null ? void 0 : _a.retime) {
|
|
1825
|
+
delete cloneNode.effects.retime;
|
|
1826
|
+
if (Object.keys(cloneNode.effects).length === 0) delete cloneNode.effects;
|
|
1827
|
+
}
|
|
1828
|
+
if (target.type === "use" && target.href) {
|
|
1829
|
+
const subId = stripHash(target.href);
|
|
1830
|
+
if (subId) {
|
|
1831
|
+
const innerRetime = (_b = target.effects) == null ? void 0 : _b.retime;
|
|
1832
|
+
const subAccum = innerRetime ? concatRetime(asRetime(innerRetime), accum) : accum;
|
|
1833
|
+
const subChain = new Set(chain);
|
|
1834
|
+
subChain.add(targetId);
|
|
1835
|
+
const subId2 = buildChainClone(subId, subAccum, ctx, subChain);
|
|
1836
|
+
if (subId2) cloneNode.href = "#" + subId2;
|
|
1837
|
+
}
|
|
1838
|
+
}
|
|
1839
|
+
ctx.defs.push(cloneNode);
|
|
1840
|
+
if (typeof cloneNode.id === "string") ctx.idMap.set(cloneNode.id, cloneNode);
|
|
1841
|
+
return typeof cloneNode.id === "string" ? cloneNode.id : void 0;
|
|
1842
|
+
}
|
|
1843
|
+
function remapKeyframeTimes(node, start, stretch) {
|
|
1844
|
+
var _a;
|
|
1845
|
+
remapKeyframeTimesOnly(node, start, stretch);
|
|
1846
|
+
(_a = node.children) == null ? void 0 : _a.forEach((c) => remapKeyframeTimes(c, start, stretch));
|
|
1847
|
+
}
|
|
1848
|
+
function remapKeyframeTimesOnly(node, start, stretch) {
|
|
1849
|
+
const remap2 = (kfs) => {
|
|
1850
|
+
for (const kf of kfs) if (typeof kf.time === "number") kf.time = start + kf.time * stretch;
|
|
1851
|
+
};
|
|
1852
|
+
if (node.transform && typeof node.transform === "object" && Array.isArray(node.transform.keyframes)) {
|
|
1853
|
+
remap2(node.transform.keyframes);
|
|
1854
|
+
}
|
|
1855
|
+
if (node.animate && typeof node.animate === "object") {
|
|
1856
|
+
for (const prop of Object.keys(node.animate)) {
|
|
1857
|
+
const anim = node.animate[prop];
|
|
1858
|
+
if (anim && Array.isArray(anim.keyframes)) remap2(anim.keyframes);
|
|
1859
|
+
}
|
|
1860
|
+
}
|
|
1861
|
+
}
|
|
1862
|
+
|
|
1863
|
+
// src/effects/textAlongPathEffect.ts
|
|
1864
|
+
function applyTextAlongPathEffect(node, fx, _ctx) {
|
|
1865
|
+
var _a;
|
|
1866
|
+
if (!fx) return node;
|
|
1867
|
+
const href = typeof fx.href === "string" && !fx.href.startsWith("#") ? "#" + fx.href : fx.href;
|
|
1868
|
+
const textPath = {
|
|
1869
|
+
type: "textPath",
|
|
1870
|
+
href,
|
|
1871
|
+
children: (_a = node.children) != null ? _a : []
|
|
1872
|
+
};
|
|
1873
|
+
if (fx.lengthAdjust !== void 0) textPath.lengthAdjust = fx.lengthAdjust;
|
|
1874
|
+
if (fx.method !== void 0) textPath.method = fx.method;
|
|
1875
|
+
if (fx.spacing !== void 0) textPath.spacing = fx.spacing;
|
|
1876
|
+
applyAnimatableNumber(textPath, "startOffset", fx.startOffset);
|
|
1877
|
+
applyAnimatableNumber(textPath, "textLength", fx.textLength);
|
|
1878
|
+
node.children = [textPath];
|
|
1879
|
+
return node;
|
|
1880
|
+
}
|
|
1881
|
+
function applyAnimatableNumber(node, attrName, raw) {
|
|
1882
|
+
if (raw === void 0 || raw === null) return;
|
|
1883
|
+
if (typeof raw === "number") {
|
|
1884
|
+
node[attrName] = String(raw);
|
|
1885
|
+
return;
|
|
1886
|
+
}
|
|
1887
|
+
if (typeof raw === "object") {
|
|
1888
|
+
const obj = raw;
|
|
1889
|
+
if (Array.isArray(obj.keyframes)) {
|
|
1890
|
+
const prevAnimate = node.animate && typeof node.animate === "object" && !Array.isArray(node.animate) ? node.animate : void 0;
|
|
1891
|
+
const animate = __spreadValues({}, prevAnimate || {});
|
|
1892
|
+
animate[attrName] = { keyframes: obj.keyframes };
|
|
1893
|
+
node.animate = animate;
|
|
1894
|
+
return;
|
|
1895
|
+
}
|
|
1896
|
+
if (typeof obj.value === "number") {
|
|
1897
|
+
node[attrName] = String(obj.value);
|
|
1898
|
+
return;
|
|
1899
|
+
}
|
|
1900
|
+
}
|
|
1901
|
+
}
|
|
1902
|
+
|
|
1903
|
+
// src/PxAnimatorUtil.ts
|
|
1904
|
+
function bezierToSvgPath(path) {
|
|
1905
|
+
var _a, _b, _c, _d;
|
|
1906
|
+
const v = path.v;
|
|
1907
|
+
const i = path.i;
|
|
1908
|
+
const o = path.o;
|
|
1909
|
+
const c = path.c;
|
|
1910
|
+
if (!v.length) return "";
|
|
1911
|
+
const d = [];
|
|
1912
|
+
const len = v.length;
|
|
1913
|
+
d.push("M" + v[0][0] + "," + v[0][1]);
|
|
1914
|
+
for (let idx = 1; idx < len; idx++) {
|
|
1915
|
+
const prevV = v[idx - 1];
|
|
1916
|
+
const prevO = (_a = o == null ? void 0 : o[idx - 1]) != null ? _a : prevV;
|
|
1917
|
+
const currI = (_b = i == null ? void 0 : i[idx]) != null ? _b : v[idx];
|
|
1918
|
+
const currV = v[idx];
|
|
1919
|
+
const isLine = prevO[0] === prevV[0] && prevO[1] === prevV[1] && (currI[0] === currV[0] && currI[1] === currV[1]);
|
|
1920
|
+
if (isLine) {
|
|
1921
|
+
d.push("L" + currV[0] + "," + currV[1]);
|
|
1922
|
+
} else {
|
|
1923
|
+
d.push("C" + prevO[0] + "," + prevO[1] + "," + currI[0] + "," + currI[1] + "," + currV[0] + "," + currV[1]);
|
|
1924
|
+
}
|
|
1925
|
+
}
|
|
1926
|
+
if (c && len > 0) {
|
|
1927
|
+
const lastV = v[len - 1];
|
|
1928
|
+
const lastO = (_c = o == null ? void 0 : o[len - 1]) != null ? _c : lastV;
|
|
1929
|
+
const firstI = (_d = i == null ? void 0 : i[0]) != null ? _d : v[0];
|
|
1930
|
+
const firstV = v[0];
|
|
1931
|
+
const isLine = lastO[0] === lastV[0] && lastO[1] === lastV[1] && (firstI[0] === firstV[0] && firstI[1] === firstV[1]);
|
|
1932
|
+
if (!isLine) {
|
|
1933
|
+
d.push("C" + lastO[0] + "," + lastO[1] + "," + firstI[0] + "," + firstI[1] + "," + firstV[0] + "," + firstV[1]);
|
|
1934
|
+
}
|
|
1935
|
+
d.push("z");
|
|
1936
|
+
}
|
|
1937
|
+
return d.join("");
|
|
1938
|
+
}
|
|
1939
|
+
function interpolateNum(a, b, t) {
|
|
1940
|
+
return a + (b - a) * t;
|
|
365
1941
|
}
|
|
366
1942
|
function interpolateVec(a, b, t) {
|
|
367
1943
|
const res = [];
|
|
@@ -557,6 +2133,24 @@ function parseColor(s) {
|
|
|
557
2133
|
var COLOUR_ATTR_NAMES = /* @__PURE__ */ new Set(["color", "fill", "flood-color", "lighting-color", "stop-color", "stroke"]);
|
|
558
2134
|
var TRANSFORM_FN_NAMES = /* @__PURE__ */ new Set(["translate", "rotate", "scale", "skew"]);
|
|
559
2135
|
var PCT_BASED_ATTR_NAMES = /* @__PURE__ */ new Set(["offset-distance", "offsetDistance"]);
|
|
2136
|
+
function composeTransformParts(parts, opts) {
|
|
2137
|
+
var _a;
|
|
2138
|
+
if (!parts) return "";
|
|
2139
|
+
const withUnits = (_a = opts == null ? void 0 : opts.withUnits) != null ? _a : true;
|
|
2140
|
+
const segs = [];
|
|
2141
|
+
const t = parts.translate;
|
|
2142
|
+
const o = parts.origin;
|
|
2143
|
+
const r = parts.rotate;
|
|
2144
|
+
const s = parts.scale;
|
|
2145
|
+
const tu = withUnits ? "px" : "";
|
|
2146
|
+
const ru = withUnits ? "deg" : "";
|
|
2147
|
+
if (t) segs.push("translate(" + t[0] + tu + "," + t[1] + tu + ")");
|
|
2148
|
+
if (o) segs.push("translate(" + o[0] + tu + "," + o[1] + tu + ")");
|
|
2149
|
+
if (r !== void 0 && r !== null) segs.push("rotate(" + r + ru + ")");
|
|
2150
|
+
if (s) segs.push("scale(" + s[0] + "," + s[1] + ")");
|
|
2151
|
+
if (o) segs.push("translate(" + -o[0] + tu + "," + -o[1] + tu + ")");
|
|
2152
|
+
return segs.join("");
|
|
2153
|
+
}
|
|
560
2154
|
var STYLE_ATTR_NAMES = /* @__PURE__ */ new Set(["offset-distance", "offsetDistance"]);
|
|
561
2155
|
var DEFAULT_DURATION_MS = 1e3;
|
|
562
2156
|
function kebabToCamelCaseWord(kebab) {
|
|
@@ -581,6 +2175,12 @@ var SVG_CAMEL_CASE_ATTRS = /* @__PURE__ */ new Set([
|
|
|
581
2175
|
"clipPathUnits",
|
|
582
2176
|
"maskUnits",
|
|
583
2177
|
"maskContentUnits",
|
|
2178
|
+
// Marker (SVG spec keeps these camelCase, like viewBox)
|
|
2179
|
+
"markerUnits",
|
|
2180
|
+
"markerWidth",
|
|
2181
|
+
"markerHeight",
|
|
2182
|
+
"refX",
|
|
2183
|
+
"refY",
|
|
584
2184
|
// Text
|
|
585
2185
|
"textLength",
|
|
586
2186
|
"lengthAdjust",
|
|
@@ -616,288 +2216,456 @@ function camelCaseToKebabWordIfNeeded(camel) {
|
|
|
616
2216
|
function clamp(value, min, max) {
|
|
617
2217
|
return Math.max(min, Math.min(value, max));
|
|
618
2218
|
}
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
"symbol",
|
|
643
|
-
"marker",
|
|
644
|
-
"filter",
|
|
645
|
-
"feGaussianBlur",
|
|
646
|
-
"feOffset",
|
|
647
|
-
"feBlend",
|
|
648
|
-
"feColorMatrix",
|
|
649
|
-
"feMerge",
|
|
650
|
-
"feMergeNode"
|
|
651
|
-
].map((tagName) => tagName.toLowerCase()));
|
|
652
|
-
var ALLOWED_RESOURCE_ATTRIBUTES = [
|
|
653
|
-
"href",
|
|
654
|
-
// <use>
|
|
655
|
-
"src",
|
|
656
|
-
// <image>
|
|
657
|
-
"filter",
|
|
658
|
-
// url(#filterId)
|
|
659
|
-
"clipPath",
|
|
660
|
-
// clip-path="url(#clipPathId)"
|
|
661
|
-
"mask",
|
|
662
|
-
// url(#maskId)
|
|
663
|
-
"markerStart",
|
|
664
|
-
// marker-start="url(#markerId)"
|
|
665
|
-
"markerMid",
|
|
666
|
-
// marker-mid="url(#markerId)"
|
|
667
|
-
"markerEnd"
|
|
668
|
-
// marker-end="url(#markerId)"
|
|
669
|
-
// 'fill', // url(#gradientId) or url(#patternId)
|
|
670
|
-
// 'stroke', // url(#gradientId) or url(#patternId)
|
|
671
|
-
// Don't allow 'cursor', can use external SVG, // url(cursor.svg)
|
|
672
|
-
];
|
|
673
|
-
var ALLOWED_RESOURCE_ATTRIBUTES_SET = new Set(ALLOWED_RESOURCE_ATTRIBUTES);
|
|
674
|
-
var ALLOWED_ATTRIBUTES_SET = /* @__PURE__ */ new Set([
|
|
675
|
-
"href",
|
|
676
|
-
"src",
|
|
677
|
-
// Presentation
|
|
678
|
-
"fill",
|
|
679
|
-
"stroke",
|
|
680
|
-
"strokeWidth",
|
|
681
|
-
"opacity",
|
|
682
|
-
"transform",
|
|
683
|
-
// Geometry
|
|
684
|
-
"x",
|
|
685
|
-
"y",
|
|
686
|
-
"cx",
|
|
687
|
-
"cy",
|
|
688
|
-
"r",
|
|
689
|
-
"rx",
|
|
690
|
-
"ry",
|
|
691
|
-
"width",
|
|
692
|
-
"height",
|
|
693
|
-
"d",
|
|
694
|
-
"x1",
|
|
695
|
-
"y1",
|
|
696
|
-
"x2",
|
|
697
|
-
"y2",
|
|
698
|
-
"points",
|
|
699
|
-
// Text
|
|
700
|
-
"fontSize",
|
|
701
|
-
"fontFamily",
|
|
702
|
-
"textAnchor",
|
|
703
|
-
// Structure
|
|
704
|
-
"id",
|
|
705
|
-
"class",
|
|
706
|
-
"viewBox",
|
|
707
|
-
"preserveAspectRatio",
|
|
708
|
-
// Gradient/Pattern
|
|
709
|
-
"offset",
|
|
710
|
-
"stopColor",
|
|
711
|
-
"stopOpacity",
|
|
712
|
-
"gradientTransform",
|
|
713
|
-
// Clippath/Mask
|
|
714
|
-
"clipPath",
|
|
715
|
-
"mask",
|
|
716
|
-
// Filter
|
|
717
|
-
"filter",
|
|
718
|
-
"stdDeviation",
|
|
719
|
-
"in",
|
|
720
|
-
"in2",
|
|
721
|
-
"result",
|
|
722
|
-
"mode",
|
|
723
|
-
...ALLOWED_RESOURCE_ATTRIBUTES
|
|
724
|
-
]);
|
|
725
|
-
function sanitiseAttributeValue(name, value) {
|
|
726
|
-
const nameLower = name.toLowerCase();
|
|
727
|
-
if (!ALLOWED_ATTRIBUTES_SET.has(nameLower)) {
|
|
728
|
-
console.warn("Attribute not in whitelist: ", nameLower);
|
|
729
|
-
return void 0;
|
|
2219
|
+
function bezier2D_pointAt(P0, P1, P2, P3, t) {
|
|
2220
|
+
if (t <= 0) return [P0[0], P0[1]];
|
|
2221
|
+
if (t >= 1) return [P3[0], P3[1]];
|
|
2222
|
+
const u = 1 - t;
|
|
2223
|
+
const u2 = u * u;
|
|
2224
|
+
const u3 = u2 * u;
|
|
2225
|
+
const t2 = t * t;
|
|
2226
|
+
const t3 = t2 * t;
|
|
2227
|
+
const w0 = u3;
|
|
2228
|
+
const w1 = 3 * t * u2;
|
|
2229
|
+
const w2 = 3 * t2 * u;
|
|
2230
|
+
const w3 = t3;
|
|
2231
|
+
return [
|
|
2232
|
+
w0 * P0[0] + w1 * P1[0] + w2 * P2[0] + w3 * P3[0],
|
|
2233
|
+
w0 * P0[1] + w1 * P1[1] + w2 * P2[1] + w3 * P3[1]
|
|
2234
|
+
];
|
|
2235
|
+
}
|
|
2236
|
+
var BEZIER_T_NUDGE = 1e-4;
|
|
2237
|
+
function bezier2D_derivativeAt(P0, P1, P2, P3, t) {
|
|
2238
|
+
const result = _bezier2D_derivativeAtRaw(P0, P1, P2, P3, t);
|
|
2239
|
+
if (result[0] === 0 && result[1] === 0) {
|
|
2240
|
+
const nudgedT = t < 0.5 ? t + BEZIER_T_NUDGE : t - BEZIER_T_NUDGE;
|
|
2241
|
+
return _bezier2D_derivativeAtRaw(P0, P1, P2, P3, nudgedT);
|
|
730
2242
|
}
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
2243
|
+
return result;
|
|
2244
|
+
}
|
|
2245
|
+
function _bezier2D_derivativeAtRaw(P0, P1, P2, P3, t) {
|
|
2246
|
+
const u = 1 - t;
|
|
2247
|
+
const a = 3 * u * u;
|
|
2248
|
+
const b = 6 * t * u;
|
|
2249
|
+
const c = 3 * t * t;
|
|
2250
|
+
return [
|
|
2251
|
+
a * (P1[0] - P0[0]) + b * (P2[0] - P1[0]) + c * (P3[0] - P2[0]),
|
|
2252
|
+
a * (P1[1] - P0[1]) + b * (P2[1] - P1[1]) + c * (P3[1] - P2[1])
|
|
2253
|
+
];
|
|
2254
|
+
}
|
|
2255
|
+
function bezier2D_arcLengthLUT(P0, P1, P2, P3, steps = 100) {
|
|
2256
|
+
const n = steps + 1;
|
|
2257
|
+
const ts = new Float64Array(n);
|
|
2258
|
+
const ds = new Float64Array(n);
|
|
2259
|
+
let prev = bezier2D_pointAt(P0, P1, P2, P3, 0);
|
|
2260
|
+
ts[0] = 0;
|
|
2261
|
+
ds[0] = 0;
|
|
2262
|
+
let cum = 0;
|
|
2263
|
+
for (let i = 1; i < n; i++) {
|
|
2264
|
+
const t = i / steps;
|
|
2265
|
+
const cur = bezier2D_pointAt(P0, P1, P2, P3, t);
|
|
2266
|
+
const dx = cur[0] - prev[0];
|
|
2267
|
+
const dy = cur[1] - prev[1];
|
|
2268
|
+
cum += Math.sqrt(dx * dx + dy * dy);
|
|
2269
|
+
ts[i] = t;
|
|
2270
|
+
ds[i] = cum;
|
|
2271
|
+
prev = cur;
|
|
738
2272
|
}
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
2273
|
+
return { ts, ds };
|
|
2274
|
+
}
|
|
2275
|
+
function bezier2D_arcAtT(lut, t) {
|
|
2276
|
+
const { ts, ds } = lut;
|
|
2277
|
+
const last = ts.length - 1;
|
|
2278
|
+
if (t <= ts[0]) return ds[0];
|
|
2279
|
+
if (t >= ts[last]) return ds[last];
|
|
2280
|
+
let lo = 1, hi = last;
|
|
2281
|
+
while (lo < hi) {
|
|
2282
|
+
const mid = lo + hi >>> 1;
|
|
2283
|
+
if (ts[mid] < t) lo = mid + 1;
|
|
2284
|
+
else hi = mid;
|
|
748
2285
|
}
|
|
749
|
-
|
|
2286
|
+
const tPrev = ts[hi - 1];
|
|
2287
|
+
const span = ts[hi] - tPrev;
|
|
2288
|
+
const frac = span > 0 ? (t - tPrev) / span : 0;
|
|
2289
|
+
return ds[hi - 1] + frac * (ds[hi] - ds[hi - 1]);
|
|
750
2290
|
}
|
|
751
|
-
function
|
|
752
|
-
if (!
|
|
753
|
-
const
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
2291
|
+
function invertEasing(easing) {
|
|
2292
|
+
if (!easing) return (y) => y;
|
|
2293
|
+
const flipped = [easing[1], easing[0], easing[3], easing[2]];
|
|
2294
|
+
return cubicBezier(flipped);
|
|
2295
|
+
}
|
|
2296
|
+
|
|
2297
|
+
// src/PxMotionPath.ts
|
|
2298
|
+
function getKfTranslate(kf) {
|
|
2299
|
+
var _a;
|
|
2300
|
+
const v = (_a = kf.value) != null ? _a : kf.v;
|
|
2301
|
+
if (!v) return void 0;
|
|
2302
|
+
if (Array.isArray(v) && v.length >= 2 && typeof v[0] === "number" && typeof v[1] === "number") {
|
|
2303
|
+
return [v[0], v[1]];
|
|
759
2304
|
}
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
2305
|
+
const tr = v.translate;
|
|
2306
|
+
if (Array.isArray(tr) && tr.length >= 2) return [tr[0], tr[1]];
|
|
2307
|
+
return void 0;
|
|
2308
|
+
}
|
|
2309
|
+
function getKfTime(kf) {
|
|
2310
|
+
var _a, _b;
|
|
2311
|
+
return (_b = (_a = kf.time) != null ? _a : kf.t) != null ? _b : 0;
|
|
2312
|
+
}
|
|
2313
|
+
function getKfEasing(kf) {
|
|
2314
|
+
var _a;
|
|
2315
|
+
return (_a = kf.easing) != null ? _a : kf.e;
|
|
2316
|
+
}
|
|
2317
|
+
function propAnimIsMotionPath(anim) {
|
|
2318
|
+
var _a, _b, _c;
|
|
2319
|
+
const kfs = (_a = anim.keyframes) != null ? _a : anim.kfs;
|
|
2320
|
+
if (!Array.isArray(kfs)) return false;
|
|
2321
|
+
if (anim.autoOrient) return true;
|
|
2322
|
+
for (const kf of kfs) {
|
|
2323
|
+
if (((_b = kf.tangentIn) != null ? _b : kf.ti) || ((_c = kf.tangentOut) != null ? _c : kf.to)) return true;
|
|
2324
|
+
}
|
|
2325
|
+
return false;
|
|
2326
|
+
}
|
|
2327
|
+
var _segmentCache = /* @__PURE__ */ new WeakMap();
|
|
2328
|
+
function getSegmentCache(prevKf, nextKf, prevPos, nextPos) {
|
|
2329
|
+
var _a, _b;
|
|
2330
|
+
const existing = _segmentCache.get(prevKf);
|
|
2331
|
+
if (existing) return existing;
|
|
2332
|
+
const to = (_a = prevKf.tangentOut) != null ? _a : prevKf.to;
|
|
2333
|
+
const ti = (_b = nextKf.tangentIn) != null ? _b : nextKf.ti;
|
|
2334
|
+
const P1 = [prevPos[0] + (to ? to[0] : 0), prevPos[1] + (to ? to[1] : 0)];
|
|
2335
|
+
const P2 = [nextPos[0] + (ti ? ti[0] : 0), nextPos[1] + (ti ? ti[1] : 0)];
|
|
2336
|
+
const lut = bezier2D_arcLengthLUT(prevPos, P1, P2, nextPos);
|
|
2337
|
+
const entry = {
|
|
2338
|
+
P0: prevPos,
|
|
2339
|
+
P1,
|
|
2340
|
+
P2,
|
|
2341
|
+
P3: nextPos,
|
|
2342
|
+
lut,
|
|
2343
|
+
totalArc: lut.ds[lut.ds.length - 1]
|
|
2344
|
+
};
|
|
2345
|
+
_segmentCache.set(prevKf, entry);
|
|
2346
|
+
return entry;
|
|
2347
|
+
}
|
|
2348
|
+
function evaluateMotionPathSegment(prevKf, nextKf, prevPos, nextPos, localProgress, autoOrient) {
|
|
2349
|
+
const seg = getSegmentCache(prevKf, nextKf, prevPos, nextPos);
|
|
2350
|
+
const t = seg.totalArc === 0 ? localProgress : tFromArcFraction(seg.lut, localProgress);
|
|
2351
|
+
const point = bezier2D_pointAt(seg.P0, seg.P1, seg.P2, seg.P3, t);
|
|
2352
|
+
if (!autoOrient) return { translate: point };
|
|
2353
|
+
const tan = bezier2D_derivativeAt(seg.P0, seg.P1, seg.P2, seg.P3, t);
|
|
2354
|
+
const rotateDeg = Math.atan2(tan[1], tan[0]) * 180 / Math.PI;
|
|
2355
|
+
return { translate: point, rotateDeg };
|
|
2356
|
+
}
|
|
2357
|
+
function tFromArcFraction(lut, arcFrac) {
|
|
2358
|
+
const total = lut.ds[lut.ds.length - 1];
|
|
2359
|
+
const target = arcFrac * total;
|
|
2360
|
+
const { ts, ds } = lut;
|
|
2361
|
+
const last = ds.length - 1;
|
|
2362
|
+
if (target <= 0) return ts[0];
|
|
2363
|
+
if (target >= ds[last]) return ts[last];
|
|
2364
|
+
let lo = 1, hi = last;
|
|
2365
|
+
while (lo < hi) {
|
|
2366
|
+
const mid = lo + hi >>> 1;
|
|
2367
|
+
if (ds[mid] < target) lo = mid + 1;
|
|
2368
|
+
else hi = mid;
|
|
2369
|
+
}
|
|
2370
|
+
const dPrev = ds[hi - 1];
|
|
2371
|
+
const span = ds[hi] - dPrev;
|
|
2372
|
+
const frac = span > 0 ? (target - dPrev) / span : 0;
|
|
2373
|
+
return ts[hi - 1] + frac * (ts[hi] - ts[hi - 1]);
|
|
2374
|
+
}
|
|
2375
|
+
var DEFAULT_FLATNESS_TOL = 0.5;
|
|
2376
|
+
var DEFAULT_ROTATION_TOL = 5;
|
|
2377
|
+
var DEFAULT_MAX_SAMPLES = 32;
|
|
2378
|
+
function materialiseMotionPathInPropAnim(anim, opts) {
|
|
2379
|
+
var _a, _b, _c, _d;
|
|
2380
|
+
if (!propAnimIsMotionPath(anim)) return anim;
|
|
2381
|
+
const kfs = (_a = anim.keyframes) != null ? _a : anim.kfs;
|
|
2382
|
+
if (!Array.isArray(kfs) || kfs.length < 2) return anim;
|
|
2383
|
+
const autoOrient = !!anim.autoOrient;
|
|
2384
|
+
const flatnessTol = (_b = opts == null ? void 0 : opts.flatnessTolerance) != null ? _b : DEFAULT_FLATNESS_TOL;
|
|
2385
|
+
const rotationTol = (_c = opts == null ? void 0 : opts.rotationTolerance) != null ? _c : DEFAULT_ROTATION_TOL;
|
|
2386
|
+
const maxSamples = (_d = opts == null ? void 0 : opts.maxSamplesPerSegment) != null ? _d : DEFAULT_MAX_SAMPLES;
|
|
2387
|
+
const out = [];
|
|
2388
|
+
const firstPos = getKfTranslate(kfs[0]);
|
|
2389
|
+
if (!firstPos) return anim;
|
|
2390
|
+
const firstRotate = autoOrient ? derivAngleForFirstKf(kfs[0], kfs[1]) : void 0;
|
|
2391
|
+
out.push(makeOutKf(
|
|
2392
|
+
getKfTime(kfs[0]),
|
|
2393
|
+
buildOutKfValue(getKfValueParts(kfs[0]), getKfValueParts(kfs[0]), 0, firstPos, firstRotate, autoOrient)
|
|
2394
|
+
));
|
|
2395
|
+
for (let i = 0; i < kfs.length - 1; i++) {
|
|
2396
|
+
const prevKf = kfs[i];
|
|
2397
|
+
const nextKf = kfs[i + 1];
|
|
2398
|
+
const prevPos = getKfTranslate(prevKf);
|
|
2399
|
+
const nextPos = getKfTranslate(nextKf);
|
|
2400
|
+
if (!prevPos || !nextPos) {
|
|
2401
|
+
out.push(makeOutKf(
|
|
2402
|
+
getKfTime(nextKf),
|
|
2403
|
+
buildOutKfValue(getKfValueParts(nextKf), getKfValueParts(nextKf), 1, nextPos != null ? nextPos : [0, 0], void 0, autoOrient)
|
|
2404
|
+
));
|
|
2405
|
+
continue;
|
|
2406
|
+
}
|
|
2407
|
+
if (autoOrient && i > 0) {
|
|
2408
|
+
insertSharpCornerStepKfIfNeeded(out, prevKf, nextKf, prevPos, nextPos, rotationTol);
|
|
763
2409
|
}
|
|
2410
|
+
materialiseSegment(out, prevKf, nextKf, prevPos, nextPos, autoOrient, flatnessTol, rotationTol, maxSamples);
|
|
764
2411
|
}
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
2412
|
+
const lastInE = getKfEasing(kfs[kfs.length - 1]);
|
|
2413
|
+
if (lastInE) out[out.length - 1].e = lastInE;
|
|
2414
|
+
if (autoOrient) unwrapAutoOrientRotations(out);
|
|
2415
|
+
const result = { kfs: out };
|
|
2416
|
+
if (anim.loop !== void 0) result.loop = anim.loop;
|
|
2417
|
+
return result;
|
|
2418
|
+
}
|
|
2419
|
+
function unwrapAutoOrientRotations(kfs) {
|
|
2420
|
+
var _a;
|
|
2421
|
+
let prev;
|
|
2422
|
+
for (const kf of kfs) {
|
|
2423
|
+
const v = (_a = kf.v) != null ? _a : kf.value;
|
|
2424
|
+
if (!v || typeof v.rotate !== "number") continue;
|
|
2425
|
+
if (prev === void 0) {
|
|
2426
|
+
prev = v.rotate;
|
|
2427
|
+
continue;
|
|
768
2428
|
}
|
|
2429
|
+
let r = v.rotate;
|
|
2430
|
+
while (r - prev > 180) r -= 360;
|
|
2431
|
+
while (r - prev < -180) r += 360;
|
|
2432
|
+
v.rotate = r;
|
|
2433
|
+
prev = r;
|
|
769
2434
|
}
|
|
770
|
-
if (textContent) element.textContent = textContent;
|
|
771
|
-
return element;
|
|
772
2435
|
}
|
|
773
|
-
function
|
|
2436
|
+
function makeOutKf(time, value) {
|
|
2437
|
+
return { t: time, v: value };
|
|
2438
|
+
}
|
|
2439
|
+
function getKfValueParts(kf) {
|
|
774
2440
|
var _a;
|
|
775
|
-
|
|
776
|
-
if (typeof
|
|
777
|
-
|
|
2441
|
+
const v = (_a = kf.value) != null ? _a : kf.v;
|
|
2442
|
+
if (!v || typeof v !== "object" || Array.isArray(v)) return void 0;
|
|
2443
|
+
return v;
|
|
2444
|
+
}
|
|
2445
|
+
function interpolatePart(prev, next, p) {
|
|
2446
|
+
if (prev === void 0) return next;
|
|
2447
|
+
if (next === void 0) return prev;
|
|
2448
|
+
if (typeof prev === "number" && typeof next === "number") {
|
|
2449
|
+
return prev + (next - prev) * p;
|
|
778
2450
|
}
|
|
779
|
-
|
|
2451
|
+
if (Array.isArray(prev) && Array.isArray(next) && prev.length === next.length) {
|
|
2452
|
+
const out = new Array(prev.length);
|
|
2453
|
+
for (let i = 0; i < prev.length; i++) {
|
|
2454
|
+
const a = typeof prev[i] === "number" ? prev[i] : 0;
|
|
2455
|
+
const b = typeof next[i] === "number" ? next[i] : 0;
|
|
2456
|
+
out[i] = a + (b - a) * p;
|
|
2457
|
+
}
|
|
2458
|
+
return out;
|
|
2459
|
+
}
|
|
2460
|
+
return p < 0.5 ? prev : next;
|
|
780
2461
|
}
|
|
781
|
-
function
|
|
782
|
-
const
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
if (
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
2462
|
+
function buildOutKfValue(prevV, nextV, p, translate, rotateDegFromAutoOrient, autoOrient) {
|
|
2463
|
+
const value = { translate };
|
|
2464
|
+
const keys = /* @__PURE__ */ new Set();
|
|
2465
|
+
if (prevV) for (const k of Object.keys(prevV)) keys.add(k);
|
|
2466
|
+
if (nextV) for (const k of Object.keys(nextV)) keys.add(k);
|
|
2467
|
+
for (const k of keys) {
|
|
2468
|
+
if (k === "translate") continue;
|
|
2469
|
+
if (k === "rotate" && autoOrient) continue;
|
|
2470
|
+
const pv = prevV == null ? void 0 : prevV[k];
|
|
2471
|
+
const nv = nextV == null ? void 0 : nextV[k];
|
|
2472
|
+
if (pv === void 0 && nv === void 0) continue;
|
|
2473
|
+
value[k] = interpolatePart(pv, nv, p);
|
|
2474
|
+
}
|
|
2475
|
+
if (rotateDegFromAutoOrient !== void 0) value.rotate = rotateDegFromAutoOrient;
|
|
2476
|
+
return value;
|
|
2477
|
+
}
|
|
2478
|
+
function derivAngleForFirstKf(kf0, kf1) {
|
|
2479
|
+
const p0 = getKfTranslate(kf0);
|
|
2480
|
+
const p1 = getKfTranslate(kf1);
|
|
2481
|
+
if (!p0 || !p1) return 0;
|
|
2482
|
+
const seg = getSegmentCache(kf0, kf1, p0, p1);
|
|
2483
|
+
const tan = bezier2D_derivativeAt(seg.P0, seg.P1, seg.P2, seg.P3, 0);
|
|
2484
|
+
return Math.atan2(tan[1], tan[0]) * 180 / Math.PI;
|
|
2485
|
+
}
|
|
2486
|
+
function wrappedAngleDelta(a, b) {
|
|
2487
|
+
let d = a - b;
|
|
2488
|
+
while (d > 180) d -= 360;
|
|
2489
|
+
while (d < -180) d += 360;
|
|
2490
|
+
return d;
|
|
2491
|
+
}
|
|
2492
|
+
function insertSharpCornerStepKfIfNeeded(out, prevKf, nextKf, prevPos, nextPos, rotationTol) {
|
|
2493
|
+
var _a;
|
|
2494
|
+
const lastKf = out[out.length - 1];
|
|
2495
|
+
const lastV = (_a = lastKf.v) != null ? _a : lastKf.value;
|
|
2496
|
+
const prevExit = lastV == null ? void 0 : lastV.rotate;
|
|
2497
|
+
if (typeof prevExit !== "number") return;
|
|
2498
|
+
const seg = getSegmentCache(prevKf, nextKf, prevPos, nextPos);
|
|
2499
|
+
const tanAtStart = bezier2D_derivativeAt(seg.P0, seg.P1, seg.P2, seg.P3, 0);
|
|
2500
|
+
const nextEntry = Math.atan2(tanAtStart[1], tanAtStart[0]) * 180 / Math.PI;
|
|
2501
|
+
const delta = wrappedAngleDelta(nextEntry, prevExit);
|
|
2502
|
+
if (Math.abs(delta) <= rotationTol) return;
|
|
2503
|
+
const dupValue = buildOutKfValue(
|
|
2504
|
+
getKfValueParts(prevKf),
|
|
2505
|
+
getKfValueParts(prevKf),
|
|
2506
|
+
0,
|
|
2507
|
+
prevPos,
|
|
2508
|
+
nextEntry,
|
|
2509
|
+
true
|
|
2510
|
+
);
|
|
2511
|
+
out.push(makeOutKf(getKfTime(prevKf), dupValue));
|
|
2512
|
+
}
|
|
2513
|
+
function materialiseSegment(out, prevKf, nextKf, prevPos, nextPos, autoOrient, flatnessTol, rotationTol, maxSamples) {
|
|
2514
|
+
const seg = getSegmentCache(prevKf, nextKf, prevPos, nextPos);
|
|
2515
|
+
const prevTime = getKfTime(prevKf);
|
|
2516
|
+
const nextTime = getKfTime(nextKf);
|
|
2517
|
+
const prevEasing = getKfEasing(prevKf);
|
|
2518
|
+
const invertFn = invertEasing(prevEasing);
|
|
2519
|
+
const prevV = getKfValueParts(prevKf);
|
|
2520
|
+
const nextV = getKfValueParts(nextKf);
|
|
2521
|
+
const interiorTs = computeSampleTs(seg, autoOrient, flatnessTol, rotationTol, maxSamples);
|
|
2522
|
+
const samples = [];
|
|
2523
|
+
for (const t of interiorTs) {
|
|
2524
|
+
const arc = bezier2D_arcAtT(seg.lut, t);
|
|
2525
|
+
const p = clamp(seg.totalArc > 0 ? arc / seg.totalArc : t, 0, 1);
|
|
2526
|
+
const u = clamp(invertFn(p), 0, 1);
|
|
2527
|
+
const pos = bezier2D_pointAt(seg.P0, seg.P1, seg.P2, seg.P3, t);
|
|
2528
|
+
const sample = { u, p, pos };
|
|
2529
|
+
if (autoOrient) {
|
|
2530
|
+
const tan = bezier2D_derivativeAt(seg.P0, seg.P1, seg.P2, seg.P3, t);
|
|
2531
|
+
sample.rotateDeg = Math.atan2(tan[1], tan[0]) * 180 / Math.PI;
|
|
798
2532
|
}
|
|
2533
|
+
samples.push(sample);
|
|
2534
|
+
}
|
|
2535
|
+
let remaining = prevEasing;
|
|
2536
|
+
let prevU = 0;
|
|
2537
|
+
const startIdx = out.length - 1;
|
|
2538
|
+
for (let i = 0; i < samples.length; i++) {
|
|
2539
|
+
const s = samples[i];
|
|
2540
|
+
const xFrac = prevU < 1 ? clamp((s.u - prevU) / (1 - prevU), 0, 1) : 1;
|
|
2541
|
+
const { left, right } = splitEasing(remaining, xFrac);
|
|
2542
|
+
const ownerIdx = i === 0 ? startIdx : out.length - 1;
|
|
2543
|
+
if (left) out[ownerIdx].e = left;
|
|
2544
|
+
else delete out[ownerIdx].e;
|
|
2545
|
+
const tGlobal = prevTime + s.u * (nextTime - prevTime);
|
|
2546
|
+
const value = buildOutKfValue(prevV, nextV, s.p, s.pos, s.rotateDeg, autoOrient);
|
|
2547
|
+
out.push(makeOutKf(tGlobal, value));
|
|
2548
|
+
remaining = right;
|
|
2549
|
+
prevU = s.u;
|
|
799
2550
|
}
|
|
800
|
-
return propsCopy;
|
|
801
2551
|
}
|
|
802
|
-
function
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
if (child) {
|
|
812
|
-
if (!childElements) childElements = [];
|
|
813
|
-
childElements.push(child);
|
|
814
|
-
}
|
|
2552
|
+
function computeSampleTs(seg, autoOrient, flatnessTol, rotationTol, maxSamples) {
|
|
2553
|
+
const extremes = [];
|
|
2554
|
+
addAxisExtremes(seg.P0[0], seg.P1[0], seg.P2[0], seg.P3[0], extremes);
|
|
2555
|
+
addAxisExtremes(seg.P0[1], seg.P1[1], seg.P2[1], seg.P3[1], extremes);
|
|
2556
|
+
extremes.sort((a, b) => a - b);
|
|
2557
|
+
const critical = [0];
|
|
2558
|
+
for (const t of extremes) {
|
|
2559
|
+
if (t > critical[critical.length - 1] + 1e-6 && t < 1 - 1e-6) {
|
|
2560
|
+
critical.push(t);
|
|
815
2561
|
}
|
|
816
2562
|
}
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
2563
|
+
critical.push(1);
|
|
2564
|
+
const out = [];
|
|
2565
|
+
const budget = { remaining: maxSamples - critical.length };
|
|
2566
|
+
for (let i = 0; i < critical.length - 1; i++) {
|
|
2567
|
+
bisect(critical[i], critical[i + 1], out, seg, autoOrient, flatnessTol, rotationTol, budget);
|
|
2568
|
+
}
|
|
2569
|
+
return out;
|
|
2570
|
+
}
|
|
2571
|
+
function addAxisExtremes(p0, p1, p2, p3, out) {
|
|
2572
|
+
const a = p1 - p0;
|
|
2573
|
+
const b = p2 - p1;
|
|
2574
|
+
const c = p3 - p2;
|
|
2575
|
+
const A = a - 2 * b + c;
|
|
2576
|
+
const B = 2 * (b - a);
|
|
2577
|
+
const C = a;
|
|
2578
|
+
if (Math.abs(A) < 1e-10) {
|
|
2579
|
+
if (Math.abs(B) > 1e-10) {
|
|
2580
|
+
const t = -C / B;
|
|
2581
|
+
if (t > 1e-6 && t < 1 - 1e-6) out.push(t);
|
|
2582
|
+
}
|
|
2583
|
+
return;
|
|
2584
|
+
}
|
|
2585
|
+
const disc = B * B - 4 * A * C;
|
|
2586
|
+
if (disc < 0) return;
|
|
2587
|
+
const sq = Math.sqrt(disc);
|
|
2588
|
+
const t1 = (-B - sq) / (2 * A);
|
|
2589
|
+
const t2 = (-B + sq) / (2 * A);
|
|
2590
|
+
if (t1 > 1e-6 && t1 < 1 - 1e-6) out.push(t1);
|
|
2591
|
+
if (t2 > 1e-6 && t2 < 1 - 1e-6) out.push(t2);
|
|
2592
|
+
}
|
|
2593
|
+
function bisect(tA, tB, out, seg, autoOrient, flatnessTol, rotationTol, budget) {
|
|
2594
|
+
const tMid = (tA + tB) / 2;
|
|
2595
|
+
const pA = bezier2D_pointAt(seg.P0, seg.P1, seg.P2, seg.P3, tA);
|
|
2596
|
+
const pB = bezier2D_pointAt(seg.P0, seg.P1, seg.P2, seg.P3, tB);
|
|
2597
|
+
const span = tB - tA;
|
|
2598
|
+
const p25 = bezier2D_pointAt(seg.P0, seg.P1, seg.P2, seg.P3, tA + span * 0.25);
|
|
2599
|
+
const p50 = bezier2D_pointAt(seg.P0, seg.P1, seg.P2, seg.P3, tMid);
|
|
2600
|
+
const p75 = bezier2D_pointAt(seg.P0, seg.P1, seg.P2, seg.P3, tA + span * 0.75);
|
|
2601
|
+
const dev = Math.max(
|
|
2602
|
+
perpDist(p25, pA, pB),
|
|
2603
|
+
perpDist(p50, pA, pB),
|
|
2604
|
+
perpDist(p75, pA, pB)
|
|
823
2605
|
);
|
|
2606
|
+
let rotOk = true;
|
|
2607
|
+
if (autoOrient) {
|
|
2608
|
+
const tanA = bezier2D_derivativeAt(seg.P0, seg.P1, seg.P2, seg.P3, tA);
|
|
2609
|
+
const tanB = bezier2D_derivativeAt(seg.P0, seg.P1, seg.P2, seg.P3, tB);
|
|
2610
|
+
const angA = Math.atan2(tanA[1], tanA[0]) * 180 / Math.PI;
|
|
2611
|
+
const angB = Math.atan2(tanB[1], tanB[0]) * 180 / Math.PI;
|
|
2612
|
+
let delta = Math.abs(angA - angB);
|
|
2613
|
+
if (delta > 180) delta = 360 - delta;
|
|
2614
|
+
if (delta > rotationTol) rotOk = false;
|
|
2615
|
+
}
|
|
2616
|
+
if (dev <= flatnessTol && rotOk || budget.remaining <= 0 || span < 1e-6) {
|
|
2617
|
+
out.push(tB);
|
|
2618
|
+
return;
|
|
2619
|
+
}
|
|
2620
|
+
budget.remaining -= 1;
|
|
2621
|
+
bisect(tA, tMid, out, seg, autoOrient, flatnessTol, rotationTol, budget);
|
|
2622
|
+
bisect(tMid, tB, out, seg, autoOrient, flatnessTol, rotationTol, budget);
|
|
824
2623
|
}
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
const
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
return
|
|
2624
|
+
function perpDist(q, pA, pB) {
|
|
2625
|
+
const dx = pB[0] - pA[0];
|
|
2626
|
+
const dy = pB[1] - pA[1];
|
|
2627
|
+
const len2 = dx * dx + dy * dy;
|
|
2628
|
+
if (len2 < 1e-20) {
|
|
2629
|
+
const qdx = q[0] - pA[0];
|
|
2630
|
+
const qdy = q[1] - pA[1];
|
|
2631
|
+
return Math.sqrt(qdx * qdx + qdy * qdy);
|
|
833
2632
|
}
|
|
834
|
-
const
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
break;
|
|
851
|
-
}
|
|
852
|
-
};
|
|
853
|
-
switch (startOn) {
|
|
854
|
-
case "load": {
|
|
855
|
-
const startHandler = () => start();
|
|
856
|
-
if (document.readyState === "complete") {
|
|
857
|
-
startHandler();
|
|
858
|
-
} else {
|
|
859
|
-
window.addEventListener("load", startHandler, { once: true });
|
|
2633
|
+
const cross = (q[0] - pA[0]) * dy - (q[1] - pA[1]) * dx;
|
|
2634
|
+
return Math.abs(cross) / Math.sqrt(len2);
|
|
2635
|
+
}
|
|
2636
|
+
function materialiseMotionPathsInTree(root, opts) {
|
|
2637
|
+
const out = walkAndMaterialise(root, opts);
|
|
2638
|
+
return out != null ? out : root;
|
|
2639
|
+
}
|
|
2640
|
+
function walkAndMaterialise(node, opts) {
|
|
2641
|
+
let newChildren;
|
|
2642
|
+
if (node.children) {
|
|
2643
|
+
for (let i = 0; i < node.children.length; i++) {
|
|
2644
|
+
const ch = node.children[i];
|
|
2645
|
+
const ret = walkAndMaterialise(ch, opts);
|
|
2646
|
+
if (ret !== null) {
|
|
2647
|
+
if (!newChildren) newChildren = node.children.slice();
|
|
2648
|
+
newChildren[i] = ret;
|
|
860
2649
|
}
|
|
861
|
-
break;
|
|
862
|
-
}
|
|
863
|
-
case "mouseOver": {
|
|
864
|
-
const mouseOverHandler = () => start();
|
|
865
|
-
const mouseOutHandler = () => handleEndAction();
|
|
866
|
-
root.addEventListener("mouseenter", mouseOverHandler);
|
|
867
|
-
root.addEventListener("mouseleave", mouseOutHandler);
|
|
868
|
-
break;
|
|
869
|
-
}
|
|
870
|
-
case "click": {
|
|
871
|
-
const clickHandler = () => {
|
|
872
|
-
if (api.isPlaying()) {
|
|
873
|
-
handleEndAction();
|
|
874
|
-
} else {
|
|
875
|
-
start();
|
|
876
|
-
}
|
|
877
|
-
};
|
|
878
|
-
root.addEventListener("click", clickHandler);
|
|
879
|
-
break;
|
|
880
2650
|
}
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
{ threshold: scrollIntoViewThreshold }
|
|
893
|
-
);
|
|
894
|
-
observer.observe(root);
|
|
895
|
-
break;
|
|
2651
|
+
}
|
|
2652
|
+
let newAnimate;
|
|
2653
|
+
const animBucket = node.animate;
|
|
2654
|
+
if (animBucket && typeof animBucket === "object" && !Array.isArray(animBucket)) {
|
|
2655
|
+
const animDef = animBucket;
|
|
2656
|
+
const transformAnim = animDef.transform;
|
|
2657
|
+
if (transformAnim && typeof transformAnim === "object" && propAnimIsMotionPath(transformAnim)) {
|
|
2658
|
+
const materialised = materialiseMotionPathInPropAnim(transformAnim, opts);
|
|
2659
|
+
if (materialised !== transformAnim) {
|
|
2660
|
+
newAnimate = __spreadProps(__spreadValues({}, animDef), { transform: materialised });
|
|
2661
|
+
}
|
|
896
2662
|
}
|
|
897
|
-
case "programmatic":
|
|
898
|
-
break;
|
|
899
2663
|
}
|
|
900
|
-
return
|
|
2664
|
+
if (!newChildren && !newAnimate) return null;
|
|
2665
|
+
const cloned = __spreadValues({}, node);
|
|
2666
|
+
if (newChildren) cloned.children = newChildren;
|
|
2667
|
+
if (newAnimate) cloned.animate = newAnimate;
|
|
2668
|
+
return cloned;
|
|
901
2669
|
}
|
|
902
2670
|
|
|
903
2671
|
// src/PxDefinitions.ts
|
|
@@ -963,6 +2731,8 @@ function parseSvgPathToBezier(d) {
|
|
|
963
2731
|
currentPath.o.push([x2, y2]);
|
|
964
2732
|
} else if (type === "Z" || type === "z") {
|
|
965
2733
|
currentPath.c = true;
|
|
2734
|
+
} else {
|
|
2735
|
+
console.warn('Unsupported path command "' + type + '"');
|
|
966
2736
|
}
|
|
967
2737
|
}
|
|
968
2738
|
return res;
|
|
@@ -980,13 +2750,17 @@ function isPathString(value) {
|
|
|
980
2750
|
return typeof value === "string" && extractPathData(value) !== void 0;
|
|
981
2751
|
}
|
|
982
2752
|
function normalizePathValue(value) {
|
|
2753
|
+
if (value && typeof value === "object" && typeof value.path === "string") {
|
|
2754
|
+
const d = extractPathData(value.path);
|
|
2755
|
+
return d ? { paths: parseSvgPathToBezier(d) } : value;
|
|
2756
|
+
}
|
|
983
2757
|
if (value && typeof value === "object" && "paths" in value) {
|
|
984
2758
|
const pathsArray = value.paths;
|
|
985
2759
|
if (Array.isArray(pathsArray) && pathsArray.length > 0) {
|
|
986
2760
|
if (isPathString(pathsArray[0])) {
|
|
987
2761
|
const paths = [];
|
|
988
|
-
for (const
|
|
989
|
-
const d = extractPathData(
|
|
2762
|
+
for (const pathStr2 of pathsArray) {
|
|
2763
|
+
const d = extractPathData(pathStr2);
|
|
990
2764
|
if (d) {
|
|
991
2765
|
paths.push(...parseSvgPathToBezier(d));
|
|
992
2766
|
}
|
|
@@ -999,8 +2773,8 @@ function normalizePathValue(value) {
|
|
|
999
2773
|
if (Array.isArray(value)) {
|
|
1000
2774
|
if (value.length > 0 && isPathString(value[0])) {
|
|
1001
2775
|
const paths = [];
|
|
1002
|
-
for (const
|
|
1003
|
-
const d = extractPathData(
|
|
2776
|
+
for (const pathStr2 of value) {
|
|
2777
|
+
const d = extractPathData(pathStr2);
|
|
1004
2778
|
if (d) {
|
|
1005
2779
|
paths.push(...parseSvgPathToBezier(d));
|
|
1006
2780
|
}
|
|
@@ -1064,11 +2838,34 @@ function interpolateValue(propName, a, b, t) {
|
|
|
1064
2838
|
if (COLOUR_ATTR_NAMES.has(propName)) {
|
|
1065
2839
|
return interpolateColor(a || [0, 0, 0, 1], b || [0, 0, 0, 1], t);
|
|
1066
2840
|
}
|
|
2841
|
+
if (propName === "transform" && typeof a === "object" && a !== null && !Array.isArray(a) && typeof b === "object" && b !== null && !Array.isArray(b)) {
|
|
2842
|
+
return interpolateTransformParts(a, b, t);
|
|
2843
|
+
}
|
|
2844
|
+
if (propName === "rotate" && typeof a === "number" && typeof b === "number") {
|
|
2845
|
+
return interpolateNum(a, b, t);
|
|
2846
|
+
}
|
|
1067
2847
|
if (TRANSFORM_FN_NAMES.has(propName) || propName === "stroke-dasharray" || propName === "strokeDasharray") {
|
|
1068
2848
|
return interpolateVec(a || [], b || [], t);
|
|
1069
2849
|
}
|
|
1070
2850
|
return interpolateNum(+(a || 0), +(b || 0), t);
|
|
1071
2851
|
}
|
|
2852
|
+
function interpolateTransformParts(a, b, t) {
|
|
2853
|
+
const keys = /* @__PURE__ */ new Set([...Object.keys(a != null ? a : {}), ...Object.keys(b != null ? b : {})]);
|
|
2854
|
+
const out = {};
|
|
2855
|
+
for (const k of keys) {
|
|
2856
|
+
const av = a == null ? void 0 : a[k];
|
|
2857
|
+
const bv = b == null ? void 0 : b[k];
|
|
2858
|
+
if (k === "rotate") {
|
|
2859
|
+
out[k] = interpolateNum(+(av != null ? av : 0), +(bv != null ? bv : 0), t);
|
|
2860
|
+
} else if (k === "translate" || k === "scale" || k === "origin") {
|
|
2861
|
+
const fallback = k === "scale" ? [1, 1] : [0, 0];
|
|
2862
|
+
out[k] = interpolateVec(av || fallback, bv || fallback, t);
|
|
2863
|
+
} else {
|
|
2864
|
+
out[k] = bv != null ? bv : av;
|
|
2865
|
+
}
|
|
2866
|
+
}
|
|
2867
|
+
return out;
|
|
2868
|
+
}
|
|
1072
2869
|
function expandLoopKeyframes(propName, keyframes, loop, duration) {
|
|
1073
2870
|
var _a, _b, _c, _d, _e;
|
|
1074
2871
|
const totalIntervals = keyframes.length - 1;
|
|
@@ -1095,11 +2892,16 @@ function expandLoopKeyframes(propName, keyframes, loop, duration) {
|
|
|
1095
2892
|
const segEndT = (_e = segKfs[segKfs.length - 1].t) != null ? _e : 0;
|
|
1096
2893
|
const segDuration = segEndT - segStartT;
|
|
1097
2894
|
if (segDuration <= 0) return keyframes;
|
|
1098
|
-
const template = segKfs.map((kf) =>
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
2895
|
+
const template = segKfs.map((kf) => {
|
|
2896
|
+
var _a2, _b2;
|
|
2897
|
+
return {
|
|
2898
|
+
relT: (kf.t - segStartT) / segDuration,
|
|
2899
|
+
v: kf.v,
|
|
2900
|
+
e: kf.e,
|
|
2901
|
+
tangentIn: (_a2 = kf.tangentIn) != null ? _a2 : kf.ti,
|
|
2902
|
+
tangentOut: (_b2 = kf.tangentOut) != null ? _b2 : kf.to
|
|
2903
|
+
};
|
|
2904
|
+
});
|
|
1103
2905
|
const fullReps = Math.floor(fillDuration / segDuration);
|
|
1104
2906
|
const remainder = fillDuration - fullReps * segDuration;
|
|
1105
2907
|
const partialFraction = remainder / segDuration;
|
|
@@ -1113,7 +2915,12 @@ function expandLoopKeyframes(propName, keyframes, loop, duration) {
|
|
|
1113
2915
|
relT: 1 - template[i].relT,
|
|
1114
2916
|
v: template[i].v,
|
|
1115
2917
|
// Easing for reversed transition: use reversed easing from the forward "from" keyframe
|
|
1116
|
-
e: i > 0 ? reverseEasing(template[i - 1].e) : void 0
|
|
2918
|
+
e: i > 0 ? reverseEasing(template[i - 1].e) : void 0,
|
|
2919
|
+
// Reversed traversal swaps each vertex's in/out spatial tangents
|
|
2920
|
+
// (geometry is identical, walked backwards), so curvature and
|
|
2921
|
+
// auto-orientation survive the reversed rep.
|
|
2922
|
+
tangentIn: template[i].tangentOut,
|
|
2923
|
+
tangentOut: template[i].tangentIn
|
|
1117
2924
|
});
|
|
1118
2925
|
}
|
|
1119
2926
|
} else {
|
|
@@ -1135,11 +2942,14 @@ function expandLoopKeyframes(propName, keyframes, loop, duration) {
|
|
|
1135
2942
|
looped.push({ t: repStart + cutRelT * segDuration, v: cutValue, e: void 0 });
|
|
1136
2943
|
return;
|
|
1137
2944
|
}
|
|
1138
|
-
|
|
2945
|
+
const pushed = {
|
|
1139
2946
|
t: repStart + entry.relT * segDuration,
|
|
1140
2947
|
v: entry.v,
|
|
1141
2948
|
e: i < entries.length - 1 ? entry.e : void 0
|
|
1142
|
-
}
|
|
2949
|
+
};
|
|
2950
|
+
if (entry.tangentIn) pushed.tangentIn = entry.tangentIn;
|
|
2951
|
+
if (entry.tangentOut) pushed.tangentOut = entry.tangentOut;
|
|
2952
|
+
looped.push(pushed);
|
|
1143
2953
|
}
|
|
1144
2954
|
}
|
|
1145
2955
|
for (let rep = 0; rep < fullReps; rep++) {
|
|
@@ -1160,7 +2970,7 @@ function expandLoopKeyframes(propName, keyframes, loop, duration) {
|
|
|
1160
2970
|
}
|
|
1161
2971
|
}
|
|
1162
2972
|
function normalizeKeyframes(propName, propAnim, duration, defs) {
|
|
1163
|
-
var _a, _b, _c, _d, _e;
|
|
2973
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
1164
2974
|
const keyframes = propAnim.keyframes || propAnim.kfs || [];
|
|
1165
2975
|
const normalized = [];
|
|
1166
2976
|
for (const kf of keyframes) {
|
|
@@ -1170,14 +2980,20 @@ function normalizeKeyframes(propName, propAnim, duration, defs) {
|
|
|
1170
2980
|
if (propName === "d") {
|
|
1171
2981
|
value = normalizePathValue(value);
|
|
1172
2982
|
}
|
|
1173
|
-
|
|
2983
|
+
const propNameKebab = isCamelCaseWord(propName) ? camelCaseToKebabWordIfNeeded(propName) : propName;
|
|
2984
|
+
if (COLOUR_ATTR_NAMES.has(propNameKebab)) {
|
|
1174
2985
|
value = (_e = parseColor(value)) != null ? _e : value;
|
|
1175
2986
|
}
|
|
1176
|
-
|
|
2987
|
+
const normKf = {
|
|
1177
2988
|
t: timePct,
|
|
1178
2989
|
v: value,
|
|
1179
2990
|
e: resolveEasing(easing, defs)
|
|
1180
|
-
}
|
|
2991
|
+
};
|
|
2992
|
+
const tIn = (_f = kf.tangentIn) != null ? _f : kf.ti;
|
|
2993
|
+
const tOut = (_g = kf.tangentOut) != null ? _g : kf.to;
|
|
2994
|
+
if (tIn) normKf.tangentIn = tIn;
|
|
2995
|
+
if (tOut) normKf.tangentOut = tOut;
|
|
2996
|
+
normalized.push(normKf);
|
|
1181
2997
|
}
|
|
1182
2998
|
normalized.sort((a, b) => {
|
|
1183
2999
|
var _a2, _b2;
|
|
@@ -1199,21 +3015,84 @@ function mergeAnimationDefinitions(animations) {
|
|
|
1199
3015
|
}
|
|
1200
3016
|
return merged;
|
|
1201
3017
|
}
|
|
3018
|
+
function materialiseInternalLoopsInPropAnim(propName, propAnim, duration) {
|
|
3019
|
+
var _a;
|
|
3020
|
+
const loopRaw = propAnim.loop;
|
|
3021
|
+
if (loopRaw === void 0 || loopRaw === null || loopRaw === false) return propAnim;
|
|
3022
|
+
const loop = loopRaw === true ? {} : loopRaw;
|
|
3023
|
+
const rawKfs = (_a = propAnim.keyframes) != null ? _a : propAnim.kfs;
|
|
3024
|
+
if (!Array.isArray(rawKfs) || rawKfs.length < 2) return propAnim;
|
|
3025
|
+
const propNameKebab = isCamelCaseWord(propName) ? camelCaseToKebabWordIfNeeded(propName) : propName;
|
|
3026
|
+
const isColour = COLOUR_ATTR_NAMES.has(propNameKebab);
|
|
3027
|
+
const kfs = rawKfs.map((kf) => {
|
|
3028
|
+
var _a2, _b, _c, _d, _e, _f, _g, _h;
|
|
3029
|
+
const t = (_a2 = kf.t) != null ? _a2 : kf.time;
|
|
3030
|
+
let v = (_b = kf.v) != null ? _b : kf.value;
|
|
3031
|
+
if (propName === "d") v = normalizePathValue(v);
|
|
3032
|
+
if (isColour) v = (_c = parseColor(v)) != null ? _c : v;
|
|
3033
|
+
const e = (_d = kf.e) != null ? _d : kf.easing;
|
|
3034
|
+
const out2 = { t, v, e };
|
|
3035
|
+
if ((_e = kf.tangentIn) != null ? _e : kf.ti) out2.tangentIn = (_f = kf.tangentIn) != null ? _f : kf.ti;
|
|
3036
|
+
if ((_g = kf.tangentOut) != null ? _g : kf.to) out2.tangentOut = (_h = kf.tangentOut) != null ? _h : kf.to;
|
|
3037
|
+
return out2;
|
|
3038
|
+
});
|
|
3039
|
+
const expanded = expandLoopKeyframes(propName, kfs, loop, duration);
|
|
3040
|
+
const out = { kfs: expanded };
|
|
3041
|
+
if (propAnim.autoOrient !== void 0) out.autoOrient = propAnim.autoOrient;
|
|
3042
|
+
return out;
|
|
3043
|
+
}
|
|
3044
|
+
function materialiseInternalLoopsInTree(root, duration) {
|
|
3045
|
+
const ret = walkAndMaterialiseLoops(root, duration);
|
|
3046
|
+
return ret != null ? ret : root;
|
|
3047
|
+
}
|
|
3048
|
+
function walkAndMaterialiseLoops(node, duration) {
|
|
3049
|
+
let newChildren;
|
|
3050
|
+
if (node.children) {
|
|
3051
|
+
for (let i = 0; i < node.children.length; i++) {
|
|
3052
|
+
const ret = walkAndMaterialiseLoops(node.children[i], duration);
|
|
3053
|
+
if (ret !== null) {
|
|
3054
|
+
if (!newChildren) newChildren = node.children.slice();
|
|
3055
|
+
newChildren[i] = ret;
|
|
3056
|
+
}
|
|
3057
|
+
}
|
|
3058
|
+
}
|
|
3059
|
+
let newAnimate;
|
|
3060
|
+
const animBucket = node.animate;
|
|
3061
|
+
if (animBucket && typeof animBucket === "object" && !Array.isArray(animBucket)) {
|
|
3062
|
+
const animDef = animBucket;
|
|
3063
|
+
for (const propName of Object.keys(animDef)) {
|
|
3064
|
+
const propAnim = animDef[propName];
|
|
3065
|
+
const materialised = materialiseInternalLoopsInPropAnim(propName, propAnim, duration);
|
|
3066
|
+
if (materialised !== propAnim) {
|
|
3067
|
+
if (!newAnimate) newAnimate = __spreadValues({}, animDef);
|
|
3068
|
+
newAnimate[propName] = materialised;
|
|
3069
|
+
}
|
|
3070
|
+
}
|
|
3071
|
+
}
|
|
3072
|
+
if (!newChildren && !newAnimate) return null;
|
|
3073
|
+
const cloned = __spreadValues({}, node);
|
|
3074
|
+
if (newChildren) cloned.children = newChildren;
|
|
3075
|
+
if (newAnimate) cloned.animate = newAnimate;
|
|
3076
|
+
return cloned;
|
|
3077
|
+
}
|
|
1202
3078
|
var _elementIdCounter = 0;
|
|
1203
3079
|
function generateElementId() {
|
|
1204
3080
|
return "_px_el_" + ++_elementIdCounter;
|
|
1205
3081
|
}
|
|
1206
|
-
function normalizeAnimationDefinition(animDef, duration, defs) {
|
|
3082
|
+
function normalizeAnimationDefinition(animDef, duration, defs, engine = PxAnimatorEngine.webapi) {
|
|
1207
3083
|
const normalized = {};
|
|
1208
3084
|
for (const [propName, propAnim] of Object.entries(animDef)) {
|
|
1209
3085
|
const normalizedKfs = normalizeKeyframes(propName, propAnim, duration, defs);
|
|
1210
3086
|
if (normalizedKfs.length > 0) {
|
|
1211
|
-
|
|
3087
|
+
const out = { kfs: normalizedKfs };
|
|
3088
|
+
if (propAnim.autoOrient !== void 0) out.autoOrient = propAnim.autoOrient;
|
|
3089
|
+
if (propAnim.loop !== void 0) out.loop = propAnim.loop;
|
|
3090
|
+
normalized[propName] = engine === PxAnimatorEngine.webapi && propName === "transform" ? materialiseMotionPathInPropAnim(out) : out;
|
|
1212
3091
|
}
|
|
1213
3092
|
}
|
|
1214
3093
|
return normalized;
|
|
1215
3094
|
}
|
|
1216
|
-
function getNormalisedBindings(doc) {
|
|
3095
|
+
function getNormalisedBindings(doc, engine = PxAnimatorEngine.webapi) {
|
|
1217
3096
|
const animatorConfig = getAnimatorConfig(doc) || {};
|
|
1218
3097
|
const defs = getDefs(doc);
|
|
1219
3098
|
const duration = animatorConfig.duration || 1e3;
|
|
@@ -1223,7 +3102,7 @@ function getNormalisedBindings(doc) {
|
|
|
1223
3102
|
const animDefs = resolveElementAnimation(animate, defs);
|
|
1224
3103
|
if (animDefs.length === 0) return null;
|
|
1225
3104
|
const merged = mergeAnimationDefinitions(animDefs);
|
|
1226
|
-
const normalizedAnim = normalizeAnimationDefinition(merged, duration, defs);
|
|
3105
|
+
const normalizedAnim = normalizeAnimationDefinition(merged, duration, defs, engine);
|
|
1227
3106
|
if (Object.keys(normalizedAnim).length === 0) return null;
|
|
1228
3107
|
return {
|
|
1229
3108
|
id,
|
|
@@ -1238,10 +3117,11 @@ function getNormalisedBindings(doc) {
|
|
|
1238
3117
|
}
|
|
1239
3118
|
}
|
|
1240
3119
|
const processNode = (node) => {
|
|
1241
|
-
|
|
3120
|
+
const inlineAnim = node.animate;
|
|
3121
|
+
if (inlineAnim && Object.keys(inlineAnim).length > 0) {
|
|
1242
3122
|
const nodeId = node.id || generateElementId();
|
|
1243
3123
|
node.id = nodeId;
|
|
1244
|
-
const normalized = processAnimation(nodeId,
|
|
3124
|
+
const normalized = processAnimation(nodeId, inlineAnim);
|
|
1245
3125
|
if (normalized) bindings.push(normalized);
|
|
1246
3126
|
}
|
|
1247
3127
|
if (node.children) {
|
|
@@ -1249,115 +3129,870 @@ function getNormalisedBindings(doc) {
|
|
|
1249
3129
|
processNode(node.children[i]);
|
|
1250
3130
|
}
|
|
1251
3131
|
}
|
|
1252
|
-
};
|
|
1253
|
-
if (doc.children) {
|
|
1254
|
-
for (let i = 0; i < doc.children.length; i++) {
|
|
1255
|
-
processNode(doc.children[i]);
|
|
1256
|
-
}
|
|
3132
|
+
};
|
|
3133
|
+
if (doc.children) {
|
|
3134
|
+
for (let i = 0; i < doc.children.length; i++) {
|
|
3135
|
+
processNode(doc.children[i]);
|
|
3136
|
+
}
|
|
3137
|
+
}
|
|
3138
|
+
return bindings;
|
|
3139
|
+
}
|
|
3140
|
+
function getKeyframesPair(keyframes, progress) {
|
|
3141
|
+
var _a, _b;
|
|
3142
|
+
let prevKf = keyframes[0];
|
|
3143
|
+
let nextKf = keyframes[keyframes.length - 1];
|
|
3144
|
+
for (let j = 0; j < keyframes.length - 1; j++) {
|
|
3145
|
+
const aOff = (_a = keyframes[j].t) != null ? _a : 0;
|
|
3146
|
+
const bOff = (_b = keyframes[j + 1].t) != null ? _b : 0;
|
|
3147
|
+
if (aOff <= progress && progress <= bOff) {
|
|
3148
|
+
prevKf = keyframes[j];
|
|
3149
|
+
nextKf = keyframes[j + 1];
|
|
3150
|
+
break;
|
|
3151
|
+
}
|
|
3152
|
+
}
|
|
3153
|
+
return { prevKf, nextKf };
|
|
3154
|
+
}
|
|
3155
|
+
function calcPropertyValue(propName, propAnim, progress) {
|
|
3156
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
3157
|
+
const keyframes = propAnim.kfs || propAnim.keyframes || [];
|
|
3158
|
+
if (keyframes.length === 0) return null;
|
|
3159
|
+
const { prevKf, nextKf } = getKeyframesPair(keyframes, progress);
|
|
3160
|
+
let localProgress = prevKf === nextKf ? 0 : remap(progress, (_a = prevKf.t) != null ? _a : 0, (_b = nextKf.t) != null ? _b : 0, 0, 1);
|
|
3161
|
+
localProgress = clamp(localProgress, 0, 1);
|
|
3162
|
+
const easing = (_c = prevKf.e) != null ? _c : prevKf.easing;
|
|
3163
|
+
if (easing && Array.isArray(easing)) {
|
|
3164
|
+
try {
|
|
3165
|
+
localProgress = cubicBezier(easing)(localProgress);
|
|
3166
|
+
} catch (e) {
|
|
3167
|
+
}
|
|
3168
|
+
}
|
|
3169
|
+
let cssAttrName = isCamelCaseWord(propName) ? camelCaseToKebabWordIfNeeded(propName) : propName;
|
|
3170
|
+
let cssValue = null;
|
|
3171
|
+
const prevV = (_d = prevKf == null ? void 0 : prevKf.v) != null ? _d : prevKf == null ? void 0 : prevKf.value;
|
|
3172
|
+
const nextV = (_e = nextKf == null ? void 0 : nextKf.v) != null ? _e : nextKf == null ? void 0 : nextKf.value;
|
|
3173
|
+
if (cssAttrName === "d") {
|
|
3174
|
+
const prevPaths = (_f = prevV == null ? void 0 : prevV.paths) != null ? _f : Array.isArray(prevV) ? prevV : [];
|
|
3175
|
+
const nextPaths = (_g = nextV == null ? void 0 : nextV.paths) != null ? _g : Array.isArray(nextV) ? nextV : [];
|
|
3176
|
+
cssValue = interpolateBeziers(
|
|
3177
|
+
prevPaths,
|
|
3178
|
+
nextPaths,
|
|
3179
|
+
localProgress
|
|
3180
|
+
).map((bz) => bezierToSvgPath(bz)).join("");
|
|
3181
|
+
} else if (COLOUR_ATTR_NAMES.has(cssAttrName)) {
|
|
3182
|
+
cssValue = toRGBA(interpolateColor(
|
|
3183
|
+
prevV || [0, 0, 0, 1],
|
|
3184
|
+
nextV || [0, 0, 0, 1],
|
|
3185
|
+
localProgress
|
|
3186
|
+
));
|
|
3187
|
+
cssAttrName = propName;
|
|
3188
|
+
} else if (cssAttrName === "stroke-dasharray") {
|
|
3189
|
+
cssValue = interpolateVec(
|
|
3190
|
+
prevV || [],
|
|
3191
|
+
nextV || [],
|
|
3192
|
+
localProgress
|
|
3193
|
+
).join(" ");
|
|
3194
|
+
cssAttrName = propName;
|
|
3195
|
+
} else if (cssAttrName === "transform" && prevV !== null && typeof prevV === "object" && !Array.isArray(prevV)) {
|
|
3196
|
+
const partKeys = /* @__PURE__ */ new Set([
|
|
3197
|
+
...prevV ? Object.keys(prevV) : [],
|
|
3198
|
+
...nextV ? Object.keys(nextV) : []
|
|
3199
|
+
]);
|
|
3200
|
+
const partsResult = {};
|
|
3201
|
+
for (const partKey of partKeys) {
|
|
3202
|
+
const prevPart = prevV == null ? void 0 : prevV[partKey];
|
|
3203
|
+
const nextPart = nextV == null ? void 0 : nextV[partKey];
|
|
3204
|
+
if (partKey === "rotate") {
|
|
3205
|
+
partsResult.rotate = interpolateNum(+(prevPart != null ? prevPart : 0), +(nextPart != null ? nextPart : 0), localProgress);
|
|
3206
|
+
} else if (partKey === "translate" || partKey === "scale" || partKey === "origin") {
|
|
3207
|
+
const fallback = partKey === "scale" ? [1, 1] : [0, 0];
|
|
3208
|
+
const interp = interpolateVec(prevPart || fallback, nextPart || fallback, localProgress);
|
|
3209
|
+
partsResult[partKey] = interp;
|
|
3210
|
+
}
|
|
3211
|
+
}
|
|
3212
|
+
if (propAnimIsMotionPath(propAnim)) {
|
|
3213
|
+
const prevTr = prevV.translate;
|
|
3214
|
+
const nextTr = nextV.translate;
|
|
3215
|
+
if (Array.isArray(prevTr) && Array.isArray(nextTr)) {
|
|
3216
|
+
const sample = evaluateMotionPathSegment(
|
|
3217
|
+
prevKf,
|
|
3218
|
+
nextKf,
|
|
3219
|
+
[+prevTr[0], +prevTr[1]],
|
|
3220
|
+
[+nextTr[0], +nextTr[1]],
|
|
3221
|
+
localProgress,
|
|
3222
|
+
!!propAnim.autoOrient
|
|
3223
|
+
);
|
|
3224
|
+
partsResult.translate = [sample.translate[0], sample.translate[1]];
|
|
3225
|
+
if (sample.rotateDeg !== void 0) partsResult.rotate = sample.rotateDeg;
|
|
3226
|
+
}
|
|
3227
|
+
}
|
|
3228
|
+
cssValue = composeTransformParts(partsResult, { withUnits: false });
|
|
3229
|
+
cssAttrName = "transform";
|
|
3230
|
+
} else if (cssAttrName === "translate") {
|
|
3231
|
+
const v = interpolateVec(
|
|
3232
|
+
prevV || [0, 0],
|
|
3233
|
+
nextV || [0, 0],
|
|
3234
|
+
localProgress
|
|
3235
|
+
);
|
|
3236
|
+
cssValue = "translate(" + v.join(",") + ")";
|
|
3237
|
+
cssAttrName = "transform";
|
|
3238
|
+
} else if (cssAttrName === "rotate") {
|
|
3239
|
+
const v = interpolateNum(
|
|
3240
|
+
+(prevV || 0),
|
|
3241
|
+
+(nextV || 0),
|
|
3242
|
+
localProgress
|
|
3243
|
+
);
|
|
3244
|
+
cssValue = "rotate(" + v + ")";
|
|
3245
|
+
cssAttrName = "transform";
|
|
3246
|
+
} else if (cssAttrName === "scale") {
|
|
3247
|
+
const v = interpolateVec(
|
|
3248
|
+
prevV || [1, 1],
|
|
3249
|
+
nextV || [1, 1],
|
|
3250
|
+
localProgress
|
|
3251
|
+
);
|
|
3252
|
+
cssValue = "scale(" + v.join(",") + ")";
|
|
3253
|
+
cssAttrName = "transform";
|
|
3254
|
+
} else {
|
|
3255
|
+
const num2 = interpolateNum(
|
|
3256
|
+
+(prevV || 0),
|
|
3257
|
+
+(nextV || 0),
|
|
3258
|
+
localProgress
|
|
3259
|
+
);
|
|
3260
|
+
cssValue = num2;
|
|
3261
|
+
}
|
|
3262
|
+
if (PCT_BASED_ATTR_NAMES.has(cssAttrName) && typeof cssValue === "number") {
|
|
3263
|
+
cssValue = cssValue * 100 + "%";
|
|
3264
|
+
}
|
|
3265
|
+
return { k: cssAttrName, v: cssValue === null ? "" : "" + cssValue };
|
|
3266
|
+
}
|
|
3267
|
+
function calcAnimationValues(animDef, progress) {
|
|
3268
|
+
const result = {};
|
|
3269
|
+
for (const [propName, propAnim] of Object.entries(animDef)) {
|
|
3270
|
+
const computed = calcPropertyValue(propName, propAnim, progress);
|
|
3271
|
+
if (computed) {
|
|
3272
|
+
result[computed.k] = computed.v;
|
|
3273
|
+
}
|
|
3274
|
+
}
|
|
3275
|
+
return result;
|
|
3276
|
+
}
|
|
3277
|
+
|
|
3278
|
+
// src/effects/trimPathEffect.ts
|
|
3279
|
+
function applyTrimPathEffect(node, trimPath, isCombinedShape, ctx) {
|
|
3280
|
+
if (!trimPath) return node;
|
|
3281
|
+
const trimAllAsOne = !!trimPath.trimAllAsOne;
|
|
3282
|
+
const leafEntries = [];
|
|
3283
|
+
let acc = 0;
|
|
3284
|
+
const measure = (n) => {
|
|
3285
|
+
if (Array.isArray(n.children) && n.children.length > 0) {
|
|
3286
|
+
for (const ch of n.children) measure(ch);
|
|
3287
|
+
return;
|
|
3288
|
+
}
|
|
3289
|
+
const d = typeof n.d === "string" ? n.d : rectToPathD(n);
|
|
3290
|
+
if (d === void 0) return;
|
|
3291
|
+
const subpaths = parseSvgPathToBezier(d);
|
|
3292
|
+
if (!subpaths.length) return;
|
|
3293
|
+
const entry = { leaf: n, subpaths: [] };
|
|
3294
|
+
for (const sp of subpaths) {
|
|
3295
|
+
if (!trimAllAsOne) acc = 0;
|
|
3296
|
+
const lengthPx = pxBezierPathLength(sp);
|
|
3297
|
+
entry.subpaths.push({ subpath: sp, lengthPx, startOffsetPx: acc });
|
|
3298
|
+
acc += lengthPx;
|
|
3299
|
+
}
|
|
3300
|
+
leafEntries.push(entry);
|
|
3301
|
+
};
|
|
3302
|
+
measure(node);
|
|
3303
|
+
if (!leafEntries.length) return node;
|
|
3304
|
+
const chainLengthPx = acc;
|
|
3305
|
+
if (trimAllAsOne && chainLengthPx < 1e-3) return node;
|
|
3306
|
+
const offsetReadRaw = readAnimatable(trimPath.offset);
|
|
3307
|
+
const offsetRead = offsetReadRaw.kind === "absent" /* Absent */ ? { kind: "static" /* Static */, value: 0 } : offsetReadRaw;
|
|
3308
|
+
const rangeReadRaw = readRangeWithCrossings(trimPath.range);
|
|
3309
|
+
const rangeRead = rangeReadRaw.kind === "absent" /* Absent */ ? { kind: "static" /* Static */, value: [0, 1] } : rangeReadRaw;
|
|
3310
|
+
const offsetValues = readScalarValues(offsetRead);
|
|
3311
|
+
const minOffset = offsetValues.length ? Math.min(...offsetValues) : 0;
|
|
3312
|
+
const maxOffset = offsetValues.length ? Math.max(...offsetValues) : 0;
|
|
3313
|
+
const minMaxOffset = [minOffset, maxOffset];
|
|
3314
|
+
if (leafEntries.length === 1 && leafEntries[0].leaf === node && leafEntries[0].subpaths.length === 1) {
|
|
3315
|
+
const entry = leafEntries[0];
|
|
3316
|
+
const sp = entry.subpaths[0];
|
|
3317
|
+
const pathLengthPx = trimAllAsOne ? chainLengthPx : sp.lengthPx;
|
|
3318
|
+
if (pathLengthPx < 1e-3) return node;
|
|
3319
|
+
const startOffsetPct = trimAllAsOne ? sp.startOffsetPx / pathLengthPx : 0;
|
|
3320
|
+
return collapseLeafWithTrim(entry.leaf, pathLengthPx, startOffsetPct, minMaxOffset, offsetRead, rangeRead);
|
|
3321
|
+
}
|
|
3322
|
+
const replacements = /* @__PURE__ */ new Map();
|
|
3323
|
+
for (const entry of leafEntries) {
|
|
3324
|
+
const newChildren = [];
|
|
3325
|
+
for (const sp of entry.subpaths) {
|
|
3326
|
+
const pathLengthPx = trimAllAsOne ? chainLengthPx : sp.lengthPx;
|
|
3327
|
+
if (pathLengthPx < 1e-3) continue;
|
|
3328
|
+
const startOffsetPct = trimAllAsOne ? sp.startOffsetPx / pathLengthPx : 0;
|
|
3329
|
+
newChildren.push(...buildSubpathNodes(entry.leaf, sp.subpath, pathLengthPx, startOffsetPct, minMaxOffset, offsetRead, rangeRead, ctx));
|
|
3330
|
+
}
|
|
3331
|
+
replacements.set(entry.leaf, wrapLeafAsGroup(entry.leaf, newChildren));
|
|
3332
|
+
}
|
|
3333
|
+
const swap = (n) => {
|
|
3334
|
+
const r = replacements.get(n);
|
|
3335
|
+
if (r) return r;
|
|
3336
|
+
if (Array.isArray(n.children) && n.children.length > 0) {
|
|
3337
|
+
return __spreadProps(__spreadValues({}, n), { children: n.children.map(swap) });
|
|
3338
|
+
}
|
|
3339
|
+
return n;
|
|
3340
|
+
};
|
|
3341
|
+
return swap(node);
|
|
3342
|
+
}
|
|
3343
|
+
function wrapLeafAsGroup(leaf, children) {
|
|
3344
|
+
const wrapper = __spreadProps(__spreadValues({}, leaf), { type: "g", children });
|
|
3345
|
+
delete wrapper.d;
|
|
3346
|
+
delete wrapper.strokeDasharray;
|
|
3347
|
+
delete wrapper.strokeDashoffset;
|
|
3348
|
+
delete wrapper.effects;
|
|
3349
|
+
return wrapper;
|
|
3350
|
+
}
|
|
3351
|
+
function buildSubpathNodes(leaf, subpath, pathLengthPx, startOffsetPct, minMaxOffset, offsetRead, rangeRead, ctx) {
|
|
3352
|
+
const offsetToDashOffset = makeOffsetToDashOffset(startOffsetPct, pathLengthPx, minMaxOffset);
|
|
3353
|
+
const rangeToDasharray = makeRangeToDasharray(pathLengthPx, minMaxOffset);
|
|
3354
|
+
const dashOffsetAttr = computeAnimAttr(offsetRead, offsetToDashOffset);
|
|
3355
|
+
const dashArrayAttr = computeAnimAttr(rangeRead, rangeToDasharray);
|
|
3356
|
+
const strokeOpacityAttr = computeOpacityFromRange(rangeRead);
|
|
3357
|
+
const dStr = bezierToSvgPath(subpath);
|
|
3358
|
+
const base = makeBareSubpath(dStr);
|
|
3359
|
+
applyAttr(base, "strokeDasharray", dashArrayAttr);
|
|
3360
|
+
applyAttr(base, "strokeDashoffset", dashOffsetAttr);
|
|
3361
|
+
applyAttr(base, "strokeOpacity", strokeOpacityAttr);
|
|
3362
|
+
return [base];
|
|
3363
|
+
}
|
|
3364
|
+
function collapseLeafWithTrim(leaf, pathLengthPx, startOffsetPct, minMaxOffset, offsetRead, rangeRead) {
|
|
3365
|
+
const offsetToDashOffset = makeOffsetToDashOffset(startOffsetPct, pathLengthPx, minMaxOffset);
|
|
3366
|
+
const rangeToDasharray = makeRangeToDasharray(pathLengthPx, minMaxOffset);
|
|
3367
|
+
const node = __spreadValues({}, leaf);
|
|
3368
|
+
delete node.effects;
|
|
3369
|
+
applyAttr(node, "strokeDasharray", computeAnimAttr(rangeRead, rangeToDasharray));
|
|
3370
|
+
applyAttr(node, "strokeDashoffset", computeAnimAttr(offsetRead, offsetToDashOffset));
|
|
3371
|
+
applyAttr(node, "strokeOpacity", computeOpacityFromRange(rangeRead));
|
|
3372
|
+
return node;
|
|
3373
|
+
}
|
|
3374
|
+
function makeBareSubpath(dStr) {
|
|
3375
|
+
return { type: "path", d: dStr };
|
|
3376
|
+
}
|
|
3377
|
+
var SMALL_PADDING_PX = 1;
|
|
3378
|
+
function makeOffsetToDashOffset(startOffsetPct, pathLengthPx, minMaxOffset) {
|
|
3379
|
+
const [minIdx] = getOffsetIndexRange(minMaxOffset);
|
|
3380
|
+
return (offsetVal) => pathLengthPx * (-offsetVal - minIdx + startOffsetPct) + SMALL_PADDING_PX;
|
|
3381
|
+
}
|
|
3382
|
+
function makeRangeToDasharray(pathLengthPx, minMaxOffset) {
|
|
3383
|
+
const [minIdx, maxIdx] = getOffsetIndexRange(minMaxOffset);
|
|
3384
|
+
const repeats = maxIdx - minIdx + 1;
|
|
3385
|
+
return (rangeVal) => {
|
|
3386
|
+
const a = clamp(rangeVal[0], 0, 1);
|
|
3387
|
+
const b = clamp(rangeVal[1], 0, 1);
|
|
3388
|
+
const minR = Math.min(a, b);
|
|
3389
|
+
const maxR = Math.max(a, b);
|
|
3390
|
+
const out = [0];
|
|
3391
|
+
let gap = SMALL_PADDING_PX;
|
|
3392
|
+
for (let i = 0; i < repeats; i++) {
|
|
3393
|
+
out.push(gap + minR * pathLengthPx);
|
|
3394
|
+
out.push((maxR - minR) * pathLengthPx);
|
|
3395
|
+
gap = (1 - maxR) * pathLengthPx;
|
|
3396
|
+
}
|
|
3397
|
+
out.push(gap + SMALL_PADDING_PX);
|
|
3398
|
+
return out;
|
|
3399
|
+
};
|
|
3400
|
+
}
|
|
3401
|
+
function getOffsetIndexRange(minMaxOffset) {
|
|
3402
|
+
return [
|
|
3403
|
+
Math.floor(Math.min(-minMaxOffset[0], -minMaxOffset[1])),
|
|
3404
|
+
Math.ceil(Math.max(-minMaxOffset[0], -minMaxOffset[1]))
|
|
3405
|
+
];
|
|
3406
|
+
}
|
|
3407
|
+
function readScalarValues(r) {
|
|
3408
|
+
var _a;
|
|
3409
|
+
if (r.kind === "absent" /* Absent */) return [];
|
|
3410
|
+
if (r.kind === "static" /* Static */) return [r.value];
|
|
3411
|
+
const out = [];
|
|
3412
|
+
for (const kf of r.keyframes) {
|
|
3413
|
+
const v = (_a = kf.value) != null ? _a : kf.v;
|
|
3414
|
+
if (typeof v === "number") out.push(v);
|
|
3415
|
+
}
|
|
3416
|
+
return out;
|
|
3417
|
+
}
|
|
3418
|
+
function computeAnimAttr(read, map) {
|
|
3419
|
+
if (read.kind === "absent" /* Absent */) return void 0;
|
|
3420
|
+
if (read.kind === "static" /* Static */) return { kind: "static" /* Static */, value: map(read.value) };
|
|
3421
|
+
return {
|
|
3422
|
+
kind: "animated" /* Animated */,
|
|
3423
|
+
keyframes: read.keyframes.map((kf) => {
|
|
3424
|
+
var _a, _b, _c, _d;
|
|
3425
|
+
return {
|
|
3426
|
+
time: (_b = (_a = kf.time) != null ? _a : kf.t) != null ? _b : 0,
|
|
3427
|
+
value: map((_c = kf.value) != null ? _c : kf.v),
|
|
3428
|
+
easing: (_d = kf.easing) != null ? _d : kf.e
|
|
3429
|
+
};
|
|
3430
|
+
})
|
|
3431
|
+
};
|
|
3432
|
+
}
|
|
3433
|
+
function applyAttr(node, attrName, attr) {
|
|
3434
|
+
if (!attr) return;
|
|
3435
|
+
if (attr.kind === "static" /* Static */) {
|
|
3436
|
+
node[attrName] = attr.value;
|
|
3437
|
+
return;
|
|
3438
|
+
}
|
|
3439
|
+
const prevAnimate = node.animate && typeof node.animate === "object" && !Array.isArray(node.animate) ? node.animate : void 0;
|
|
3440
|
+
const animate = __spreadValues({}, prevAnimate || {});
|
|
3441
|
+
animate[attrName] = { keyframes: attr.keyframes };
|
|
3442
|
+
node.animate = animate;
|
|
3443
|
+
}
|
|
3444
|
+
function computeOpacityFromRange(rangeRead) {
|
|
3445
|
+
var _a, _b, _c, _d, _e, _f;
|
|
3446
|
+
const hide = (v) => v[0] === v[1];
|
|
3447
|
+
if (rangeRead.kind === "absent" /* Absent */) return void 0;
|
|
3448
|
+
if (rangeRead.kind === "static" /* Static */) return hide(rangeRead.value) ? { kind: "static" /* Static */, value: 0 } : void 0;
|
|
3449
|
+
const kfs = rangeRead.keyframes;
|
|
3450
|
+
let anyHide = false;
|
|
3451
|
+
let allHide = true;
|
|
3452
|
+
for (const kf of kfs) {
|
|
3453
|
+
if (hide((_a = kf.value) != null ? _a : kf.v)) anyHide = true;
|
|
3454
|
+
else allHide = false;
|
|
3455
|
+
}
|
|
3456
|
+
if (!anyHide) return void 0;
|
|
3457
|
+
if (allHide) return { kind: "static" /* Static */, value: 0 };
|
|
3458
|
+
const out = [];
|
|
3459
|
+
for (let i = 0; i < kfs.length; i++) {
|
|
3460
|
+
const kf = kfs[i];
|
|
3461
|
+
const prevKf = i > 0 ? kfs[i - 1] : void 0;
|
|
3462
|
+
const nextKf = i < kfs.length - 1 ? kfs[i + 1] : void 0;
|
|
3463
|
+
const t = (_c = (_b = kf.time) != null ? _b : kf.t) != null ? _c : 0;
|
|
3464
|
+
const thisHide = hide((_d = kf.value) != null ? _d : kf.v);
|
|
3465
|
+
const prevHide = prevKf ? thisHide && hide((_e = prevKf.value) != null ? _e : prevKf.v) : thisHide;
|
|
3466
|
+
const nextHide = nextKf ? thisHide && hide((_f = nextKf.value) != null ? _f : nextKf.v) : thisHide;
|
|
3467
|
+
if (prevHide && !nextHide) {
|
|
3468
|
+
out.push({ time: t, value: 0 });
|
|
3469
|
+
out.push({ time: t + 1, value: 1 });
|
|
3470
|
+
} else if (!prevHide && nextHide) {
|
|
3471
|
+
out.push({ time: t - 1, value: 1 });
|
|
3472
|
+
out.push({ time: t, value: 0 });
|
|
3473
|
+
}
|
|
3474
|
+
}
|
|
3475
|
+
if (out.length <= 1) return void 0;
|
|
3476
|
+
return { kind: "animated" /* Animated */, keyframes: out };
|
|
3477
|
+
}
|
|
3478
|
+
function readRangeWithCrossings(raw) {
|
|
3479
|
+
const r = readAnimatable(raw);
|
|
3480
|
+
if (r.kind !== "animated" /* Animated */) return r;
|
|
3481
|
+
const kfs = r.keyframes.map((kf) => {
|
|
3482
|
+
var _a, _b, _c, _d;
|
|
3483
|
+
return {
|
|
3484
|
+
time: (_b = (_a = kf.time) != null ? _a : kf.t) != null ? _b : 0,
|
|
3485
|
+
value: (_c = kf.value) != null ? _c : kf.v,
|
|
3486
|
+
easing: (_d = kf.easing) != null ? _d : kf.e
|
|
3487
|
+
};
|
|
3488
|
+
});
|
|
3489
|
+
const hasReverse = kfs.some((kf) => kf.value[0] > kf.value[1]);
|
|
3490
|
+
if (!hasReverse) {
|
|
3491
|
+
return {
|
|
3492
|
+
kind: "animated" /* Animated */,
|
|
3493
|
+
keyframes: kfs.map((kf) => ({ time: kf.time, value: kf.value, easing: kf.easing }))
|
|
3494
|
+
};
|
|
3495
|
+
}
|
|
3496
|
+
const crossingTimes = [];
|
|
3497
|
+
for (let i = 1; i < kfs.length; i++) {
|
|
3498
|
+
const prev = kfs[i - 1];
|
|
3499
|
+
const cur = kfs[i];
|
|
3500
|
+
const dPrev = prev.value[1] - prev.value[0];
|
|
3501
|
+
const dCur = cur.value[1] - cur.value[0];
|
|
3502
|
+
if (dPrev * dCur < 0) {
|
|
3503
|
+
const t = bisectionForRangeCrossing(prev, cur);
|
|
3504
|
+
if (t !== null && t > prev.time && t < cur.time) {
|
|
3505
|
+
crossingTimes.push(Math.round(t));
|
|
3506
|
+
}
|
|
3507
|
+
}
|
|
3508
|
+
}
|
|
3509
|
+
const uniqueTs = Array.from(new Set(crossingTimes)).sort((a, b) => a - b);
|
|
3510
|
+
const out = [];
|
|
3511
|
+
let j = 0;
|
|
3512
|
+
for (const kf of kfs) {
|
|
3513
|
+
while (j < uniqueTs.length && uniqueTs[j] < kf.time) {
|
|
3514
|
+
const t = uniqueTs[j++];
|
|
3515
|
+
const v2 = interpolateRangeAt(kfs, t);
|
|
3516
|
+
const m = (v2[0] + v2[1]) / 2;
|
|
3517
|
+
out.push({ time: t, value: [m, m] });
|
|
3518
|
+
}
|
|
3519
|
+
const v = kf.value[0] > kf.value[1] ? [kf.value[1], kf.value[0]] : kf.value;
|
|
3520
|
+
out.push({ time: kf.time, value: v, easing: kf.easing });
|
|
3521
|
+
}
|
|
3522
|
+
while (j < uniqueTs.length) {
|
|
3523
|
+
const t = uniqueTs[j++];
|
|
3524
|
+
const v = interpolateRangeAt(kfs, t);
|
|
3525
|
+
const m = (v[0] + v[1]) / 2;
|
|
3526
|
+
out.push({ time: t, value: [m, m] });
|
|
3527
|
+
}
|
|
3528
|
+
return { kind: "animated" /* Animated */, keyframes: out };
|
|
3529
|
+
}
|
|
3530
|
+
function bisectionForRangeCrossing(prev, cur) {
|
|
3531
|
+
const f = (t) => {
|
|
3532
|
+
const a = (t - prev.time) / (cur.time - prev.time);
|
|
3533
|
+
const v0 = prev.value[0] + (cur.value[0] - prev.value[0]) * a;
|
|
3534
|
+
const v1 = prev.value[1] + (cur.value[1] - prev.value[1]) * a;
|
|
3535
|
+
return v1 - v0;
|
|
3536
|
+
};
|
|
3537
|
+
let lo = prev.time, hi = cur.time;
|
|
3538
|
+
let fLo = f(lo);
|
|
3539
|
+
if (fLo === 0) return lo;
|
|
3540
|
+
const fHi = f(hi);
|
|
3541
|
+
if (fHi === 0) return hi;
|
|
3542
|
+
if (fLo * fHi > 0) return null;
|
|
3543
|
+
for (let i = 0; i < 100; i++) {
|
|
3544
|
+
const mid = (lo + hi) / 2;
|
|
3545
|
+
const fMid = f(mid);
|
|
3546
|
+
if (fMid === 0 || Math.abs(hi - lo) < 1e-4) return mid;
|
|
3547
|
+
if (fLo * fMid < 0) {
|
|
3548
|
+
hi = mid;
|
|
3549
|
+
} else {
|
|
3550
|
+
lo = mid;
|
|
3551
|
+
fLo = fMid;
|
|
3552
|
+
}
|
|
3553
|
+
}
|
|
3554
|
+
return (lo + hi) / 2;
|
|
3555
|
+
}
|
|
3556
|
+
function interpolateRangeAt(kfs, t) {
|
|
3557
|
+
if (t <= kfs[0].time) return kfs[0].value;
|
|
3558
|
+
if (t >= kfs[kfs.length - 1].time) return kfs[kfs.length - 1].value;
|
|
3559
|
+
for (let i = 1; i < kfs.length; i++) {
|
|
3560
|
+
if (t <= kfs[i].time) {
|
|
3561
|
+
const prev = kfs[i - 1];
|
|
3562
|
+
const cur = kfs[i];
|
|
3563
|
+
const a = (t - prev.time) / (cur.time - prev.time);
|
|
3564
|
+
return [
|
|
3565
|
+
prev.value[0] + (cur.value[0] - prev.value[0]) * a,
|
|
3566
|
+
prev.value[1] + (cur.value[1] - prev.value[1]) * a
|
|
3567
|
+
];
|
|
3568
|
+
}
|
|
3569
|
+
}
|
|
3570
|
+
return kfs[kfs.length - 1].value;
|
|
3571
|
+
}
|
|
3572
|
+
function pxBezierPathLength(path) {
|
|
3573
|
+
const v = path.v;
|
|
3574
|
+
if (!v || v.length < 2) return 0;
|
|
3575
|
+
let total = 0;
|
|
3576
|
+
for (let i = 0; i < v.length - 1; i++) {
|
|
3577
|
+
total += segmentLength(path, i, i + 1);
|
|
3578
|
+
}
|
|
3579
|
+
if (path.c && v.length > 1) {
|
|
3580
|
+
total += segmentLength(path, v.length - 1, 0);
|
|
3581
|
+
}
|
|
3582
|
+
return total;
|
|
3583
|
+
}
|
|
3584
|
+
function segmentLength(path, from, to) {
|
|
3585
|
+
var _a, _b, _c, _d;
|
|
3586
|
+
const v = path.v;
|
|
3587
|
+
const p0 = v[from];
|
|
3588
|
+
const p3 = v[to];
|
|
3589
|
+
const p1 = (_b = (_a = path.o) == null ? void 0 : _a[from]) != null ? _b : p0;
|
|
3590
|
+
const p2 = (_d = (_c = path.i) == null ? void 0 : _c[to]) != null ? _d : p3;
|
|
3591
|
+
const lut = bezier2D_arcLengthLUT(p0, p1, p2, p3);
|
|
3592
|
+
return lut.ds[lut.ds.length - 1];
|
|
3593
|
+
}
|
|
3594
|
+
function rectToPathD(node) {
|
|
3595
|
+
var _a, _b, _c, _d;
|
|
3596
|
+
if (node.type !== "rect") return void 0;
|
|
3597
|
+
const x = Number((_a = node.x) != null ? _a : 0), y = Number((_b = node.y) != null ? _b : 0);
|
|
3598
|
+
const w = Number((_c = node.width) != null ? _c : 0), h = Number((_d = node.height) != null ? _d : 0);
|
|
3599
|
+
return "M" + (x + w) + "," + y + "L" + (x + w) + "," + (y + h) + "L" + x + "," + (y + h) + "L" + x + "," + y + "L" + (x + w) + "," + y + "z";
|
|
3600
|
+
}
|
|
3601
|
+
|
|
3602
|
+
// src/effects/PlayerEffectsUtil.ts
|
|
3603
|
+
function applyPlayerEffects(root) {
|
|
3604
|
+
const ctx = {
|
|
3605
|
+
defs: [],
|
|
3606
|
+
warnings: [],
|
|
3607
|
+
errors: [],
|
|
3608
|
+
idMap: /* @__PURE__ */ new Map(),
|
|
3609
|
+
nextId: 0,
|
|
3610
|
+
contentRefInnerIds: /* @__PURE__ */ new Map(),
|
|
3611
|
+
maskAncestorChains: /* @__PURE__ */ new Map()
|
|
3612
|
+
};
|
|
3613
|
+
const working = clone(root);
|
|
3614
|
+
indexById(working, ctx.idMap);
|
|
3615
|
+
identifyContentRefTargets(working, ctx, () => genId(ctx, "inner"));
|
|
3616
|
+
collectMaskAncestorChains(working, ctx);
|
|
3617
|
+
const afterPass1 = applyPlayerEffects_exceptRetime(working, ctx);
|
|
3618
|
+
const out = applyPlayerEffects_retime(afterPass1, ctx);
|
|
3619
|
+
spliceDefs(out, ctx.defs);
|
|
3620
|
+
return { root: out, defs: ctx.defs, warnings: ctx.warnings, errors: ctx.errors };
|
|
3621
|
+
}
|
|
3622
|
+
function applyPlayerEffects_exceptRetime(node, ctx) {
|
|
3623
|
+
if (node.children) node.children = node.children.map((child) => applyPlayerEffects_exceptRetime(child, ctx));
|
|
3624
|
+
const fx = node.effects;
|
|
3625
|
+
const originalId = typeof node.id === "string" ? node.id : void 0;
|
|
3626
|
+
const innerIdForContentRef = originalId ? ctx.contentRefInnerIds.get(originalId) : void 0;
|
|
3627
|
+
if (!fx && !innerIdForContentRef) return node;
|
|
3628
|
+
const { transformation, repeater, maskedBy, trimPath, retime, ref, fillGradient, strokeGradient, textAlongPath } = fx != null ? fx : {};
|
|
3629
|
+
const isCombinedShape = fx == null ? void 0 : fx.isCombinedShape;
|
|
3630
|
+
if (fx) delete node.effects;
|
|
3631
|
+
let n = node;
|
|
3632
|
+
n = applyTextAlongPathEffect(n, textAlongPath, ctx);
|
|
3633
|
+
n = applyFillGradientEffect(n, fillGradient, ctx);
|
|
3634
|
+
n = applyStrokeGradientEffect(n, strokeGradient, ctx);
|
|
3635
|
+
n = applyTrimPathEffect(n, trimPath, isCombinedShape, ctx);
|
|
3636
|
+
n = applyRepeaterEffect(n, repeater, ctx);
|
|
3637
|
+
n = applyMaskedByEffect(n, maskedBy, transformation, ctx);
|
|
3638
|
+
if (innerIdForContentRef) {
|
|
3639
|
+
n = splitForContentRef(n, transformation, originalId, innerIdForContentRef, ctx);
|
|
3640
|
+
} else {
|
|
3641
|
+
n = applyRefAndTransformationEffect(n, ref, transformation, ctx);
|
|
3642
|
+
}
|
|
3643
|
+
if (retime) node.effects = { retime };
|
|
3644
|
+
if (originalId) ctx.idMap.set(originalId, n);
|
|
3645
|
+
return n;
|
|
3646
|
+
}
|
|
3647
|
+
function applyPlayerEffects_retime(node, ctx) {
|
|
3648
|
+
applyAllRetimeEffects(node, ctx);
|
|
3649
|
+
return node;
|
|
3650
|
+
}
|
|
3651
|
+
|
|
3652
|
+
// src/PxAnimatorUseMaterialiser.ts
|
|
3653
|
+
function materialiseAnimatedUseInstances(root) {
|
|
3654
|
+
var _a;
|
|
3655
|
+
const idMap = buildIdMap(root);
|
|
3656
|
+
const animatedIds = computeAnimatedSubtreeIds(root, idMap);
|
|
3657
|
+
if (animatedIds.size === 0) return root;
|
|
3658
|
+
let idCounter = 0;
|
|
3659
|
+
const genId3 = () => "_lw_use_mat_" + ++idCounter;
|
|
3660
|
+
const defsCollector = [];
|
|
3661
|
+
const walked = walkAndMaterialise2(root, idMap, animatedIds, genId3, defsCollector);
|
|
3662
|
+
if (defsCollector.length === 0) return walked;
|
|
3663
|
+
const defsNode = { type: "defs", children: defsCollector };
|
|
3664
|
+
const newChildren = [...(_a = walked.children) != null ? _a : [], defsNode];
|
|
3665
|
+
return __spreadProps(__spreadValues({}, walked), { children: newChildren });
|
|
3666
|
+
}
|
|
3667
|
+
function buildIdMap(root) {
|
|
3668
|
+
const map = /* @__PURE__ */ new Map();
|
|
3669
|
+
const visit = (n) => {
|
|
3670
|
+
var _a;
|
|
3671
|
+
if (typeof n.id === "string") map.set(n.id, n);
|
|
3672
|
+
(_a = n.children) == null ? void 0 : _a.forEach(visit);
|
|
3673
|
+
};
|
|
3674
|
+
visit(root);
|
|
3675
|
+
return map;
|
|
3676
|
+
}
|
|
3677
|
+
function computeAnimatedSubtreeIds(root, idMap) {
|
|
3678
|
+
const cache = /* @__PURE__ */ new WeakMap();
|
|
3679
|
+
const result = /* @__PURE__ */ new Set();
|
|
3680
|
+
const hasAnim = (n, visiting) => {
|
|
3681
|
+
const cached = cache.get(n);
|
|
3682
|
+
if (cached !== void 0) return cached;
|
|
3683
|
+
if (visiting.has(n)) return false;
|
|
3684
|
+
visiting.add(n);
|
|
3685
|
+
let r = false;
|
|
3686
|
+
if (n.animate && typeof n.animate === "object" && !Array.isArray(n.animate)) {
|
|
3687
|
+
for (const _ in n.animate) {
|
|
3688
|
+
r = true;
|
|
3689
|
+
break;
|
|
3690
|
+
}
|
|
3691
|
+
}
|
|
3692
|
+
if (!r && n.children) {
|
|
3693
|
+
for (const ch of n.children) {
|
|
3694
|
+
if (hasAnim(ch, visiting)) {
|
|
3695
|
+
r = true;
|
|
3696
|
+
break;
|
|
3697
|
+
}
|
|
3698
|
+
}
|
|
3699
|
+
}
|
|
3700
|
+
if (!r && n.type === "use" && typeof n.href === "string") {
|
|
3701
|
+
const targetId = stripHash2(n.href);
|
|
3702
|
+
const target = targetId ? idMap.get(targetId) : void 0;
|
|
3703
|
+
if (target) r = hasAnim(target, visiting);
|
|
3704
|
+
}
|
|
3705
|
+
visiting.delete(n);
|
|
3706
|
+
cache.set(n, r);
|
|
3707
|
+
return r;
|
|
3708
|
+
};
|
|
3709
|
+
for (const [id, node] of idMap) {
|
|
3710
|
+
if (hasAnim(node, /* @__PURE__ */ new Set())) result.add(id);
|
|
3711
|
+
}
|
|
3712
|
+
return result;
|
|
3713
|
+
}
|
|
3714
|
+
function stripHash2(href) {
|
|
3715
|
+
if (typeof href !== "string") return void 0;
|
|
3716
|
+
return href.startsWith("#") ? href.slice(1) : href;
|
|
3717
|
+
}
|
|
3718
|
+
function materialiseOneUse(useNode, target, idMap, animatedIds, genId3, defsCollector) {
|
|
3719
|
+
const clone2 = deepClonePxNode(target);
|
|
3720
|
+
regenerateIdsAndRewriteRefs(clone2, genId3);
|
|
3721
|
+
const rewrittenClone = clone2.type === "symbol" ? rewriteSymbolRootToGroup(clone2, genId3, defsCollector) : clone2;
|
|
3722
|
+
const materialisedClone = walkAndMaterialise2(rewrittenClone, idMap, animatedIds, genId3, defsCollector);
|
|
3723
|
+
const newNode = __spreadProps(__spreadValues({}, useNode), { type: "g", children: [materialisedClone] });
|
|
3724
|
+
delete newNode.href;
|
|
3725
|
+
return applyUseOffsetToG(newNode);
|
|
3726
|
+
}
|
|
3727
|
+
function rewriteSymbolRootToGroup(symbolNode, genId3, defsCollector) {
|
|
3728
|
+
const viewBox = parseViewBox(symbolNode.viewBox);
|
|
3729
|
+
const g = __spreadProps(__spreadValues({}, symbolNode), { type: "g" });
|
|
3730
|
+
delete g.viewBox;
|
|
3731
|
+
delete g.preserveAspectRatio;
|
|
3732
|
+
delete g.width;
|
|
3733
|
+
delete g.height;
|
|
3734
|
+
if (!viewBox) return g;
|
|
3735
|
+
const [vbX, vbY, vbW, vbH] = viewBox;
|
|
3736
|
+
if (vbX !== 0 || vbY !== 0) {
|
|
3737
|
+
g.transform = "translate(" + -vbX + "," + -vbY + ")";
|
|
3738
|
+
}
|
|
3739
|
+
const clipId = genId3();
|
|
3740
|
+
defsCollector.push({
|
|
3741
|
+
type: "clipPath",
|
|
3742
|
+
id: clipId,
|
|
3743
|
+
children: [{ type: "rect", x: vbX, y: vbY, width: vbW, height: vbH }]
|
|
3744
|
+
});
|
|
3745
|
+
g.clipPath = "url(#" + clipId + ")";
|
|
3746
|
+
return g;
|
|
3747
|
+
}
|
|
3748
|
+
function parseViewBox(v) {
|
|
3749
|
+
if (typeof v !== "string") return void 0;
|
|
3750
|
+
const parts = v.trim().split(/[\s,]+/).map(Number);
|
|
3751
|
+
if (parts.length < 4 || parts.some((n) => !Number.isFinite(n))) return void 0;
|
|
3752
|
+
return [parts[0], parts[1], parts[2], parts[3]];
|
|
3753
|
+
}
|
|
3754
|
+
function walkAndMaterialise2(node, idMap, animatedIds, genId3, defsCollector) {
|
|
3755
|
+
if (node.type === "use" && typeof node.href === "string") {
|
|
3756
|
+
const targetId = stripHash2(node.href);
|
|
3757
|
+
if (targetId && animatedIds.has(targetId)) {
|
|
3758
|
+
const target = idMap.get(targetId);
|
|
3759
|
+
if (target) return materialiseOneUse(node, target, idMap, animatedIds, genId3, defsCollector);
|
|
3760
|
+
}
|
|
3761
|
+
}
|
|
3762
|
+
if (!node.children) return node;
|
|
3763
|
+
let changed = false;
|
|
3764
|
+
const newChildren = node.children.map((ch) => {
|
|
3765
|
+
const m = walkAndMaterialise2(ch, idMap, animatedIds, genId3, defsCollector);
|
|
3766
|
+
if (m !== ch) changed = true;
|
|
3767
|
+
return m;
|
|
3768
|
+
});
|
|
3769
|
+
return changed ? __spreadProps(__spreadValues({}, node), { children: newChildren }) : node;
|
|
3770
|
+
}
|
|
3771
|
+
|
|
3772
|
+
// src/PxAnimatorMaterialiseAll.ts
|
|
3773
|
+
function materialiseAllInTree(doc, engine, opts) {
|
|
3774
|
+
var _a, _b;
|
|
3775
|
+
let root = applyPlayerEffects(doc).root;
|
|
3776
|
+
const duration = (_b = (_a = getAnimatorConfig(root)) == null ? void 0 : _a.duration) != null ? _b : DEFAULT_DURATION_MS;
|
|
3777
|
+
root = materialiseInternalLoopsInTree(root, duration);
|
|
3778
|
+
if (engine === PxAnimatorEngine.webapi) {
|
|
3779
|
+
root = materialiseMotionPathsInTree(root, opts == null ? void 0 : opts.motionPath);
|
|
3780
|
+
root = materialiseAnimatedUseInstances(root);
|
|
3781
|
+
}
|
|
3782
|
+
return root;
|
|
3783
|
+
}
|
|
3784
|
+
|
|
3785
|
+
// src/PxAnimatorDOM.ts
|
|
3786
|
+
var SVG_NS = "http://www.w3.org/2000/svg";
|
|
3787
|
+
var DISALLOWED_SVG_TAGS_LOWER = /* @__PURE__ */ new Set([
|
|
3788
|
+
"script",
|
|
3789
|
+
"foreignobject"
|
|
3790
|
+
]);
|
|
3791
|
+
var URL_VALUE_ATTRS_LOWER = /* @__PURE__ */ new Set([
|
|
3792
|
+
"href",
|
|
3793
|
+
// <use>, <image>
|
|
3794
|
+
"xlink:href",
|
|
3795
|
+
// legacy <use>
|
|
3796
|
+
"src",
|
|
3797
|
+
// <image>
|
|
3798
|
+
"filter",
|
|
3799
|
+
// url(#filterId)
|
|
3800
|
+
"clippath",
|
|
3801
|
+
// clip-path="url(#…)"
|
|
3802
|
+
"mask",
|
|
3803
|
+
// url(#maskId)
|
|
3804
|
+
"markerstart",
|
|
3805
|
+
// marker-start="url(#…)"
|
|
3806
|
+
"markermid",
|
|
3807
|
+
// marker-mid="url(#…)"
|
|
3808
|
+
"markerend"
|
|
3809
|
+
// marker-end="url(#…)"
|
|
3810
|
+
]);
|
|
3811
|
+
var IMAGE_REF_ATTRS_LOWER = /* @__PURE__ */ new Set(["href", "xlink:href", "src"]);
|
|
3812
|
+
var DATA_RASTER_IMAGE_RE = /^data:image\/(?:png|jpe?g|gif|webp|bmp);base64,/i;
|
|
3813
|
+
function isDangerousAttrName(nameLower) {
|
|
3814
|
+
if (nameLower.startsWith("on")) return true;
|
|
3815
|
+
return false;
|
|
3816
|
+
}
|
|
3817
|
+
function sanitiseAttributeValue(name, value) {
|
|
3818
|
+
const nameLower = name.toLowerCase();
|
|
3819
|
+
if (isDangerousAttrName(nameLower)) {
|
|
3820
|
+
console.warn("Attribute blocked (event handler / dangerous): ", nameLower);
|
|
3821
|
+
return void 0;
|
|
3822
|
+
}
|
|
3823
|
+
if (nameLower === "fill" || nameLower === "stroke" || nameLower === "stopcolor") {
|
|
3824
|
+
const str = String(value);
|
|
3825
|
+
if (str.includes("url(") && !/^url\(#[^)]+\)$/.test(str)) {
|
|
3826
|
+
console.warn('Attribute "' + nameLower + '" blocked: url() must be internal url(#id), got:', value);
|
|
3827
|
+
return void 0;
|
|
3828
|
+
}
|
|
3829
|
+
return value;
|
|
3830
|
+
}
|
|
3831
|
+
if (URL_VALUE_ATTRS_LOWER.has(nameLower)) {
|
|
3832
|
+
const str = String(value);
|
|
3833
|
+
if (str.startsWith("#")) return value;
|
|
3834
|
+
if (/^url\(#[^)]+\)$/.test(str)) return value;
|
|
3835
|
+
if (IMAGE_REF_ATTRS_LOWER.has(nameLower) && DATA_RASTER_IMAGE_RE.test(str)) return value;
|
|
3836
|
+
console.warn('Attribute "' + nameLower + '" blocked: must be #id, url(#id), or base64 raster data: URI, got:', value);
|
|
3837
|
+
return void 0;
|
|
3838
|
+
}
|
|
3839
|
+
return value;
|
|
3840
|
+
}
|
|
3841
|
+
function createElement(tagName, normalisedProps, style, children, textContent) {
|
|
3842
|
+
if (DISALLOWED_SVG_TAGS_LOWER.has(tagName.toLowerCase())) {
|
|
3843
|
+
console.warn("SVG tag blocked (dangerous): ", tagName);
|
|
3844
|
+
return null;
|
|
3845
|
+
}
|
|
3846
|
+
const element = document.createElementNS(SVG_NS, tagName);
|
|
3847
|
+
for (const propName in normalisedProps) {
|
|
3848
|
+
const sanitised = sanitiseAttributeValue(propName, normalisedProps[propName]);
|
|
3849
|
+
if (sanitised === void 0) continue;
|
|
3850
|
+
element.setAttribute(camelCaseToKebabWordIfNeeded(propName), sanitised);
|
|
3851
|
+
}
|
|
3852
|
+
if (style) {
|
|
3853
|
+
for (const styleProp in style) {
|
|
3854
|
+
element.style[styleProp] = String(style[styleProp]);
|
|
3855
|
+
}
|
|
3856
|
+
}
|
|
3857
|
+
if (children) {
|
|
3858
|
+
for (const child of children) {
|
|
3859
|
+
element.appendChild(child);
|
|
3860
|
+
}
|
|
3861
|
+
}
|
|
3862
|
+
if (textContent) element.textContent = textContent;
|
|
3863
|
+
return element;
|
|
3864
|
+
}
|
|
3865
|
+
function resolveStyle(style, defs) {
|
|
3866
|
+
var _a;
|
|
3867
|
+
if (!style) return void 0;
|
|
3868
|
+
if (typeof style === "string") {
|
|
3869
|
+
return (_a = defs == null ? void 0 : defs.styles) == null ? void 0 : _a[style];
|
|
3870
|
+
}
|
|
3871
|
+
return style;
|
|
3872
|
+
}
|
|
3873
|
+
function getNormalizedProps(props) {
|
|
3874
|
+
const propsCopy = {};
|
|
3875
|
+
for (const rawKey of Object.keys(props)) {
|
|
3876
|
+
const key = kebabToCamelCaseWord(rawKey);
|
|
3877
|
+
if (INTERNAL_ATTRS.has(key)) continue;
|
|
3878
|
+
if (key === "style") continue;
|
|
3879
|
+
let value = props[rawKey];
|
|
3880
|
+
if (COLOUR_ATTR_NAMES.has(key) && Array.isArray(value)) {
|
|
3881
|
+
propsCopy[key] = toRGBA(value);
|
|
3882
|
+
} else if (key === "transform" && value !== null && typeof value === "object" && !Array.isArray(value) && value.value && typeof value.value === "object") {
|
|
3883
|
+
propsCopy["transform"] = composeTransformParts(value.value, { withUnits: false });
|
|
3884
|
+
} else if (TRANSFORM_FN_NAMES.has(key)) {
|
|
3885
|
+
if (Array.isArray(value)) {
|
|
3886
|
+
if (key === "translate") value = value.map((v) => v + "px");
|
|
3887
|
+
value = value.join(",");
|
|
3888
|
+
}
|
|
3889
|
+
if (key === "rotate") value = value + "deg";
|
|
3890
|
+
propsCopy["transform"] = key + "(" + value + ")";
|
|
3891
|
+
} else if (value !== void 0 && value !== null) {
|
|
3892
|
+
propsCopy[key] = String(value);
|
|
3893
|
+
}
|
|
3894
|
+
}
|
|
3895
|
+
return propsCopy;
|
|
3896
|
+
}
|
|
3897
|
+
function renderNode(node, defs) {
|
|
3898
|
+
if (!node) return null;
|
|
3899
|
+
const _a = node, { type, children, style } = _a, props = __objRest(_a, ["type", "children", "style"]);
|
|
3900
|
+
const nodeDefs = getDefs(node) || defs;
|
|
3901
|
+
const resolvedStyle = resolveStyle(style, nodeDefs);
|
|
3902
|
+
let childElements;
|
|
3903
|
+
if (children) {
|
|
3904
|
+
for (const ch of children) {
|
|
3905
|
+
const child = renderNode(ch, nodeDefs);
|
|
3906
|
+
if (child) {
|
|
3907
|
+
if (!childElements) childElements = [];
|
|
3908
|
+
childElements.push(child);
|
|
3909
|
+
}
|
|
3910
|
+
}
|
|
1257
3911
|
}
|
|
1258
|
-
return
|
|
3912
|
+
return createElement(
|
|
3913
|
+
type || "g",
|
|
3914
|
+
getNormalizedProps(props),
|
|
3915
|
+
resolvedStyle,
|
|
3916
|
+
childElements,
|
|
3917
|
+
props[TEXT_ATTR] || props[TEXT_CONTENT_ATTR]
|
|
3918
|
+
);
|
|
1259
3919
|
}
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
3920
|
+
|
|
3921
|
+
// src/PxAnimatorTriggers.ts
|
|
3922
|
+
function setupAnimationTriggers(api, config) {
|
|
3923
|
+
const { startOn, outAction = "continue", scrollIntoViewThreshold = 0.5 } = config;
|
|
3924
|
+
const root = api.getRootElement();
|
|
3925
|
+
if (!root) {
|
|
3926
|
+
console.warn("setupAnimationTriggers: No root element found for animation.");
|
|
3927
|
+
return api;
|
|
3928
|
+
}
|
|
3929
|
+
const start = () => {
|
|
3930
|
+
api.play();
|
|
3931
|
+
};
|
|
3932
|
+
const handleEndAction = () => {
|
|
3933
|
+
switch (outAction) {
|
|
3934
|
+
case "pause":
|
|
3935
|
+
api.pause();
|
|
3936
|
+
break;
|
|
3937
|
+
case "reset":
|
|
3938
|
+
api.cancel();
|
|
3939
|
+
break;
|
|
3940
|
+
case "reverse":
|
|
3941
|
+
api.play();
|
|
3942
|
+
break;
|
|
3943
|
+
case "continue":
|
|
3944
|
+
default:
|
|
3945
|
+
break;
|
|
3946
|
+
}
|
|
3947
|
+
};
|
|
3948
|
+
switch (startOn) {
|
|
3949
|
+
case "load": {
|
|
3950
|
+
const startHandler = () => start();
|
|
3951
|
+
if (document.readyState === "complete") {
|
|
3952
|
+
startHandler();
|
|
3953
|
+
} else {
|
|
3954
|
+
window.addEventListener("load", startHandler, { once: true });
|
|
3955
|
+
}
|
|
1270
3956
|
break;
|
|
1271
3957
|
}
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
if (keyframes.length === 0) return null;
|
|
1279
|
-
const { prevKf, nextKf } = getKeyframesPair(keyframes, progress);
|
|
1280
|
-
let localProgress = prevKf === nextKf ? 0 : remap(progress, (_a = prevKf.t) != null ? _a : 0, (_b = nextKf.t) != null ? _b : 0, 0, 1);
|
|
1281
|
-
localProgress = clamp(localProgress, 0, 1);
|
|
1282
|
-
const easing = (_c = prevKf.e) != null ? _c : prevKf.easing;
|
|
1283
|
-
if (easing && Array.isArray(easing)) {
|
|
1284
|
-
try {
|
|
1285
|
-
localProgress = cubicBezier(easing)(localProgress);
|
|
1286
|
-
} catch (e) {
|
|
3958
|
+
case "mouseOver": {
|
|
3959
|
+
const mouseOverHandler = () => start();
|
|
3960
|
+
const mouseOutHandler = () => handleEndAction();
|
|
3961
|
+
root.addEventListener("mouseenter", mouseOverHandler);
|
|
3962
|
+
root.addEventListener("mouseleave", mouseOutHandler);
|
|
3963
|
+
break;
|
|
1287
3964
|
}
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
cssAttrName = propName;
|
|
1315
|
-
} else if (cssAttrName === "translate") {
|
|
1316
|
-
const v = interpolateVec(
|
|
1317
|
-
prevV || [0, 0],
|
|
1318
|
-
nextV || [0, 0],
|
|
1319
|
-
localProgress
|
|
1320
|
-
);
|
|
1321
|
-
cssValue = "translate(" + v.join(",") + ")";
|
|
1322
|
-
cssAttrName = "transform";
|
|
1323
|
-
} else if (cssAttrName === "rotate") {
|
|
1324
|
-
const v = interpolateNum(
|
|
1325
|
-
+(prevV || 0),
|
|
1326
|
-
+(nextV || 0),
|
|
1327
|
-
localProgress
|
|
1328
|
-
);
|
|
1329
|
-
cssValue = "rotate(" + v + ")";
|
|
1330
|
-
cssAttrName = "transform";
|
|
1331
|
-
} else if (cssAttrName === "scale") {
|
|
1332
|
-
const v = interpolateVec(
|
|
1333
|
-
prevV || [1, 1],
|
|
1334
|
-
nextV || [1, 1],
|
|
1335
|
-
localProgress
|
|
1336
|
-
);
|
|
1337
|
-
cssValue = "scale(" + v.join(",") + ")";
|
|
1338
|
-
cssAttrName = "transform";
|
|
1339
|
-
} else {
|
|
1340
|
-
const num = interpolateNum(
|
|
1341
|
-
+(prevV || 0),
|
|
1342
|
-
+(nextV || 0),
|
|
1343
|
-
localProgress
|
|
1344
|
-
);
|
|
1345
|
-
cssValue = num;
|
|
1346
|
-
}
|
|
1347
|
-
if (PCT_BASED_ATTR_NAMES.has(cssAttrName) && typeof cssValue === "number") {
|
|
1348
|
-
cssValue = cssValue * 100 + "%";
|
|
1349
|
-
}
|
|
1350
|
-
return { k: cssAttrName, v: cssValue === null ? "" : "" + cssValue };
|
|
1351
|
-
}
|
|
1352
|
-
function calcAnimationValues(animDef, progress) {
|
|
1353
|
-
const result = {};
|
|
1354
|
-
for (const [propName, propAnim] of Object.entries(animDef)) {
|
|
1355
|
-
const computed = calcPropertyValue(propName, propAnim, progress);
|
|
1356
|
-
if (computed) {
|
|
1357
|
-
result[computed.k] = computed.v;
|
|
3965
|
+
case "click": {
|
|
3966
|
+
const clickHandler = () => {
|
|
3967
|
+
if (api.isPlaying()) {
|
|
3968
|
+
handleEndAction();
|
|
3969
|
+
} else {
|
|
3970
|
+
start();
|
|
3971
|
+
}
|
|
3972
|
+
};
|
|
3973
|
+
root.addEventListener("click", clickHandler);
|
|
3974
|
+
break;
|
|
3975
|
+
}
|
|
3976
|
+
case "scrollIntoView": {
|
|
3977
|
+
const observer = new IntersectionObserver(
|
|
3978
|
+
(entries) => {
|
|
3979
|
+
entries.forEach((entry) => {
|
|
3980
|
+
if (entry.isIntersecting && entry.intersectionRatio >= scrollIntoViewThreshold) {
|
|
3981
|
+
start();
|
|
3982
|
+
} else {
|
|
3983
|
+
handleEndAction();
|
|
3984
|
+
}
|
|
3985
|
+
});
|
|
3986
|
+
},
|
|
3987
|
+
{ threshold: scrollIntoViewThreshold }
|
|
3988
|
+
);
|
|
3989
|
+
observer.observe(root);
|
|
3990
|
+
break;
|
|
1358
3991
|
}
|
|
3992
|
+
case "programmatic":
|
|
3993
|
+
break;
|
|
1359
3994
|
}
|
|
1360
|
-
return
|
|
3995
|
+
return api;
|
|
1361
3996
|
}
|
|
1362
3997
|
|
|
1363
3998
|
// src/PxAnimatorFrameLoop.ts
|
|
@@ -1366,7 +4001,7 @@ function getSelector(id) {
|
|
|
1366
4001
|
}
|
|
1367
4002
|
function createBasicFrameLoopAnimator(doc, adapter, callbacks) {
|
|
1368
4003
|
const config = getAnimatorConfig(doc) || {};
|
|
1369
|
-
const bindings = getNormalisedBindings(doc);
|
|
4004
|
+
const bindings = getNormalisedBindings(doc, PxAnimatorEngine.frames);
|
|
1370
4005
|
const _iterations = config.iterations;
|
|
1371
4006
|
let iterations = 1;
|
|
1372
4007
|
if (typeof _iterations === "number") iterations = _iterations || 1;
|
|
@@ -1484,6 +4119,10 @@ function createBasicFrameLoopAnimator(doc, adapter, callbacks) {
|
|
|
1484
4119
|
};
|
|
1485
4120
|
const startAnim = () => {
|
|
1486
4121
|
if (playing) return;
|
|
4122
|
+
if (Number.isFinite(totalDuration) && timeBeforeLastStartMs >= totalDuration) {
|
|
4123
|
+
timeBeforeLastStartMs = 0;
|
|
4124
|
+
finishCalled = false;
|
|
4125
|
+
}
|
|
1487
4126
|
playing = true;
|
|
1488
4127
|
lastStartedTs = Date.now();
|
|
1489
4128
|
loopAnim(true);
|
|
@@ -1634,6 +4273,9 @@ function createCssKf(kf, t, propName, unsupportedSet) {
|
|
|
1634
4273
|
let cssKey = propName;
|
|
1635
4274
|
if (COLOUR_ATTR_NAMES.has(propName) && Array.isArray(value)) {
|
|
1636
4275
|
cssValue = toRGBA(value);
|
|
4276
|
+
} else if (propName === "transform" && value !== null && typeof value === "object" && !Array.isArray(value)) {
|
|
4277
|
+
cssValue = composeTransformParts(value, { withUnits: true });
|
|
4278
|
+
cssKey = "transform";
|
|
1637
4279
|
} else if (TRANSFORM_FN_NAMES.has(propName)) {
|
|
1638
4280
|
if (Array.isArray(value)) {
|
|
1639
4281
|
if (propName === "translate") value = value.map((v) => v + "px");
|
|
@@ -1650,28 +4292,59 @@ function createCssKf(kf, t, propName, unsupportedSet) {
|
|
|
1650
4292
|
cssKf[cssKey] = cssValue;
|
|
1651
4293
|
return cssKf;
|
|
1652
4294
|
}
|
|
4295
|
+
function clipKeyframesToDuration(propName, keyframes, duration) {
|
|
4296
|
+
var _a, _b, _c, _d, _e;
|
|
4297
|
+
const result = [];
|
|
4298
|
+
for (let i = 0; i < keyframes.length; i++) {
|
|
4299
|
+
const kf = keyframes[i];
|
|
4300
|
+
const t = (_a = kf.t) != null ? _a : 0;
|
|
4301
|
+
if (t < 0) {
|
|
4302
|
+
const next = keyframes[i + 1];
|
|
4303
|
+
if (next && ((_b = next.t) != null ? _b : 0) >= 0) {
|
|
4304
|
+
const nextT = (_c = next.t) != null ? _c : 0;
|
|
4305
|
+
const localFrac = (0 - t) / (nextT - t);
|
|
4306
|
+
const easedFrac = kf.e ? cubicBezier(kf.e)(localFrac) : localFrac;
|
|
4307
|
+
const { right: rightEasing } = splitEasing(kf.e, localFrac);
|
|
4308
|
+
result.push({ t: 0, v: interpolateValue(propName, kf.v, next.v, easedFrac), e: rightEasing });
|
|
4309
|
+
}
|
|
4310
|
+
continue;
|
|
4311
|
+
}
|
|
4312
|
+
if (t > duration) {
|
|
4313
|
+
const prev = keyframes[i - 1];
|
|
4314
|
+
if (prev && ((_d = prev.t) != null ? _d : 0) <= duration) {
|
|
4315
|
+
const prevT = (_e = prev.t) != null ? _e : 0;
|
|
4316
|
+
const localFrac = (duration - prevT) / (t - prevT);
|
|
4317
|
+
const easedFrac = prev.e ? cubicBezier(prev.e)(localFrac) : localFrac;
|
|
4318
|
+
const { left: leftEasing } = splitEasing(prev.e, localFrac);
|
|
4319
|
+
if (result.length > 0) result[result.length - 1] = __spreadProps(__spreadValues({}, result[result.length - 1]), { e: leftEasing });
|
|
4320
|
+
result.push({ t: duration, v: interpolateValue(propName, prev.v, kf.v, easedFrac), e: void 0 });
|
|
4321
|
+
}
|
|
4322
|
+
break;
|
|
4323
|
+
}
|
|
4324
|
+
result.push(kf);
|
|
4325
|
+
}
|
|
4326
|
+
return result;
|
|
4327
|
+
}
|
|
1653
4328
|
function convertToWebApiKeyframes(animDef, unsupportedSet, config) {
|
|
1654
|
-
var _a
|
|
4329
|
+
var _a;
|
|
1655
4330
|
const result = /* @__PURE__ */ new Map();
|
|
1656
4331
|
for (const [propName, propAnim] of Object.entries(animDef)) {
|
|
1657
|
-
const
|
|
4332
|
+
const duration = config.duration || 1;
|
|
4333
|
+
const clippedKeyframes = clipKeyframesToDuration(propName, propAnim.kfs || propAnim.keyframes || [], duration);
|
|
1658
4334
|
const cssKeyframes = [];
|
|
1659
|
-
for (let i = 0; i <
|
|
1660
|
-
const kf =
|
|
1661
|
-
|
|
1662
|
-
t = clamp(t / (config.duration || 1), 0, 1);
|
|
4335
|
+
for (let i = 0; i < clippedKeyframes.length; i++) {
|
|
4336
|
+
const kf = clippedKeyframes[i];
|
|
4337
|
+
const t = clamp(((_a = kf.t) != null ? _a : 0) / duration, 0, 1);
|
|
1663
4338
|
const cssKf = createCssKf(kf, t, propName, unsupportedSet);
|
|
1664
4339
|
if (i === 0 && (cssKf.offset || 0) > 0) {
|
|
1665
|
-
cssKeyframes.push(__spreadProps(__spreadValues({}, cssKf), {
|
|
1666
|
-
offset: 0
|
|
1667
|
-
}));
|
|
4340
|
+
cssKeyframes.push(__spreadProps(__spreadValues({}, cssKf), { offset: 0 }));
|
|
1668
4341
|
}
|
|
1669
4342
|
cssKeyframes.push(cssKf);
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
}
|
|
4343
|
+
}
|
|
4344
|
+
if (cssKeyframes.length > 0 && (cssKeyframes[cssKeyframes.length - 1].offset || 0) < 1) {
|
|
4345
|
+
cssKeyframes.push(__spreadProps(__spreadValues({}, cssKeyframes[cssKeyframes.length - 1]), {
|
|
4346
|
+
offset: 1
|
|
4347
|
+
}));
|
|
1675
4348
|
}
|
|
1676
4349
|
if (cssKeyframes.length > 0) {
|
|
1677
4350
|
result.set(propName, cssKeyframes);
|
|
@@ -1680,8 +4353,8 @@ function convertToWebApiKeyframes(animDef, unsupportedSet, config) {
|
|
|
1680
4353
|
return result;
|
|
1681
4354
|
}
|
|
1682
4355
|
function createWebApiAnimator(doc, callbacks, rootElement, forceEvenIfHasUnsupportedAttrs) {
|
|
4356
|
+
var _a;
|
|
1683
4357
|
const config = getAnimatorConfig(doc) || {};
|
|
1684
|
-
const bindings = getNormalisedBindings(doc);
|
|
1685
4358
|
if (!rootElement) {
|
|
1686
4359
|
if (doc.id) {
|
|
1687
4360
|
const rootSelector = getSelector(doc.id);
|
|
@@ -1691,6 +4364,7 @@ function createWebApiAnimator(doc, callbacks, rootElement, forceEvenIfHasUnsuppo
|
|
|
1691
4364
|
console.warn("createFrameLoopAnimator: No root element provided");
|
|
1692
4365
|
}
|
|
1693
4366
|
}
|
|
4367
|
+
const bindings = getNormalisedBindings(doc, PxAnimatorEngine.webapi);
|
|
1694
4368
|
const animations = [];
|
|
1695
4369
|
const _iterations = config.iterations;
|
|
1696
4370
|
let iterations;
|
|
@@ -1717,7 +4391,11 @@ function createWebApiAnimator(doc, callbacks, rootElement, forceEvenIfHasUnsuppo
|
|
|
1717
4391
|
const effectOptions = {
|
|
1718
4392
|
duration: config.duration,
|
|
1719
4393
|
delay: positiveDelay,
|
|
1720
|
-
|
|
4394
|
+
// Default to 'forwards' so elements hold their final state after the
|
|
4395
|
+
// animation ends — consistent with Lottie and other animation runtimes.
|
|
4396
|
+
// Without this, seeking to the last frame reverts elements to their
|
|
4397
|
+
// pre-animation state (the Web Animations API "after" phase with fill:'none').
|
|
4398
|
+
fill: (_a = config.fill) != null ? _a : "forwards",
|
|
1721
4399
|
direction: config.direction,
|
|
1722
4400
|
iterations
|
|
1723
4401
|
};
|
|
@@ -1729,12 +4407,12 @@ function createWebApiAnimator(doc, callbacks, rootElement, forceEvenIfHasUnsuppo
|
|
|
1729
4407
|
const effect = new KeyframeEffect(element, keyframes, effectOptions);
|
|
1730
4408
|
const anim = new Animation(effect, document.timeline);
|
|
1731
4409
|
if (callbacks == null ? void 0 : callbacks.onFinish) anim.onfinish = () => {
|
|
1732
|
-
var
|
|
1733
|
-
return (
|
|
4410
|
+
var _a2;
|
|
4411
|
+
return (_a2 = callbacks.onFinish) == null ? void 0 : _a2.call(callbacks);
|
|
1734
4412
|
};
|
|
1735
4413
|
if (callbacks == null ? void 0 : callbacks.onRemove) anim.onremove = () => {
|
|
1736
|
-
var
|
|
1737
|
-
return (
|
|
4414
|
+
var _a2;
|
|
4415
|
+
return (_a2 = callbacks.onRemove) == null ? void 0 : _a2.call(callbacks);
|
|
1738
4416
|
};
|
|
1739
4417
|
if (seekPosition) {
|
|
1740
4418
|
anim.currentTime = seekPosition;
|
|
@@ -1755,29 +4433,29 @@ function createWebApiAnimator(doc, callbacks, rootElement, forceEvenIfHasUnsuppo
|
|
|
1755
4433
|
"isReady": () => true,
|
|
1756
4434
|
"getRootElement": () => rootElement || null,
|
|
1757
4435
|
"isPlaying": () => {
|
|
1758
|
-
var
|
|
1759
|
-
return ((
|
|
4436
|
+
var _a2;
|
|
4437
|
+
return ((_a2 = animations[0]) == null ? void 0 : _a2.playState) === "running";
|
|
1760
4438
|
},
|
|
1761
4439
|
"play": () => {
|
|
1762
|
-
var
|
|
4440
|
+
var _a2;
|
|
1763
4441
|
animations.forEach((a) => a.play());
|
|
1764
|
-
(
|
|
4442
|
+
(_a2 = callbacks == null ? void 0 : callbacks.onPlay) == null ? void 0 : _a2.call(callbacks);
|
|
1765
4443
|
},
|
|
1766
4444
|
"pause": () => {
|
|
1767
|
-
var
|
|
4445
|
+
var _a2;
|
|
1768
4446
|
animations.forEach((a) => a.pause());
|
|
1769
|
-
(
|
|
4447
|
+
(_a2 = callbacks == null ? void 0 : callbacks.onPause) == null ? void 0 : _a2.call(callbacks);
|
|
1770
4448
|
},
|
|
1771
4449
|
"cancel": () => {
|
|
1772
|
-
var
|
|
4450
|
+
var _a2;
|
|
1773
4451
|
animations.forEach((a) => a.cancel());
|
|
1774
|
-
(
|
|
4452
|
+
(_a2 = callbacks == null ? void 0 : callbacks.onCancel) == null ? void 0 : _a2.call(callbacks);
|
|
1775
4453
|
},
|
|
1776
4454
|
"finish": () => {
|
|
1777
|
-
var
|
|
4455
|
+
var _a2;
|
|
1778
4456
|
for (const a of animations) {
|
|
1779
4457
|
try {
|
|
1780
|
-
if (((
|
|
4458
|
+
if (((_a2 = a.effect) == null ? void 0 : _a2.getTiming().iterations) === Infinity) {
|
|
1781
4459
|
a.effect.updateTiming({ iterations: 1 });
|
|
1782
4460
|
a.finish();
|
|
1783
4461
|
a.effect.updateTiming({ iterations: Infinity });
|
|
@@ -1794,8 +4472,8 @@ function createWebApiAnimator(doc, callbacks, rootElement, forceEvenIfHasUnsuppo
|
|
|
1794
4472
|
return api;
|
|
1795
4473
|
},
|
|
1796
4474
|
"getCurrentTime": () => {
|
|
1797
|
-
var
|
|
1798
|
-
const res = (_b = (
|
|
4475
|
+
var _a2, _b;
|
|
4476
|
+
const res = (_b = (_a2 = animations[0]) == null ? void 0 : _a2.currentTime) != null ? _b : null;
|
|
1799
4477
|
return res !== null ? +res : null;
|
|
1800
4478
|
},
|
|
1801
4479
|
"setCurrentTime": (time) => {
|
|
@@ -1818,15 +4496,15 @@ function createWebApiAnimator(doc, callbacks, rootElement, forceEvenIfHasUnsuppo
|
|
|
1818
4496
|
function createAnimatorFromConfig(doc, adapter, callbacks, rootElement) {
|
|
1819
4497
|
const animatorConfig = getAnimatorConfig(doc) || {};
|
|
1820
4498
|
let res;
|
|
1821
|
-
if (animatorConfig.mode ===
|
|
4499
|
+
if (animatorConfig.mode === PxAnimatorMode.frames) {
|
|
1822
4500
|
res = createFrameLoopAnimator(doc, adapter, callbacks, rootElement);
|
|
1823
4501
|
} else {
|
|
1824
4502
|
res = createWebApiAnimator(
|
|
1825
4503
|
doc,
|
|
1826
4504
|
callbacks,
|
|
1827
4505
|
rootElement,
|
|
1828
|
-
animatorConfig.mode ===
|
|
1829
|
-
//
|
|
4506
|
+
animatorConfig.mode === PxAnimatorMode.webapi
|
|
4507
|
+
// forcing webapi
|
|
1830
4508
|
) || createFrameLoopAnimator(doc, adapter, callbacks, rootElement);
|
|
1831
4509
|
}
|
|
1832
4510
|
if (animatorConfig.debugInstName) {
|
|
@@ -1852,6 +4530,7 @@ function deepClone(value) {
|
|
|
1852
4530
|
return cloned;
|
|
1853
4531
|
}
|
|
1854
4532
|
function generateNewIds(doc) {
|
|
4533
|
+
var _a, _b;
|
|
1855
4534
|
const cloned = deepClone(doc);
|
|
1856
4535
|
const idMap = /* @__PURE__ */ new Map();
|
|
1857
4536
|
const hashRefAttrs = /* @__PURE__ */ new Set(["href", "xlink:href"]);
|
|
@@ -1877,6 +4556,8 @@ function generateNewIds(doc) {
|
|
|
1877
4556
|
const newId = generateUniqueId();
|
|
1878
4557
|
idMap.set(oldId, newId);
|
|
1879
4558
|
node.id = newId;
|
|
4559
|
+
} else if (node.animate) {
|
|
4560
|
+
node.id = generateUniqueId();
|
|
1880
4561
|
}
|
|
1881
4562
|
if (Array.isArray(node.children)) {
|
|
1882
4563
|
for (const child of node.children) {
|
|
@@ -1918,23 +4599,21 @@ function generateNewIds(doc) {
|
|
|
1918
4599
|
value[styleProp] = replaceUrlRefs(styleValue, idMap);
|
|
1919
4600
|
}
|
|
1920
4601
|
}
|
|
1921
|
-
} else if (typeof value === "object" && value !== null
|
|
4602
|
+
} else if (typeof value === "object" && value !== null) {
|
|
1922
4603
|
updateRefs(value);
|
|
1923
4604
|
}
|
|
1924
4605
|
}
|
|
1925
4606
|
}
|
|
1926
4607
|
collectIds(cloned);
|
|
1927
4608
|
updateRefs(cloned);
|
|
1928
|
-
const
|
|
1929
|
-
if (
|
|
1930
|
-
|
|
1931
|
-
|
|
1932
|
-
|
|
1933
|
-
|
|
1934
|
-
binding.id = newId;
|
|
1935
|
-
}
|
|
1936
|
-
}
|
|
4609
|
+
const docAnimate = (_a = cloned.animator) == null ? void 0 : _a.animate;
|
|
4610
|
+
if (docAnimate && typeof docAnimate === "object") {
|
|
4611
|
+
const updatedAnimate = {};
|
|
4612
|
+
for (const [id, anim] of Object.entries(docAnimate)) {
|
|
4613
|
+
const newId = (_b = idMap.get(id)) != null ? _b : id;
|
|
4614
|
+
updatedAnimate[newId] = anim;
|
|
1937
4615
|
}
|
|
4616
|
+
cloned.animator = __spreadProps(__spreadValues({}, cloned.animator), { animate: updatedAnimate });
|
|
1938
4617
|
}
|
|
1939
4618
|
return cloned;
|
|
1940
4619
|
}
|
|
@@ -1945,8 +4624,12 @@ function replaceUrlRefs(value, idMap) {
|
|
|
1945
4624
|
});
|
|
1946
4625
|
}
|
|
1947
4626
|
function createAnimatorImpl(doc, adapter, callbacks, containerElement) {
|
|
4627
|
+
const effectsWarnings = validateNodeEffects(doc);
|
|
4628
|
+
for (const w of effectsWarnings) console.warn("[PxAnimator] effects shape warning:", w);
|
|
1948
4629
|
const animatorConfig = getAnimatorConfig(doc) || {};
|
|
1949
4630
|
animatorConfig.debug = true;
|
|
4631
|
+
const engine = animatorConfig.mode === PxAnimatorMode.frames ? PxAnimatorEngine.frames : PxAnimatorEngine.webapi;
|
|
4632
|
+
doc = materialiseAllInTree(doc, engine);
|
|
1950
4633
|
let rootElement = null;
|
|
1951
4634
|
if (containerElement && doc.children) {
|
|
1952
4635
|
doc = generateNewIds(doc);
|
|
@@ -1960,14 +4643,22 @@ function createAnimatorImpl(doc, adapter, callbacks, containerElement) {
|
|
|
1960
4643
|
}
|
|
1961
4644
|
return createAnimatorFromConfig(doc, adapter, callbacks, rootElement);
|
|
1962
4645
|
}
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
4646
|
+
var PX_ANIMATOR_DATA_KEY = "data";
|
|
4647
|
+
function createAnimator(options) {
|
|
4648
|
+
const { src, data, adapter, callbacks, container } = options;
|
|
4649
|
+
if (data !== void 0 && src !== void 0) {
|
|
4650
|
+
throw new Error("createAnimator: provide either `src` or `data`, not both");
|
|
4651
|
+
}
|
|
4652
|
+
if (data === void 0 && src === void 0) {
|
|
4653
|
+
throw new Error("createAnimator: either `src` or `data` is required");
|
|
4654
|
+
}
|
|
4655
|
+
if (data !== void 0) {
|
|
4656
|
+
return createAnimatorImpl(data, adapter, callbacks, container);
|
|
1966
4657
|
}
|
|
1967
4658
|
let animator = null;
|
|
1968
|
-
fetch(
|
|
4659
|
+
fetch(src).then((res) => res.json()).then((json) => {
|
|
1969
4660
|
if (isPxElementFileFormat(json)) {
|
|
1970
|
-
animator = createAnimatorImpl(json, adapter, callbacks,
|
|
4661
|
+
animator = createAnimatorImpl(json, adapter, callbacks, container);
|
|
1971
4662
|
} else {
|
|
1972
4663
|
console.error("Invalid animation document format");
|
|
1973
4664
|
}
|
|
@@ -2007,7 +4698,7 @@ function loadTagAnimators() {
|
|
|
2007
4698
|
if (!element[PX_ANIM_ATTR_NAME]) {
|
|
2008
4699
|
const src = element.getAttribute(PX_ANIM_SRC_ATTR_NAME);
|
|
2009
4700
|
if (src) {
|
|
2010
|
-
element[PX_ANIM_ATTR_NAME] = createAnimator(src,
|
|
4701
|
+
element[PX_ANIM_ATTR_NAME] = createAnimator({ src, container: element });
|
|
2011
4702
|
}
|
|
2012
4703
|
}
|
|
2013
4704
|
}
|
|
@@ -2017,19 +4708,268 @@ if (typeof window !== "undefined") {
|
|
|
2017
4708
|
window["createAnimator"] = createAnimator;
|
|
2018
4709
|
window["setupAnimationTriggers"] = setupAnimationTriggers;
|
|
2019
4710
|
}
|
|
4711
|
+
|
|
4712
|
+
// src/effects/PlayerEffectsUtil.visualModel.ts
|
|
4713
|
+
var IDENTITY = [1, 0, 0, 1, 0, 0];
|
|
4714
|
+
function mul(m, n) {
|
|
4715
|
+
return [
|
|
4716
|
+
m[0] * n[0] + m[2] * n[1],
|
|
4717
|
+
m[1] * n[0] + m[3] * n[1],
|
|
4718
|
+
m[0] * n[2] + m[2] * n[3],
|
|
4719
|
+
m[1] * n[2] + m[3] * n[3],
|
|
4720
|
+
m[0] * n[4] + m[2] * n[5] + m[4],
|
|
4721
|
+
m[1] * n[4] + m[3] * n[5] + m[5]
|
|
4722
|
+
];
|
|
4723
|
+
}
|
|
4724
|
+
var translateM = (x, y) => [1, 0, 0, 1, x, y];
|
|
4725
|
+
var scaleM = (sx, sy) => [sx, 0, 0, sy, 0, 0];
|
|
4726
|
+
function rotateM(deg) {
|
|
4727
|
+
const r = deg * Math.PI / 180;
|
|
4728
|
+
return [Math.cos(r), Math.sin(r), -Math.sin(r), Math.cos(r), 0, 0];
|
|
4729
|
+
}
|
|
4730
|
+
var skewXM = (deg) => [1, 0, Math.tan(deg * Math.PI / 180), 1, 0, 0];
|
|
4731
|
+
var skewYM = (deg) => [1, Math.tan(deg * Math.PI / 180), 0, 1, 0, 0];
|
|
4732
|
+
function parseTransformString(s) {
|
|
4733
|
+
let m = IDENTITY;
|
|
4734
|
+
const re = /(translate|rotate|scale|matrix|skewX|skewY)\(([^)]*)\)/g;
|
|
4735
|
+
let hit;
|
|
4736
|
+
while (hit = re.exec(s)) {
|
|
4737
|
+
const fn = hit[1];
|
|
4738
|
+
const a = hit[2].split(/[\s,]+/).filter(Boolean).map(Number);
|
|
4739
|
+
if (fn === "translate") m = mul(m, translateM(a[0] || 0, a[1] || 0));
|
|
4740
|
+
else if (fn === "scale") m = mul(m, scaleM(a[0], a.length > 1 ? a[1] : a[0]));
|
|
4741
|
+
else if (fn === "rotate") m = mul(m, rotateM(a[0]));
|
|
4742
|
+
else if (fn === "skewX") m = mul(m, skewXM(a[0]));
|
|
4743
|
+
else if (fn === "skewY") m = mul(m, skewYM(a[0]));
|
|
4744
|
+
else if (fn === "matrix") m = mul(m, [a[0], a[1], a[2], a[3], a[4], a[5]]);
|
|
4745
|
+
}
|
|
4746
|
+
return m;
|
|
4747
|
+
}
|
|
4748
|
+
function partsToMatrix(p) {
|
|
4749
|
+
let m = IDENTITY;
|
|
4750
|
+
if (p.translate) m = mul(m, translateM(p.translate[0], p.translate[1]));
|
|
4751
|
+
const pivot = p.origin && (p.rotate !== void 0 || p.scale);
|
|
4752
|
+
if (pivot) m = mul(m, translateM(p.origin[0], p.origin[1]));
|
|
4753
|
+
if (p.rotate !== void 0) m = mul(m, rotateM(p.rotate));
|
|
4754
|
+
if (p.scale) m = mul(m, scaleM(p.scale[0], p.scale[1]));
|
|
4755
|
+
if (pivot) m = mul(m, translateM(-p.origin[0], -p.origin[1]));
|
|
4756
|
+
return m;
|
|
4757
|
+
}
|
|
4758
|
+
function lerp(a, b, f) {
|
|
4759
|
+
return a + (b - a) * f;
|
|
4760
|
+
}
|
|
4761
|
+
function interpParts(kfs, t) {
|
|
4762
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
4763
|
+
if (!kfs.length) return {};
|
|
4764
|
+
if (t <= ((_a = kfs[0].time) != null ? _a : 0)) return kfs[0].value || {};
|
|
4765
|
+
if (t >= ((_b = kfs[kfs.length - 1].time) != null ? _b : 0)) return kfs[kfs.length - 1].value || {};
|
|
4766
|
+
let i = 0;
|
|
4767
|
+
while (i < kfs.length - 1 && ((_c = kfs[i + 1].time) != null ? _c : 0) < t) i++;
|
|
4768
|
+
const a = kfs[i], b = kfs[i + 1];
|
|
4769
|
+
const f = (t - ((_d = a.time) != null ? _d : 0)) / (((_e = b.time) != null ? _e : 0) - ((_f = a.time) != null ? _f : 0) || 1);
|
|
4770
|
+
const va = a.value || {}, vb = b.value || {};
|
|
4771
|
+
const out = {};
|
|
4772
|
+
if (va.translate && vb.translate) out.translate = [lerp(va.translate[0], vb.translate[0], f), lerp(va.translate[1], vb.translate[1], f)];
|
|
4773
|
+
else out.translate = va.translate || vb.translate;
|
|
4774
|
+
if (va.rotate !== void 0 && vb.rotate !== void 0) out.rotate = lerp(va.rotate, vb.rotate, f);
|
|
4775
|
+
else out.rotate = (_g = va.rotate) != null ? _g : vb.rotate;
|
|
4776
|
+
if (va.scale && vb.scale) out.scale = [lerp(va.scale[0], vb.scale[0], f), lerp(va.scale[1], vb.scale[1], f)];
|
|
4777
|
+
else out.scale = va.scale || vb.scale;
|
|
4778
|
+
out.origin = va.origin || vb.origin;
|
|
4779
|
+
return out;
|
|
4780
|
+
}
|
|
4781
|
+
function evalTransformValue(v, t) {
|
|
4782
|
+
if (v === void 0 || v === null) return IDENTITY;
|
|
4783
|
+
if (typeof v === "string") return parseTransformString(v);
|
|
4784
|
+
if (v.keyframes) return partsToMatrix(interpParts(v.keyframes, t));
|
|
4785
|
+
if (v.value) return partsToMatrix(v.value);
|
|
4786
|
+
return IDENTITY;
|
|
4787
|
+
}
|
|
4788
|
+
function nodeMatrix(node, t) {
|
|
4789
|
+
if (node.animate && node.animate.transform) return evalTransformValue(node.animate.transform, t);
|
|
4790
|
+
if (node.transform !== void 0) return evalTransformValue(node.transform, t);
|
|
4791
|
+
return IDENTITY;
|
|
4792
|
+
}
|
|
4793
|
+
function evalScalar(animated, staticVal, fallback, t) {
|
|
4794
|
+
var _a, _b, _c, _d, _e, _f;
|
|
4795
|
+
if (animated && animated.keyframes && animated.keyframes.length) {
|
|
4796
|
+
const kfs = animated.keyframes;
|
|
4797
|
+
if (t <= ((_a = kfs[0].time) != null ? _a : 0)) return kfs[0].value;
|
|
4798
|
+
if (t >= ((_b = kfs[kfs.length - 1].time) != null ? _b : 0)) return kfs[kfs.length - 1].value;
|
|
4799
|
+
let i = 0;
|
|
4800
|
+
while (i < kfs.length - 1 && ((_c = kfs[i + 1].time) != null ? _c : 0) < t) i++;
|
|
4801
|
+
const a = kfs[i], b = kfs[i + 1];
|
|
4802
|
+
const f = (t - ((_d = a.time) != null ? _d : 0)) / (((_e = b.time) != null ? _e : 0) - ((_f = a.time) != null ? _f : 0) || 1);
|
|
4803
|
+
return lerp(a.value, b.value, f);
|
|
4804
|
+
}
|
|
4805
|
+
return staticVal !== void 0 ? Number(staticVal) : fallback;
|
|
4806
|
+
}
|
|
4807
|
+
var CONTAINER_TYPES = /* @__PURE__ */ new Set(["svg", "g", "symbol"]);
|
|
4808
|
+
var SKIP_TYPES = /* @__PURE__ */ new Set(["defs", "mask", "clipPath", "title"]);
|
|
4809
|
+
function buildIdMap2(node, map) {
|
|
4810
|
+
var _a;
|
|
4811
|
+
if (typeof node.id === "string") map.set(node.id, node);
|
|
4812
|
+
(_a = node.children) == null ? void 0 : _a.forEach((c) => buildIdMap2(c, map));
|
|
4813
|
+
}
|
|
4814
|
+
function num(v) {
|
|
4815
|
+
return v === void 0 || v === null ? 0 : Number(v);
|
|
4816
|
+
}
|
|
4817
|
+
function round(n) {
|
|
4818
|
+
return Math.round(n * 100) / 100 + 0;
|
|
4819
|
+
}
|
|
4820
|
+
function geomKey(node) {
|
|
4821
|
+
var _a;
|
|
4822
|
+
switch (node.type) {
|
|
4823
|
+
case "rect":
|
|
4824
|
+
return num(node.width) + "," + num(node.height) + "," + num(node.x) + "," + num(node.y);
|
|
4825
|
+
case "ellipse":
|
|
4826
|
+
return num(node.rx) + "," + num(node.ry) + "," + num(node.cx) + "," + num(node.cy);
|
|
4827
|
+
case "circle":
|
|
4828
|
+
return num(node.r) + "," + num(node.cx) + "," + num(node.cy);
|
|
4829
|
+
case "path":
|
|
4830
|
+
return String((_a = node.d) != null ? _a : "");
|
|
4831
|
+
default:
|
|
4832
|
+
return "";
|
|
4833
|
+
}
|
|
4834
|
+
}
|
|
4835
|
+
function describePrimitive(node, m, t) {
|
|
4836
|
+
var _a, _b, _c, _d, _e;
|
|
4837
|
+
const fill = (_a = node.fill) != null ? _a : "";
|
|
4838
|
+
const stroke = (_b = node.stroke) != null ? _b : "";
|
|
4839
|
+
const sw = (_d = (_c = node["stroke-width"]) != null ? _c : node.strokeWidth) != null ? _d : "";
|
|
4840
|
+
const opacity = round(evalScalar((_e = node.animate) == null ? void 0 : _e.opacity, node.opacity, 1, t));
|
|
4841
|
+
const masked = node.mask ? 1 : 0;
|
|
4842
|
+
const mat = m.map(round).join(",");
|
|
4843
|
+
return node.type + "|" + geomKey(node) + "|[" + mat + "]|f:" + fill + "|s:" + stroke + "|sw:" + (num(sw) || "") + "|o:" + opacity + "|m:" + masked;
|
|
4844
|
+
}
|
|
4845
|
+
function flatten(node, parent, t, idMap, out) {
|
|
4846
|
+
var _a;
|
|
4847
|
+
const type = node.type || "";
|
|
4848
|
+
if (SKIP_TYPES.has(type)) return;
|
|
4849
|
+
const m = mul(parent, nodeMatrix(node, t));
|
|
4850
|
+
if (type === "use") {
|
|
4851
|
+
const targetId = typeof node.href === "string" ? node.href.replace(/^#/, "") : "";
|
|
4852
|
+
const target = idMap.get(targetId);
|
|
4853
|
+
const useM = mul(m, translateM(num(node.x), num(node.y)));
|
|
4854
|
+
if (target) flatten(target, useM, t, idMap, out);
|
|
4855
|
+
else out.push("UNRESOLVED_USE:#" + targetId);
|
|
4856
|
+
return;
|
|
4857
|
+
}
|
|
4858
|
+
if (CONTAINER_TYPES.has(type)) {
|
|
4859
|
+
(_a = node.children) == null ? void 0 : _a.forEach((c) => flatten(c, m, t, idMap, out));
|
|
4860
|
+
return;
|
|
4861
|
+
}
|
|
4862
|
+
out.push(describePrimitive(node, m, t));
|
|
4863
|
+
}
|
|
4864
|
+
function collectSampleTimes(node, into) {
|
|
4865
|
+
var _a;
|
|
4866
|
+
into.add(0);
|
|
4867
|
+
const scanAnim = (anim) => {
|
|
4868
|
+
var _a2;
|
|
4869
|
+
if (!anim || typeof anim !== "object") return;
|
|
4870
|
+
for (const key of Object.keys(anim)) {
|
|
4871
|
+
const kfs = (_a2 = anim[key]) == null ? void 0 : _a2.keyframes;
|
|
4872
|
+
if (Array.isArray(kfs)) kfs.forEach((kf) => {
|
|
4873
|
+
var _a3;
|
|
4874
|
+
return into.add((_a3 = kf.time) != null ? _a3 : 0);
|
|
4875
|
+
});
|
|
4876
|
+
}
|
|
4877
|
+
};
|
|
4878
|
+
scanAnim(node.animate);
|
|
4879
|
+
if (node.transform && typeof node.transform === "object" && node.transform.keyframes) {
|
|
4880
|
+
node.transform.keyframes.forEach((kf) => {
|
|
4881
|
+
var _a2;
|
|
4882
|
+
return into.add((_a2 = kf.time) != null ? _a2 : 0);
|
|
4883
|
+
});
|
|
4884
|
+
}
|
|
4885
|
+
(_a = node.children) == null ? void 0 : _a.forEach((c) => collectSampleTimes(c, into));
|
|
4886
|
+
}
|
|
4887
|
+
function visualModelAt(root, t) {
|
|
4888
|
+
const idMap = /* @__PURE__ */ new Map();
|
|
4889
|
+
buildIdMap2(root, idMap);
|
|
4890
|
+
const out = [];
|
|
4891
|
+
flatten(root, IDENTITY, t, idMap, out);
|
|
4892
|
+
return out.sort();
|
|
4893
|
+
}
|
|
4894
|
+
function diffInEffect(a, b) {
|
|
4895
|
+
const times = /* @__PURE__ */ new Set();
|
|
4896
|
+
collectSampleTimes(a, times);
|
|
4897
|
+
collectSampleTimes(b, times);
|
|
4898
|
+
const diffs = [];
|
|
4899
|
+
for (const t of Array.from(times).sort((x, y) => x - y)) {
|
|
4900
|
+
const ma = visualModelAt(a, t);
|
|
4901
|
+
const mb = visualModelAt(b, t);
|
|
4902
|
+
const onlyInA = subtractMultiset(ma, mb);
|
|
4903
|
+
const onlyInB = subtractMultiset(mb, ma);
|
|
4904
|
+
if (onlyInA.length || onlyInB.length) diffs.push({ time: t, onlyInA, onlyInB });
|
|
4905
|
+
}
|
|
4906
|
+
return diffs;
|
|
4907
|
+
}
|
|
4908
|
+
function subtractMultiset(a, b) {
|
|
4909
|
+
const counts = /* @__PURE__ */ new Map();
|
|
4910
|
+
for (const x of b) counts.set(x, (counts.get(x) || 0) + 1);
|
|
4911
|
+
const extra = [];
|
|
4912
|
+
for (const x of a) {
|
|
4913
|
+
const c = counts.get(x) || 0;
|
|
4914
|
+
if (c > 0) counts.set(x, c - 1);
|
|
4915
|
+
else extra.push(x);
|
|
4916
|
+
}
|
|
4917
|
+
return extra;
|
|
4918
|
+
}
|
|
2020
4919
|
export {
|
|
2021
4920
|
COLOUR_ATTR_NAMES,
|
|
4921
|
+
PX_ANIMATOR_DATA_KEY,
|
|
2022
4922
|
PX_ANIM_ATTR_NAME,
|
|
2023
4923
|
PX_ANIM_SRC_ATTR_NAME,
|
|
4924
|
+
PX_TRANSFORM_PART_KEYS,
|
|
4925
|
+
PxAnimatedSvgDocumentSchema,
|
|
4926
|
+
PxAnimationDefinitionSchema,
|
|
4927
|
+
PxAnimatorConfigSchema,
|
|
4928
|
+
PxAnimatorEngine,
|
|
4929
|
+
PxAnimatorMode,
|
|
4930
|
+
PxAttrValueSchema,
|
|
4931
|
+
PxBezierPathSchema,
|
|
4932
|
+
PxBindingSchema,
|
|
4933
|
+
PxDefsSchema,
|
|
4934
|
+
PxEasingOrRefSchema,
|
|
4935
|
+
PxEffectsSchema,
|
|
4936
|
+
PxElementAnimationSchema,
|
|
4937
|
+
PxFillGradientEffectSchema,
|
|
4938
|
+
PxGradientSpreadMethod,
|
|
4939
|
+
PxGradientStopSchema,
|
|
4940
|
+
PxGradientType,
|
|
4941
|
+
PxGradientUnits,
|
|
4942
|
+
PxKeyframeSchema,
|
|
4943
|
+
PxLoopSchema,
|
|
4944
|
+
PxMaskedByEffectSchema,
|
|
4945
|
+
PxNodeBase,
|
|
4946
|
+
PxNodeSchema,
|
|
4947
|
+
PxPropertyAnimationSchema,
|
|
4948
|
+
PxRefEffectSchema,
|
|
4949
|
+
PxRepeaterEffectSchema,
|
|
4950
|
+
PxRetimeEffectSchema,
|
|
4951
|
+
PxStrokeGradientEffectSchema,
|
|
4952
|
+
PxSvgNodeExtra,
|
|
4953
|
+
PxTextAlongPathEffectSchema,
|
|
4954
|
+
PxTransformPartsSchema,
|
|
4955
|
+
PxTransformValueSchema,
|
|
4956
|
+
PxTransformationEffectSchema,
|
|
4957
|
+
PxTriggerSchema,
|
|
4958
|
+
PxTrimPathEffectSchema,
|
|
2024
4959
|
STYLE_ATTR_NAMES,
|
|
2025
4960
|
TRANSFORM_FN_NAMES,
|
|
4961
|
+
applyPlayerEffects,
|
|
2026
4962
|
calcAnimationValues,
|
|
2027
4963
|
camelCaseToKebabWordIfNeeded,
|
|
4964
|
+
collectSampleTimes,
|
|
2028
4965
|
createAnimator,
|
|
2029
4966
|
createAnimatorImpl,
|
|
2030
4967
|
createBasicFrameLoopAnimator,
|
|
2031
4968
|
createFrameLoopAnimator,
|
|
2032
4969
|
createWebApiAnimator,
|
|
4970
|
+
describeSchema,
|
|
4971
|
+
diffInEffect,
|
|
4972
|
+
evaluateMotionPathSegment,
|
|
2033
4973
|
generateNewIds,
|
|
2034
4974
|
getAnimatorConfig,
|
|
2035
4975
|
getBindings,
|
|
@@ -2039,9 +4979,20 @@ export {
|
|
|
2039
4979
|
isPxElementFileFormat,
|
|
2040
4980
|
isPxElementFileFormatDeep,
|
|
2041
4981
|
loadTagAnimators,
|
|
4982
|
+
materialiseAllInTree,
|
|
4983
|
+
materialiseAnimatedUseInstances,
|
|
4984
|
+
materialiseInternalLoopsInPropAnim,
|
|
4985
|
+
materialiseInternalLoopsInTree,
|
|
4986
|
+
materialiseMotionPathInPropAnim,
|
|
4987
|
+
materialiseMotionPathsInTree,
|
|
2042
4988
|
getNormalisedBindings as normalizeDocument,
|
|
4989
|
+
propAnimIsMotionPath,
|
|
4990
|
+
px,
|
|
2043
4991
|
renderNode,
|
|
4992
|
+
schemaKeys,
|
|
2044
4993
|
setupAnimationTriggers,
|
|
2045
|
-
toRGBA
|
|
4994
|
+
toRGBA,
|
|
4995
|
+
validateNodeEffects,
|
|
4996
|
+
visualModelAt
|
|
2046
4997
|
};
|
|
2047
4998
|
//# sourceMappingURL=index.js.map
|