@pixodesk/svg-animator-web 1.0.24 → 1.0.27
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 +1062 -665
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +8 -1
- package/dist/index.d.ts +8 -1
- package/dist/index.js +1062 -665
- package/dist/index.js.map +1 -1
- package/dist/index.min.cjs +1 -1
- package/dist/index.min.js +1 -1
- package/dist/index.prerendered-waapi.umd.js +74 -40
- package/dist/index.prerendered-waapi.umd.js.map +1 -1
- package/dist/index.prerendered-waapi.umd.min.js +1 -1
- package/dist/index.prerendered.umd.js +292 -41
- package/dist/index.prerendered.umd.js.map +1 -1
- package/dist/index.prerendered.umd.min.js +1 -1
- package/dist/index.umd.js +1070 -669
- package/dist/index.umd.js.map +1 -1
- package/dist/index.umd.min.js +1 -1
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -172,114 +172,582 @@ var __objRest2 = (source, exclude) => {
|
|
|
172
172
|
}
|
|
173
173
|
return target;
|
|
174
174
|
};
|
|
175
|
-
function
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
175
|
+
function bezierToSvgPath(path, forceCurves = false) {
|
|
176
|
+
var _a, _b, _c, _d;
|
|
177
|
+
const v = path.v;
|
|
178
|
+
const i = path.i;
|
|
179
|
+
const o = path.o;
|
|
180
|
+
const c = path.c;
|
|
181
|
+
if (!v.length) return "";
|
|
182
|
+
const d = [];
|
|
183
|
+
const len = v.length;
|
|
184
|
+
d.push("M" + v[0][0] + "," + v[0][1]);
|
|
185
|
+
for (let idx = 1; idx < len; idx++) {
|
|
186
|
+
const prevV = v[idx - 1];
|
|
187
|
+
const prevO = (_a = o == null ? void 0 : o[idx - 1]) != null ? _a : prevV;
|
|
188
|
+
const currI = (_b = i == null ? void 0 : i[idx]) != null ? _b : v[idx];
|
|
189
|
+
const currV = v[idx];
|
|
190
|
+
const isLine = !forceCurves && (prevO[0] === prevV[0] && prevO[1] === prevV[1]) && (currI[0] === currV[0] && currI[1] === currV[1]);
|
|
191
|
+
if (isLine) {
|
|
192
|
+
d.push("L" + currV[0] + "," + currV[1]);
|
|
193
|
+
} else {
|
|
194
|
+
d.push("C" + prevO[0] + "," + prevO[1] + "," + currI[0] + "," + currI[1] + "," + currV[0] + "," + currV[1]);
|
|
195
|
+
}
|
|
187
196
|
}
|
|
188
|
-
|
|
189
|
-
|
|
197
|
+
if (c && len > 0) {
|
|
198
|
+
const lastV = v[len - 1];
|
|
199
|
+
const lastO = (_c = o == null ? void 0 : o[len - 1]) != null ? _c : lastV;
|
|
200
|
+
const firstI = (_d = i == null ? void 0 : i[0]) != null ? _d : v[0];
|
|
201
|
+
const firstV = v[0];
|
|
202
|
+
const isLine = !forceCurves && (lastO[0] === lastV[0] && lastO[1] === lastV[1]) && (firstI[0] === firstV[0] && firstI[1] === firstV[1]);
|
|
203
|
+
if (!isLine) {
|
|
204
|
+
d.push("C" + lastO[0] + "," + lastO[1] + "," + firstI[0] + "," + firstI[1] + "," + firstV[0] + "," + firstV[1]);
|
|
205
|
+
}
|
|
206
|
+
d.push("z");
|
|
190
207
|
}
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
208
|
+
return d.join("");
|
|
209
|
+
}
|
|
210
|
+
function interpolateNum(a, b, t) {
|
|
211
|
+
return a + (b - a) * t;
|
|
212
|
+
}
|
|
213
|
+
function interpolateVec(a, b, t) {
|
|
214
|
+
const res = [];
|
|
215
|
+
const count = Math.max(a.length, b.length);
|
|
216
|
+
for (let i = 0; i < count; i++) {
|
|
217
|
+
res[i] = interpolateNum(a[i] || 0, b[i] || 0, t);
|
|
197
218
|
}
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
219
|
+
return res;
|
|
220
|
+
}
|
|
221
|
+
function interpolateColor(a, b, t) {
|
|
222
|
+
return [
|
|
223
|
+
interpolateNum(a[0] || 0, b[0] || 0, t),
|
|
224
|
+
interpolateNum(a[1] || 0, b[1] || 0, t),
|
|
225
|
+
interpolateNum(a[2] || 0, b[2] || 0, t),
|
|
226
|
+
interpolateNum(a[3] === void 0 ? 1 : a[3], b[3] === void 0 ? 1 : b[3], t)
|
|
227
|
+
];
|
|
228
|
+
}
|
|
229
|
+
function interpolateBeziers(paths1, paths2, progress) {
|
|
230
|
+
const count = Math.max(paths1.length, paths2.length);
|
|
231
|
+
const res = [];
|
|
232
|
+
for (let i = 0; i < count; i++) {
|
|
233
|
+
res.push(interpolateBezier(paths1[i], paths2[i], progress));
|
|
201
234
|
}
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
235
|
+
return res;
|
|
236
|
+
}
|
|
237
|
+
function interpolateBezier(path1, path2, progress) {
|
|
238
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i;
|
|
239
|
+
if (!path1 || !path2) return path1 || path2 || { v: [] };
|
|
240
|
+
const t = Math.min(Math.max(progress, 0), 1);
|
|
241
|
+
const len = Math.min(path1.v.length, path2.v.length);
|
|
242
|
+
const v = [];
|
|
243
|
+
const i = [];
|
|
244
|
+
const o = [];
|
|
245
|
+
for (let idx = 0; idx < len; idx++) {
|
|
246
|
+
const v1 = path1.v[idx];
|
|
247
|
+
const v2 = path2.v[idx];
|
|
248
|
+
v.push(interpolateVec(v1, v2, t));
|
|
249
|
+
const i1 = (_b = (_a = path1.i) == null ? void 0 : _a[idx]) != null ? _b : v1;
|
|
250
|
+
const i2 = (_d = (_c = path2.i) == null ? void 0 : _c[idx]) != null ? _d : v2;
|
|
251
|
+
i.push(interpolateVec(i1, i2, t));
|
|
252
|
+
const o1 = (_f = (_e = path1.o) == null ? void 0 : _e[idx]) != null ? _f : v1;
|
|
253
|
+
const o2 = (_h = (_g = path2.o) == null ? void 0 : _g[idx]) != null ? _h : v2;
|
|
254
|
+
o.push(interpolateVec(o1, o2, t));
|
|
205
255
|
}
|
|
206
|
-
|
|
207
|
-
|
|
256
|
+
return { v, i: i.length ? i : void 0, o: o.length ? o : void 0, c: (_i = path1.c) != null ? _i : path2.c };
|
|
257
|
+
}
|
|
258
|
+
function remap(value, inMin, inMax, outMin, outMax) {
|
|
259
|
+
if (inMax === inMin) return outMin;
|
|
260
|
+
const t = (value - inMin) / (inMax - inMin);
|
|
261
|
+
return outMin + t * (outMax - outMin);
|
|
262
|
+
}
|
|
263
|
+
function solveCubicBezierX(p1x, p2x, x) {
|
|
264
|
+
if (x <= 0) return 0;
|
|
265
|
+
if (x >= 1) return 1;
|
|
266
|
+
const cx = 3 * p1x;
|
|
267
|
+
const bx = 3 * (p2x - p1x) - cx;
|
|
268
|
+
const ax = 1 - cx - bx;
|
|
269
|
+
function sampleX(t) {
|
|
270
|
+
return ((ax * t + bx) * t + cx) * t;
|
|
208
271
|
}
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
constructor(_default = "") {
|
|
212
|
-
super();
|
|
213
|
-
this._default = _default;
|
|
272
|
+
function sampleDX(t) {
|
|
273
|
+
return (3 * ax * t + 2 * bx) * t + cx;
|
|
214
274
|
}
|
|
215
|
-
|
|
216
|
-
|
|
275
|
+
let t2 = x;
|
|
276
|
+
let t0 = 0;
|
|
277
|
+
let t1 = 1;
|
|
278
|
+
for (let i = 0; i < 8; i++) {
|
|
279
|
+
const x2 = sampleX(t2) - x;
|
|
280
|
+
if (Math.abs(x2) < 1e-6) return t2;
|
|
281
|
+
const d2 = sampleDX(t2);
|
|
282
|
+
if (Math.abs(d2) < 1e-6) break;
|
|
283
|
+
t2 -= x2 / d2;
|
|
217
284
|
}
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
return
|
|
285
|
+
t2 = x;
|
|
286
|
+
while (t0 < t1) {
|
|
287
|
+
const x2 = sampleX(t2);
|
|
288
|
+
if (Math.abs(x2 - x) < 1e-6) return t2;
|
|
289
|
+
if (x > x2) t0 = t2;
|
|
290
|
+
else t1 = t2;
|
|
291
|
+
t2 = (t1 + t0) / 2;
|
|
222
292
|
}
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
293
|
+
return t2;
|
|
294
|
+
}
|
|
295
|
+
function cubicBezier(easing) {
|
|
296
|
+
const [p1x, p1y, p2x, p2y] = easing;
|
|
297
|
+
const cy = 3 * p1y;
|
|
298
|
+
const by = 3 * (p2y - p1y) - cy;
|
|
299
|
+
const ay = 1 - cy - by;
|
|
300
|
+
function sampleCurveY(t) {
|
|
301
|
+
return ((ay * t + by) * t + cy) * t;
|
|
228
302
|
}
|
|
229
|
-
|
|
230
|
-
return
|
|
303
|
+
return function(x) {
|
|
304
|
+
return sampleCurveY(solveCubicBezierX(p1x, p2x, x));
|
|
305
|
+
};
|
|
306
|
+
}
|
|
307
|
+
function lerp2(a, b, t) {
|
|
308
|
+
return [a[0] + (b[0] - a[0]) * t, a[1] + (b[1] - a[1]) * t];
|
|
309
|
+
}
|
|
310
|
+
function subdivideCubicBezier(p0, p1, p2, p3, t) {
|
|
311
|
+
const q0 = lerp2(p0, p1, t);
|
|
312
|
+
const q1 = lerp2(p1, p2, t);
|
|
313
|
+
const q2 = lerp2(p2, p3, t);
|
|
314
|
+
const r0 = lerp2(q0, q1, t);
|
|
315
|
+
const r1 = lerp2(q1, q2, t);
|
|
316
|
+
const s = lerp2(r0, r1, t);
|
|
317
|
+
return {
|
|
318
|
+
left: [p0, q0, r0, s],
|
|
319
|
+
right: [s, r1, q2, p3]
|
|
320
|
+
};
|
|
321
|
+
}
|
|
322
|
+
function splitEasing(easing, xFraction) {
|
|
323
|
+
if (!easing) return { left: void 0, right: void 0 };
|
|
324
|
+
if (xFraction <= 0) return { left: void 0, right: easing };
|
|
325
|
+
if (xFraction >= 1) return { left: easing, right: void 0 };
|
|
326
|
+
const [x1, y1, x2, y2] = easing;
|
|
327
|
+
const t = solveCubicBezierX(x1, x2, xFraction);
|
|
328
|
+
const p0 = [0, 0];
|
|
329
|
+
const p1 = [x1, y1];
|
|
330
|
+
const p2 = [x2, y2];
|
|
331
|
+
const p3 = [1, 1];
|
|
332
|
+
const { left, right } = subdivideCubicBezier(p0, p1, p2, p3, t);
|
|
333
|
+
const sx = left[3][0];
|
|
334
|
+
const sy = left[3][1];
|
|
335
|
+
let leftEasing;
|
|
336
|
+
if (sx > 1e-9 && Math.abs(sy) > 1e-9) {
|
|
337
|
+
leftEasing = [
|
|
338
|
+
left[1][0] / sx,
|
|
339
|
+
left[1][1] / sy,
|
|
340
|
+
left[2][0] / sx,
|
|
341
|
+
left[2][1] / sy
|
|
342
|
+
];
|
|
231
343
|
}
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
344
|
+
let rightEasing;
|
|
345
|
+
const rx = 1 - sx;
|
|
346
|
+
const ry = 1 - sy;
|
|
347
|
+
if (rx > 1e-9 && Math.abs(ry) > 1e-9) {
|
|
348
|
+
rightEasing = [
|
|
349
|
+
(right[1][0] - sx) / rx,
|
|
350
|
+
(right[1][1] - sy) / ry,
|
|
351
|
+
(right[2][0] - sx) / rx,
|
|
352
|
+
(right[2][1] - sy) / ry
|
|
353
|
+
];
|
|
236
354
|
}
|
|
237
|
-
};
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
355
|
+
return { left: leftEasing, right: rightEasing };
|
|
356
|
+
}
|
|
357
|
+
function reverseEasing(easing) {
|
|
358
|
+
if (!easing) return void 0;
|
|
359
|
+
return [1 - easing[2], 1 - easing[3], 1 - easing[0], 1 - easing[1]];
|
|
360
|
+
}
|
|
361
|
+
function toRGBA(color) {
|
|
362
|
+
const r = Math.round(color[0] * 255);
|
|
363
|
+
const g = Math.round(color[1] * 255);
|
|
364
|
+
const b = Math.round(color[2] * 255);
|
|
365
|
+
return color.length === 4 ? "rgba(" + r + "," + g + "," + b + "," + color[3] + ")" : "rgb(" + r + "," + g + "," + b + ")";
|
|
366
|
+
}
|
|
367
|
+
function parseRgba(s) {
|
|
368
|
+
var _a;
|
|
369
|
+
const inner = (_a = s.match(/rgba?\((.*)\)/)) == null ? void 0 : _a[1];
|
|
370
|
+
if (!inner) throw new Error("Invalid rgb/rgba format");
|
|
371
|
+
const parts = inner.split(",").map((v) => +v.trim());
|
|
372
|
+
return [parts[0] / 255, parts[1] / 255, parts[2] / 255, ...parts[3] !== void 0 ? [parts[3]] : []];
|
|
373
|
+
}
|
|
374
|
+
function parseHex(s) {
|
|
375
|
+
const hex = s.slice(1);
|
|
376
|
+
const isShort = hex.length <= 4;
|
|
377
|
+
const r = isShort ? hex[0] + hex[0] : hex.slice(0, 2);
|
|
378
|
+
const g = isShort ? hex[1] + hex[1] : hex.slice(2, 4);
|
|
379
|
+
const b = isShort ? hex[2] + hex[2] : hex.slice(4, 6);
|
|
380
|
+
const a = hex.length === 4 ? hex[3] + hex[3] : hex.length === 8 ? hex.slice(6, 8) : null;
|
|
381
|
+
const result = [
|
|
382
|
+
parseInt(r, 16) / 255,
|
|
383
|
+
parseInt(g, 16) / 255,
|
|
384
|
+
parseInt(b, 16) / 255
|
|
385
|
+
];
|
|
386
|
+
if (a !== null) {
|
|
387
|
+
result.push(parseInt(a, 16) / 255);
|
|
242
388
|
}
|
|
243
|
-
|
|
244
|
-
|
|
389
|
+
return result;
|
|
390
|
+
}
|
|
391
|
+
function parseColor(s) {
|
|
392
|
+
if (!s) return void 0;
|
|
393
|
+
if (Array.isArray(s)) return s;
|
|
394
|
+
if (typeof s !== "string") return void 0;
|
|
395
|
+
if (s.startsWith("#")) {
|
|
396
|
+
return parseHex(s);
|
|
397
|
+
} else if (s.startsWith("rgb")) {
|
|
398
|
+
return parseRgba(s);
|
|
399
|
+
} else {
|
|
400
|
+
console.warn("Unsupported color format: " + s);
|
|
245
401
|
}
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
402
|
+
return void 0;
|
|
403
|
+
}
|
|
404
|
+
var COLOUR_ATTR_NAMES = /* @__PURE__ */ new Set(["color", "fill", "flood-color", "lighting-color", "stop-color", "stroke"]);
|
|
405
|
+
var TRANSFORM_FN_NAMES = /* @__PURE__ */ new Set(["translate", "rotate", "scale", "skew"]);
|
|
406
|
+
var PCT_BASED_ATTR_NAMES = /* @__PURE__ */ new Set(["offset-distance", "offsetDistance"]);
|
|
407
|
+
function composeTransformParts(parts, opts) {
|
|
408
|
+
var _a;
|
|
409
|
+
if (!parts) return "";
|
|
410
|
+
const withUnits = (_a = opts == null ? void 0 : opts.withUnits) != null ? _a : true;
|
|
411
|
+
const segs = [];
|
|
412
|
+
const t = parts.translate;
|
|
413
|
+
const o = parts.origin;
|
|
414
|
+
const r = parts.rotate;
|
|
415
|
+
const k = parts.skew;
|
|
416
|
+
const s = parts.scale;
|
|
417
|
+
const tu = withUnits ? "px" : "";
|
|
418
|
+
const ru = withUnits ? "deg" : "";
|
|
419
|
+
if (t) segs.push("translate(" + t[0] + tu + "," + t[1] + tu + ")");
|
|
420
|
+
if (o) segs.push("translate(" + o[0] + tu + "," + o[1] + tu + ")");
|
|
421
|
+
if (r !== void 0 && r !== null) segs.push("rotate(" + r + ru + ")");
|
|
422
|
+
if (k !== void 0 && k !== null) segs.push("skewX(" + k + ru + ")");
|
|
423
|
+
if (s) segs.push("scale(" + s[0] + "," + s[1] + ")");
|
|
424
|
+
if (o) segs.push("translate(" + -o[0] + tu + "," + -o[1] + tu + ")");
|
|
425
|
+
return segs.join("");
|
|
426
|
+
}
|
|
427
|
+
var STYLE_ATTR_NAMES = /* @__PURE__ */ new Set(["offset-distance", "offsetDistance"]);
|
|
428
|
+
var DEFAULT_DURATION_MS = 1e3;
|
|
429
|
+
function kebabToCamelCaseWord(kebab) {
|
|
430
|
+
return kebab.includes("-") ? kebab.replace(/-([a-z])/g, (_, letter) => letter.toUpperCase()) : kebab;
|
|
431
|
+
}
|
|
432
|
+
function isCamelCaseWord(word) {
|
|
433
|
+
return !word.includes("-") && /[a-z][A-Z]/.test(word);
|
|
434
|
+
}
|
|
435
|
+
var SVG_CAMEL_CASE_ATTRS = /* @__PURE__ */ new Set([
|
|
436
|
+
// Transform/positioning
|
|
437
|
+
"viewBox",
|
|
438
|
+
"preserveAspectRatio",
|
|
439
|
+
// Gradient
|
|
440
|
+
"gradientUnits",
|
|
441
|
+
"gradientTransform",
|
|
442
|
+
"spreadMethod",
|
|
443
|
+
// Pattern
|
|
444
|
+
"patternUnits",
|
|
445
|
+
"patternContentUnits",
|
|
446
|
+
"patternTransform",
|
|
447
|
+
// Clipping/masking
|
|
448
|
+
"clipPathUnits",
|
|
449
|
+
"maskUnits",
|
|
450
|
+
"maskContentUnits",
|
|
451
|
+
// Marker (SVG spec keeps these camelCase, like viewBox)
|
|
452
|
+
"markerUnits",
|
|
453
|
+
"markerWidth",
|
|
454
|
+
"markerHeight",
|
|
455
|
+
"refX",
|
|
456
|
+
"refY",
|
|
457
|
+
// Text
|
|
458
|
+
"textLength",
|
|
459
|
+
"lengthAdjust",
|
|
460
|
+
"startOffset",
|
|
461
|
+
// Filter
|
|
462
|
+
"filterUnits",
|
|
463
|
+
"primitiveUnits",
|
|
464
|
+
"tableValues",
|
|
465
|
+
// feFuncR/G/B/A transfer table (type="table")
|
|
466
|
+
"stdDeviation",
|
|
467
|
+
"baseFrequency",
|
|
468
|
+
"numOctaves",
|
|
469
|
+
"surfaceScale",
|
|
470
|
+
"diffuseConstant",
|
|
471
|
+
"specularConstant",
|
|
472
|
+
"specularExponent",
|
|
473
|
+
"kernelMatrix",
|
|
474
|
+
"kernelUnitLength",
|
|
475
|
+
"edgeMode",
|
|
476
|
+
"preserveAlpha",
|
|
477
|
+
"targetX",
|
|
478
|
+
"targetY"
|
|
479
|
+
// // Animation
|
|
480
|
+
// 'attributeName',
|
|
481
|
+
// 'attributeType',
|
|
482
|
+
// 'calcMode',
|
|
483
|
+
// 'keyTimes',
|
|
484
|
+
// 'keySplines',
|
|
485
|
+
// 'repeatCount',
|
|
486
|
+
// 'repeatDur'
|
|
487
|
+
]);
|
|
488
|
+
function camelCaseToKebabWordIfNeeded(camel) {
|
|
489
|
+
return SVG_CAMEL_CASE_ATTRS.has(camel) ? camel : camel.replace(/([a-z0-9])([A-Z])/g, "$1-$2").toLowerCase();
|
|
490
|
+
}
|
|
491
|
+
function clamp(value, min, max) {
|
|
492
|
+
return Math.max(min, Math.min(value, max));
|
|
493
|
+
}
|
|
494
|
+
function bezier2D_pointAt(P0, P1, P2, P3, t) {
|
|
495
|
+
if (t <= 0) return [P0[0], P0[1]];
|
|
496
|
+
if (t >= 1) return [P3[0], P3[1]];
|
|
497
|
+
const u = 1 - t;
|
|
498
|
+
const u2 = u * u;
|
|
499
|
+
const u3 = u2 * u;
|
|
500
|
+
const t2 = t * t;
|
|
501
|
+
const t3 = t2 * t;
|
|
502
|
+
const w0 = u3;
|
|
503
|
+
const w1 = 3 * t * u2;
|
|
504
|
+
const w2 = 3 * t2 * u;
|
|
505
|
+
const w3 = t3;
|
|
506
|
+
return [
|
|
507
|
+
w0 * P0[0] + w1 * P1[0] + w2 * P2[0] + w3 * P3[0],
|
|
508
|
+
w0 * P0[1] + w1 * P1[1] + w2 * P2[1] + w3 * P3[1]
|
|
509
|
+
];
|
|
510
|
+
}
|
|
511
|
+
var BEZIER_T_NUDGE = 1e-4;
|
|
512
|
+
function bezier2D_derivativeAt(P0, P1, P2, P3, t) {
|
|
513
|
+
const result = _bezier2D_derivativeAtRaw(P0, P1, P2, P3, t);
|
|
514
|
+
if (result[0] === 0 && result[1] === 0) {
|
|
515
|
+
const nudgedT = t < 0.5 ? t + BEZIER_T_NUDGE : t - BEZIER_T_NUDGE;
|
|
516
|
+
return _bezier2D_derivativeAtRaw(P0, P1, P2, P3, nudgedT);
|
|
517
|
+
}
|
|
518
|
+
return result;
|
|
519
|
+
}
|
|
520
|
+
function _bezier2D_derivativeAtRaw(P0, P1, P2, P3, t) {
|
|
521
|
+
const u = 1 - t;
|
|
522
|
+
const a = 3 * u * u;
|
|
523
|
+
const b = 6 * t * u;
|
|
524
|
+
const c = 3 * t * t;
|
|
525
|
+
return [
|
|
526
|
+
a * (P1[0] - P0[0]) + b * (P2[0] - P1[0]) + c * (P3[0] - P2[0]),
|
|
527
|
+
a * (P1[1] - P0[1]) + b * (P2[1] - P1[1]) + c * (P3[1] - P2[1])
|
|
528
|
+
];
|
|
529
|
+
}
|
|
530
|
+
function bezier2D_arcLengthLUT(P0, P1, P2, P3, steps = 100) {
|
|
531
|
+
const n = steps + 1;
|
|
532
|
+
const ts = new Float64Array(n);
|
|
533
|
+
const ds = new Float64Array(n);
|
|
534
|
+
let prev = bezier2D_pointAt(P0, P1, P2, P3, 0);
|
|
535
|
+
ts[0] = 0;
|
|
536
|
+
ds[0] = 0;
|
|
537
|
+
let cum = 0;
|
|
538
|
+
for (let i = 1; i < n; i++) {
|
|
539
|
+
const t = i / steps;
|
|
540
|
+
const cur = bezier2D_pointAt(P0, P1, P2, P3, t);
|
|
541
|
+
const dx = cur[0] - prev[0];
|
|
542
|
+
const dy = cur[1] - prev[1];
|
|
543
|
+
cum += Math.sqrt(dx * dx + dy * dy);
|
|
544
|
+
ts[i] = t;
|
|
545
|
+
ds[i] = cum;
|
|
546
|
+
prev = cur;
|
|
547
|
+
}
|
|
548
|
+
return { ts, ds };
|
|
549
|
+
}
|
|
550
|
+
function bezier2D_tForDistance(lut, distance) {
|
|
551
|
+
const { ts, ds } = lut;
|
|
552
|
+
const last = ds.length - 1;
|
|
553
|
+
if (distance <= 0) return ts[0];
|
|
554
|
+
if (distance >= ds[last]) return ts[last];
|
|
555
|
+
let lo = 1;
|
|
556
|
+
let hi = last;
|
|
557
|
+
while (lo < hi) {
|
|
558
|
+
const mid = lo + hi >>> 1;
|
|
559
|
+
if (ds[mid] < distance) lo = mid + 1;
|
|
560
|
+
else hi = mid;
|
|
561
|
+
}
|
|
562
|
+
const dPrev = ds[hi - 1];
|
|
563
|
+
const dCur = ds[hi];
|
|
564
|
+
const span = dCur - dPrev;
|
|
565
|
+
const frac = span > 0 ? (distance - dPrev) / span : 0;
|
|
566
|
+
return ts[hi - 1] + frac * (ts[hi] - ts[hi - 1]);
|
|
567
|
+
}
|
|
568
|
+
function bezier2D_arcAtT(lut, t) {
|
|
569
|
+
const { ts, ds } = lut;
|
|
570
|
+
const last = ts.length - 1;
|
|
571
|
+
if (t <= ts[0]) return ds[0];
|
|
572
|
+
if (t >= ts[last]) return ds[last];
|
|
573
|
+
let lo = 1, hi = last;
|
|
574
|
+
while (lo < hi) {
|
|
575
|
+
const mid = lo + hi >>> 1;
|
|
576
|
+
if (ts[mid] < t) lo = mid + 1;
|
|
577
|
+
else hi = mid;
|
|
578
|
+
}
|
|
579
|
+
const tPrev = ts[hi - 1];
|
|
580
|
+
const span = ts[hi] - tPrev;
|
|
581
|
+
const frac = span > 0 ? (t - tPrev) / span : 0;
|
|
582
|
+
return ds[hi - 1] + frac * (ds[hi] - ds[hi - 1]);
|
|
583
|
+
}
|
|
584
|
+
function invertEasing(easing) {
|
|
585
|
+
if (!easing) return (y) => y;
|
|
586
|
+
const flipped = [easing[1], easing[0], easing[3], easing[2]];
|
|
587
|
+
return cubicBezier(flipped);
|
|
588
|
+
}
|
|
589
|
+
function isScrollTimeline(config) {
|
|
590
|
+
return (config == null ? void 0 : config.timelineSource) === "scroll";
|
|
591
|
+
}
|
|
592
|
+
function scrollTotalDurationMs(config) {
|
|
593
|
+
const duration = typeof (config == null ? void 0 : config.duration) === "number" && config.duration > 0 ? config.duration : DEFAULT_DURATION_MS;
|
|
594
|
+
const iterations = typeof (config == null ? void 0 : config.iterations) === "number" && config.iterations > 0 ? config.iterations : 1;
|
|
595
|
+
return duration * iterations;
|
|
596
|
+
}
|
|
597
|
+
function scrollPhaseInterval(phase, subjectSize, scrollportSize) {
|
|
598
|
+
const s = subjectSize, vp = scrollportSize;
|
|
599
|
+
switch (phase) {
|
|
600
|
+
case "cover":
|
|
601
|
+
return [0, s + vp];
|
|
602
|
+
case "entry":
|
|
603
|
+
return [0, Math.min(s, vp)];
|
|
604
|
+
case "contain":
|
|
605
|
+
return [Math.min(s, vp), Math.max(s, vp)];
|
|
606
|
+
case "exit":
|
|
607
|
+
return [Math.max(s, vp), s + vp];
|
|
608
|
+
case "entry-crossing":
|
|
609
|
+
return [0, s];
|
|
610
|
+
case "exit-crossing":
|
|
611
|
+
return [vp, s + vp];
|
|
612
|
+
}
|
|
613
|
+
}
|
|
614
|
+
var DEFAULT_PHASE = "cover";
|
|
615
|
+
function resolveRangePointU(point, defaultFraction, subjectSize, scrollportSize) {
|
|
616
|
+
var _a;
|
|
617
|
+
const [u0, u1] = scrollPhaseInterval((_a = point == null ? void 0 : point.phase) != null ? _a : DEFAULT_PHASE, subjectSize, scrollportSize);
|
|
618
|
+
const fraction = typeof (point == null ? void 0 : point.fraction) === "number" ? point.fraction : defaultFraction;
|
|
619
|
+
return u0 + fraction * (u1 - u0);
|
|
620
|
+
}
|
|
621
|
+
function scrollViewProgress(subjectStart, subjectSize, scrollportSize, range) {
|
|
622
|
+
const u = scrollportSize - subjectStart;
|
|
623
|
+
const uStart = resolveRangePointU(range == null ? void 0 : range.start, 0, subjectSize, scrollportSize);
|
|
624
|
+
const uEnd = resolveRangePointU(range == null ? void 0 : range.end, 1, subjectSize, scrollportSize);
|
|
625
|
+
if (uEnd <= uStart) return u >= uEnd ? 1 : 0;
|
|
626
|
+
return clamp((u - uStart) / (uEnd - uStart), 0, 1);
|
|
627
|
+
}
|
|
628
|
+
function scrollOffsetProgress(offset, maxOffset, range) {
|
|
629
|
+
var _a, _b;
|
|
630
|
+
const raw = maxOffset > 0 ? clamp(offset / maxOffset, 0, 1) : 1;
|
|
631
|
+
const start = typeof ((_a = range == null ? void 0 : range.start) == null ? void 0 : _a.fraction) === "number" ? range.start.fraction : 0;
|
|
632
|
+
const end = typeof ((_b = range == null ? void 0 : range.end) == null ? void 0 : _b.fraction) === "number" ? range.end.fraction : 1;
|
|
633
|
+
if (end <= start) return raw >= end ? 1 : 0;
|
|
634
|
+
return clamp((raw - start) / (end - start), 0, 1);
|
|
635
|
+
}
|
|
636
|
+
function scrollResolveAxis(axis, writingMode) {
|
|
637
|
+
const a = axis != null ? axis : "block";
|
|
638
|
+
if (a === "x" || a === "y") return a;
|
|
639
|
+
const vertical = !!writingMode && writingMode.startsWith("vertical");
|
|
640
|
+
if (a === "inline") return vertical ? "y" : "x";
|
|
641
|
+
return vertical ? "x" : "y";
|
|
642
|
+
}
|
|
643
|
+
function pathStr(path) {
|
|
644
|
+
if (!path.length) return ".";
|
|
645
|
+
let result = "";
|
|
646
|
+
for (const seg of path) {
|
|
647
|
+
if (seg.startsWith("[")) result += seg;
|
|
648
|
+
else result += (result ? "." : "") + seg;
|
|
649
|
+
}
|
|
650
|
+
return result;
|
|
651
|
+
}
|
|
652
|
+
var Base = class {
|
|
653
|
+
_canSanitize(raw) {
|
|
654
|
+
return this.isValid(raw);
|
|
655
|
+
}
|
|
656
|
+
optional() {
|
|
657
|
+
return new Optional(this);
|
|
250
658
|
}
|
|
251
659
|
};
|
|
252
|
-
var
|
|
253
|
-
constructor(
|
|
660
|
+
var Optional = class extends Base {
|
|
661
|
+
constructor(inner) {
|
|
254
662
|
super();
|
|
255
|
-
this.
|
|
256
|
-
this._default =
|
|
663
|
+
this.inner = inner;
|
|
664
|
+
this._default = void 0;
|
|
257
665
|
}
|
|
258
666
|
sanitize(raw) {
|
|
259
|
-
|
|
667
|
+
if (raw === void 0 || raw === null) return void 0;
|
|
668
|
+
return this.inner._canSanitize(raw) ? this.inner.sanitize(raw) : void 0;
|
|
260
669
|
}
|
|
261
670
|
isValid(raw, ctx, path) {
|
|
262
|
-
if (raw ===
|
|
263
|
-
|
|
264
|
-
|
|
671
|
+
if (raw === void 0 || raw === null) return true;
|
|
672
|
+
return this.inner.isValid(raw, ctx, path);
|
|
673
|
+
}
|
|
674
|
+
_canSanitize(raw) {
|
|
675
|
+
return raw === void 0 || raw === null || this.inner._canSanitize(raw);
|
|
265
676
|
}
|
|
266
677
|
};
|
|
267
|
-
var
|
|
268
|
-
constructor(
|
|
678
|
+
var Str = class extends Base {
|
|
679
|
+
constructor(_default = "") {
|
|
269
680
|
super();
|
|
270
|
-
this.
|
|
271
|
-
this._default = defaultVal != null ? defaultVal : values[0];
|
|
681
|
+
this._default = _default;
|
|
272
682
|
}
|
|
273
683
|
sanitize(raw) {
|
|
274
|
-
return
|
|
684
|
+
return typeof raw === "string" ? raw : this._default;
|
|
275
685
|
}
|
|
276
686
|
isValid(raw, ctx, path) {
|
|
277
|
-
if (
|
|
278
|
-
ctx == null ? void 0 : ctx.errors.push(pathStr(path != null ? path : []) + ": expected
|
|
687
|
+
if (typeof raw === "string") return true;
|
|
688
|
+
ctx == null ? void 0 : ctx.errors.push(pathStr(path != null ? path : []) + ": expected string, got " + typeof raw);
|
|
279
689
|
return false;
|
|
280
690
|
}
|
|
281
691
|
};
|
|
282
|
-
var
|
|
692
|
+
var Num = class extends Base {
|
|
693
|
+
constructor(_default = 0) {
|
|
694
|
+
super();
|
|
695
|
+
this._default = _default;
|
|
696
|
+
}
|
|
697
|
+
sanitize(raw) {
|
|
698
|
+
return typeof raw === "number" && isFinite(raw) ? raw : this._default;
|
|
699
|
+
}
|
|
700
|
+
isValid(raw, ctx, path) {
|
|
701
|
+
if (typeof raw === "number" && isFinite(raw)) return true;
|
|
702
|
+
ctx == null ? void 0 : ctx.errors.push(pathStr(path != null ? path : []) + ": expected finite number, got " + JSON.stringify(raw));
|
|
703
|
+
return false;
|
|
704
|
+
}
|
|
705
|
+
};
|
|
706
|
+
var Bool = class extends Base {
|
|
707
|
+
constructor(_default = false) {
|
|
708
|
+
super();
|
|
709
|
+
this._default = _default;
|
|
710
|
+
}
|
|
711
|
+
sanitize(raw) {
|
|
712
|
+
return typeof raw === "boolean" ? raw : this._default;
|
|
713
|
+
}
|
|
714
|
+
isValid(raw, ctx, path) {
|
|
715
|
+
if (typeof raw === "boolean") return true;
|
|
716
|
+
ctx == null ? void 0 : ctx.errors.push(pathStr(path != null ? path : []) + ": expected boolean, got " + typeof raw);
|
|
717
|
+
return false;
|
|
718
|
+
}
|
|
719
|
+
};
|
|
720
|
+
var Literal = class extends Base {
|
|
721
|
+
constructor(value) {
|
|
722
|
+
super();
|
|
723
|
+
this.value = value;
|
|
724
|
+
this._default = value;
|
|
725
|
+
}
|
|
726
|
+
sanitize(raw) {
|
|
727
|
+
return raw === this.value ? this.value : this._default;
|
|
728
|
+
}
|
|
729
|
+
isValid(raw, ctx, path) {
|
|
730
|
+
if (raw === this.value) return true;
|
|
731
|
+
ctx == null ? void 0 : ctx.errors.push(pathStr(path != null ? path : []) + ": expected " + JSON.stringify(this.value) + ", got " + JSON.stringify(raw));
|
|
732
|
+
return false;
|
|
733
|
+
}
|
|
734
|
+
};
|
|
735
|
+
var Enum = class extends Base {
|
|
736
|
+
constructor(values, defaultVal) {
|
|
737
|
+
super();
|
|
738
|
+
this.values = values;
|
|
739
|
+
this._default = defaultVal != null ? defaultVal : values[0];
|
|
740
|
+
}
|
|
741
|
+
sanitize(raw) {
|
|
742
|
+
return this.values.includes(raw) ? raw : this._default;
|
|
743
|
+
}
|
|
744
|
+
isValid(raw, ctx, path) {
|
|
745
|
+
if (this.values.includes(raw)) return true;
|
|
746
|
+
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));
|
|
747
|
+
return false;
|
|
748
|
+
}
|
|
749
|
+
};
|
|
750
|
+
var Union = class extends Base {
|
|
283
751
|
constructor(schemas, defaultVal) {
|
|
284
752
|
super();
|
|
285
753
|
this.schemas = schemas;
|
|
@@ -834,6 +1302,22 @@ var PxDefsSchema = implementsInterface()(px.object({
|
|
|
834
1302
|
styles: px.record(px.any()).optional(),
|
|
835
1303
|
glyphs: px.record(PxGlyphFontSchema).optional()
|
|
836
1304
|
}));
|
|
1305
|
+
var PX_SCROLL_PHASES = ["cover", "contain", "entry", "exit", "entry-crossing", "exit-crossing"];
|
|
1306
|
+
var PxScrollRangePointSchema = implementsInterface()(px.object({
|
|
1307
|
+
phase: px.enum(PX_SCROLL_PHASES).optional(),
|
|
1308
|
+
fraction: px.number().optional()
|
|
1309
|
+
}));
|
|
1310
|
+
var PxScrollRangeSchema = px.object({
|
|
1311
|
+
start: PxScrollRangePointSchema.optional(),
|
|
1312
|
+
end: PxScrollRangePointSchema.optional()
|
|
1313
|
+
});
|
|
1314
|
+
var PxScrollSchema = implementsInterface()(px.object({
|
|
1315
|
+
driver: px.enum(["custom", "native"]).optional(),
|
|
1316
|
+
kind: px.enum(["view", "scroll"]).optional(),
|
|
1317
|
+
axis: px.enum(["block", "inline", "x", "y"]).optional(),
|
|
1318
|
+
source: px.enum(["nearest", "root"]).optional(),
|
|
1319
|
+
range: PxScrollRangeSchema.optional()
|
|
1320
|
+
}));
|
|
837
1321
|
var PxAnimatorConfigSchema = implementsInterface()(px.object({
|
|
838
1322
|
mode: px.enum([PxAnimatorMode.auto, PxAnimatorMode.waapi, PxAnimatorMode.frames]).optional(),
|
|
839
1323
|
duration: px.number().optional(),
|
|
@@ -849,6 +1333,7 @@ var PxAnimatorConfigSchema = implementsInterface()(px.object({
|
|
|
849
1333
|
definitions: PxDefsSchema.optional(),
|
|
850
1334
|
animateById: px.record(PxElementAnimationSchema).optional(),
|
|
851
1335
|
timelineSource: px.string().optional(),
|
|
1336
|
+
scroll: PxScrollSchema.optional(),
|
|
852
1337
|
debugInstName: px.string().optional()
|
|
853
1338
|
}));
|
|
854
1339
|
var PxBindingSchema = implementsInterface()(px.object({
|
|
@@ -868,589 +1353,177 @@ var PxAttrValueSchema = px.union([
|
|
|
868
1353
|
var PxAnimatableNumberSchema = px.union([
|
|
869
1354
|
px.number(),
|
|
870
1355
|
px.object({ value: px.number() }),
|
|
871
|
-
PxPropertyAnimationSchema
|
|
872
|
-
]);
|
|
873
|
-
var PxAnimatableVec2Schema = px.union([
|
|
874
|
-
px.tuple([px.number(), px.number()]),
|
|
875
|
-
px.object({ value: px.tuple([px.number(), px.number()]) }),
|
|
876
|
-
PxPropertyAnimationSchema
|
|
877
|
-
]);
|
|
878
|
-
var PxAnimatableStringSchema = px.union([
|
|
879
|
-
px.string(),
|
|
880
|
-
px.object({ value: px.string() }),
|
|
881
|
-
PxPropertyAnimationSchema
|
|
882
|
-
]);
|
|
883
|
-
var PxTransformByEffectSchema = implementsInterface()(px.object({
|
|
884
|
-
translate: PxAnimatableVec2Schema.optional(),
|
|
885
|
-
rotate: PxAnimatableNumberSchema.optional(),
|
|
886
|
-
scale: PxAnimatableVec2Schema.optional(),
|
|
887
|
-
skew: PxAnimatableNumberSchema.optional(),
|
|
888
|
-
origin: PxAnimatableVec2Schema.optional()
|
|
889
|
-
}));
|
|
890
|
-
var PxRepeaterEffectSchema = implementsInterface()(px.object({
|
|
891
|
-
// STATIC config, not a channel (V2/SCHEMA-DESIGN R5): the copy COUNT is read
|
|
892
|
-
// once at expansion time and never sampled — plain number, no `keyframes`.
|
|
893
|
-
copies: px.number().optional(),
|
|
894
|
-
translate: PxAnimatableVec2Schema.optional(),
|
|
895
|
-
rotate: PxAnimatableNumberSchema.optional(),
|
|
896
|
-
skew: PxAnimatableNumberSchema.optional(),
|
|
897
|
-
scale: PxAnimatableVec2Schema.optional(),
|
|
898
|
-
origin: PxAnimatableVec2Schema.optional()
|
|
899
|
-
}));
|
|
900
|
-
var PxMaskedByEffectSchema = implementsInterface()(px.object({
|
|
901
|
-
sourceId: px.string().optional(),
|
|
902
|
-
maskType: px.enum([PxMaskType.luminance, PxMaskType.alpha]).optional(),
|
|
903
|
-
maskUnits: px.enum([PxUnits.userSpaceOnUse, PxUnits.objectBoundingBox]).optional(),
|
|
904
|
-
maskContentUnits: px.enum([PxUnits.userSpaceOnUse, PxUnits.objectBoundingBox]).optional(),
|
|
905
|
-
x: px.number().optional(),
|
|
906
|
-
y: px.number().optional(),
|
|
907
|
-
width: px.number().optional(),
|
|
908
|
-
height: px.number().optional()
|
|
909
|
-
}));
|
|
910
|
-
var PxClipPathEffectSchema = implementsInterface()(px.object({
|
|
911
|
-
d: PxAnimatableStringSchema.optional(),
|
|
912
|
-
animate: PxPropertyAnimationSchema.optional()
|
|
913
|
-
}));
|
|
914
|
-
var PxTrimPathEffectSchema = implementsInterface()(px.object({
|
|
915
|
-
offset: PxAnimatableNumberSchema.optional(),
|
|
916
|
-
range: PxAnimatableVec2Schema.optional(),
|
|
917
|
-
subPaths: px.enum([PxTrimSubPaths.separate, PxTrimSubPaths.combined]).optional()
|
|
918
|
-
}));
|
|
919
|
-
var PxRetimeEffectSchema = implementsInterface()(px.object({
|
|
920
|
-
sourceId: px.string().optional(),
|
|
921
|
-
start: px.number().optional(),
|
|
922
|
-
stretch: px.number().optional(),
|
|
923
|
-
timeCrop: px.tuple([px.number(), px.number()]).optional()
|
|
924
|
-
}));
|
|
925
|
-
var PxCloneEffectSchema = implementsInterface()(px.object({
|
|
926
|
-
// Contextual kind — the `type` convention, see `PxNodeBase.type`.
|
|
927
|
-
type: px.enum([PxCloneType.content]).optional(),
|
|
928
|
-
sourceId: px.string().optional(),
|
|
929
|
-
retime: PxRetimeEffectSchema.optional()
|
|
930
|
-
}));
|
|
931
|
-
var PxGradientStopSchema = implementsInterface()(px.object({
|
|
932
|
-
offset: px.number(),
|
|
933
|
-
color: px.string()
|
|
934
|
-
}));
|
|
935
|
-
var PxAnimatableGradientStopsSchema = px.union([
|
|
936
|
-
px.array(PxGradientStopSchema),
|
|
937
|
-
px.object({ value: px.array(PxGradientStopSchema) }),
|
|
938
|
-
PxPropertyAnimationSchema
|
|
939
|
-
]);
|
|
940
|
-
var PxFillGradientEffectSchema = implementsInterface()(px.object({
|
|
941
|
-
// Contextual kind — the `type` convention, see `PxNodeBase.type`.
|
|
942
|
-
type: px.enum([PxGradientType.linear, PxGradientType.radial]),
|
|
943
|
-
p1: PxAnimatableVec2Schema.optional(),
|
|
944
|
-
p2: PxAnimatableVec2Schema.optional(),
|
|
945
|
-
c: PxAnimatableVec2Schema.optional(),
|
|
946
|
-
r: PxAnimatableNumberSchema.optional(),
|
|
947
|
-
fp: PxAnimatableVec2Schema.optional(),
|
|
948
|
-
stops: PxAnimatableGradientStopsSchema.optional(),
|
|
949
|
-
gradientUnits: px.enum([PxGradientUnits.userSpaceOnUse, PxGradientUnits.objectBoundingBox]).optional(),
|
|
950
|
-
spreadMethod: px.enum([PxGradientSpreadMethod.pad, PxGradientSpreadMethod.reflect, PxGradientSpreadMethod.repeat]).optional(),
|
|
951
|
-
gradientTransform: px.string().optional()
|
|
952
|
-
}));
|
|
953
|
-
var PxStrokeGradientEffectSchema = PxFillGradientEffectSchema;
|
|
954
|
-
var PxTextPathEffectSchema = implementsInterface()(px.object({
|
|
955
|
-
path: px.string(),
|
|
956
|
-
pathOverflow: px.enum([PxPathOverflow.clip, PxPathOverflow.extend]).optional(),
|
|
957
|
-
lengthAdjust: px.enum([PxLengthAdjust.spacing, PxLengthAdjust.spacingAndGlyphs]).optional(),
|
|
958
|
-
method: px.enum([PxTextPathMethod.align, PxTextPathMethod.stretch]).optional(),
|
|
959
|
-
spacing: px.enum([PxTextPathSpacing.auto, PxTextPathSpacing.exact]).optional(),
|
|
960
|
-
startOffset: PxAnimatableNumberSchema.optional(),
|
|
961
|
-
textLength: PxAnimatableNumberSchema.optional()
|
|
962
|
-
}));
|
|
963
|
-
var PxTextEffectSchema = implementsInterface()(px.object({
|
|
964
|
-
useGlyphs: px.boolean().optional()
|
|
965
|
-
}));
|
|
966
|
-
var PxEffectsSchema = implementsInterface()(px.object({
|
|
967
|
-
transformBy: PxTransformByEffectSchema.optional(),
|
|
968
|
-
repeater: PxRepeaterEffectSchema.optional(),
|
|
969
|
-
maskedBy: PxMaskedByEffectSchema.optional(),
|
|
970
|
-
clipPath: PxClipPathEffectSchema.optional(),
|
|
971
|
-
trimPath: PxTrimPathEffectSchema.optional(),
|
|
972
|
-
clone: PxCloneEffectSchema.optional(),
|
|
973
|
-
fillGradient: PxFillGradientEffectSchema.optional(),
|
|
974
|
-
strokeGradient: PxStrokeGradientEffectSchema.optional(),
|
|
975
|
-
textPath: PxTextPathEffectSchema.optional(),
|
|
976
|
-
text: PxTextEffectSchema.optional()
|
|
977
|
-
}));
|
|
978
|
-
function validateNodeEffects(root, opts) {
|
|
979
|
-
const warnings = [];
|
|
980
|
-
const walk = (node, path) => {
|
|
981
|
-
if (node && node.effects) {
|
|
982
|
-
const ctx = { errors: [], warnings: [], strict: !!(opts == null ? void 0 : opts.strict) };
|
|
983
|
-
const ok = PxEffectsSchema.isValid(node.effects, ctx, [path + ".effects"]);
|
|
984
|
-
if (!ok) {
|
|
985
|
-
for (const err of ctx.errors) warnings.push(err);
|
|
986
|
-
}
|
|
987
|
-
}
|
|
988
|
-
if (node && Array.isArray(node.children)) {
|
|
989
|
-
node.children.forEach((c, i) => walk(c, path + ".children[" + i + "]"));
|
|
990
|
-
}
|
|
991
|
-
};
|
|
992
|
-
walk(root, "root");
|
|
993
|
-
return warnings;
|
|
994
|
-
}
|
|
995
|
-
var PxNodeBase = px.openObject({
|
|
996
|
-
// CONVENTION (SCHEMA-DESIGN R1 / issues N4): `type` is the ONE word for "what
|
|
997
|
-
// kind of thing is this", discriminated by its CARRIER — here the node TAG
|
|
998
|
-
// (`rect`, `text`), and inside a sub-object that object's kind (`clone.type`,
|
|
999
|
-
// `fillGradient.type`, editor `preset.type`). Each sits in its own object, so
|
|
1000
|
-
// the carrier disambiguates completely; synonyms (`cloneKind`, `presetShape`)
|
|
1001
|
-
// would add words that all mean "type" and still need the carrier to read.
|
|
1002
|
-
// Guarding a `type` SLOT against a wrong VALUE is the job of strict enums
|
|
1003
|
-
// (issues V3), never of distinct key names.
|
|
1004
|
-
type: px.string(),
|
|
1005
|
-
id: px.string().optional(),
|
|
1006
|
-
meta: px.any().optional(),
|
|
1007
|
-
// Player-effects bucket emitted by the Editor's lightweight design format.
|
|
1008
|
-
// Consumed and removed by `applyPlayerEffects` before any other normalisation
|
|
1009
|
-
// (see `createAnimatorImpl`), so downstream code never sees it.
|
|
1010
|
-
effects: PxEffectsSchema.optional(),
|
|
1011
|
-
// `PxElementAnimation` (not just `PxAnimationDefinition`) — accepts
|
|
1012
|
-
// string ref / array of refs / inline definition / mixed array; mirrors
|
|
1013
|
-
// `animator.animateById` map values and what `processNode` resolves at runtime.
|
|
1014
|
-
animate: PxElementAnimationSchema.optional(),
|
|
1015
|
-
style: px.union([px.string(), px.record(px.union([px.string(), px.number()]))]).optional()
|
|
1016
|
-
}, PxAttrValueSchema);
|
|
1017
|
-
var PxNodeSchema = px.openObject(__spreadProps2(__spreadValues2({}, PxNodeBase._shape), {
|
|
1018
|
-
children: px.lazy(() => px.array(PxNodeSchema), []).optional()
|
|
1019
|
-
}), PxAttrValueSchema);
|
|
1020
|
-
var PxSvgNodeExtra = px.object({
|
|
1021
|
-
width: px.number().optional(),
|
|
1022
|
-
height: px.number().optional(),
|
|
1023
|
-
viewBox: px.string().optional(),
|
|
1024
|
-
animator: PxAnimatorConfigSchema.optional()
|
|
1025
|
-
});
|
|
1026
|
-
var PxAnimatedSvgDocumentSchema = px.openObject(__spreadProps2(__spreadValues2(__spreadValues2({}, PxNodeBase._shape), PxSvgNodeExtra._shape), {
|
|
1027
|
-
type: px.literal("svg"),
|
|
1028
|
-
// override string → literal to require 'svg'
|
|
1029
|
-
children: px.array(PxNodeSchema).optional()
|
|
1030
|
-
}), PxAttrValueSchema);
|
|
1031
|
-
var PxBezierPathSchema = implementsInterface()(px.object({
|
|
1032
|
-
v: px.array(px.array(px.number())),
|
|
1033
|
-
i: px.array(px.array(px.number())).optional(),
|
|
1034
|
-
o: px.array(px.array(px.number())).optional(),
|
|
1035
|
-
c: px.boolean().optional()
|
|
1036
|
-
}));
|
|
1037
|
-
function isPxElementFileFormatDeep(fileJson) {
|
|
1038
|
-
const valid = PxAnimatedSvgDocumentSchema.isValid(fileJson);
|
|
1039
|
-
return { valid, errors: valid ? [] : ["Document failed schema validation"] };
|
|
1040
|
-
}
|
|
1041
|
-
function bezierToSvgPath(path, forceCurves = false) {
|
|
1042
|
-
var _a, _b, _c, _d;
|
|
1043
|
-
const v = path.v;
|
|
1044
|
-
const i = path.i;
|
|
1045
|
-
const o = path.o;
|
|
1046
|
-
const c = path.c;
|
|
1047
|
-
if (!v.length) return "";
|
|
1048
|
-
const d = [];
|
|
1049
|
-
const len = v.length;
|
|
1050
|
-
d.push("M" + v[0][0] + "," + v[0][1]);
|
|
1051
|
-
for (let idx = 1; idx < len; idx++) {
|
|
1052
|
-
const prevV = v[idx - 1];
|
|
1053
|
-
const prevO = (_a = o == null ? void 0 : o[idx - 1]) != null ? _a : prevV;
|
|
1054
|
-
const currI = (_b = i == null ? void 0 : i[idx]) != null ? _b : v[idx];
|
|
1055
|
-
const currV = v[idx];
|
|
1056
|
-
const isLine = !forceCurves && (prevO[0] === prevV[0] && prevO[1] === prevV[1]) && (currI[0] === currV[0] && currI[1] === currV[1]);
|
|
1057
|
-
if (isLine) {
|
|
1058
|
-
d.push("L" + currV[0] + "," + currV[1]);
|
|
1059
|
-
} else {
|
|
1060
|
-
d.push("C" + prevO[0] + "," + prevO[1] + "," + currI[0] + "," + currI[1] + "," + currV[0] + "," + currV[1]);
|
|
1061
|
-
}
|
|
1062
|
-
}
|
|
1063
|
-
if (c && len > 0) {
|
|
1064
|
-
const lastV = v[len - 1];
|
|
1065
|
-
const lastO = (_c = o == null ? void 0 : o[len - 1]) != null ? _c : lastV;
|
|
1066
|
-
const firstI = (_d = i == null ? void 0 : i[0]) != null ? _d : v[0];
|
|
1067
|
-
const firstV = v[0];
|
|
1068
|
-
const isLine = !forceCurves && (lastO[0] === lastV[0] && lastO[1] === lastV[1]) && (firstI[0] === firstV[0] && firstI[1] === firstV[1]);
|
|
1069
|
-
if (!isLine) {
|
|
1070
|
-
d.push("C" + lastO[0] + "," + lastO[1] + "," + firstI[0] + "," + firstI[1] + "," + firstV[0] + "," + firstV[1]);
|
|
1071
|
-
}
|
|
1072
|
-
d.push("z");
|
|
1073
|
-
}
|
|
1074
|
-
return d.join("");
|
|
1075
|
-
}
|
|
1076
|
-
function interpolateNum(a, b, t) {
|
|
1077
|
-
return a + (b - a) * t;
|
|
1078
|
-
}
|
|
1079
|
-
function interpolateVec(a, b, t) {
|
|
1080
|
-
const res = [];
|
|
1081
|
-
const count = Math.max(a.length, b.length);
|
|
1082
|
-
for (let i = 0; i < count; i++) {
|
|
1083
|
-
res[i] = interpolateNum(a[i] || 0, b[i] || 0, t);
|
|
1084
|
-
}
|
|
1085
|
-
return res;
|
|
1086
|
-
}
|
|
1087
|
-
function interpolateColor(a, b, t) {
|
|
1088
|
-
return [
|
|
1089
|
-
interpolateNum(a[0] || 0, b[0] || 0, t),
|
|
1090
|
-
interpolateNum(a[1] || 0, b[1] || 0, t),
|
|
1091
|
-
interpolateNum(a[2] || 0, b[2] || 0, t),
|
|
1092
|
-
interpolateNum(a[3] === void 0 ? 1 : a[3], b[3] === void 0 ? 1 : b[3], t)
|
|
1093
|
-
];
|
|
1094
|
-
}
|
|
1095
|
-
function interpolateBeziers(paths1, paths2, progress) {
|
|
1096
|
-
const count = Math.max(paths1.length, paths2.length);
|
|
1097
|
-
const res = [];
|
|
1098
|
-
for (let i = 0; i < count; i++) {
|
|
1099
|
-
res.push(interpolateBezier(paths1[i], paths2[i], progress));
|
|
1100
|
-
}
|
|
1101
|
-
return res;
|
|
1102
|
-
}
|
|
1103
|
-
function interpolateBezier(path1, path2, progress) {
|
|
1104
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _i;
|
|
1105
|
-
if (!path1 || !path2) return path1 || path2 || { v: [] };
|
|
1106
|
-
const t = Math.min(Math.max(progress, 0), 1);
|
|
1107
|
-
const len = Math.min(path1.v.length, path2.v.length);
|
|
1108
|
-
const v = [];
|
|
1109
|
-
const i = [];
|
|
1110
|
-
const o = [];
|
|
1111
|
-
for (let idx = 0; idx < len; idx++) {
|
|
1112
|
-
const v1 = path1.v[idx];
|
|
1113
|
-
const v2 = path2.v[idx];
|
|
1114
|
-
v.push(interpolateVec(v1, v2, t));
|
|
1115
|
-
const i1 = (_b = (_a = path1.i) == null ? void 0 : _a[idx]) != null ? _b : v1;
|
|
1116
|
-
const i2 = (_d = (_c = path2.i) == null ? void 0 : _c[idx]) != null ? _d : v2;
|
|
1117
|
-
i.push(interpolateVec(i1, i2, t));
|
|
1118
|
-
const o1 = (_f = (_e = path1.o) == null ? void 0 : _e[idx]) != null ? _f : v1;
|
|
1119
|
-
const o2 = (_h = (_g = path2.o) == null ? void 0 : _g[idx]) != null ? _h : v2;
|
|
1120
|
-
o.push(interpolateVec(o1, o2, t));
|
|
1121
|
-
}
|
|
1122
|
-
return { v, i: i.length ? i : void 0, o: o.length ? o : void 0, c: (_i = path1.c) != null ? _i : path2.c };
|
|
1123
|
-
}
|
|
1124
|
-
function remap(value, inMin, inMax, outMin, outMax) {
|
|
1125
|
-
if (inMax === inMin) return outMin;
|
|
1126
|
-
const t = (value - inMin) / (inMax - inMin);
|
|
1127
|
-
return outMin + t * (outMax - outMin);
|
|
1128
|
-
}
|
|
1129
|
-
function solveCubicBezierX(p1x, p2x, x) {
|
|
1130
|
-
if (x <= 0) return 0;
|
|
1131
|
-
if (x >= 1) return 1;
|
|
1132
|
-
const cx = 3 * p1x;
|
|
1133
|
-
const bx = 3 * (p2x - p1x) - cx;
|
|
1134
|
-
const ax = 1 - cx - bx;
|
|
1135
|
-
function sampleX(t) {
|
|
1136
|
-
return ((ax * t + bx) * t + cx) * t;
|
|
1137
|
-
}
|
|
1138
|
-
function sampleDX(t) {
|
|
1139
|
-
return (3 * ax * t + 2 * bx) * t + cx;
|
|
1140
|
-
}
|
|
1141
|
-
let t2 = x;
|
|
1142
|
-
let t0 = 0;
|
|
1143
|
-
let t1 = 1;
|
|
1144
|
-
for (let i = 0; i < 8; i++) {
|
|
1145
|
-
const x2 = sampleX(t2) - x;
|
|
1146
|
-
if (Math.abs(x2) < 1e-6) return t2;
|
|
1147
|
-
const d2 = sampleDX(t2);
|
|
1148
|
-
if (Math.abs(d2) < 1e-6) break;
|
|
1149
|
-
t2 -= x2 / d2;
|
|
1150
|
-
}
|
|
1151
|
-
t2 = x;
|
|
1152
|
-
while (t0 < t1) {
|
|
1153
|
-
const x2 = sampleX(t2);
|
|
1154
|
-
if (Math.abs(x2 - x) < 1e-6) return t2;
|
|
1155
|
-
if (x > x2) t0 = t2;
|
|
1156
|
-
else t1 = t2;
|
|
1157
|
-
t2 = (t1 + t0) / 2;
|
|
1158
|
-
}
|
|
1159
|
-
return t2;
|
|
1160
|
-
}
|
|
1161
|
-
function cubicBezier(easing) {
|
|
1162
|
-
const [p1x, p1y, p2x, p2y] = easing;
|
|
1163
|
-
const cy = 3 * p1y;
|
|
1164
|
-
const by = 3 * (p2y - p1y) - cy;
|
|
1165
|
-
const ay = 1 - cy - by;
|
|
1166
|
-
function sampleCurveY(t) {
|
|
1167
|
-
return ((ay * t + by) * t + cy) * t;
|
|
1168
|
-
}
|
|
1169
|
-
return function(x) {
|
|
1170
|
-
return sampleCurveY(solveCubicBezierX(p1x, p2x, x));
|
|
1171
|
-
};
|
|
1172
|
-
}
|
|
1173
|
-
function lerp2(a, b, t) {
|
|
1174
|
-
return [a[0] + (b[0] - a[0]) * t, a[1] + (b[1] - a[1]) * t];
|
|
1175
|
-
}
|
|
1176
|
-
function subdivideCubicBezier(p0, p1, p2, p3, t) {
|
|
1177
|
-
const q0 = lerp2(p0, p1, t);
|
|
1178
|
-
const q1 = lerp2(p1, p2, t);
|
|
1179
|
-
const q2 = lerp2(p2, p3, t);
|
|
1180
|
-
const r0 = lerp2(q0, q1, t);
|
|
1181
|
-
const r1 = lerp2(q1, q2, t);
|
|
1182
|
-
const s = lerp2(r0, r1, t);
|
|
1183
|
-
return {
|
|
1184
|
-
left: [p0, q0, r0, s],
|
|
1185
|
-
right: [s, r1, q2, p3]
|
|
1186
|
-
};
|
|
1187
|
-
}
|
|
1188
|
-
function splitEasing(easing, xFraction) {
|
|
1189
|
-
if (!easing) return { left: void 0, right: void 0 };
|
|
1190
|
-
if (xFraction <= 0) return { left: void 0, right: easing };
|
|
1191
|
-
if (xFraction >= 1) return { left: easing, right: void 0 };
|
|
1192
|
-
const [x1, y1, x2, y2] = easing;
|
|
1193
|
-
const t = solveCubicBezierX(x1, x2, xFraction);
|
|
1194
|
-
const p0 = [0, 0];
|
|
1195
|
-
const p1 = [x1, y1];
|
|
1196
|
-
const p2 = [x2, y2];
|
|
1197
|
-
const p3 = [1, 1];
|
|
1198
|
-
const { left, right } = subdivideCubicBezier(p0, p1, p2, p3, t);
|
|
1199
|
-
const sx = left[3][0];
|
|
1200
|
-
const sy = left[3][1];
|
|
1201
|
-
let leftEasing;
|
|
1202
|
-
if (sx > 1e-9 && Math.abs(sy) > 1e-9) {
|
|
1203
|
-
leftEasing = [
|
|
1204
|
-
left[1][0] / sx,
|
|
1205
|
-
left[1][1] / sy,
|
|
1206
|
-
left[2][0] / sx,
|
|
1207
|
-
left[2][1] / sy
|
|
1208
|
-
];
|
|
1209
|
-
}
|
|
1210
|
-
let rightEasing;
|
|
1211
|
-
const rx = 1 - sx;
|
|
1212
|
-
const ry = 1 - sy;
|
|
1213
|
-
if (rx > 1e-9 && Math.abs(ry) > 1e-9) {
|
|
1214
|
-
rightEasing = [
|
|
1215
|
-
(right[1][0] - sx) / rx,
|
|
1216
|
-
(right[1][1] - sy) / ry,
|
|
1217
|
-
(right[2][0] - sx) / rx,
|
|
1218
|
-
(right[2][1] - sy) / ry
|
|
1219
|
-
];
|
|
1220
|
-
}
|
|
1221
|
-
return { left: leftEasing, right: rightEasing };
|
|
1222
|
-
}
|
|
1223
|
-
function reverseEasing(easing) {
|
|
1224
|
-
if (!easing) return void 0;
|
|
1225
|
-
return [1 - easing[2], 1 - easing[3], 1 - easing[0], 1 - easing[1]];
|
|
1226
|
-
}
|
|
1227
|
-
function toRGBA(color) {
|
|
1228
|
-
const r = Math.round(color[0] * 255);
|
|
1229
|
-
const g = Math.round(color[1] * 255);
|
|
1230
|
-
const b = Math.round(color[2] * 255);
|
|
1231
|
-
return color.length === 4 ? "rgba(" + r + "," + g + "," + b + "," + color[3] + ")" : "rgb(" + r + "," + g + "," + b + ")";
|
|
1232
|
-
}
|
|
1233
|
-
function parseRgba(s) {
|
|
1234
|
-
var _a;
|
|
1235
|
-
const inner = (_a = s.match(/rgba?\((.*)\)/)) == null ? void 0 : _a[1];
|
|
1236
|
-
if (!inner) throw new Error("Invalid rgb/rgba format");
|
|
1237
|
-
const parts = inner.split(",").map((v) => +v.trim());
|
|
1238
|
-
return [parts[0] / 255, parts[1] / 255, parts[2] / 255, ...parts[3] !== void 0 ? [parts[3]] : []];
|
|
1239
|
-
}
|
|
1240
|
-
function parseHex(s) {
|
|
1241
|
-
const hex = s.slice(1);
|
|
1242
|
-
const isShort = hex.length <= 4;
|
|
1243
|
-
const r = isShort ? hex[0] + hex[0] : hex.slice(0, 2);
|
|
1244
|
-
const g = isShort ? hex[1] + hex[1] : hex.slice(2, 4);
|
|
1245
|
-
const b = isShort ? hex[2] + hex[2] : hex.slice(4, 6);
|
|
1246
|
-
const a = hex.length === 4 ? hex[3] + hex[3] : hex.length === 8 ? hex.slice(6, 8) : null;
|
|
1247
|
-
const result = [
|
|
1248
|
-
parseInt(r, 16) / 255,
|
|
1249
|
-
parseInt(g, 16) / 255,
|
|
1250
|
-
parseInt(b, 16) / 255
|
|
1251
|
-
];
|
|
1252
|
-
if (a !== null) {
|
|
1253
|
-
result.push(parseInt(a, 16) / 255);
|
|
1254
|
-
}
|
|
1255
|
-
return result;
|
|
1256
|
-
}
|
|
1257
|
-
function parseColor(s) {
|
|
1258
|
-
if (!s) return void 0;
|
|
1259
|
-
if (Array.isArray(s)) return s;
|
|
1260
|
-
if (typeof s !== "string") return void 0;
|
|
1261
|
-
if (s.startsWith("#")) {
|
|
1262
|
-
return parseHex(s);
|
|
1263
|
-
} else if (s.startsWith("rgb")) {
|
|
1264
|
-
return parseRgba(s);
|
|
1265
|
-
} else {
|
|
1266
|
-
console.warn("Unsupported color format: " + s);
|
|
1267
|
-
}
|
|
1268
|
-
return void 0;
|
|
1269
|
-
}
|
|
1270
|
-
var COLOUR_ATTR_NAMES = /* @__PURE__ */ new Set(["color", "fill", "flood-color", "lighting-color", "stop-color", "stroke"]);
|
|
1271
|
-
var TRANSFORM_FN_NAMES = /* @__PURE__ */ new Set(["translate", "rotate", "scale", "skew"]);
|
|
1272
|
-
var PCT_BASED_ATTR_NAMES = /* @__PURE__ */ new Set(["offset-distance", "offsetDistance"]);
|
|
1273
|
-
function composeTransformParts(parts, opts) {
|
|
1274
|
-
var _a;
|
|
1275
|
-
if (!parts) return "";
|
|
1276
|
-
const withUnits = (_a = opts == null ? void 0 : opts.withUnits) != null ? _a : true;
|
|
1277
|
-
const segs = [];
|
|
1278
|
-
const t = parts.translate;
|
|
1279
|
-
const o = parts.origin;
|
|
1280
|
-
const r = parts.rotate;
|
|
1281
|
-
const k = parts.skew;
|
|
1282
|
-
const s = parts.scale;
|
|
1283
|
-
const tu = withUnits ? "px" : "";
|
|
1284
|
-
const ru = withUnits ? "deg" : "";
|
|
1285
|
-
if (t) segs.push("translate(" + t[0] + tu + "," + t[1] + tu + ")");
|
|
1286
|
-
if (o) segs.push("translate(" + o[0] + tu + "," + o[1] + tu + ")");
|
|
1287
|
-
if (r !== void 0 && r !== null) segs.push("rotate(" + r + ru + ")");
|
|
1288
|
-
if (k !== void 0 && k !== null) segs.push("skewX(" + k + ru + ")");
|
|
1289
|
-
if (s) segs.push("scale(" + s[0] + "," + s[1] + ")");
|
|
1290
|
-
if (o) segs.push("translate(" + -o[0] + tu + "," + -o[1] + tu + ")");
|
|
1291
|
-
return segs.join("");
|
|
1292
|
-
}
|
|
1293
|
-
var STYLE_ATTR_NAMES = /* @__PURE__ */ new Set(["offset-distance", "offsetDistance"]);
|
|
1294
|
-
var DEFAULT_DURATION_MS = 1e3;
|
|
1295
|
-
function kebabToCamelCaseWord(kebab) {
|
|
1296
|
-
return kebab.includes("-") ? kebab.replace(/-([a-z])/g, (_, letter) => letter.toUpperCase()) : kebab;
|
|
1297
|
-
}
|
|
1298
|
-
function isCamelCaseWord(word) {
|
|
1299
|
-
return !word.includes("-") && /[a-z][A-Z]/.test(word);
|
|
1300
|
-
}
|
|
1301
|
-
var SVG_CAMEL_CASE_ATTRS = /* @__PURE__ */ new Set([
|
|
1302
|
-
// Transform/positioning
|
|
1303
|
-
"viewBox",
|
|
1304
|
-
"preserveAspectRatio",
|
|
1305
|
-
// Gradient
|
|
1306
|
-
"gradientUnits",
|
|
1307
|
-
"gradientTransform",
|
|
1308
|
-
"spreadMethod",
|
|
1309
|
-
// Pattern
|
|
1310
|
-
"patternUnits",
|
|
1311
|
-
"patternContentUnits",
|
|
1312
|
-
"patternTransform",
|
|
1313
|
-
// Clipping/masking
|
|
1314
|
-
"clipPathUnits",
|
|
1315
|
-
"maskUnits",
|
|
1316
|
-
"maskContentUnits",
|
|
1317
|
-
// Marker (SVG spec keeps these camelCase, like viewBox)
|
|
1318
|
-
"markerUnits",
|
|
1319
|
-
"markerWidth",
|
|
1320
|
-
"markerHeight",
|
|
1321
|
-
"refX",
|
|
1322
|
-
"refY",
|
|
1323
|
-
// Text
|
|
1324
|
-
"textLength",
|
|
1325
|
-
"lengthAdjust",
|
|
1326
|
-
"startOffset",
|
|
1327
|
-
// Filter
|
|
1328
|
-
"filterUnits",
|
|
1329
|
-
"primitiveUnits",
|
|
1330
|
-
"tableValues",
|
|
1331
|
-
// feFuncR/G/B/A transfer table (type="table")
|
|
1332
|
-
"stdDeviation",
|
|
1333
|
-
"baseFrequency",
|
|
1334
|
-
"numOctaves",
|
|
1335
|
-
"surfaceScale",
|
|
1336
|
-
"diffuseConstant",
|
|
1337
|
-
"specularConstant",
|
|
1338
|
-
"specularExponent",
|
|
1339
|
-
"kernelMatrix",
|
|
1340
|
-
"kernelUnitLength",
|
|
1341
|
-
"edgeMode",
|
|
1342
|
-
"preserveAlpha",
|
|
1343
|
-
"targetX",
|
|
1344
|
-
"targetY"
|
|
1345
|
-
// // Animation
|
|
1346
|
-
// 'attributeName',
|
|
1347
|
-
// 'attributeType',
|
|
1348
|
-
// 'calcMode',
|
|
1349
|
-
// 'keyTimes',
|
|
1350
|
-
// 'keySplines',
|
|
1351
|
-
// 'repeatCount',
|
|
1352
|
-
// 'repeatDur'
|
|
1353
|
-
]);
|
|
1354
|
-
function camelCaseToKebabWordIfNeeded(camel) {
|
|
1355
|
-
return SVG_CAMEL_CASE_ATTRS.has(camel) ? camel : camel.replace(/([a-z0-9])([A-Z])/g, "$1-$2").toLowerCase();
|
|
1356
|
-
}
|
|
1357
|
-
function clamp(value, min, max) {
|
|
1358
|
-
return Math.max(min, Math.min(value, max));
|
|
1359
|
-
}
|
|
1360
|
-
function bezier2D_pointAt(P0, P1, P2, P3, t) {
|
|
1361
|
-
if (t <= 0) return [P0[0], P0[1]];
|
|
1362
|
-
if (t >= 1) return [P3[0], P3[1]];
|
|
1363
|
-
const u = 1 - t;
|
|
1364
|
-
const u2 = u * u;
|
|
1365
|
-
const u3 = u2 * u;
|
|
1366
|
-
const t2 = t * t;
|
|
1367
|
-
const t3 = t2 * t;
|
|
1368
|
-
const w0 = u3;
|
|
1369
|
-
const w1 = 3 * t * u2;
|
|
1370
|
-
const w2 = 3 * t2 * u;
|
|
1371
|
-
const w3 = t3;
|
|
1372
|
-
return [
|
|
1373
|
-
w0 * P0[0] + w1 * P1[0] + w2 * P2[0] + w3 * P3[0],
|
|
1374
|
-
w0 * P0[1] + w1 * P1[1] + w2 * P2[1] + w3 * P3[1]
|
|
1375
|
-
];
|
|
1376
|
-
}
|
|
1377
|
-
var BEZIER_T_NUDGE = 1e-4;
|
|
1378
|
-
function bezier2D_derivativeAt(P0, P1, P2, P3, t) {
|
|
1379
|
-
const result = _bezier2D_derivativeAtRaw(P0, P1, P2, P3, t);
|
|
1380
|
-
if (result[0] === 0 && result[1] === 0) {
|
|
1381
|
-
const nudgedT = t < 0.5 ? t + BEZIER_T_NUDGE : t - BEZIER_T_NUDGE;
|
|
1382
|
-
return _bezier2D_derivativeAtRaw(P0, P1, P2, P3, nudgedT);
|
|
1383
|
-
}
|
|
1384
|
-
return result;
|
|
1385
|
-
}
|
|
1386
|
-
function _bezier2D_derivativeAtRaw(P0, P1, P2, P3, t) {
|
|
1387
|
-
const u = 1 - t;
|
|
1388
|
-
const a = 3 * u * u;
|
|
1389
|
-
const b = 6 * t * u;
|
|
1390
|
-
const c = 3 * t * t;
|
|
1391
|
-
return [
|
|
1392
|
-
a * (P1[0] - P0[0]) + b * (P2[0] - P1[0]) + c * (P3[0] - P2[0]),
|
|
1393
|
-
a * (P1[1] - P0[1]) + b * (P2[1] - P1[1]) + c * (P3[1] - P2[1])
|
|
1394
|
-
];
|
|
1395
|
-
}
|
|
1396
|
-
function bezier2D_arcLengthLUT(P0, P1, P2, P3, steps = 100) {
|
|
1397
|
-
const n = steps + 1;
|
|
1398
|
-
const ts = new Float64Array(n);
|
|
1399
|
-
const ds = new Float64Array(n);
|
|
1400
|
-
let prev = bezier2D_pointAt(P0, P1, P2, P3, 0);
|
|
1401
|
-
ts[0] = 0;
|
|
1402
|
-
ds[0] = 0;
|
|
1403
|
-
let cum = 0;
|
|
1404
|
-
for (let i = 1; i < n; i++) {
|
|
1405
|
-
const t = i / steps;
|
|
1406
|
-
const cur = bezier2D_pointAt(P0, P1, P2, P3, t);
|
|
1407
|
-
const dx = cur[0] - prev[0];
|
|
1408
|
-
const dy = cur[1] - prev[1];
|
|
1409
|
-
cum += Math.sqrt(dx * dx + dy * dy);
|
|
1410
|
-
ts[i] = t;
|
|
1411
|
-
ds[i] = cum;
|
|
1412
|
-
prev = cur;
|
|
1413
|
-
}
|
|
1414
|
-
return { ts, ds };
|
|
1415
|
-
}
|
|
1416
|
-
function bezier2D_tForDistance(lut, distance) {
|
|
1417
|
-
const { ts, ds } = lut;
|
|
1418
|
-
const last = ds.length - 1;
|
|
1419
|
-
if (distance <= 0) return ts[0];
|
|
1420
|
-
if (distance >= ds[last]) return ts[last];
|
|
1421
|
-
let lo = 1;
|
|
1422
|
-
let hi = last;
|
|
1423
|
-
while (lo < hi) {
|
|
1424
|
-
const mid = lo + hi >>> 1;
|
|
1425
|
-
if (ds[mid] < distance) lo = mid + 1;
|
|
1426
|
-
else hi = mid;
|
|
1427
|
-
}
|
|
1428
|
-
const dPrev = ds[hi - 1];
|
|
1429
|
-
const dCur = ds[hi];
|
|
1430
|
-
const span = dCur - dPrev;
|
|
1431
|
-
const frac = span > 0 ? (distance - dPrev) / span : 0;
|
|
1432
|
-
return ts[hi - 1] + frac * (ts[hi] - ts[hi - 1]);
|
|
1433
|
-
}
|
|
1434
|
-
function bezier2D_arcAtT(lut, t) {
|
|
1435
|
-
const { ts, ds } = lut;
|
|
1436
|
-
const last = ts.length - 1;
|
|
1437
|
-
if (t <= ts[0]) return ds[0];
|
|
1438
|
-
if (t >= ts[last]) return ds[last];
|
|
1439
|
-
let lo = 1, hi = last;
|
|
1440
|
-
while (lo < hi) {
|
|
1441
|
-
const mid = lo + hi >>> 1;
|
|
1442
|
-
if (ts[mid] < t) lo = mid + 1;
|
|
1443
|
-
else hi = mid;
|
|
1444
|
-
}
|
|
1445
|
-
const tPrev = ts[hi - 1];
|
|
1446
|
-
const span = ts[hi] - tPrev;
|
|
1447
|
-
const frac = span > 0 ? (t - tPrev) / span : 0;
|
|
1448
|
-
return ds[hi - 1] + frac * (ds[hi] - ds[hi - 1]);
|
|
1356
|
+
PxPropertyAnimationSchema
|
|
1357
|
+
]);
|
|
1358
|
+
var PxAnimatableVec2Schema = px.union([
|
|
1359
|
+
px.tuple([px.number(), px.number()]),
|
|
1360
|
+
px.object({ value: px.tuple([px.number(), px.number()]) }),
|
|
1361
|
+
PxPropertyAnimationSchema
|
|
1362
|
+
]);
|
|
1363
|
+
var PxAnimatableStringSchema = px.union([
|
|
1364
|
+
px.string(),
|
|
1365
|
+
px.object({ value: px.string() }),
|
|
1366
|
+
PxPropertyAnimationSchema
|
|
1367
|
+
]);
|
|
1368
|
+
var PxTransformByEffectSchema = implementsInterface()(px.object({
|
|
1369
|
+
translate: PxAnimatableVec2Schema.optional(),
|
|
1370
|
+
rotate: PxAnimatableNumberSchema.optional(),
|
|
1371
|
+
scale: PxAnimatableVec2Schema.optional(),
|
|
1372
|
+
skew: PxAnimatableNumberSchema.optional(),
|
|
1373
|
+
origin: PxAnimatableVec2Schema.optional()
|
|
1374
|
+
}));
|
|
1375
|
+
var PxRepeaterEffectSchema = implementsInterface()(px.object({
|
|
1376
|
+
// STATIC config, not a channel (V2/SCHEMA-DESIGN R5): the copy COUNT is read
|
|
1377
|
+
// once at expansion time and never sampled — plain number, no `keyframes`.
|
|
1378
|
+
copies: px.number().optional(),
|
|
1379
|
+
translate: PxAnimatableVec2Schema.optional(),
|
|
1380
|
+
rotate: PxAnimatableNumberSchema.optional(),
|
|
1381
|
+
skew: PxAnimatableNumberSchema.optional(),
|
|
1382
|
+
scale: PxAnimatableVec2Schema.optional(),
|
|
1383
|
+
origin: PxAnimatableVec2Schema.optional()
|
|
1384
|
+
}));
|
|
1385
|
+
var PxMaskedByEffectSchema = implementsInterface()(px.object({
|
|
1386
|
+
sourceId: px.string().optional(),
|
|
1387
|
+
maskType: px.enum([PxMaskType.luminance, PxMaskType.alpha]).optional(),
|
|
1388
|
+
maskUnits: px.enum([PxUnits.userSpaceOnUse, PxUnits.objectBoundingBox]).optional(),
|
|
1389
|
+
maskContentUnits: px.enum([PxUnits.userSpaceOnUse, PxUnits.objectBoundingBox]).optional(),
|
|
1390
|
+
x: px.number().optional(),
|
|
1391
|
+
y: px.number().optional(),
|
|
1392
|
+
width: px.number().optional(),
|
|
1393
|
+
height: px.number().optional()
|
|
1394
|
+
}));
|
|
1395
|
+
var PxClipPathEffectSchema = implementsInterface()(px.object({
|
|
1396
|
+
d: PxAnimatableStringSchema.optional(),
|
|
1397
|
+
animate: PxPropertyAnimationSchema.optional()
|
|
1398
|
+
}));
|
|
1399
|
+
var PxTrimPathEffectSchema = implementsInterface()(px.object({
|
|
1400
|
+
offset: PxAnimatableNumberSchema.optional(),
|
|
1401
|
+
range: PxAnimatableVec2Schema.optional(),
|
|
1402
|
+
subPaths: px.enum([PxTrimSubPaths.separate, PxTrimSubPaths.combined]).optional()
|
|
1403
|
+
}));
|
|
1404
|
+
var PxRetimeEffectSchema = implementsInterface()(px.object({
|
|
1405
|
+
sourceId: px.string().optional(),
|
|
1406
|
+
start: px.number().optional(),
|
|
1407
|
+
stretch: px.number().optional(),
|
|
1408
|
+
timeCrop: px.tuple([px.number(), px.number()]).optional()
|
|
1409
|
+
}));
|
|
1410
|
+
var PxCloneEffectSchema = implementsInterface()(px.object({
|
|
1411
|
+
// Contextual kind — the `type` convention, see `PxNodeBase.type`.
|
|
1412
|
+
type: px.enum([PxCloneType.content]).optional(),
|
|
1413
|
+
sourceId: px.string().optional(),
|
|
1414
|
+
retime: PxRetimeEffectSchema.optional()
|
|
1415
|
+
}));
|
|
1416
|
+
var PxGradientStopSchema = implementsInterface()(px.object({
|
|
1417
|
+
offset: px.number(),
|
|
1418
|
+
color: px.string()
|
|
1419
|
+
}));
|
|
1420
|
+
var PxAnimatableGradientStopsSchema = px.union([
|
|
1421
|
+
px.array(PxGradientStopSchema),
|
|
1422
|
+
px.object({ value: px.array(PxGradientStopSchema) }),
|
|
1423
|
+
PxPropertyAnimationSchema
|
|
1424
|
+
]);
|
|
1425
|
+
var PxFillGradientEffectSchema = implementsInterface()(px.object({
|
|
1426
|
+
// Contextual kind — the `type` convention, see `PxNodeBase.type`.
|
|
1427
|
+
type: px.enum([PxGradientType.linear, PxGradientType.radial]),
|
|
1428
|
+
p1: PxAnimatableVec2Schema.optional(),
|
|
1429
|
+
p2: PxAnimatableVec2Schema.optional(),
|
|
1430
|
+
c: PxAnimatableVec2Schema.optional(),
|
|
1431
|
+
r: PxAnimatableNumberSchema.optional(),
|
|
1432
|
+
fp: PxAnimatableVec2Schema.optional(),
|
|
1433
|
+
stops: PxAnimatableGradientStopsSchema.optional(),
|
|
1434
|
+
gradientUnits: px.enum([PxGradientUnits.userSpaceOnUse, PxGradientUnits.objectBoundingBox]).optional(),
|
|
1435
|
+
spreadMethod: px.enum([PxGradientSpreadMethod.pad, PxGradientSpreadMethod.reflect, PxGradientSpreadMethod.repeat]).optional(),
|
|
1436
|
+
gradientTransform: px.string().optional()
|
|
1437
|
+
}));
|
|
1438
|
+
var PxStrokeGradientEffectSchema = PxFillGradientEffectSchema;
|
|
1439
|
+
var PxTextPathEffectSchema = implementsInterface()(px.object({
|
|
1440
|
+
path: px.string(),
|
|
1441
|
+
pathOverflow: px.enum([PxPathOverflow.clip, PxPathOverflow.extend]).optional(),
|
|
1442
|
+
lengthAdjust: px.enum([PxLengthAdjust.spacing, PxLengthAdjust.spacingAndGlyphs]).optional(),
|
|
1443
|
+
method: px.enum([PxTextPathMethod.align, PxTextPathMethod.stretch]).optional(),
|
|
1444
|
+
spacing: px.enum([PxTextPathSpacing.auto, PxTextPathSpacing.exact]).optional(),
|
|
1445
|
+
startOffset: PxAnimatableNumberSchema.optional(),
|
|
1446
|
+
textLength: PxAnimatableNumberSchema.optional()
|
|
1447
|
+
}));
|
|
1448
|
+
var PxTextEffectSchema = implementsInterface()(px.object({
|
|
1449
|
+
useGlyphs: px.boolean().optional()
|
|
1450
|
+
}));
|
|
1451
|
+
var PxEffectsSchema = implementsInterface()(px.object({
|
|
1452
|
+
transformBy: PxTransformByEffectSchema.optional(),
|
|
1453
|
+
repeater: PxRepeaterEffectSchema.optional(),
|
|
1454
|
+
maskedBy: PxMaskedByEffectSchema.optional(),
|
|
1455
|
+
clipPath: PxClipPathEffectSchema.optional(),
|
|
1456
|
+
trimPath: PxTrimPathEffectSchema.optional(),
|
|
1457
|
+
clone: PxCloneEffectSchema.optional(),
|
|
1458
|
+
fillGradient: PxFillGradientEffectSchema.optional(),
|
|
1459
|
+
strokeGradient: PxStrokeGradientEffectSchema.optional(),
|
|
1460
|
+
textPath: PxTextPathEffectSchema.optional(),
|
|
1461
|
+
text: PxTextEffectSchema.optional()
|
|
1462
|
+
}));
|
|
1463
|
+
function validateNodeEffects(root, opts) {
|
|
1464
|
+
const warnings = [];
|
|
1465
|
+
const walk = (node, path) => {
|
|
1466
|
+
if (node && node.effects) {
|
|
1467
|
+
const ctx = { errors: [], warnings: [], strict: !!(opts == null ? void 0 : opts.strict) };
|
|
1468
|
+
const ok = PxEffectsSchema.isValid(node.effects, ctx, [path + ".effects"]);
|
|
1469
|
+
if (!ok) {
|
|
1470
|
+
for (const err of ctx.errors) warnings.push(err);
|
|
1471
|
+
}
|
|
1472
|
+
}
|
|
1473
|
+
if (node && Array.isArray(node.children)) {
|
|
1474
|
+
node.children.forEach((c, i) => walk(c, path + ".children[" + i + "]"));
|
|
1475
|
+
}
|
|
1476
|
+
};
|
|
1477
|
+
walk(root, "root");
|
|
1478
|
+
return warnings;
|
|
1449
1479
|
}
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1480
|
+
var PxNodeBase = px.openObject({
|
|
1481
|
+
// CONVENTION (SCHEMA-DESIGN R1 / issues N4): `type` is the ONE word for "what
|
|
1482
|
+
// kind of thing is this", discriminated by its CARRIER — here the node TAG
|
|
1483
|
+
// (`rect`, `text`), and inside a sub-object that object's kind (`clone.type`,
|
|
1484
|
+
// `fillGradient.type`, editor `preset.type`). Each sits in its own object, so
|
|
1485
|
+
// the carrier disambiguates completely; synonyms (`cloneKind`, `presetShape`)
|
|
1486
|
+
// would add words that all mean "type" and still need the carrier to read.
|
|
1487
|
+
// Guarding a `type` SLOT against a wrong VALUE is the job of strict enums
|
|
1488
|
+
// (issues V3), never of distinct key names.
|
|
1489
|
+
type: px.string(),
|
|
1490
|
+
id: px.string().optional(),
|
|
1491
|
+
meta: px.any().optional(),
|
|
1492
|
+
// Player-effects bucket emitted by the Editor's lightweight design format.
|
|
1493
|
+
// Consumed and removed by `applyPlayerEffects` before any other normalisation
|
|
1494
|
+
// (see `createAnimatorImpl`), so downstream code never sees it.
|
|
1495
|
+
effects: PxEffectsSchema.optional(),
|
|
1496
|
+
// `PxElementAnimation` (not just `PxAnimationDefinition`) — accepts
|
|
1497
|
+
// string ref / array of refs / inline definition / mixed array; mirrors
|
|
1498
|
+
// `animator.animateById` map values and what `processNode` resolves at runtime.
|
|
1499
|
+
animate: PxElementAnimationSchema.optional(),
|
|
1500
|
+
style: px.union([px.string(), px.record(px.union([px.string(), px.number()]))]).optional()
|
|
1501
|
+
}, PxAttrValueSchema);
|
|
1502
|
+
var PxNodeSchema = px.openObject(__spreadProps2(__spreadValues2({}, PxNodeBase._shape), {
|
|
1503
|
+
children: px.lazy(() => px.array(PxNodeSchema), []).optional()
|
|
1504
|
+
}), PxAttrValueSchema);
|
|
1505
|
+
var PxSvgNodeExtra = px.object({
|
|
1506
|
+
// `"100%"` and other SVG length strings are legal here — a number-only slot rejected
|
|
1507
|
+
// real documents (e.g. apple-store-look-14-main.json) at the root <svg>.
|
|
1508
|
+
width: px.union([px.number(), px.string()]).optional(),
|
|
1509
|
+
height: px.union([px.number(), px.string()]).optional(),
|
|
1510
|
+
viewBox: px.string().optional(),
|
|
1511
|
+
animator: PxAnimatorConfigSchema.optional()
|
|
1512
|
+
});
|
|
1513
|
+
var PxAnimatedSvgDocumentSchema = px.openObject(__spreadProps2(__spreadValues2(__spreadValues2({}, PxNodeBase._shape), PxSvgNodeExtra._shape), {
|
|
1514
|
+
type: px.literal("svg"),
|
|
1515
|
+
// override string → literal to require 'svg'
|
|
1516
|
+
children: px.array(PxNodeSchema).optional()
|
|
1517
|
+
}), PxAttrValueSchema);
|
|
1518
|
+
var PxBezierPathSchema = implementsInterface()(px.object({
|
|
1519
|
+
v: px.array(px.array(px.number())),
|
|
1520
|
+
i: px.array(px.array(px.number())).optional(),
|
|
1521
|
+
o: px.array(px.array(px.number())).optional(),
|
|
1522
|
+
c: px.boolean().optional()
|
|
1523
|
+
}));
|
|
1524
|
+
function isPxElementFileFormatDeep(fileJson) {
|
|
1525
|
+
const valid = PxAnimatedSvgDocumentSchema.isValid(fileJson);
|
|
1526
|
+
return { valid, errors: valid ? [] : ["Document failed schema validation"] };
|
|
1454
1527
|
}
|
|
1455
1528
|
var _idCounter = 0;
|
|
1456
1529
|
function generateUniqueId() {
|
|
@@ -2052,7 +2125,7 @@ function walkAndMaterialise(node, opts) {
|
|
|
2052
2125
|
if (newAnimate) cloned.animate = newAnimate;
|
|
2053
2126
|
return cloned;
|
|
2054
2127
|
}
|
|
2055
|
-
var LOOP_JUMP_SHIFT_MS =
|
|
2128
|
+
var LOOP_JUMP_SHIFT_MS = 1;
|
|
2056
2129
|
function deepEqualValue(a, b) {
|
|
2057
2130
|
if (a === b) return true;
|
|
2058
2131
|
if (typeof a !== typeof b || a === null || b === null || typeof a !== "object") return false;
|
|
@@ -2301,6 +2374,8 @@ function expandLoopKeyframes(propName, keyframes, loop, duration) {
|
|
|
2301
2374
|
const looped = [];
|
|
2302
2375
|
const separateBoundary = loop.extend !== PxLoopExtend.before;
|
|
2303
2376
|
const originalTerminalKf = keyframes[keyframes.length - 1];
|
|
2377
|
+
let terminalEasingOverride;
|
|
2378
|
+
let hasTerminalEasingOverride = false;
|
|
2304
2379
|
function appendRep(repStart, isReversed, partial) {
|
|
2305
2380
|
var _a2;
|
|
2306
2381
|
let entries;
|
|
@@ -2341,7 +2416,16 @@ function expandLoopKeyframes(propName, keyframes, loop, duration) {
|
|
|
2341
2416
|
const prevKf = looped.length > 0 ? looped[looped.length - 1] : originalTerminalKf;
|
|
2342
2417
|
const isBoundary = separateBoundary && i === 0 && prevKf !== void 0 && Math.abs(((_a2 = prevKf.t) != null ? _a2 : 0) - (repStart + entry.relT * segDuration)) < 1e-9;
|
|
2343
2418
|
if (isBoundary) {
|
|
2344
|
-
if (deepEqualValue(prevKf.v, entry.v))
|
|
2419
|
+
if (deepEqualValue(prevKf.v, entry.v)) {
|
|
2420
|
+
if (looped.length > 0) {
|
|
2421
|
+
prevKf.e = entry.e;
|
|
2422
|
+
prevKf.tangentOut = entry.tangentOut;
|
|
2423
|
+
} else {
|
|
2424
|
+
terminalEasingOverride = entry.e;
|
|
2425
|
+
hasTerminalEasingOverride = true;
|
|
2426
|
+
}
|
|
2427
|
+
continue;
|
|
2428
|
+
}
|
|
2345
2429
|
if (looped.length > 0) {
|
|
2346
2430
|
delete prevKf.tangentIn;
|
|
2347
2431
|
delete prevKf.tangentOut;
|
|
@@ -2422,6 +2506,11 @@ function expandLoopKeyframes(propName, keyframes, loop, duration) {
|
|
|
2422
2506
|
if (loop.extend === PxLoopExtend.before) {
|
|
2423
2507
|
return [...looped, ...keyframes];
|
|
2424
2508
|
} else {
|
|
2509
|
+
if (hasTerminalEasingOverride && keyframes.length > 0) {
|
|
2510
|
+
const head = keyframes.slice(0, -1);
|
|
2511
|
+
const tail = __spreadProps2(__spreadValues2({}, keyframes[keyframes.length - 1]), { e: terminalEasingOverride });
|
|
2512
|
+
return [...head, tail, ...looped];
|
|
2513
|
+
}
|
|
2425
2514
|
return [...keyframes, ...looped];
|
|
2426
2515
|
}
|
|
2427
2516
|
}
|
|
@@ -2538,6 +2627,9 @@ function generateElementId() {
|
|
|
2538
2627
|
function normalizeAnimationDefinition(animDef, duration, defs, engine = PxAnimatorEngine.waapi) {
|
|
2539
2628
|
const normalized = {};
|
|
2540
2629
|
for (const [propName, propAnim] of Object.entries(animDef)) {
|
|
2630
|
+
if (propName === "transform" && propAnim.alongPathMode === "offsetPath" && animDef["offsetDistance"] !== void 0) {
|
|
2631
|
+
continue;
|
|
2632
|
+
}
|
|
2541
2633
|
const normalizedKfs = normalizeKeyframes(propName, propAnim, duration, defs);
|
|
2542
2634
|
if (normalizedKfs.length > 0) {
|
|
2543
2635
|
const out = { kfs: normalizedKfs };
|
|
@@ -5349,9 +5441,138 @@ function applyPlayerEffects_retime(node, ctx) {
|
|
|
5349
5441
|
applyAllRetimeEffects(node, ctx);
|
|
5350
5442
|
return node;
|
|
5351
5443
|
}
|
|
5444
|
+
var kfTime = (kf) => {
|
|
5445
|
+
var _a, _b;
|
|
5446
|
+
return (_b = (_a = kf.t) != null ? _a : kf.time) != null ? _b : 0;
|
|
5447
|
+
};
|
|
5448
|
+
var kfValue = (kf) => {
|
|
5449
|
+
var _a;
|
|
5450
|
+
return (_a = kf.v) != null ? _a : kf.value;
|
|
5451
|
+
};
|
|
5452
|
+
var kfEasing = (kf) => {
|
|
5453
|
+
var _a;
|
|
5454
|
+
return (_a = kf.e) != null ? _a : kf.easing;
|
|
5455
|
+
};
|
|
5456
|
+
var kfTangentIn = (kf) => {
|
|
5457
|
+
var _a;
|
|
5458
|
+
return (_a = kf.tangentIn) != null ? _a : kf.ti;
|
|
5459
|
+
};
|
|
5460
|
+
var kfTangentOut = (kf) => {
|
|
5461
|
+
var _a;
|
|
5462
|
+
return (_a = kf.tangentOut) != null ? _a : kf.to;
|
|
5463
|
+
};
|
|
5464
|
+
function cubicAt(p0, c1, c2, p1, t) {
|
|
5465
|
+
const u = 1 - t;
|
|
5466
|
+
const a = u * u * u, b = 3 * u * u * t, c = 3 * u * t * t, d = t * t * t;
|
|
5467
|
+
return [
|
|
5468
|
+
a * p0[0] + b * c1[0] + c * c2[0] + d * p1[0],
|
|
5469
|
+
a * p0[1] + b * c1[1] + c * c2[1] + d * p1[1]
|
|
5470
|
+
];
|
|
5471
|
+
}
|
|
5472
|
+
function cubicLength(p0, c1, c2, p1, steps = 64) {
|
|
5473
|
+
let len = 0;
|
|
5474
|
+
let prev = p0;
|
|
5475
|
+
for (let i = 1; i <= steps; i++) {
|
|
5476
|
+
const pt = cubicAt(p0, c1, c2, p1, i / steps);
|
|
5477
|
+
len += Math.hypot(pt[0] - prev[0], pt[1] - prev[1]);
|
|
5478
|
+
prev = pt;
|
|
5479
|
+
}
|
|
5480
|
+
return len;
|
|
5481
|
+
}
|
|
5482
|
+
var fmt2 = (n) => {
|
|
5483
|
+
const r = Math.round(n * 1e4) / 1e4;
|
|
5484
|
+
return Object.is(r, -0) ? "0" : String(r);
|
|
5485
|
+
};
|
|
5486
|
+
function buildOffsetPath(propAnim) {
|
|
5487
|
+
var _a, _b, _c, _d;
|
|
5488
|
+
if (propAnim.alongPathMode !== "offsetPath") return void 0;
|
|
5489
|
+
const kfs = (_a = propAnim.keyframes) != null ? _a : propAnim.kfs;
|
|
5490
|
+
if (!kfs || kfs.length < 2) return void 0;
|
|
5491
|
+
const first = kfValue(kfs[0]);
|
|
5492
|
+
const anchor = (first == null ? void 0 : first.origin) && first.origin.length >= 2 ? [first.origin[0], first.origin[1]] : [0, 0];
|
|
5493
|
+
const points = [];
|
|
5494
|
+
for (const kf of kfs) {
|
|
5495
|
+
const v = kfValue(kf);
|
|
5496
|
+
const tr = v == null ? void 0 : v.translate;
|
|
5497
|
+
if (!tr || tr.length < 2) return void 0;
|
|
5498
|
+
const parts = Object.keys(v);
|
|
5499
|
+
if (parts.some((p) => p !== "translate" && p !== "origin")) return void 0;
|
|
5500
|
+
const o = (_b = v == null ? void 0 : v.origin) != null ? _b : [0, 0];
|
|
5501
|
+
if (o[0] !== anchor[0] || o[1] !== anchor[1]) return void 0;
|
|
5502
|
+
points.push([tr[0] + anchor[0], tr[1] + anchor[1]]);
|
|
5503
|
+
}
|
|
5504
|
+
if (!kfs.some((kf) => kfTangentIn(kf) || kfTangentOut(kf))) return void 0;
|
|
5505
|
+
let d = "M" + fmt2(points[0][0]) + "," + fmt2(points[0][1]);
|
|
5506
|
+
const segLens = [];
|
|
5507
|
+
for (let i = 0; i < points.length - 1; i++) {
|
|
5508
|
+
const p0 = points[i], p1 = points[i + 1];
|
|
5509
|
+
const to = (_c = kfTangentOut(kfs[i])) != null ? _c : [0, 0];
|
|
5510
|
+
const ti = (_d = kfTangentIn(kfs[i + 1])) != null ? _d : [0, 0];
|
|
5511
|
+
const c1 = [p0[0] + to[0], p0[1] + to[1]];
|
|
5512
|
+
const c2 = [p1[0] + ti[0], p1[1] + ti[1]];
|
|
5513
|
+
d += "C" + fmt2(c1[0]) + "," + fmt2(c1[1]) + "," + fmt2(c2[0]) + "," + fmt2(c2[1]) + "," + fmt2(p1[0]) + "," + fmt2(p1[1]);
|
|
5514
|
+
segLens.push(cubicLength(p0, c1, c2, p1));
|
|
5515
|
+
}
|
|
5516
|
+
const total = segLens.reduce((a, b) => a + b, 0);
|
|
5517
|
+
if (!(total > 0)) return void 0;
|
|
5518
|
+
const distanceKfs = [];
|
|
5519
|
+
let cum = 0;
|
|
5520
|
+
for (let i = 0; i < kfs.length; i++) {
|
|
5521
|
+
if (i > 0) cum += segLens[i - 1];
|
|
5522
|
+
const out = { t: kfTime(kfs[i]), v: cum / total };
|
|
5523
|
+
const e = kfEasing(kfs[i]);
|
|
5524
|
+
if (e !== void 0) out.e = e;
|
|
5525
|
+
distanceKfs.push(out);
|
|
5526
|
+
}
|
|
5527
|
+
return { pathStr: d, distanceKfs, autoOrient: !!propAnim.autoOrient, anchor };
|
|
5528
|
+
}
|
|
5529
|
+
function materialiseOffsetPathsInTree(root) {
|
|
5530
|
+
const walk = (node) => {
|
|
5531
|
+
var _a;
|
|
5532
|
+
let out = node;
|
|
5533
|
+
const anim = node.animate;
|
|
5534
|
+
const transform = anim == null ? void 0 : anim["transform"];
|
|
5535
|
+
if (transform) {
|
|
5536
|
+
const built = buildOffsetPath(transform);
|
|
5537
|
+
if (built) {
|
|
5538
|
+
const newAnimate = __spreadValues2({}, anim);
|
|
5539
|
+
delete newAnimate["transform"];
|
|
5540
|
+
const distance = { keyframes: built.distanceKfs };
|
|
5541
|
+
if (transform.loop !== void 0) distance.loop = transform.loop;
|
|
5542
|
+
newAnimate["offsetDistance"] = distance;
|
|
5543
|
+
const staticTr = node.transform;
|
|
5544
|
+
let newTransform = staticTr;
|
|
5545
|
+
if (staticTr && typeof staticTr === "object") {
|
|
5546
|
+
const t = __spreadValues2({}, staticTr);
|
|
5547
|
+
delete t["translate"];
|
|
5548
|
+
delete t["origin"];
|
|
5549
|
+
newTransform = Object.keys(t).length ? t : void 0;
|
|
5550
|
+
}
|
|
5551
|
+
out = __spreadProps2(__spreadValues2({}, node), {
|
|
5552
|
+
animate: newAnimate,
|
|
5553
|
+
style: __spreadProps2(__spreadValues2({}, node.style), {
|
|
5554
|
+
offsetPath: "path('" + built.pathStr + "')",
|
|
5555
|
+
offsetAnchor: fmt2(built.anchor[0]) + "px " + fmt2(built.anchor[1]) + "px",
|
|
5556
|
+
offsetRotate: built.autoOrient ? "auto" : "0deg",
|
|
5557
|
+
offsetDistance: "0%"
|
|
5558
|
+
})
|
|
5559
|
+
});
|
|
5560
|
+
if (newTransform !== void 0) out.transform = newTransform;
|
|
5561
|
+
else delete out.transform;
|
|
5562
|
+
}
|
|
5563
|
+
}
|
|
5564
|
+
if ((_a = out.children) == null ? void 0 : _a.length) {
|
|
5565
|
+
const children = out.children.map(walk);
|
|
5566
|
+
if (children.some((c, i) => c !== out.children[i])) out = __spreadProps2(__spreadValues2({}, out), { children });
|
|
5567
|
+
}
|
|
5568
|
+
return out;
|
|
5569
|
+
};
|
|
5570
|
+
return walk(root);
|
|
5571
|
+
}
|
|
5352
5572
|
function materialiseAllInTree(doc, engine, opts) {
|
|
5353
5573
|
var _a, _b;
|
|
5354
5574
|
let root = applyPlayerEffects(doc).root;
|
|
5575
|
+
root = materialiseOffsetPathsInTree(root);
|
|
5355
5576
|
const duration = (_b = (_a = getAnimatorConfig(root)) == null ? void 0 : _a.duration) != null ? _b : DEFAULT_DURATION_MS;
|
|
5356
5577
|
root = materialiseInternalLoopsInTree(root, duration);
|
|
5357
5578
|
if (engine === PxAnimatorEngine.waapi) {
|
|
@@ -6002,7 +6223,13 @@ function createFrameLoopAnimator(doc, adapter, callbacks, rootElement) {
|
|
|
6002
6223
|
const api = __spreadProps(__spreadValues({}, basicApi), {
|
|
6003
6224
|
"getRootElement": () => rootElement || null
|
|
6004
6225
|
});
|
|
6005
|
-
if (config.trigger)
|
|
6226
|
+
if (config.trigger) {
|
|
6227
|
+
if (isScrollTimeline(config)) {
|
|
6228
|
+
console.warn("scroll timeline: `animator.trigger` is ignored (triggers do not apply to scroll-driven playback)");
|
|
6229
|
+
} else {
|
|
6230
|
+
setupAnimationTriggers(api, config.trigger);
|
|
6231
|
+
}
|
|
6232
|
+
}
|
|
6006
6233
|
return api;
|
|
6007
6234
|
}
|
|
6008
6235
|
function createDomAdapter(rootElement) {
|
|
@@ -6060,6 +6287,8 @@ function createCssKf(kf, t, propName, unsupportedSet) {
|
|
|
6060
6287
|
} else if (propName === "d") {
|
|
6061
6288
|
const paths = value && typeof value === "object" && Array.isArray(value.paths) ? value.paths : [];
|
|
6062
6289
|
cssValue = 'path("' + paths.map((bz) => bezierToSvgPath(bz, true)).join("") + '")';
|
|
6290
|
+
} else if (PCT_BASED_ATTR_NAMES.has(propName) && typeof value === "number") {
|
|
6291
|
+
cssValue = value * 100 + "%";
|
|
6063
6292
|
} else {
|
|
6064
6293
|
cssValue = "" + value;
|
|
6065
6294
|
}
|
|
@@ -6128,7 +6357,7 @@ function convertToWebApiKeyframes(animDef, unsupportedSet, config) {
|
|
|
6128
6357
|
}
|
|
6129
6358
|
return result;
|
|
6130
6359
|
}
|
|
6131
|
-
function createWebApiAnimator(doc, callbacks, rootElement, forceEvenIfHasUnsupportedAttrs) {
|
|
6360
|
+
function createWebApiAnimator(doc, callbacks, rootElement, forceEvenIfHasUnsupportedAttrs, scrollTimeline) {
|
|
6132
6361
|
var _a;
|
|
6133
6362
|
const config = getAnimatorConfig(doc) || {};
|
|
6134
6363
|
if (!rootElement) {
|
|
@@ -6187,7 +6416,12 @@ function createWebApiAnimator(doc, callbacks, rootElement, forceEvenIfHasUnsuppo
|
|
|
6187
6416
|
if (keyframes.length > 0) {
|
|
6188
6417
|
try {
|
|
6189
6418
|
const effect = new KeyframeEffect(element, keyframes, effectOptions);
|
|
6190
|
-
const anim = new Animation(effect, document.timeline);
|
|
6419
|
+
const anim = new Animation(effect, scrollTimeline ? scrollTimeline.timeline : document.timeline);
|
|
6420
|
+
if (scrollTimeline) {
|
|
6421
|
+
const a = anim;
|
|
6422
|
+
if (scrollTimeline.rangeStart) a.rangeStart = scrollTimeline.rangeStart;
|
|
6423
|
+
if (scrollTimeline.rangeEnd) a.rangeEnd = scrollTimeline.rangeEnd;
|
|
6424
|
+
}
|
|
6191
6425
|
if (callbacks == null ? void 0 : callbacks.onFinish) anim.onfinish = () => {
|
|
6192
6426
|
var _a2;
|
|
6193
6427
|
if (finishNotified) return;
|
|
@@ -6281,11 +6515,136 @@ function createWebApiAnimator(doc, callbacks, rootElement, forceEvenIfHasUnsuppo
|
|
|
6281
6515
|
}
|
|
6282
6516
|
};
|
|
6283
6517
|
if (config.trigger) {
|
|
6284
|
-
|
|
6518
|
+
if (config.timelineSource === "scroll") {
|
|
6519
|
+
console.warn("scroll timeline: `animator.trigger` is ignored (triggers do not apply to scroll-driven playback)");
|
|
6520
|
+
} else {
|
|
6521
|
+
setupAnimationTriggers(api, config.trigger);
|
|
6522
|
+
}
|
|
6523
|
+
}
|
|
6524
|
+
if (scrollTimeline) {
|
|
6525
|
+
animations.forEach((a) => a.play());
|
|
6285
6526
|
}
|
|
6286
6527
|
return api;
|
|
6287
6528
|
}
|
|
6288
6529
|
|
|
6530
|
+
// src/PxScrollDriver.ts
|
|
6531
|
+
function nativeRangeOffset(point, defaultFraction, view) {
|
|
6532
|
+
var _a, _b, _c;
|
|
6533
|
+
const fraction = typeof (point == null ? void 0 : point.fraction) === "number" ? point.fraction : defaultFraction;
|
|
6534
|
+
const pct = (_b = (_a = globalThis.CSS) == null ? void 0 : _a.percent) == null ? void 0 : _b.call(_a, fraction * 100);
|
|
6535
|
+
if (pct === void 0) return void 0;
|
|
6536
|
+
return view ? { rangeName: (_c = point == null ? void 0 : point.phase) != null ? _c : "cover", offset: pct } : { offset: pct };
|
|
6537
|
+
}
|
|
6538
|
+
function createNativeScrollTimeline(subject, config) {
|
|
6539
|
+
var _a, _b, _c, _d;
|
|
6540
|
+
if (!config || !isScrollTimeline(config)) return null;
|
|
6541
|
+
const scroll = config.scroll || {};
|
|
6542
|
+
const kind = (_a = scroll.kind) != null ? _a : "view";
|
|
6543
|
+
const g = globalThis;
|
|
6544
|
+
const view = kind === "view";
|
|
6545
|
+
const Ctor = view ? g.ViewTimeline : g.ScrollTimeline;
|
|
6546
|
+
if (typeof Ctor !== "function") return null;
|
|
6547
|
+
const axis = (_b = scroll.axis) != null ? _b : "block";
|
|
6548
|
+
let timeline;
|
|
6549
|
+
try {
|
|
6550
|
+
if (view) {
|
|
6551
|
+
timeline = new Ctor({ subject, axis });
|
|
6552
|
+
} else {
|
|
6553
|
+
const source = scroll.source === "root" ? documentScroller() : findNearestScroller(subject, "y") || findNearestScroller(subject, "x") || documentScroller();
|
|
6554
|
+
timeline = new Ctor({ source, axis });
|
|
6555
|
+
}
|
|
6556
|
+
} catch (e) {
|
|
6557
|
+
console.warn("scroll timeline: native timeline construction failed \u2014 falling back to the custom driver", e);
|
|
6558
|
+
return null;
|
|
6559
|
+
}
|
|
6560
|
+
return {
|
|
6561
|
+
timeline,
|
|
6562
|
+
rangeStart: nativeRangeOffset((_c = scroll.range) == null ? void 0 : _c.start, 0, view),
|
|
6563
|
+
rangeEnd: nativeRangeOffset((_d = scroll.range) == null ? void 0 : _d.end, 1, view)
|
|
6564
|
+
};
|
|
6565
|
+
}
|
|
6566
|
+
function findNearestScroller(el, axis) {
|
|
6567
|
+
for (let p = el.parentElement; p; p = p.parentElement) {
|
|
6568
|
+
const style = getComputedStyle(p);
|
|
6569
|
+
const overflow = axis === "y" ? style.overflowY : style.overflowX;
|
|
6570
|
+
if (overflow === "auto" || overflow === "scroll" || overflow === "hidden" || overflow === "overlay") {
|
|
6571
|
+
return p;
|
|
6572
|
+
}
|
|
6573
|
+
}
|
|
6574
|
+
return null;
|
|
6575
|
+
}
|
|
6576
|
+
function documentScroller() {
|
|
6577
|
+
return document.scrollingElement || document.documentElement;
|
|
6578
|
+
}
|
|
6579
|
+
function createScrollDriver(subject, config, onProgress) {
|
|
6580
|
+
var _a;
|
|
6581
|
+
if (!config || !isScrollTimeline(config)) return null;
|
|
6582
|
+
const scroll = config.scroll || {};
|
|
6583
|
+
const kind = (_a = scroll.kind) != null ? _a : "view";
|
|
6584
|
+
const nearest = findNearestScroller(subject, "y") || findNearestScroller(subject, "x");
|
|
6585
|
+
const scroller = kind === "scroll" && scroll.source === "root" ? documentScroller() : nearest || documentScroller();
|
|
6586
|
+
const isRootScroller = scroller === documentScroller();
|
|
6587
|
+
const axis = scrollResolveAxis(scroll.axis, getComputedStyle(scroller).writingMode);
|
|
6588
|
+
const compute = () => {
|
|
6589
|
+
if (kind === "scroll") {
|
|
6590
|
+
const offset = axis === "y" ? scroller.scrollTop : scroller.scrollLeft;
|
|
6591
|
+
const maxOffset = axis === "y" ? scroller.scrollHeight - scroller.clientHeight : scroller.scrollWidth - scroller.clientWidth;
|
|
6592
|
+
return scrollOffsetProgress(offset, maxOffset, scroll.range);
|
|
6593
|
+
}
|
|
6594
|
+
const subjectRect = subject.getBoundingClientRect();
|
|
6595
|
+
let portStart, portSize;
|
|
6596
|
+
if (isRootScroller) {
|
|
6597
|
+
portStart = 0;
|
|
6598
|
+
portSize = axis === "y" ? document.documentElement.clientHeight : document.documentElement.clientWidth;
|
|
6599
|
+
} else {
|
|
6600
|
+
const portRect = scroller.getBoundingClientRect();
|
|
6601
|
+
portStart = axis === "y" ? portRect.top : portRect.left;
|
|
6602
|
+
portSize = axis === "y" ? scroller.clientHeight : scroller.clientWidth;
|
|
6603
|
+
}
|
|
6604
|
+
const subjectStart = (axis === "y" ? subjectRect.top : subjectRect.left) - portStart;
|
|
6605
|
+
const subjectSize = axis === "y" ? subjectRect.height : subjectRect.width;
|
|
6606
|
+
return scrollViewProgress(subjectStart, subjectSize, portSize, scroll.range);
|
|
6607
|
+
};
|
|
6608
|
+
let rafId = null;
|
|
6609
|
+
let destroyed = false;
|
|
6610
|
+
const tick = () => {
|
|
6611
|
+
rafId = null;
|
|
6612
|
+
if (destroyed) return;
|
|
6613
|
+
onProgress(compute());
|
|
6614
|
+
};
|
|
6615
|
+
const schedule = () => {
|
|
6616
|
+
if (destroyed || rafId !== null) return;
|
|
6617
|
+
rafId = requestAnimationFrame(tick);
|
|
6618
|
+
};
|
|
6619
|
+
const scrollTarget = isRootScroller ? window : scroller;
|
|
6620
|
+
scrollTarget.addEventListener("scroll", schedule, { passive: true });
|
|
6621
|
+
window.addEventListener("resize", schedule, { passive: true });
|
|
6622
|
+
let resizeObserver;
|
|
6623
|
+
if (typeof ResizeObserver !== "undefined") {
|
|
6624
|
+
resizeObserver = new ResizeObserver(schedule);
|
|
6625
|
+
resizeObserver.observe(subject);
|
|
6626
|
+
if (!isRootScroller) resizeObserver.observe(scroller);
|
|
6627
|
+
}
|
|
6628
|
+
const driver = {
|
|
6629
|
+
destroy: () => {
|
|
6630
|
+
if (destroyed) return;
|
|
6631
|
+
destroyed = true;
|
|
6632
|
+
scrollTarget.removeEventListener("scroll", schedule);
|
|
6633
|
+
window.removeEventListener("resize", schedule);
|
|
6634
|
+
resizeObserver == null ? void 0 : resizeObserver.disconnect();
|
|
6635
|
+
if (rafId !== null) {
|
|
6636
|
+
cancelAnimationFrame(rafId);
|
|
6637
|
+
rafId = null;
|
|
6638
|
+
}
|
|
6639
|
+
},
|
|
6640
|
+
refresh: () => {
|
|
6641
|
+
if (!destroyed) onProgress(compute());
|
|
6642
|
+
}
|
|
6643
|
+
};
|
|
6644
|
+
driver.refresh();
|
|
6645
|
+
return driver;
|
|
6646
|
+
}
|
|
6647
|
+
|
|
6289
6648
|
// src/PxAnimatorBind.ts
|
|
6290
6649
|
function finaliseAnimator(animatorConfig, callbacks, make) {
|
|
6291
6650
|
let apiRef;
|
|
@@ -6308,6 +6667,44 @@ function finaliseAnimator(animatorConfig, callbacks, make) {
|
|
|
6308
6667
|
}
|
|
6309
6668
|
function bindWithEngineChoice(doc, adapter, callbacks, rootElement) {
|
|
6310
6669
|
const animatorConfig = getAnimatorConfig(doc) || {};
|
|
6670
|
+
if (isScrollTimeline(animatorConfig)) {
|
|
6671
|
+
return finaliseAnimator(animatorConfig, callbacks, (cb) => {
|
|
6672
|
+
var _a, _b;
|
|
6673
|
+
if (animatorConfig.mode !== PxAnimatorMode.frames && ((_a = animatorConfig.scroll) == null ? void 0 : _a.driver) === "native" && rootElement) {
|
|
6674
|
+
const native = createNativeScrollTimeline(rootElement, animatorConfig);
|
|
6675
|
+
if (native) {
|
|
6676
|
+
const api2 = createWebApiAnimator(
|
|
6677
|
+
doc,
|
|
6678
|
+
cb,
|
|
6679
|
+
rootElement,
|
|
6680
|
+
animatorConfig.mode === PxAnimatorMode.waapi,
|
|
6681
|
+
native
|
|
6682
|
+
);
|
|
6683
|
+
if (api2) return api2;
|
|
6684
|
+
}
|
|
6685
|
+
}
|
|
6686
|
+
const api = (animatorConfig.mode !== PxAnimatorMode.frames ? createWebApiAnimator(doc, cb, rootElement, animatorConfig.mode === PxAnimatorMode.waapi) : null) || createFrameLoopAnimator(doc, adapter, cb, rootElement);
|
|
6687
|
+
const subject = ((_b = api.getRootElement) == null ? void 0 : _b.call(api)) || rootElement;
|
|
6688
|
+
if (subject) {
|
|
6689
|
+
const totalMs = scrollTotalDurationMs(animatorConfig);
|
|
6690
|
+
const driver = createScrollDriver(
|
|
6691
|
+
subject,
|
|
6692
|
+
animatorConfig,
|
|
6693
|
+
(progress) => api.setCurrentTime(progress * totalMs)
|
|
6694
|
+
);
|
|
6695
|
+
if (driver) {
|
|
6696
|
+
const destroy = api.destroy.bind(api);
|
|
6697
|
+
api.destroy = () => {
|
|
6698
|
+
driver.destroy();
|
|
6699
|
+
destroy();
|
|
6700
|
+
};
|
|
6701
|
+
}
|
|
6702
|
+
} else {
|
|
6703
|
+
console.warn("scroll timeline: no root element to observe \u2014 animation will stay at frame 0");
|
|
6704
|
+
}
|
|
6705
|
+
return api;
|
|
6706
|
+
});
|
|
6707
|
+
}
|
|
6311
6708
|
return finaliseAnimator(animatorConfig, callbacks, (cb) => {
|
|
6312
6709
|
if (animatorConfig.mode === PxAnimatorMode.frames) {
|
|
6313
6710
|
return createFrameLoopAnimator(doc, adapter, cb, rootElement);
|