@pixodesk/svg-animator-web 1.0.39 → 1.0.41

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.
@@ -55,7 +55,7 @@ var PixodeskAnimator = (() => {
55
55
  PX_ANIM_ATTR_NAME: () => PX_ANIM_ATTR_NAME,
56
56
  PX_ANIM_SRC_ATTR_NAME: () => PX_ANIM_SRC_ATTR_NAME,
57
57
  PxTimelineEngine: () => PxTimelineEngine,
58
- PxTimelineEngineExtra: () => PxTimelineEngineExtra,
58
+ PxTimelineEngineSetting: () => PxTimelineEngineSetting,
59
59
  createAnimator: () => createAnimator,
60
60
  generateNewIds: () => generateNewIds,
61
61
  loadTagAnimators: () => loadTagAnimators,
@@ -63,597 +63,93 @@ var PixodeskAnimator = (() => {
63
63
  validateDocument: () => validateDocument
64
64
  });
65
65
 
66
- // ../svg-animator-core/src/util/PxAnimatorUtil.ts
67
- function bezierToSvgPath(path, forceCurves = false) {
68
- var _a2, _b, _c, _d;
69
- const v = path.v;
70
- const i = path.i;
71
- const o = path.o;
72
- const c = path.c;
73
- if (!v.length) return "";
74
- const d = [];
75
- const len = v.length;
76
- d.push("M" + v[0][0] + "," + v[0][1]);
77
- for (let idx = 1; idx < len; idx++) {
78
- const prevV = v[idx - 1];
79
- const prevO = (_a2 = o == null ? void 0 : o[idx - 1]) != null ? _a2 : prevV;
80
- const currI = (_b = i == null ? void 0 : i[idx]) != null ? _b : v[idx];
81
- const currV = v[idx];
82
- const isLine = !forceCurves && (prevO[0] === prevV[0] && prevO[1] === prevV[1]) && (currI[0] === currV[0] && currI[1] === currV[1]);
83
- if (isLine) {
84
- d.push("L" + currV[0] + "," + currV[1]);
85
- } else {
86
- d.push("C" + prevO[0] + "," + prevO[1] + "," + currI[0] + "," + currI[1] + "," + currV[0] + "," + currV[1]);
87
- }
88
- }
89
- if (c && len > 0) {
90
- const lastV = v[len - 1];
91
- const lastO = (_c = o == null ? void 0 : o[len - 1]) != null ? _c : lastV;
92
- const firstI = (_d = i == null ? void 0 : i[0]) != null ? _d : v[0];
93
- const firstV = v[0];
94
- const isLine = !forceCurves && (lastO[0] === lastV[0] && lastO[1] === lastV[1]) && (firstI[0] === firstV[0] && firstI[1] === firstV[1]);
95
- if (!isLine) {
96
- d.push("C" + lastO[0] + "," + lastO[1] + "," + firstI[0] + "," + firstI[1] + "," + firstV[0] + "," + firstV[1]);
97
- }
98
- d.push("z");
66
+ // ../svg-animator-core/src/schema/PxSchema.ts
67
+ var PX_UNKNOWN_KEY_ERROR = "unexpected extra key";
68
+ function pathStr(path) {
69
+ if (!path.length) return ".";
70
+ let result = "";
71
+ for (const seg of path) {
72
+ if (seg.startsWith("[")) result += seg;
73
+ else result += (result ? "." : "") + seg;
99
74
  }
100
- return d.join("");
101
- }
102
- function interpolateNum(a, b, t) {
103
- return a + (b - a) * t;
75
+ return result;
104
76
  }
105
- function interpolateVec(a, b, t) {
106
- const res = [];
107
- const count = Math.max(a.length, b.length);
108
- for (let i = 0; i < count; i++) {
109
- res[i] = interpolateNum(a[i] || 0, b[i] || 0, t);
77
+ var Base = class {
78
+ _canSanitize(raw) {
79
+ return this.isValid(raw);
110
80
  }
111
- return res;
112
- }
113
- function interpolateColor(a, b, t) {
114
- return [
115
- interpolateNum(a[0] || 0, b[0] || 0, t),
116
- interpolateNum(a[1] || 0, b[1] || 0, t),
117
- interpolateNum(a[2] || 0, b[2] || 0, t),
118
- interpolateNum(a[3] === void 0 ? 1 : a[3], b[3] === void 0 ? 1 : b[3], t)
119
- ];
120
- }
121
- function interpolateBeziers(paths1, paths2, progress) {
122
- const count = Math.max(paths1.length, paths2.length);
123
- const res = [];
124
- for (let i = 0; i < count; i++) {
125
- res.push(interpolateBezier(paths1[i], paths2[i], progress));
81
+ optional() {
82
+ return new Optional(this);
126
83
  }
127
- return res;
128
- }
129
- function interpolateBezier(path1, path2, progress) {
130
- var _a2, _b, _c, _d, _e, _f, _g, _h, _i;
131
- if (!path1 || !path2) return path1 || path2 || { v: [] };
132
- const t = Math.min(Math.max(progress, 0), 1);
133
- const len = Math.min(path1.v.length, path2.v.length);
134
- const v = [];
135
- const i = [];
136
- const o = [];
137
- for (let idx = 0; idx < len; idx++) {
138
- const v1 = path1.v[idx];
139
- const v2 = path2.v[idx];
140
- v.push(interpolateVec(v1, v2, t));
141
- const i1 = (_b = (_a2 = path1.i) == null ? void 0 : _a2[idx]) != null ? _b : v1;
142
- const i2 = (_d = (_c = path2.i) == null ? void 0 : _c[idx]) != null ? _d : v2;
143
- i.push(interpolateVec(i1, i2, t));
144
- const o1 = (_f = (_e = path1.o) == null ? void 0 : _e[idx]) != null ? _f : v1;
145
- const o2 = (_h = (_g = path2.o) == null ? void 0 : _g[idx]) != null ? _h : v2;
146
- o.push(interpolateVec(o1, o2, t));
84
+ };
85
+ var Optional = class extends Base {
86
+ constructor(inner) {
87
+ super();
88
+ this.inner = inner;
89
+ this._default = void 0;
147
90
  }
148
- return { v, i: i.length ? i : void 0, o: o.length ? o : void 0, c: (_i = path1.c) != null ? _i : path2.c };
149
- }
150
- function remap(value, inMin, inMax, outMin, outMax) {
151
- if (inMax === inMin) return outMin;
152
- const t = (value - inMin) / (inMax - inMin);
153
- return outMin + t * (outMax - outMin);
154
- }
155
- function solveCubicBezierX(p1x, p2x, x) {
156
- if (x <= 0) return 0;
157
- if (x >= 1) return 1;
158
- const cx = 3 * p1x;
159
- const bx = 3 * (p2x - p1x) - cx;
160
- const ax = 1 - cx - bx;
161
- function sampleX(t) {
162
- return ((ax * t + bx) * t + cx) * t;
91
+ sanitize(raw) {
92
+ if (raw === void 0 || raw === null) return void 0;
93
+ return this.inner._canSanitize(raw) ? this.inner.sanitize(raw) : void 0;
163
94
  }
164
- function sampleDX(t) {
165
- return (3 * ax * t + 2 * bx) * t + cx;
95
+ isValid(raw, ctx, path) {
96
+ if (raw === void 0 || raw === null) return true;
97
+ return this.inner.isValid(raw, ctx, path);
166
98
  }
167
- let t2 = x;
168
- let t0 = 0;
169
- let t1 = 1;
170
- for (let i = 0; i < 8; i++) {
171
- const x2 = sampleX(t2) - x;
172
- if (Math.abs(x2) < 1e-6) return t2;
173
- const d2 = sampleDX(t2);
174
- if (Math.abs(d2) < 1e-6) break;
175
- t2 -= x2 / d2;
99
+ _canSanitize(raw) {
100
+ return raw === void 0 || raw === null || this.inner._canSanitize(raw);
176
101
  }
177
- t2 = x;
178
- while (t0 < t1) {
179
- const x2 = sampleX(t2);
180
- if (Math.abs(x2 - x) < 1e-6) return t2;
181
- if (x > x2) t0 = t2;
182
- else t1 = t2;
183
- t2 = (t1 + t0) / 2;
102
+ };
103
+ var Str = class extends Base {
104
+ constructor(_default = "") {
105
+ super();
106
+ this._default = _default;
184
107
  }
185
- return t2;
186
- }
187
- function cubicBezier(easing) {
188
- const [p1x, p1y, p2x, p2y] = easing;
189
- const cy = 3 * p1y;
190
- const by = 3 * (p2y - p1y) - cy;
191
- const ay = 1 - cy - by;
192
- function sampleCurveY(t) {
193
- return ((ay * t + by) * t + cy) * t;
108
+ sanitize(raw) {
109
+ return typeof raw === "string" ? raw : this._default;
194
110
  }
195
- return function(x) {
196
- return sampleCurveY(solveCubicBezierX(p1x, p2x, x));
197
- };
198
- }
199
- function lerp2(a, b, t) {
200
- return [a[0] + (b[0] - a[0]) * t, a[1] + (b[1] - a[1]) * t];
201
- }
202
- function subdivideCubicBezier(p0, p1, p2, p3, t) {
203
- const q0 = lerp2(p0, p1, t);
204
- const q1 = lerp2(p1, p2, t);
205
- const q2 = lerp2(p2, p3, t);
206
- const r0 = lerp2(q0, q1, t);
207
- const r1 = lerp2(q1, q2, t);
208
- const s = lerp2(r0, r1, t);
209
- return {
210
- left: [p0, q0, r0, s],
211
- right: [s, r1, q2, p3]
212
- };
213
- }
214
- function splitEasing(easing, xFraction) {
215
- if (!easing) return { left: void 0, right: void 0 };
216
- if (xFraction <= 0) return { left: void 0, right: easing };
217
- if (xFraction >= 1) return { left: easing, right: void 0 };
218
- const [x1, y1, x2, y2] = easing;
219
- const t = solveCubicBezierX(x1, x2, xFraction);
220
- const p0 = [0, 0];
221
- const p1 = [x1, y1];
222
- const p2 = [x2, y2];
223
- const p3 = [1, 1];
224
- const { left, right } = subdivideCubicBezier(p0, p1, p2, p3, t);
225
- const sx = left[3][0];
226
- const sy = left[3][1];
227
- let leftEasing;
228
- if (sx > 1e-9 && Math.abs(sy) > 1e-9) {
229
- leftEasing = [
230
- left[1][0] / sx,
231
- left[1][1] / sy,
232
- left[2][0] / sx,
233
- left[2][1] / sy
234
- ];
111
+ isValid(raw, ctx, path) {
112
+ if (typeof raw === "string") return true;
113
+ ctx == null ? void 0 : ctx.errors.push(pathStr(path != null ? path : []) + ": expected string, got " + typeof raw);
114
+ return false;
235
115
  }
236
- let rightEasing;
237
- const rx = 1 - sx;
238
- const ry = 1 - sy;
239
- if (rx > 1e-9 && Math.abs(ry) > 1e-9) {
240
- rightEasing = [
241
- (right[1][0] - sx) / rx,
242
- (right[1][1] - sy) / ry,
243
- (right[2][0] - sx) / rx,
244
- (right[2][1] - sy) / ry
245
- ];
116
+ };
117
+ var Num = class extends Base {
118
+ constructor(_default = 0) {
119
+ super();
120
+ this._default = _default;
246
121
  }
247
- return { left: leftEasing, right: rightEasing };
248
- }
249
- function reverseEasing(easing) {
250
- if (!easing) return void 0;
251
- return [1 - easing[2], 1 - easing[3], 1 - easing[0], 1 - easing[1]];
252
- }
253
- function toRGBA(color) {
254
- const r = Math.round(color[0] * 255);
255
- const g = Math.round(color[1] * 255);
256
- const b = Math.round(color[2] * 255);
257
- return color.length === 4 ? "rgba(" + r + "," + g + "," + b + "," + color[3] + ")" : "rgb(" + r + "," + g + "," + b + ")";
258
- }
259
- function parseRgba(s) {
260
- var _a2;
261
- const inner = (_a2 = s.match(/rgba?\((.*)\)/)) == null ? void 0 : _a2[1];
262
- if (!inner) throw new Error("Invalid rgb/rgba format");
263
- const parts = inner.split(",").map((v) => +v.trim());
264
- return [parts[0] / 255, parts[1] / 255, parts[2] / 255, ...parts[3] !== void 0 ? [parts[3]] : []];
265
- }
266
- function parseHex(s) {
267
- const hex = s.slice(1);
268
- const isShort = hex.length <= 4;
269
- const r = isShort ? hex[0] + hex[0] : hex.slice(0, 2);
270
- const g = isShort ? hex[1] + hex[1] : hex.slice(2, 4);
271
- const b = isShort ? hex[2] + hex[2] : hex.slice(4, 6);
272
- const a = hex.length === 4 ? hex[3] + hex[3] : hex.length === 8 ? hex.slice(6, 8) : null;
273
- const result = [
274
- parseInt(r, 16) / 255,
275
- parseInt(g, 16) / 255,
276
- parseInt(b, 16) / 255
277
- ];
278
- if (a !== null) {
279
- result.push(parseInt(a, 16) / 255);
122
+ sanitize(raw) {
123
+ return typeof raw === "number" && isFinite(raw) ? raw : this._default;
280
124
  }
281
- return result;
282
- }
283
- function parseColor(s) {
284
- if (!s) return void 0;
285
- if (Array.isArray(s)) return s;
286
- if (typeof s !== "string") return void 0;
287
- if (s.startsWith("#")) {
288
- return parseHex(s);
289
- } else if (s.startsWith("rgb")) {
290
- return parseRgba(s);
291
- } else {
292
- console.warn("Unsupported color format: " + s);
125
+ isValid(raw, ctx, path) {
126
+ if (typeof raw === "number" && isFinite(raw)) return true;
127
+ ctx == null ? void 0 : ctx.errors.push(pathStr(path != null ? path : []) + ": expected finite number, got " + JSON.stringify(raw));
128
+ return false;
293
129
  }
294
- return void 0;
295
- }
296
- var COLOR_ATTR_NAMES = /* @__PURE__ */ new Set(["color", "fill", "flood-color", "lighting-color", "stop-color", "stroke"]);
297
- var TRANSFORM_FN_NAMES = /* @__PURE__ */ new Set(["translate", "rotate", "scale", "skew"]);
298
- var PCT_BASED_ATTR_NAMES = /* @__PURE__ */ new Set(["offset-distance", "offsetDistance"]);
299
- function composeTransformParts(parts, opts) {
300
- var _a2;
301
- if (!parts) return "";
302
- const withUnits = (_a2 = opts == null ? void 0 : opts.withUnits) != null ? _a2 : true;
303
- const segs = [];
304
- const t = parts.translate;
305
- const o = parts.origin;
306
- const r = parts.rotate;
307
- const k = parts.skew;
308
- const s = parts.scale;
309
- const tu = withUnits ? "px" : "";
310
- const ru = withUnits ? "deg" : "";
311
- if (t) segs.push("translate(" + t[0] + tu + "," + t[1] + tu + ")");
312
- if (o) segs.push("translate(" + o[0] + tu + "," + o[1] + tu + ")");
313
- if (r !== void 0 && r !== null) segs.push("rotate(" + r + ru + ")");
314
- if (k !== void 0 && k !== null) segs.push("skewX(" + k + ru + ")");
315
- if (s) segs.push("scale(" + s[0] + "," + s[1] + ")");
316
- if (o) segs.push("translate(" + -o[0] + tu + "," + -o[1] + tu + ")");
317
- return segs.join("");
318
- }
319
- function parseTransformParts(str2) {
320
- var _a2, _b;
321
- if (!str2 || typeof str2 !== "string") return void 0;
322
- const out = {};
323
- const re = /([a-zA-Z]+)\s*\(([^)]*)\)/g;
324
- const order = ["translate", "rotate", "skewX", "scale"];
325
- let lastIdx = -1;
326
- let m;
327
- while ((m = re.exec(str2)) !== null) {
328
- const fn = m[1];
329
- const idx = order.indexOf(fn);
330
- if (idx < 0 || idx <= lastIdx) return void 0;
331
- lastIdx = idx;
332
- const nums = m[2].split(/[\s,]+/).filter(Boolean).map(Number);
333
- if (nums.some((n) => Number.isNaN(n))) return void 0;
334
- if (fn === "translate") {
335
- if (nums.length < 1 || nums.length > 2) return void 0;
336
- out.translate = [nums[0], (_a2 = nums[1]) != null ? _a2 : 0];
337
- } else if (fn === "rotate") {
338
- if (nums.length !== 1) return void 0;
339
- out.rotate = nums[0];
340
- } else if (fn === "skewX") {
341
- if (nums.length !== 1) return void 0;
342
- out.skew = nums[0];
343
- } else {
344
- if (nums.length < 1 || nums.length > 2) return void 0;
345
- out.scale = [nums[0], (_b = nums[1]) != null ? _b : nums[0]];
346
- }
130
+ };
131
+ var Bool = class extends Base {
132
+ constructor(_default = false) {
133
+ super();
134
+ this._default = _default;
347
135
  }
348
- if (str2.replace(/([a-zA-Z]+)\s*\(([^)]*)\)/g, "").replace(/[\s,]/g, "").length) return void 0;
349
- return Object.keys(out).length ? out : void 0;
350
- }
351
- var STYLE_ATTR_NAMES = /* @__PURE__ */ new Set(["offset-distance", "offsetDistance"]);
352
- var DEFAULT_DURATION_MS = 1e3;
353
- function kebabToCamelCaseWord(kebab) {
354
- return kebab.includes("-") ? kebab.replace(/-([a-z])/g, (_, letter) => letter.toUpperCase()) : kebab;
355
- }
356
- function isCamelCaseWord(word) {
357
- return !word.includes("-") && /[a-z][A-Z]/.test(word);
358
- }
359
- var SVG_CAMEL_CASE_ATTRS = /* @__PURE__ */ new Set([
360
- // Transform/positioning
361
- "viewBox",
362
- "preserveAspectRatio",
363
- // Gradient
364
- "gradientUnits",
365
- "gradientTransform",
366
- "spreadMethod",
367
- // Pattern
368
- "patternUnits",
369
- "patternContentUnits",
370
- "patternTransform",
371
- // Clipping/masking
372
- "clipPathUnits",
373
- "maskUnits",
374
- "maskContentUnits",
375
- // Marker (SVG spec keeps these camelCase, like viewBox)
376
- "markerUnits",
377
- "markerWidth",
378
- "markerHeight",
379
- "refX",
380
- "refY",
381
- // Text
382
- "textLength",
383
- "lengthAdjust",
384
- "startOffset",
385
- // Filter
386
- "filterUnits",
387
- "primitiveUnits",
388
- "tableValues",
389
- // feFuncR/G/B/A transfer table (type="table")
390
- "stdDeviation",
391
- "baseFrequency",
392
- "numOctaves",
393
- "surfaceScale",
394
- "diffuseConstant",
395
- "specularConstant",
396
- "specularExponent",
397
- "kernelMatrix",
398
- "kernelUnitLength",
399
- "edgeMode",
400
- "preserveAlpha",
401
- "targetX",
402
- "targetY"
403
- // // Animation
404
- // 'attributeName',
405
- // 'attributeType',
406
- // 'calcMode',
407
- // 'keyTimes',
408
- // 'keySplines',
409
- // 'repeatCount',
410
- // 'repeatDur'
411
- ]);
412
- function camelCaseToKebabWordIfNeeded(camel) {
413
- return SVG_CAMEL_CASE_ATTRS.has(camel) ? camel : camel.replace(/([a-z0-9])([A-Z])/g, "$1-$2").toLowerCase();
414
- }
415
- function clamp(value, min, max) {
416
- return Math.max(min, Math.min(value, max));
417
- }
418
- function bezier2D_pointAt(P0, P1, P2, P3, t) {
419
- if (t <= 0) return [P0[0], P0[1]];
420
- if (t >= 1) return [P3[0], P3[1]];
421
- const u = 1 - t;
422
- const u2 = u * u;
423
- const u3 = u2 * u;
424
- const t2 = t * t;
425
- const t3 = t2 * t;
426
- const w0 = u3;
427
- const w1 = 3 * t * u2;
428
- const w2 = 3 * t2 * u;
429
- const w3 = t3;
430
- return [
431
- w0 * P0[0] + w1 * P1[0] + w2 * P2[0] + w3 * P3[0],
432
- w0 * P0[1] + w1 * P1[1] + w2 * P2[1] + w3 * P3[1]
433
- ];
434
- }
435
- var BEZIER_T_NUDGE = 1e-4;
436
- function bezier2D_derivativeAt(P0, P1, P2, P3, t) {
437
- const result = _bezier2D_derivativeAtRaw(P0, P1, P2, P3, t);
438
- if (result[0] === 0 && result[1] === 0) {
439
- const nudgedT = t < 0.5 ? t + BEZIER_T_NUDGE : t - BEZIER_T_NUDGE;
440
- return _bezier2D_derivativeAtRaw(P0, P1, P2, P3, nudgedT);
136
+ sanitize(raw) {
137
+ return typeof raw === "boolean" ? raw : this._default;
441
138
  }
442
- return result;
443
- }
444
- function _bezier2D_derivativeAtRaw(P0, P1, P2, P3, t) {
445
- const u = 1 - t;
446
- const a = 3 * u * u;
447
- const b = 6 * t * u;
448
- const c = 3 * t * t;
449
- return [
450
- a * (P1[0] - P0[0]) + b * (P2[0] - P1[0]) + c * (P3[0] - P2[0]),
451
- a * (P1[1] - P0[1]) + b * (P2[1] - P1[1]) + c * (P3[1] - P2[1])
452
- ];
453
- }
454
- function bezier2D_arcLengthLUT(P0, P1, P2, P3, steps = 100) {
455
- const n = steps + 1;
456
- const ts = new Float64Array(n);
457
- const ds = new Float64Array(n);
458
- let prev = bezier2D_pointAt(P0, P1, P2, P3, 0);
459
- ts[0] = 0;
460
- ds[0] = 0;
461
- let cum = 0;
462
- for (let i = 1; i < n; i++) {
463
- const t = i / steps;
464
- const cur = bezier2D_pointAt(P0, P1, P2, P3, t);
465
- const dx = cur[0] - prev[0];
466
- const dy = cur[1] - prev[1];
467
- cum += Math.sqrt(dx * dx + dy * dy);
468
- ts[i] = t;
469
- ds[i] = cum;
470
- prev = cur;
139
+ isValid(raw, ctx, path) {
140
+ if (typeof raw === "boolean") return true;
141
+ ctx == null ? void 0 : ctx.errors.push(pathStr(path != null ? path : []) + ": expected boolean, got " + typeof raw);
142
+ return false;
471
143
  }
472
- return { ts, ds };
473
- }
474
- function bezier2D_tForDistance(lut, distance) {
475
- const { ts, ds } = lut;
476
- const last = ds.length - 1;
477
- if (distance <= 0) return ts[0];
478
- if (distance >= ds[last]) return ts[last];
479
- let lo = 1;
480
- let hi = last;
481
- while (lo < hi) {
482
- const mid = lo + hi >>> 1;
483
- if (ds[mid] < distance) lo = mid + 1;
484
- else hi = mid;
144
+ };
145
+ var Literal = class extends Base {
146
+ constructor(value) {
147
+ super();
148
+ this.value = value;
149
+ this._default = value;
485
150
  }
486
- const dPrev = ds[hi - 1];
487
- const dCur = ds[hi];
488
- const span = dCur - dPrev;
489
- const frac = span > 0 ? (distance - dPrev) / span : 0;
490
- return ts[hi - 1] + frac * (ts[hi] - ts[hi - 1]);
491
- }
492
- function bezier2D_arcAtT(lut, t) {
493
- const { ts, ds } = lut;
494
- const last = ts.length - 1;
495
- if (t <= ts[0]) return ds[0];
496
- if (t >= ts[last]) return ds[last];
497
- let lo = 1, hi = last;
498
- while (lo < hi) {
499
- const mid = lo + hi >>> 1;
500
- if (ts[mid] < t) lo = mid + 1;
501
- else hi = mid;
502
- }
503
- const tPrev = ts[hi - 1];
504
- const span = ts[hi] - tPrev;
505
- const frac = span > 0 ? (t - tPrev) / span : 0;
506
- return ds[hi - 1] + frac * (ds[hi] - ds[hi - 1]);
507
- }
508
- function invertEasing(easing) {
509
- if (!easing) return (y) => y;
510
- const flipped = [easing[1], easing[0], easing[3], easing[2]];
511
- return cubicBezier(flipped);
512
- }
513
-
514
- // ../svg-animator-core/src/playback/PxScrollMath.ts
515
- function isScrollTimeline(config) {
516
- return (config == null ? void 0 : config.timelineSource) === "scroll";
517
- }
518
- function scrollTotalDurationMs(config) {
519
- const duration = typeof (config == null ? void 0 : config.duration) === "number" && config.duration > 0 ? config.duration : DEFAULT_DURATION_MS;
520
- const iterations = typeof (config == null ? void 0 : config.iterations) === "number" && config.iterations > 0 ? config.iterations : 1;
521
- return duration * iterations;
522
- }
523
- function scrollPhaseInterval(phase, subjectSize, scrollportSize) {
524
- const s = subjectSize, vp = scrollportSize;
525
- switch (phase) {
526
- case "cover":
527
- return [0, s + vp];
528
- case "entry":
529
- return [0, Math.min(s, vp)];
530
- case "contain":
531
- return [Math.min(s, vp), Math.max(s, vp)];
532
- case "exit":
533
- return [Math.max(s, vp), s + vp];
534
- case "entry-crossing":
535
- return [0, s];
536
- case "exit-crossing":
537
- return [vp, s + vp];
538
- }
539
- }
540
- var DEFAULT_PHASE = "cover";
541
- function resolveRangePointU(point, defaultFraction, subjectSize, scrollportSize) {
542
- var _a2;
543
- const [u0, u1] = scrollPhaseInterval((_a2 = point == null ? void 0 : point.phase) != null ? _a2 : DEFAULT_PHASE, subjectSize, scrollportSize);
544
- const fraction = typeof (point == null ? void 0 : point.fraction) === "number" ? point.fraction : defaultFraction;
545
- return u0 + fraction * (u1 - u0);
546
- }
547
- function scrollViewProgress(subjectStart, subjectSize, scrollportSize, range) {
548
- const u = scrollportSize - subjectStart;
549
- const uStart = resolveRangePointU(range == null ? void 0 : range.start, 0, subjectSize, scrollportSize);
550
- const uEnd = resolveRangePointU(range == null ? void 0 : range.end, 1, subjectSize, scrollportSize);
551
- if (uEnd <= uStart) return u >= uEnd ? 1 : 0;
552
- return clamp((u - uStart) / (uEnd - uStart), 0, 1);
553
- }
554
- function scrollOffsetProgress(offset, maxOffset, range) {
555
- var _a2, _b;
556
- const raw = maxOffset > 0 ? clamp(offset / maxOffset, 0, 1) : 1;
557
- const start = typeof ((_a2 = range == null ? void 0 : range.start) == null ? void 0 : _a2.fraction) === "number" ? range.start.fraction : 0;
558
- const end = typeof ((_b = range == null ? void 0 : range.end) == null ? void 0 : _b.fraction) === "number" ? range.end.fraction : 1;
559
- if (end <= start) return raw >= end ? 1 : 0;
560
- return clamp((raw - start) / (end - start), 0, 1);
561
- }
562
- function scrollResolveAxis(axis, writingMode) {
563
- const a = axis != null ? axis : "block";
564
- if (a === "x" || a === "y") return a;
565
- const vertical = !!writingMode && writingMode.startsWith("vertical");
566
- if (a === "inline") return vertical ? "y" : "x";
567
- return vertical ? "x" : "y";
568
- }
569
-
570
- // ../svg-animator-core/src/schema/PxSchema.ts
571
- var PX_UNKNOWN_KEY_ERROR = "unexpected extra key";
572
- function pathStr(path) {
573
- if (!path.length) return ".";
574
- let result = "";
575
- for (const seg of path) {
576
- if (seg.startsWith("[")) result += seg;
577
- else result += (result ? "." : "") + seg;
578
- }
579
- return result;
580
- }
581
- var Base = class {
582
- _canSanitize(raw) {
583
- return this.isValid(raw);
584
- }
585
- optional() {
586
- return new Optional(this);
587
- }
588
- };
589
- var Optional = class extends Base {
590
- constructor(inner) {
591
- super();
592
- this.inner = inner;
593
- this._default = void 0;
594
- }
595
- sanitize(raw) {
596
- if (raw === void 0 || raw === null) return void 0;
597
- return this.inner._canSanitize(raw) ? this.inner.sanitize(raw) : void 0;
598
- }
599
- isValid(raw, ctx, path) {
600
- if (raw === void 0 || raw === null) return true;
601
- return this.inner.isValid(raw, ctx, path);
602
- }
603
- _canSanitize(raw) {
604
- return raw === void 0 || raw === null || this.inner._canSanitize(raw);
605
- }
606
- };
607
- var Str = class extends Base {
608
- constructor(_default = "") {
609
- super();
610
- this._default = _default;
611
- }
612
- sanitize(raw) {
613
- return typeof raw === "string" ? raw : this._default;
614
- }
615
- isValid(raw, ctx, path) {
616
- if (typeof raw === "string") return true;
617
- ctx == null ? void 0 : ctx.errors.push(pathStr(path != null ? path : []) + ": expected string, got " + typeof raw);
618
- return false;
619
- }
620
- };
621
- var Num = class extends Base {
622
- constructor(_default = 0) {
623
- super();
624
- this._default = _default;
625
- }
626
- sanitize(raw) {
627
- return typeof raw === "number" && isFinite(raw) ? raw : this._default;
628
- }
629
- isValid(raw, ctx, path) {
630
- if (typeof raw === "number" && isFinite(raw)) return true;
631
- ctx == null ? void 0 : ctx.errors.push(pathStr(path != null ? path : []) + ": expected finite number, got " + JSON.stringify(raw));
632
- return false;
633
- }
634
- };
635
- var Bool = class extends Base {
636
- constructor(_default = false) {
637
- super();
638
- this._default = _default;
639
- }
640
- sanitize(raw) {
641
- return typeof raw === "boolean" ? raw : this._default;
642
- }
643
- isValid(raw, ctx, path) {
644
- if (typeof raw === "boolean") return true;
645
- ctx == null ? void 0 : ctx.errors.push(pathStr(path != null ? path : []) + ": expected boolean, got " + typeof raw);
646
- return false;
647
- }
648
- };
649
- var Literal = class extends Base {
650
- constructor(value) {
651
- super();
652
- this.value = value;
653
- this._default = value;
654
- }
655
- sanitize(raw) {
656
- return raw === this.value ? this.value : this._default;
151
+ sanitize(raw) {
152
+ return raw === this.value ? this.value : this._default;
657
153
  }
658
154
  isValid(raw, ctx, path) {
659
155
  if (raw === this.value) return true;
@@ -1057,7 +553,7 @@ var PixodeskAnimator = (() => {
1057
553
  * The base can be the result of px.object() or px.openObject() — anything with a _shape property.
1058
554
  *
1059
555
  * @example
1060
- * const PxSvgNodeSchema = px.extendedObject(PxNodeBase, { width: px.number().optional() });
556
+ * const PxSvgNodeSchema = px.extendedObject(PxNodeBaseSchema, { width: px.number().optional() });
1061
557
  */
1062
558
  extendedObject: (base, extra) => new Obj(__spreadValues(__spreadValues({}, base._shape), extra)),
1063
559
  /** Array whose unrecoverable items are filtered out. Default: []. */
@@ -1075,7 +571,7 @@ var PixodeskAnimator = (() => {
1075
571
  };
1076
572
 
1077
573
  // ../svg-animator-core/src/version/PxSchemaVersion.ts
1078
- var PX_PLAYER_SCHEMA_VERSION = "1.1";
574
+ var PX_WIRE_SCHEMA_VERSION = "1.1";
1079
575
 
1080
576
  // ../svg-animator-core/src/version/PxWireVersion.ts
1081
577
  var VERSION_RE = /^(\d+)\.(\d+)(?:\.(\d+))?$/;
@@ -1086,7 +582,7 @@ var PixodeskAnimator = (() => {
1086
582
  return { a: Number(m[1]), b: Number(m[2]), c: m[3] === void 0 ? 0 : Number(m[3]) };
1087
583
  }
1088
584
  var _a;
1089
- var PLAYER_WIRE_VERSION = (_a = parseWireVersion(PX_PLAYER_SCHEMA_VERSION)) != null ? _a : { a: 1, b: 1, c: 0 };
585
+ var PX_WIRE_VERSION = (_a = parseWireVersion(PX_WIRE_SCHEMA_VERSION)) != null ? _a : { a: 1, b: 1, c: 0 };
1090
586
 
1091
587
  // ../svg-animator-core/src/format/PxAnimatorConstants.ts
1092
588
  var PxFillMode = {
@@ -1165,17 +661,17 @@ var PixodeskAnimator = (() => {
1165
661
  native: "native",
1166
662
  js: "js"
1167
663
  };
1168
- var PxTimelineEngineExtra = __spreadProps(__spreadValues({}, PxTimelineEngine), {
664
+ var PxTimelineEngineSetting = __spreadProps(__spreadValues({}, PxTimelineEngine), {
1169
665
  auto: "auto"
1170
666
  });
1171
667
  function resolveTimelineEngine(engine) {
1172
- return engine === PxTimelineEngineExtra.js ? PxTimelineEngine.js : PxTimelineEngine.native;
668
+ return engine === PxTimelineEngineSetting.js ? PxTimelineEngine.js : PxTimelineEngine.native;
1173
669
  }
1174
670
  function isNativeForced(engine) {
1175
- return engine === PxTimelineEngineExtra.native;
671
+ return engine === PxTimelineEngineSetting.native;
1176
672
  }
1177
673
  function mayUseNativeScrollTimeline(engine) {
1178
- return engine !== PxTimelineEngineExtra.js;
674
+ return engine !== PxTimelineEngineSetting.js;
1179
675
  }
1180
676
  var PX_TRIGGER_DEFAULTS = {
1181
677
  startOn: "load",
@@ -1236,7 +732,7 @@ var PixodeskAnimator = (() => {
1236
732
  separate: "separate",
1237
733
  combined: "combined"
1238
734
  };
1239
- var TEXT_CONTENT_ATTR = "textContent";
735
+ var PX_TEXT_CONTENT_ATTR = "textContent";
1240
736
  var CLASS_ATTR = "class";
1241
737
  var TRANSFORM_ATTR = "transform";
1242
738
  var OFFSET_DISTANCE_ATTR = "offsetDistance";
@@ -1247,7 +743,7 @@ var PixodeskAnimator = (() => {
1247
743
  "meta",
1248
744
  "animate",
1249
745
  "effects",
1250
- TEXT_CONTENT_ATTR
746
+ PX_TEXT_CONTENT_ATTR
1251
747
  ]);
1252
748
  var TRANSFORM_PART = {
1253
749
  translate: "translate",
@@ -1270,11 +766,11 @@ var PixodeskAnimator = (() => {
1270
766
  linear: "linear",
1271
767
  radial: "radial"
1272
768
  };
1273
- function isPxElementFileFormat(fileJson) {
1274
- if (!(fileJson && typeof fileJson === "object" && !Array.isArray(fileJson))) {
769
+ function isPxDocument(doc) {
770
+ if (!(doc && typeof doc === "object" && !Array.isArray(doc))) {
1275
771
  return false;
1276
772
  }
1277
- return fileJson.type === "svg";
773
+ return doc.type === "svg";
1278
774
  }
1279
775
  function getAnimatorConfig(doc) {
1280
776
  var _a2;
@@ -1335,7 +831,7 @@ var PixodeskAnimator = (() => {
1335
831
  flattenMemo.set(cfg, flat);
1336
832
  return flat;
1337
833
  }
1338
- function getDefs(doc) {
834
+ function getDefinitions(doc) {
1339
835
  var _a2;
1340
836
  if (!doc) return void 0;
1341
837
  return (_a2 = getAnimatorConfig(doc)) == null ? void 0 : _a2.definitions;
@@ -1343,9 +839,7 @@ var PixodeskAnimator = (() => {
1343
839
  function getBindings(doc) {
1344
840
  var _a2;
1345
841
  if (!doc) return void 0;
1346
- const animateById = (_a2 = getAnimatorConfig(doc)) == null ? void 0 : _a2.animateById;
1347
- if (!animateById) return void 0;
1348
- return Object.entries(animateById).map(([id, anim]) => ({ id: id.startsWith("#") ? id.slice(1) : id, animate: anim }));
842
+ return (_a2 = getAnimatorConfig(doc)) == null ? void 0 : _a2.bindings;
1349
843
  }
1350
844
 
1351
845
  // ../svg-animator-core/src/format/PxAnimatorTypes.ts
@@ -1380,20 +874,20 @@ var PixodeskAnimator = (() => {
1380
874
  // its internal COPY-PASTE payload, which never validates against this schema.)
1381
875
  }));
1382
876
  var anyKf = (kf) => kf;
1383
- var kfTime = (kf) => {
877
+ var keyframeTime = (kf) => {
1384
878
  var _a2, _b;
1385
879
  return (_b = (_a2 = anyKf(kf).time) != null ? _a2 : anyKf(kf).t) != null ? _b : 0;
1386
880
  };
1387
- var kfValue = (kf) => {
881
+ var keyframeValue = (kf) => {
1388
882
  var _a2;
1389
883
  return (_a2 = anyKf(kf).value) != null ? _a2 : anyKf(kf).v;
1390
884
  };
1391
- var kfEasing = (kf) => {
885
+ var keyframeEasing = (kf) => {
1392
886
  var _a2;
1393
887
  return (_a2 = anyKf(kf).easing) != null ? _a2 : anyKf(kf).e;
1394
888
  };
1395
- var kfTangentIn = (kf) => anyKf(kf).tangentIn;
1396
- var kfTangentOut = (kf) => anyKf(kf).tangentOut;
889
+ var keyframeTangentIn = (kf) => anyKf(kf).tangentIn;
890
+ var keyframeTangentOut = (kf) => anyKf(kf).tangentOut;
1397
891
  var PxLoopSchema = implementsInterface()(px.object({
1398
892
  segmentCount: px.number().optional(),
1399
893
  repeatAt: px.enum([PxLoopRepeatAt.start, PxLoopRepeatAt.end]).optional(),
@@ -1447,12 +941,9 @@ var PixodeskAnimator = (() => {
1447
941
  unitsPerEm: px.number(),
1448
942
  glyphs: px.record(PxGlyphSchema)
1449
943
  }));
1450
- var PxDefsSchema = implementsInterface()(px.object({
944
+ var PxDefinitionsSchema = implementsInterface()(px.object({
1451
945
  easings: px.record(px.tuple([px.number(), px.number(), px.number(), px.number()])).optional(),
1452
946
  animations: px.record(PxAnimationDefinitionSchema).optional(),
1453
- // Review §2.6: the schema now matches the declared type — a style preset is a flat
1454
- // record of string|number attribute values, nothing nested.
1455
- styles: px.record(px.record(px.union([px.string(), px.number()]))).optional(),
1456
947
  fonts: px.record(PxGlyphFontSchema).optional()
1457
948
  }));
1458
949
  var PxScrollRangePointSchema = implementsInterface()(px.object({
@@ -1488,7 +979,7 @@ var PixodeskAnimator = (() => {
1488
979
  offset: px.number().optional(),
1489
980
  distance: px.number().optional()
1490
981
  }));
1491
- var PxTimelineEngineSchema = px.enum([PxTimelineEngineExtra.auto, PxTimelineEngineExtra.native, PxTimelineEngineExtra.js]).optional();
982
+ var PxTimelineEngineSchema = px.enum([PxTimelineEngineSetting.auto, PxTimelineEngineSetting.native, PxTimelineEngineSetting.js]).optional();
1492
983
  var PxTimeTimelineSchema = implementsInterface()(px.object({
1493
984
  type: px.literal("time").optional(),
1494
985
  engine: PxTimelineEngineSchema,
@@ -1533,22 +1024,22 @@ var PixodeskAnimator = (() => {
1533
1024
  PxScrollTimelineSchema,
1534
1025
  PxViewTimelineSchema
1535
1026
  ]);
1027
+ var PxBindingSchema = implementsInterface()(px.object({
1028
+ target: px.string(),
1029
+ animateWith: px.array(px.string())
1030
+ }));
1536
1031
  var PxAnimatorConfigSchema = implementsInterface()(px.object({
1537
1032
  // (`mode`, `duration` and `frameRate` live INSIDE `timeline` on the wire — §2.8; they exist
1538
1033
  // at this level only on the runtime view, like the rest of the playback dynamics.)
1539
1034
  // THE spelling of "what advances progress" — clock / scroll / view (review §2.1).
1540
1035
  timeline: PxTimelineSchema.optional(),
1541
- definitions: PxDefsSchema.optional(),
1542
- animateById: px.record(PxElementAnimationSchema).optional(),
1036
+ definitions: PxDefinitionsSchema.optional(),
1037
+ bindings: px.array(PxBindingSchema).optional(),
1543
1038
  debugGlobalName: px.string().optional(),
1544
1039
  // Declared HERE because this is a closed object: an undeclared key would be stripped by
1545
1040
  // `sanitize` and flagged by strict validation on our own files.
1546
1041
  version: px.string().optional()
1547
1042
  }));
1548
- var PxBindingSchema = implementsInterface()(px.object({
1549
- id: px.string(),
1550
- animate: PxElementAnimationSchema
1551
- }));
1552
1043
  var PxAttrValueSchema = px.union([
1553
1044
  px.string(),
1554
1045
  px.number(),
@@ -1631,7 +1122,7 @@ var PixodeskAnimator = (() => {
1631
1122
  PxPropertyAnimationSchema
1632
1123
  ]);
1633
1124
  var PxFillGradientEffectSchema = implementsInterface()(px.object({
1634
- // Contextual kind — the `type` convention, see `PxNodeBase.type`.
1125
+ // Contextual kind — the `type` convention, see `PxNodeBaseSchema.type`.
1635
1126
  type: px.enum([PxGradientType.linear, PxGradientType.radial]),
1636
1127
  start: PxAnimatableVec2Schema.optional(),
1637
1128
  end: PxAnimatableVec2Schema.optional(),
@@ -1668,11 +1159,11 @@ var PixodeskAnimator = (() => {
1668
1159
  textPath: PxTextPathEffectSchema.optional(),
1669
1160
  text: PxTextEffectSchema.optional()
1670
1161
  }));
1671
- function validateNodeEffects(root, opts) {
1162
+ function validateNodeEffects(root, options) {
1672
1163
  const warnings = [];
1673
1164
  const walk = (node, path) => {
1674
1165
  if (node && node.effects) {
1675
- const ctx = { errors: [], warnings: [], strict: !!(opts == null ? void 0 : opts.strict) };
1166
+ const ctx = { errors: [], warnings: [], strict: !!(options == null ? void 0 : options.strict) };
1676
1167
  const ok = PxEffectsSchema.isValid(node.effects, ctx, [path + ".effects"]);
1677
1168
  if (!ok) {
1678
1169
  for (const err of ctx.errors) warnings.push(err);
@@ -1726,209 +1217,657 @@ var PixodeskAnimator = (() => {
1726
1217
  walk(root, "root");
1727
1218
  return problems;
1728
1219
  }
1729
- function validateVersionStamp(doc) {
1730
- var _a2;
1731
- const version = (_a2 = getAnimatorConfig(doc)) == null ? void 0 : _a2.version;
1732
- if (version === void 0) return [];
1733
- if (parseWireVersion(version) !== void 0) return [];
1734
- return ["root.animator.version: " + JSON.stringify(version) + ' is not a version stamp ("a.b" or "a.b.c") \u2014 it reads as unstamped'];
1220
+ function validateVersionStamp(doc) {
1221
+ var _a2;
1222
+ const version = (_a2 = getAnimatorConfig(doc)) == null ? void 0 : _a2.version;
1223
+ if (version === void 0) return [];
1224
+ if (parseWireVersion(version) !== void 0) return [];
1225
+ return ["root.animator.version: " + JSON.stringify(version) + ' is not a version stamp ("a.b" or "a.b.c") \u2014 it reads as unstamped'];
1226
+ }
1227
+ function validateDocument(doc, options) {
1228
+ var _a2;
1229
+ const strict = (options == null ? void 0 : options.strict) !== false;
1230
+ const ctx = { errors: [], warnings: [], strict };
1231
+ const problems = PxAnimatedSvgDocumentSchema.isValid(doc, ctx, ["root"]) ? [] : [...ctx.errors];
1232
+ if (doc && typeof doc === "object") {
1233
+ for (const w of validateNodeEffects(doc, { strict })) {
1234
+ if (!problems.includes(w)) problems.push(w);
1235
+ }
1236
+ const defs = (_a2 = getAnimatorConfig(doc)) == null ? void 0 : _a2.definitions;
1237
+ for (const w of validateGlyphFontRefs(doc, defs == null ? void 0 : defs.fonts)) {
1238
+ if (!problems.includes(w)) problems.push(w);
1239
+ }
1240
+ for (const w of validateEasingRefs(doc, defs == null ? void 0 : defs.easings)) {
1241
+ if (!problems.includes(w)) problems.push(w);
1242
+ }
1243
+ for (const w of validateVersionStamp(doc)) {
1244
+ if (!problems.includes(w)) problems.push(w);
1245
+ }
1246
+ }
1247
+ return problems;
1248
+ }
1249
+ var PxNodeBaseSchema = px.openObject({
1250
+ // CONVENTION (SCHEMA-DESIGN R1 / issues N4): `type` is the ONE word for "what
1251
+ // kind of thing is this", discriminated by its CARRIER — here the node TAG
1252
+ // (`rect`, `text`), and inside a sub-object that object's kind (`fillGradient.type`,
1253
+ // `fillGradient.type`, editor `preset.type`). Each sits in its own object, so
1254
+ // the carrier disambiguates completely; synonyms (`cloneKind`, `presetShape`)
1255
+ // would add words that all mean "type" and still need the carrier to read.
1256
+ // Guarding a `type` SLOT against a wrong VALUE is the job of strict enums
1257
+ // (issues V3), never of distinct key names.
1258
+ type: px.string(),
1259
+ // The escape hatch for elements that carry a REAL `type` attribute — `<feTurbulence
1260
+ // type="fractalNoise">`, `<feFuncR type="table">`, `<feColorMatrix type="saturate">`.
1261
+ // `type` is taken by the tag name, so the attribute travels here and the renderer puts
1262
+ // it back (`PxAnimatorDOM.renderNode`, `PxRnRender`). Declared here — not merely
1263
+ // documented — because a wire key that is not in a schema is invisible to the
1264
+ // minifier's reserve list and gets renamed (dev-docs/plans/minification-boundary.md §1.1).
1265
+ domType: px.string().optional(),
1266
+ // Text content of a `<text>` / `<tspan>`. Declared, so a non-string value is a schema error
1267
+ // and the minifier reserves the key; `text` is NOT an alias for it and is not read anywhere.
1268
+ textContent: px.string().optional(),
1269
+ id: px.string().optional(),
1270
+ meta: px.any().optional(),
1271
+ // Player-effects bucket emitted by the Editor's lightweight design format.
1272
+ // Consumed and removed by `materializeNodeEffects` before any other normalization
1273
+ // (see `createAnimatorImpl`), so downstream code never sees it.
1274
+ effects: PxEffectsSchema.optional(),
1275
+ // `PxElementAnimation` (not just `PxAnimationDefinition`) — accepts
1276
+ // string ref / array of refs / inline definition / mixed array; mirrors
1277
+ // `node.animate` values and what `processNode` resolves at runtime.
1278
+ animate: PxElementAnimationSchema.optional(),
1279
+ style: px.record(px.union([px.string(), px.number()])).optional()
1280
+ }, PxAttrValueSchema);
1281
+ var PxNodeSchema = px.openObject(__spreadProps(__spreadValues({}, PxNodeBaseSchema._shape), {
1282
+ children: px.lazy(() => px.array(PxNodeSchema), []).optional()
1283
+ }), PxAttrValueSchema);
1284
+ var PxSvgNodeRootSchema = px.object({
1285
+ // `"100%"` and other SVG length strings are legal here — a number-only slot rejected
1286
+ // real documents (e.g. apple-store-look-14-main.json) at the root <svg>.
1287
+ width: px.union([px.number(), px.string()]).optional(),
1288
+ height: px.union([px.number(), px.string()]).optional(),
1289
+ viewBox: px.string().optional(),
1290
+ animator: PxAnimatorConfigSchema.optional()
1291
+ });
1292
+ var PxAnimatedSvgDocumentSchema = px.openObject(__spreadProps(__spreadValues(__spreadValues({}, PxNodeBaseSchema._shape), PxSvgNodeRootSchema._shape), {
1293
+ type: px.literal("svg"),
1294
+ // override string → literal to require 'svg'
1295
+ children: px.array(PxNodeSchema).optional()
1296
+ }), PxAttrValueSchema);
1297
+ var PxBezierPathSchema = implementsInterface()(px.object({
1298
+ v: px.array(px.array(px.number())),
1299
+ i: px.array(px.array(px.number())).optional(),
1300
+ o: px.array(px.array(px.number())).optional(),
1301
+ c: px.boolean().optional()
1302
+ }));
1303
+
1304
+ // ../svg-animator-core/src/util/PxIdUtil.ts
1305
+ var _idCounter = 0;
1306
+ function generateUniqueId() {
1307
+ const timestamp = Date.now().toString(36);
1308
+ const counter = (++_idCounter).toString(36);
1309
+ const random = Math.random().toString(36).substring(2, 6);
1310
+ return "_px_" + timestamp + counter + random;
1311
+ }
1312
+ function deepClone(value) {
1313
+ if (value === null || typeof value !== "object") return value;
1314
+ if (Array.isArray(value)) return value.map((item) => deepClone(item));
1315
+ const obj = value;
1316
+ const cloned = {};
1317
+ for (const key of Object.keys(obj)) {
1318
+ cloned[key] = deepClone(obj[key]);
1319
+ }
1320
+ return cloned;
1321
+ }
1322
+ function generateNewIds(doc) {
1323
+ var _a2;
1324
+ const cloned = deepClone(doc);
1325
+ const idMap = /* @__PURE__ */ new Map();
1326
+ const hashRefAttrs = /* @__PURE__ */ new Set(["href", "xlink:href"]);
1327
+ const urlRefAttrs = /* @__PURE__ */ new Set([
1328
+ "fill",
1329
+ "stroke",
1330
+ "clip-path",
1331
+ "clipPath",
1332
+ "mask",
1333
+ "marker",
1334
+ "marker-start",
1335
+ "marker-mid",
1336
+ "marker-end",
1337
+ "filter",
1338
+ "flood-color",
1339
+ "lighting-color"
1340
+ ]);
1341
+ const directIdRefAttrs = /* @__PURE__ */ new Set(["targetId", "boundElementId"]);
1342
+ const isEffectSourceRef = (key, parentKey) => key === "source" && (parentKey === "maskedBy" || parentKey === "clone");
1343
+ function collectIds(node) {
1344
+ if (!node || typeof node !== "object") return;
1345
+ if (node.id && typeof node.id === "string") {
1346
+ const oldId = node.id;
1347
+ const newId = generateUniqueId();
1348
+ idMap.set(oldId, newId);
1349
+ node.id = newId;
1350
+ } else if (node.animate) {
1351
+ node.id = generateUniqueId();
1352
+ }
1353
+ if (Array.isArray(node.children)) {
1354
+ for (const child of node.children) {
1355
+ collectIds(child);
1356
+ }
1357
+ }
1358
+ }
1359
+ function updateRefs(node, parentKey) {
1360
+ if (!node || typeof node !== "object") return;
1361
+ for (const [key, value] of Object.entries(node)) {
1362
+ if (key === "children") {
1363
+ if (Array.isArray(value)) {
1364
+ for (const child of value) {
1365
+ updateRefs(child);
1366
+ }
1367
+ }
1368
+ continue;
1369
+ }
1370
+ if (typeof value === "string") {
1371
+ if (hashRefAttrs.has(key) && value.startsWith("#")) {
1372
+ const oldId = value.slice(1);
1373
+ const newId = idMap.get(oldId);
1374
+ if (newId) {
1375
+ node[key] = "#" + newId;
1376
+ }
1377
+ } else if (urlRefAttrs.has(key)) {
1378
+ node[key] = replaceUrlRefs(value, idMap);
1379
+ } else if (directIdRefAttrs.has(key) || isEffectSourceRef(key, parentKey)) {
1380
+ const hasHash = value.startsWith("#");
1381
+ const newId = idMap.get(hasHash ? value.slice(1) : value);
1382
+ if (newId) {
1383
+ node[key] = hasHash ? "#" + newId : newId;
1384
+ }
1385
+ } else if (value.includes("url(#")) {
1386
+ node[key] = replaceUrlRefs(value, idMap);
1387
+ }
1388
+ } else if (key === "style" && typeof value === "object" && value !== null) {
1389
+ for (const [styleProp, styleValue] of Object.entries(value)) {
1390
+ if (typeof styleValue === "string") {
1391
+ value[styleProp] = replaceUrlRefs(styleValue, idMap);
1392
+ }
1393
+ }
1394
+ } else if (typeof value === "object" && value !== null) {
1395
+ updateRefs(value, key);
1396
+ }
1397
+ }
1398
+ }
1399
+ collectIds(cloned);
1400
+ updateRefs(cloned);
1401
+ const docBindings = (_a2 = cloned.animator) == null ? void 0 : _a2.bindings;
1402
+ if (Array.isArray(docBindings)) {
1403
+ const updatedBindings = docBindings.map((binding) => {
1404
+ var _a3;
1405
+ const hashed = binding.target.startsWith("#");
1406
+ const id = hashed ? binding.target.slice(1) : binding.target;
1407
+ const newId = (_a3 = idMap.get(id)) != null ? _a3 : id;
1408
+ return __spreadProps(__spreadValues({}, binding), { target: hashed ? "#" + newId : newId });
1409
+ });
1410
+ cloned.animator = __spreadProps(__spreadValues({}, cloned.animator), { bindings: updatedBindings });
1411
+ }
1412
+ return cloned;
1413
+ }
1414
+ function replaceUrlRefs(value, idMap) {
1415
+ return value.replace(/url\(#([^)]+)\)/g, (match, oldId) => {
1416
+ const newId = idMap.get(oldId);
1417
+ return newId ? "url(#" + newId + ")" : match;
1418
+ });
1419
+ }
1420
+
1421
+ // ../svg-animator-core/src/util/PxAnimatorUtil.ts
1422
+ function bezierToSvgPath(path, forceCurves = false) {
1423
+ var _a2, _b, _c, _d;
1424
+ const v = path.v;
1425
+ const i = path.i;
1426
+ const o = path.o;
1427
+ const c = path.c;
1428
+ if (!v.length) return "";
1429
+ const d = [];
1430
+ const len = v.length;
1431
+ d.push("M" + v[0][0] + "," + v[0][1]);
1432
+ for (let idx = 1; idx < len; idx++) {
1433
+ const prevV = v[idx - 1];
1434
+ const prevO = (_a2 = o == null ? void 0 : o[idx - 1]) != null ? _a2 : prevV;
1435
+ const currI = (_b = i == null ? void 0 : i[idx]) != null ? _b : v[idx];
1436
+ const currV = v[idx];
1437
+ const isLine = !forceCurves && (prevO[0] === prevV[0] && prevO[1] === prevV[1]) && (currI[0] === currV[0] && currI[1] === currV[1]);
1438
+ if (isLine) {
1439
+ d.push("L" + currV[0] + "," + currV[1]);
1440
+ } else {
1441
+ d.push("C" + prevO[0] + "," + prevO[1] + "," + currI[0] + "," + currI[1] + "," + currV[0] + "," + currV[1]);
1442
+ }
1443
+ }
1444
+ if (c && len > 0) {
1445
+ const lastV = v[len - 1];
1446
+ const lastO = (_c = o == null ? void 0 : o[len - 1]) != null ? _c : lastV;
1447
+ const firstI = (_d = i == null ? void 0 : i[0]) != null ? _d : v[0];
1448
+ const firstV = v[0];
1449
+ const isLine = !forceCurves && (lastO[0] === lastV[0] && lastO[1] === lastV[1]) && (firstI[0] === firstV[0] && firstI[1] === firstV[1]);
1450
+ if (!isLine) {
1451
+ d.push("C" + lastO[0] + "," + lastO[1] + "," + firstI[0] + "," + firstI[1] + "," + firstV[0] + "," + firstV[1]);
1452
+ }
1453
+ d.push("z");
1454
+ }
1455
+ return d.join("");
1456
+ }
1457
+ function interpolateNum(a, b, t) {
1458
+ return a + (b - a) * t;
1459
+ }
1460
+ function interpolateVec(a, b, t) {
1461
+ const res = [];
1462
+ const count = Math.max(a.length, b.length);
1463
+ for (let i = 0; i < count; i++) {
1464
+ res[i] = interpolateNum(a[i] || 0, b[i] || 0, t);
1465
+ }
1466
+ return res;
1467
+ }
1468
+ function interpolateColor(a, b, t) {
1469
+ return [
1470
+ interpolateNum(a[0] || 0, b[0] || 0, t),
1471
+ interpolateNum(a[1] || 0, b[1] || 0, t),
1472
+ interpolateNum(a[2] || 0, b[2] || 0, t),
1473
+ interpolateNum(a[3] === void 0 ? 1 : a[3], b[3] === void 0 ? 1 : b[3], t)
1474
+ ];
1475
+ }
1476
+ function interpolateBeziers(paths1, paths2, progress) {
1477
+ const count = Math.max(paths1.length, paths2.length);
1478
+ const res = [];
1479
+ for (let i = 0; i < count; i++) {
1480
+ res.push(interpolateBezier(paths1[i], paths2[i], progress));
1481
+ }
1482
+ return res;
1483
+ }
1484
+ function interpolateBezier(path1, path2, progress) {
1485
+ var _a2, _b, _c, _d, _e, _f, _g, _h, _i;
1486
+ if (!path1 || !path2) return path1 || path2 || { v: [] };
1487
+ const t = Math.min(Math.max(progress, 0), 1);
1488
+ const len = Math.min(path1.v.length, path2.v.length);
1489
+ const v = [];
1490
+ const i = [];
1491
+ const o = [];
1492
+ for (let idx = 0; idx < len; idx++) {
1493
+ const v1 = path1.v[idx];
1494
+ const v2 = path2.v[idx];
1495
+ v.push(interpolateVec(v1, v2, t));
1496
+ const i1 = (_b = (_a2 = path1.i) == null ? void 0 : _a2[idx]) != null ? _b : v1;
1497
+ const i2 = (_d = (_c = path2.i) == null ? void 0 : _c[idx]) != null ? _d : v2;
1498
+ i.push(interpolateVec(i1, i2, t));
1499
+ const o1 = (_f = (_e = path1.o) == null ? void 0 : _e[idx]) != null ? _f : v1;
1500
+ const o2 = (_h = (_g = path2.o) == null ? void 0 : _g[idx]) != null ? _h : v2;
1501
+ o.push(interpolateVec(o1, o2, t));
1502
+ }
1503
+ return { v, i: i.length ? i : void 0, o: o.length ? o : void 0, c: (_i = path1.c) != null ? _i : path2.c };
1504
+ }
1505
+ function remap(value, inMin, inMax, outMin, outMax) {
1506
+ if (inMax === inMin) return outMin;
1507
+ const t = (value - inMin) / (inMax - inMin);
1508
+ return outMin + t * (outMax - outMin);
1509
+ }
1510
+ function solveCubicBezierX(p1x, p2x, x) {
1511
+ if (x <= 0) return 0;
1512
+ if (x >= 1) return 1;
1513
+ const cx = 3 * p1x;
1514
+ const bx = 3 * (p2x - p1x) - cx;
1515
+ const ax = 1 - cx - bx;
1516
+ function sampleX(t) {
1517
+ return ((ax * t + bx) * t + cx) * t;
1518
+ }
1519
+ function sampleDX(t) {
1520
+ return (3 * ax * t + 2 * bx) * t + cx;
1521
+ }
1522
+ let t2 = x;
1523
+ let t0 = 0;
1524
+ let t1 = 1;
1525
+ for (let i = 0; i < 8; i++) {
1526
+ const x2 = sampleX(t2) - x;
1527
+ if (Math.abs(x2) < 1e-6) return t2;
1528
+ const d2 = sampleDX(t2);
1529
+ if (Math.abs(d2) < 1e-6) break;
1530
+ t2 -= x2 / d2;
1531
+ }
1532
+ t2 = x;
1533
+ while (t0 < t1) {
1534
+ const x2 = sampleX(t2);
1535
+ if (Math.abs(x2 - x) < 1e-6) return t2;
1536
+ if (x > x2) t0 = t2;
1537
+ else t1 = t2;
1538
+ t2 = (t1 + t0) / 2;
1539
+ }
1540
+ return t2;
1541
+ }
1542
+ function cubicBezier(easing) {
1543
+ const [p1x, p1y, p2x, p2y] = easing;
1544
+ const cy = 3 * p1y;
1545
+ const by = 3 * (p2y - p1y) - cy;
1546
+ const ay = 1 - cy - by;
1547
+ function sampleCurveY(t) {
1548
+ return ((ay * t + by) * t + cy) * t;
1549
+ }
1550
+ return function(x) {
1551
+ return sampleCurveY(solveCubicBezierX(p1x, p2x, x));
1552
+ };
1553
+ }
1554
+ function lerp2(a, b, t) {
1555
+ return [a[0] + (b[0] - a[0]) * t, a[1] + (b[1] - a[1]) * t];
1556
+ }
1557
+ function subdivideCubicBezier(p0, p1, p2, p3, t) {
1558
+ const q0 = lerp2(p0, p1, t);
1559
+ const q1 = lerp2(p1, p2, t);
1560
+ const q2 = lerp2(p2, p3, t);
1561
+ const r0 = lerp2(q0, q1, t);
1562
+ const r1 = lerp2(q1, q2, t);
1563
+ const s = lerp2(r0, r1, t);
1564
+ return {
1565
+ left: [p0, q0, r0, s],
1566
+ right: [s, r1, q2, p3]
1567
+ };
1568
+ }
1569
+ function splitEasing(easing, xFraction) {
1570
+ if (!easing) return { left: void 0, right: void 0 };
1571
+ if (xFraction <= 0) return { left: void 0, right: easing };
1572
+ if (xFraction >= 1) return { left: easing, right: void 0 };
1573
+ const [x1, y1, x2, y2] = easing;
1574
+ const t = solveCubicBezierX(x1, x2, xFraction);
1575
+ const p0 = [0, 0];
1576
+ const p1 = [x1, y1];
1577
+ const p2 = [x2, y2];
1578
+ const p3 = [1, 1];
1579
+ const { left, right } = subdivideCubicBezier(p0, p1, p2, p3, t);
1580
+ const sx = left[3][0];
1581
+ const sy = left[3][1];
1582
+ let leftEasing;
1583
+ if (sx > 1e-9 && Math.abs(sy) > 1e-9) {
1584
+ leftEasing = [
1585
+ left[1][0] / sx,
1586
+ left[1][1] / sy,
1587
+ left[2][0] / sx,
1588
+ left[2][1] / sy
1589
+ ];
1590
+ }
1591
+ let rightEasing;
1592
+ const rx = 1 - sx;
1593
+ const ry = 1 - sy;
1594
+ if (rx > 1e-9 && Math.abs(ry) > 1e-9) {
1595
+ rightEasing = [
1596
+ (right[1][0] - sx) / rx,
1597
+ (right[1][1] - sy) / ry,
1598
+ (right[2][0] - sx) / rx,
1599
+ (right[2][1] - sy) / ry
1600
+ ];
1601
+ }
1602
+ return { left: leftEasing, right: rightEasing };
1603
+ }
1604
+ function reverseEasing(easing) {
1605
+ if (!easing) return void 0;
1606
+ return [1 - easing[2], 1 - easing[3], 1 - easing[0], 1 - easing[1]];
1607
+ }
1608
+ function toRGBA(color) {
1609
+ const r = Math.round(color[0] * 255);
1610
+ const g = Math.round(color[1] * 255);
1611
+ const b = Math.round(color[2] * 255);
1612
+ return color.length === 4 ? "rgba(" + r + "," + g + "," + b + "," + color[3] + ")" : "rgb(" + r + "," + g + "," + b + ")";
1613
+ }
1614
+ function parseRgba(s) {
1615
+ var _a2;
1616
+ const inner = (_a2 = s.match(/rgba?\((.*)\)/)) == null ? void 0 : _a2[1];
1617
+ if (!inner) throw new Error("Invalid rgb/rgba format");
1618
+ const parts = inner.split(",").map((v) => +v.trim());
1619
+ return [parts[0] / 255, parts[1] / 255, parts[2] / 255, ...parts[3] !== void 0 ? [parts[3]] : []];
1620
+ }
1621
+ function parseHex(s) {
1622
+ const hex = s.slice(1);
1623
+ const isShort = hex.length <= 4;
1624
+ const r = isShort ? hex[0] + hex[0] : hex.slice(0, 2);
1625
+ const g = isShort ? hex[1] + hex[1] : hex.slice(2, 4);
1626
+ const b = isShort ? hex[2] + hex[2] : hex.slice(4, 6);
1627
+ const a = hex.length === 4 ? hex[3] + hex[3] : hex.length === 8 ? hex.slice(6, 8) : null;
1628
+ const result = [
1629
+ parseInt(r, 16) / 255,
1630
+ parseInt(g, 16) / 255,
1631
+ parseInt(b, 16) / 255
1632
+ ];
1633
+ if (a !== null) {
1634
+ result.push(parseInt(a, 16) / 255);
1635
+ }
1636
+ return result;
1637
+ }
1638
+ function parseColor(s) {
1639
+ if (!s) return void 0;
1640
+ if (Array.isArray(s)) return s;
1641
+ if (typeof s !== "string") return void 0;
1642
+ if (s.startsWith("#")) {
1643
+ return parseHex(s);
1644
+ } else if (s.startsWith("rgb")) {
1645
+ return parseRgba(s);
1646
+ } else {
1647
+ console.warn("Unsupported color format: " + s);
1648
+ }
1649
+ return void 0;
1650
+ }
1651
+ var PX_COLOR_ATTR_NAMES = /* @__PURE__ */ new Set(["color", "fill", "flood-color", "lighting-color", "stop-color", "stroke"]);
1652
+ var PX_TRANSFORM_FN_NAMES = /* @__PURE__ */ new Set(["translate", "rotate", "scale", "skew"]);
1653
+ var PX_PCT_BASED_ATTR_NAMES = /* @__PURE__ */ new Set(["offset-distance", "offsetDistance"]);
1654
+ function composeTransformParts(parts, opts) {
1655
+ var _a2;
1656
+ if (!parts) return "";
1657
+ const withUnits = (_a2 = opts == null ? void 0 : opts.withUnits) != null ? _a2 : true;
1658
+ const segs = [];
1659
+ const t = parts.translate;
1660
+ const o = parts.origin;
1661
+ const r = parts.rotate;
1662
+ const k = parts.skew;
1663
+ const s = parts.scale;
1664
+ const tu = withUnits ? "px" : "";
1665
+ const ru = withUnits ? "deg" : "";
1666
+ if (t) segs.push("translate(" + t[0] + tu + "," + t[1] + tu + ")");
1667
+ if (o) segs.push("translate(" + o[0] + tu + "," + o[1] + tu + ")");
1668
+ if (r !== void 0 && r !== null) segs.push("rotate(" + r + ru + ")");
1669
+ if (k !== void 0 && k !== null) segs.push("skewX(" + k + ru + ")");
1670
+ if (s) segs.push("scale(" + s[0] + "," + s[1] + ")");
1671
+ if (o) segs.push("translate(" + -o[0] + tu + "," + -o[1] + tu + ")");
1672
+ return segs.join("");
1673
+ }
1674
+ function parseTransformParts(str2) {
1675
+ var _a2, _b;
1676
+ if (!str2 || typeof str2 !== "string") return void 0;
1677
+ const out = {};
1678
+ const re = /([a-zA-Z]+)\s*\(([^)]*)\)/g;
1679
+ const order = ["translate", "rotate", "skewX", "scale"];
1680
+ let lastIdx = -1;
1681
+ let m;
1682
+ while ((m = re.exec(str2)) !== null) {
1683
+ const fn = m[1];
1684
+ const idx = order.indexOf(fn);
1685
+ if (idx < 0 || idx <= lastIdx) return void 0;
1686
+ lastIdx = idx;
1687
+ const nums = m[2].split(/[\s,]+/).filter(Boolean).map(Number);
1688
+ if (nums.some((n) => Number.isNaN(n))) return void 0;
1689
+ if (fn === "translate") {
1690
+ if (nums.length < 1 || nums.length > 2) return void 0;
1691
+ out.translate = [nums[0], (_a2 = nums[1]) != null ? _a2 : 0];
1692
+ } else if (fn === "rotate") {
1693
+ if (nums.length !== 1) return void 0;
1694
+ out.rotate = nums[0];
1695
+ } else if (fn === "skewX") {
1696
+ if (nums.length !== 1) return void 0;
1697
+ out.skew = nums[0];
1698
+ } else {
1699
+ if (nums.length < 1 || nums.length > 2) return void 0;
1700
+ out.scale = [nums[0], (_b = nums[1]) != null ? _b : nums[0]];
1701
+ }
1702
+ }
1703
+ if (str2.replace(/([a-zA-Z]+)\s*\(([^)]*)\)/g, "").replace(/[\s,]/g, "").length) return void 0;
1704
+ return Object.keys(out).length ? out : void 0;
1705
+ }
1706
+ var PX_STYLE_ATTR_NAMES = /* @__PURE__ */ new Set(["offset-distance", "offsetDistance"]);
1707
+ var PX_DEFAULT_DURATION_MS = 1e3;
1708
+ function kebabToCamelCaseWord(kebab) {
1709
+ return kebab.includes("-") ? kebab.replace(/-([a-z])/g, (_, letter) => letter.toUpperCase()) : kebab;
1710
+ }
1711
+ function isCamelCaseWord(word) {
1712
+ return !word.includes("-") && /[a-z][A-Z]/.test(word);
1713
+ }
1714
+ var SVG_CAMEL_CASE_ATTRS = /* @__PURE__ */ new Set([
1715
+ // Transform/positioning
1716
+ "viewBox",
1717
+ "preserveAspectRatio",
1718
+ // Gradient
1719
+ "gradientUnits",
1720
+ "gradientTransform",
1721
+ "spreadMethod",
1722
+ // Pattern
1723
+ "patternUnits",
1724
+ "patternContentUnits",
1725
+ "patternTransform",
1726
+ // Clipping/masking
1727
+ "clipPathUnits",
1728
+ "maskUnits",
1729
+ "maskContentUnits",
1730
+ // Marker (SVG spec keeps these camelCase, like viewBox)
1731
+ "markerUnits",
1732
+ "markerWidth",
1733
+ "markerHeight",
1734
+ "refX",
1735
+ "refY",
1736
+ // Text
1737
+ "textLength",
1738
+ "lengthAdjust",
1739
+ "startOffset",
1740
+ // Filter
1741
+ "filterUnits",
1742
+ "primitiveUnits",
1743
+ "tableValues",
1744
+ // feFuncR/G/B/A transfer table (type="table")
1745
+ "stdDeviation",
1746
+ "baseFrequency",
1747
+ "numOctaves",
1748
+ "surfaceScale",
1749
+ "diffuseConstant",
1750
+ "specularConstant",
1751
+ "specularExponent",
1752
+ "kernelMatrix",
1753
+ "kernelUnitLength",
1754
+ "edgeMode",
1755
+ "preserveAlpha",
1756
+ "targetX",
1757
+ "targetY"
1758
+ // // Animation
1759
+ // 'attributeName',
1760
+ // 'attributeType',
1761
+ // 'calcMode',
1762
+ // 'keyTimes',
1763
+ // 'keySplines',
1764
+ // 'repeatCount',
1765
+ // 'repeatDur'
1766
+ ]);
1767
+ function camelCaseToKebabWordIfNeeded(camel) {
1768
+ return SVG_CAMEL_CASE_ATTRS.has(camel) ? camel : camel.replace(/([a-z0-9])([A-Z])/g, "$1-$2").toLowerCase();
1769
+ }
1770
+ function clamp(value, min, max) {
1771
+ return Math.max(min, Math.min(value, max));
1735
1772
  }
1736
- function validateDocument(doc, opts) {
1737
- var _a2;
1738
- const strict = (opts == null ? void 0 : opts.strict) !== false;
1739
- const ctx = { errors: [], warnings: [], strict };
1740
- const problems = PxAnimatedSvgDocumentSchema.isValid(doc, ctx, ["root"]) ? [] : [...ctx.errors];
1741
- if (doc && typeof doc === "object") {
1742
- for (const w of validateNodeEffects(doc, { strict })) {
1743
- if (!problems.includes(w)) problems.push(w);
1744
- }
1745
- const defs = (_a2 = getAnimatorConfig(doc)) == null ? void 0 : _a2.definitions;
1746
- for (const w of validateGlyphFontRefs(doc, defs == null ? void 0 : defs.fonts)) {
1747
- if (!problems.includes(w)) problems.push(w);
1748
- }
1749
- for (const w of validateEasingRefs(doc, defs == null ? void 0 : defs.easings)) {
1750
- if (!problems.includes(w)) problems.push(w);
1751
- }
1752
- for (const w of validateVersionStamp(doc)) {
1753
- if (!problems.includes(w)) problems.push(w);
1754
- }
1773
+ function bezier2D_pointAt(P0, P1, P2, P3, t) {
1774
+ if (t <= 0) return [P0[0], P0[1]];
1775
+ if (t >= 1) return [P3[0], P3[1]];
1776
+ const u = 1 - t;
1777
+ const u2 = u * u;
1778
+ const u3 = u2 * u;
1779
+ const t2 = t * t;
1780
+ const t3 = t2 * t;
1781
+ const w0 = u3;
1782
+ const w1 = 3 * t * u2;
1783
+ const w2 = 3 * t2 * u;
1784
+ const w3 = t3;
1785
+ return [
1786
+ w0 * P0[0] + w1 * P1[0] + w2 * P2[0] + w3 * P3[0],
1787
+ w0 * P0[1] + w1 * P1[1] + w2 * P2[1] + w3 * P3[1]
1788
+ ];
1789
+ }
1790
+ var BEZIER_T_NUDGE = 1e-4;
1791
+ function bezier2D_derivativeAt(P0, P1, P2, P3, t) {
1792
+ const result = _bezier2D_derivativeAtRaw(P0, P1, P2, P3, t);
1793
+ if (result[0] === 0 && result[1] === 0) {
1794
+ const nudgedT = t < 0.5 ? t + BEZIER_T_NUDGE : t - BEZIER_T_NUDGE;
1795
+ return _bezier2D_derivativeAtRaw(P0, P1, P2, P3, nudgedT);
1755
1796
  }
1756
- return problems;
1797
+ return result;
1757
1798
  }
1758
- var PxNodeBase = px.openObject({
1759
- // CONVENTION (SCHEMA-DESIGN R1 / issues N4): `type` is the ONE word for "what
1760
- // kind of thing is this", discriminated by its CARRIER — here the node TAG
1761
- // (`rect`, `text`), and inside a sub-object that object's kind (`fillGradient.type`,
1762
- // `fillGradient.type`, editor `preset.type`). Each sits in its own object, so
1763
- // the carrier disambiguates completely; synonyms (`cloneKind`, `presetShape`)
1764
- // would add words that all mean "type" and still need the carrier to read.
1765
- // Guarding a `type` SLOT against a wrong VALUE is the job of strict enums
1766
- // (issues V3), never of distinct key names.
1767
- type: px.string(),
1768
- // The escape hatch for elements that carry a REAL `type` attribute — `<feTurbulence
1769
- // type="fractalNoise">`, `<feFuncR type="table">`, `<feColorMatrix type="saturate">`.
1770
- // `type` is taken by the tag name, so the attribute travels here and the renderer puts
1771
- // it back (`PxAnimatorDOM.renderNode`, `PxRnRender`). Declared here — not merely
1772
- // documented — because a wire key that is not in a schema is invisible to the
1773
- // minifier's reserve list and gets renamed (MINIFICATION-BOUNDARY-PLAN.md §1.1).
1774
- domType: px.string().optional(),
1775
- // Text content of a `<text>` / `<tspan>`. Declared, so a non-string value is a schema error
1776
- // and the minifier reserves the key; `text` is NOT an alias for it and is not read anywhere.
1777
- textContent: px.string().optional(),
1778
- id: px.string().optional(),
1779
- meta: px.any().optional(),
1780
- // Player-effects bucket emitted by the Editor's lightweight design format.
1781
- // Consumed and removed by `applyPlayerEffects` before any other normalization
1782
- // (see `createAnimatorImpl`), so downstream code never sees it.
1783
- effects: PxEffectsSchema.optional(),
1784
- // `PxElementAnimation` (not just `PxAnimationDefinition`) — accepts
1785
- // string ref / array of refs / inline definition / mixed array; mirrors
1786
- // `animator.animateById` map values and what `processNode` resolves at runtime.
1787
- animate: PxElementAnimationSchema.optional(),
1788
- style: px.union([px.string(), px.record(px.union([px.string(), px.number()]))]).optional()
1789
- }, PxAttrValueSchema);
1790
- var PxNodeSchema = px.openObject(__spreadProps(__spreadValues({}, PxNodeBase._shape), {
1791
- children: px.lazy(() => px.array(PxNodeSchema), []).optional()
1792
- }), PxAttrValueSchema);
1793
- var PxSvgNodeExtra = px.object({
1794
- // `"100%"` and other SVG length strings are legal here — a number-only slot rejected
1795
- // real documents (e.g. apple-store-look-14-main.json) at the root <svg>.
1796
- width: px.union([px.number(), px.string()]).optional(),
1797
- height: px.union([px.number(), px.string()]).optional(),
1798
- viewBox: px.string().optional(),
1799
- animator: PxAnimatorConfigSchema.optional()
1800
- });
1801
- var PxAnimatedSvgDocumentSchema = px.openObject(__spreadProps(__spreadValues(__spreadValues({}, PxNodeBase._shape), PxSvgNodeExtra._shape), {
1802
- type: px.literal("svg"),
1803
- // override string → literal to require 'svg'
1804
- children: px.array(PxNodeSchema).optional()
1805
- }), PxAttrValueSchema);
1806
- var PxBezierPathSchema = implementsInterface()(px.object({
1807
- v: px.array(px.array(px.number())),
1808
- i: px.array(px.array(px.number())).optional(),
1809
- o: px.array(px.array(px.number())).optional(),
1810
- c: px.boolean().optional()
1811
- }));
1812
-
1813
- // ../svg-animator-core/src/util/PxIdUtil.ts
1814
- var _idCounter = 0;
1815
- function generateUniqueId() {
1816
- const timestamp = Date.now().toString(36);
1817
- const counter = (++_idCounter).toString(36);
1818
- const random = Math.random().toString(36).substring(2, 6);
1819
- return "_px_" + timestamp + counter + random;
1799
+ function _bezier2D_derivativeAtRaw(P0, P1, P2, P3, t) {
1800
+ const u = 1 - t;
1801
+ const a = 3 * u * u;
1802
+ const b = 6 * t * u;
1803
+ const c = 3 * t * t;
1804
+ return [
1805
+ a * (P1[0] - P0[0]) + b * (P2[0] - P1[0]) + c * (P3[0] - P2[0]),
1806
+ a * (P1[1] - P0[1]) + b * (P2[1] - P1[1]) + c * (P3[1] - P2[1])
1807
+ ];
1820
1808
  }
1821
- function deepClone(value) {
1822
- if (value === null || typeof value !== "object") return value;
1823
- if (Array.isArray(value)) return value.map((item) => deepClone(item));
1824
- const obj = value;
1825
- const cloned = {};
1826
- for (const key of Object.keys(obj)) {
1827
- cloned[key] = deepClone(obj[key]);
1809
+ function bezier2D_arcLengthLUT(P0, P1, P2, P3, steps = 100) {
1810
+ const n = steps + 1;
1811
+ const ts = new Float64Array(n);
1812
+ const ds = new Float64Array(n);
1813
+ let prev = bezier2D_pointAt(P0, P1, P2, P3, 0);
1814
+ ts[0] = 0;
1815
+ ds[0] = 0;
1816
+ let cum = 0;
1817
+ for (let i = 1; i < n; i++) {
1818
+ const t = i / steps;
1819
+ const cur = bezier2D_pointAt(P0, P1, P2, P3, t);
1820
+ const dx = cur[0] - prev[0];
1821
+ const dy = cur[1] - prev[1];
1822
+ cum += Math.sqrt(dx * dx + dy * dy);
1823
+ ts[i] = t;
1824
+ ds[i] = cum;
1825
+ prev = cur;
1828
1826
  }
1829
- return cloned;
1827
+ return { ts, ds };
1830
1828
  }
1831
- function generateNewIds(doc) {
1832
- var _a2, _b;
1833
- const cloned = deepClone(doc);
1834
- const idMap = /* @__PURE__ */ new Map();
1835
- const hashRefAttrs = /* @__PURE__ */ new Set(["href", "xlink:href"]);
1836
- const urlRefAttrs = /* @__PURE__ */ new Set([
1837
- "fill",
1838
- "stroke",
1839
- "clip-path",
1840
- "clipPath",
1841
- "mask",
1842
- "marker",
1843
- "marker-start",
1844
- "marker-mid",
1845
- "marker-end",
1846
- "filter",
1847
- "flood-color",
1848
- "lighting-color"
1849
- ]);
1850
- const directIdRefAttrs = /* @__PURE__ */ new Set(["targetId", "boundElementId"]);
1851
- const isEffectSourceRef = (key, parentKey) => key === "source" && (parentKey === "maskedBy" || parentKey === "clone");
1852
- function collectIds(node) {
1853
- if (!node || typeof node !== "object") return;
1854
- if (node.id && typeof node.id === "string") {
1855
- const oldId = node.id;
1856
- const newId = generateUniqueId();
1857
- idMap.set(oldId, newId);
1858
- node.id = newId;
1859
- } else if (node.animate) {
1860
- node.id = generateUniqueId();
1861
- }
1862
- if (Array.isArray(node.children)) {
1863
- for (const child of node.children) {
1864
- collectIds(child);
1865
- }
1866
- }
1867
- }
1868
- function updateRefs(node, parentKey) {
1869
- if (!node || typeof node !== "object") return;
1870
- for (const [key, value] of Object.entries(node)) {
1871
- if (key === "children") {
1872
- if (Array.isArray(value)) {
1873
- for (const child of value) {
1874
- updateRefs(child);
1875
- }
1876
- }
1877
- continue;
1878
- }
1879
- if (typeof value === "string") {
1880
- if (hashRefAttrs.has(key) && value.startsWith("#")) {
1881
- const oldId = value.slice(1);
1882
- const newId = idMap.get(oldId);
1883
- if (newId) {
1884
- node[key] = "#" + newId;
1885
- }
1886
- } else if (urlRefAttrs.has(key)) {
1887
- node[key] = replaceUrlRefs(value, idMap);
1888
- } else if (directIdRefAttrs.has(key) || isEffectSourceRef(key, parentKey)) {
1889
- const hasHash = value.startsWith("#");
1890
- const newId = idMap.get(hasHash ? value.slice(1) : value);
1891
- if (newId) {
1892
- node[key] = hasHash ? "#" + newId : newId;
1893
- }
1894
- } else if (value.includes("url(#")) {
1895
- node[key] = replaceUrlRefs(value, idMap);
1896
- }
1897
- } else if (key === "style" && typeof value === "object" && value !== null) {
1898
- for (const [styleProp, styleValue] of Object.entries(value)) {
1899
- if (typeof styleValue === "string") {
1900
- value[styleProp] = replaceUrlRefs(styleValue, idMap);
1901
- }
1902
- }
1903
- } else if (typeof value === "object" && value !== null) {
1904
- updateRefs(value, key);
1905
- }
1906
- }
1829
+ function bezier2D_tForDistance(lut, distance) {
1830
+ const { ts, ds } = lut;
1831
+ const last = ds.length - 1;
1832
+ if (distance <= 0) return ts[0];
1833
+ if (distance >= ds[last]) return ts[last];
1834
+ let lo = 1;
1835
+ let hi = last;
1836
+ while (lo < hi) {
1837
+ const mid = lo + hi >>> 1;
1838
+ if (ds[mid] < distance) lo = mid + 1;
1839
+ else hi = mid;
1907
1840
  }
1908
- collectIds(cloned);
1909
- updateRefs(cloned);
1910
- const docAnimate = (_a2 = cloned.animator) == null ? void 0 : _a2.animateById;
1911
- if (docAnimate && typeof docAnimate === "object") {
1912
- const updatedAnimate = {};
1913
- for (const [key, anim] of Object.entries(docAnimate)) {
1914
- const hashed = key.startsWith("#");
1915
- const id = hashed ? key.slice(1) : key;
1916
- const newId = (_b = idMap.get(id)) != null ? _b : id;
1917
- updatedAnimate[hashed ? "#" + newId : newId] = anim;
1918
- }
1919
- cloned.animator = __spreadProps(__spreadValues({}, cloned.animator), { animateById: updatedAnimate });
1841
+ const dPrev = ds[hi - 1];
1842
+ const dCur = ds[hi];
1843
+ const span = dCur - dPrev;
1844
+ const frac = span > 0 ? (distance - dPrev) / span : 0;
1845
+ return ts[hi - 1] + frac * (ts[hi] - ts[hi - 1]);
1846
+ }
1847
+ function bezier2D_arcAtT(lut, t) {
1848
+ const { ts, ds } = lut;
1849
+ const last = ts.length - 1;
1850
+ if (t <= ts[0]) return ds[0];
1851
+ if (t >= ts[last]) return ds[last];
1852
+ let lo = 1, hi = last;
1853
+ while (lo < hi) {
1854
+ const mid = lo + hi >>> 1;
1855
+ if (ts[mid] < t) lo = mid + 1;
1856
+ else hi = mid;
1920
1857
  }
1921
- return cloned;
1858
+ const tPrev = ts[hi - 1];
1859
+ const span = ts[hi] - tPrev;
1860
+ const frac = span > 0 ? (t - tPrev) / span : 0;
1861
+ return ds[hi - 1] + frac * (ds[hi] - ds[hi - 1]);
1922
1862
  }
1923
- function replaceUrlRefs(value, idMap) {
1924
- return value.replace(/url\(#([^)]+)\)/g, (match, oldId) => {
1925
- const newId = idMap.get(oldId);
1926
- return newId ? "url(#" + newId + ")" : match;
1927
- });
1863
+ function invertEasing(easing) {
1864
+ if (!easing) return (y) => y;
1865
+ const flipped = [easing[1], easing[0], easing[3], easing[2]];
1866
+ return cubicBezier(flipped);
1928
1867
  }
1929
1868
 
1930
1869
  // ../svg-animator-core/src/util/PxNodeProps.ts
1931
- var DISALLOWED_SVG_TAGS_LOWER = /* @__PURE__ */ new Set([
1870
+ var PX_DISALLOWED_SVG_TAGS_LOWER = /* @__PURE__ */ new Set([
1932
1871
  "script",
1933
1872
  "foreignobject"
1934
1873
  ]);
@@ -1953,7 +1892,7 @@ var PixodeskAnimator = (() => {
1953
1892
  // marker-end="url(#…)"
1954
1893
  ]);
1955
1894
  var IMAGE_REF_ATTRS_LOWER = /* @__PURE__ */ new Set(["href", "xlink:href", "src"]);
1956
- var CSS_ONLY_STYLE_PROPS = /* @__PURE__ */ new Set(["mixBlendMode", "isolation"]);
1895
+ var PX_CSS_ONLY_STYLE_PROPS = /* @__PURE__ */ new Set(["mixBlendMode", "isolation"]);
1957
1896
  var DATA_RASTER_IMAGE_RE = /^data:image\/(?:png|jpe?g|gif|webp|bmp);base64,/i;
1958
1897
  var DATA_SVG_IMAGE_RE = /^data:image\/svg\+xml(?:;[^,]*)?,/i;
1959
1898
  var DATA_IMAGE_BASE64_PAYLOAD_RE = /^data:image\/[^;,]*;base64,([A-Za-z0-9+/]{8})/i;
@@ -1990,27 +1929,19 @@ var PixodeskAnimator = (() => {
1990
1929
  }
1991
1930
  return value;
1992
1931
  }
1993
- function resolveStyle(style, defs) {
1994
- var _a2;
1995
- if (!style) return void 0;
1996
- if (typeof style === "string") {
1997
- return (_a2 = defs == null ? void 0 : defs.styles) == null ? void 0 : _a2[style];
1998
- }
1999
- return style;
2000
- }
2001
- function getNormalizedProps(props) {
1932
+ function toDomProps(props) {
2002
1933
  const propsCopy = {};
2003
1934
  for (const rawKey of Object.keys(props)) {
2004
1935
  const key = kebabToCamelCaseWord(rawKey);
2005
1936
  if (INTERNAL_ATTRS.has(key)) continue;
2006
1937
  if (key === "style") continue;
2007
1938
  let value = props[rawKey];
2008
- if (COLOR_ATTR_NAMES.has(key) && Array.isArray(value)) {
1939
+ if (PX_COLOR_ATTR_NAMES.has(key) && Array.isArray(value)) {
2009
1940
  propsCopy[key] = toRGBA(value);
2010
1941
  } else if (key === "transform" && value !== null && typeof value === "object" && !Array.isArray(value) && !value.keyframes) {
2011
1942
  const parts = value.value && typeof value.value === "object" ? value.value : value;
2012
1943
  propsCopy[TRANSFORM_ATTR] = composeTransformParts(parts, { withUnits: false });
2013
- } else if (TRANSFORM_FN_NAMES.has(key)) {
1944
+ } else if (PX_TRANSFORM_FN_NAMES.has(key)) {
2014
1945
  if (Array.isArray(value)) {
2015
1946
  if (key === "translate") value = value.map((v) => v + "px");
2016
1947
  value = value.join(",");
@@ -2028,7 +1959,7 @@ var PixodeskAnimator = (() => {
2028
1959
 
2029
1960
  // ../svg-animator-core/src/materialize/PxMotionPath.ts
2030
1961
  function getKfTranslate(kf) {
2031
- const v = kfValue(kf);
1962
+ const v = keyframeValue(kf);
2032
1963
  if (!v) return void 0;
2033
1964
  if (Array.isArray(v) && v.length >= 2 && typeof v[0] === "number" && typeof v[1] === "number") {
2034
1965
  return [v[0], v[1]];
@@ -2038,17 +1969,17 @@ var PixodeskAnimator = (() => {
2038
1969
  return void 0;
2039
1970
  }
2040
1971
  function getKfTime(kf) {
2041
- return kfTime(kf);
1972
+ return keyframeTime(kf);
2042
1973
  }
2043
1974
  function getKfEasing(kf) {
2044
- return kfEasing(kf);
1975
+ return keyframeEasing(kf);
2045
1976
  }
2046
1977
  function propAnimIsMotionPath(anim) {
2047
1978
  const kfs = anim.keyframes;
2048
1979
  if (!Array.isArray(kfs)) return false;
2049
1980
  if (anim.autoOrient) return true;
2050
1981
  for (const kf of kfs) {
2051
- if (kfTangentIn(kf) || kfTangentOut(kf)) return true;
1982
+ if (keyframeTangentIn(kf) || keyframeTangentOut(kf)) return true;
2052
1983
  }
2053
1984
  return false;
2054
1985
  }
@@ -2057,8 +1988,8 @@ var PixodeskAnimator = (() => {
2057
1988
  let byNext = _segmentCache.get(prevKf);
2058
1989
  const existing = byNext == null ? void 0 : byNext.get(nextKf);
2059
1990
  if (existing) return existing;
2060
- const to = kfTangentOut(prevKf);
2061
- const ti = kfTangentIn(nextKf);
1991
+ const to = keyframeTangentOut(prevKf);
1992
+ const ti = keyframeTangentIn(nextKf);
2062
1993
  const P1 = [prevPos[0] + (to ? to[0] : 0), prevPos[1] + (to ? to[1] : 0)];
2063
1994
  const P2 = [nextPos[0] + (ti ? ti[0] : 0), nextPos[1] + (ti ? ti[1] : 0)];
2064
1995
  const lut = bezier2D_arcLengthLUT(prevPos, P1, P2, nextPos);
@@ -2151,7 +2082,7 @@ var PixodeskAnimator = (() => {
2151
2082
  function unwrapAutoOrientRotations(kfs) {
2152
2083
  let prev;
2153
2084
  for (const kf of kfs) {
2154
- const v = kfValue(kf);
2085
+ const v = keyframeValue(kf);
2155
2086
  if (!v || typeof v.rotate !== "number") continue;
2156
2087
  if (prev === void 0) {
2157
2088
  prev = v.rotate;
@@ -2168,7 +2099,7 @@ var PixodeskAnimator = (() => {
2168
2099
  return { t: time, v: value };
2169
2100
  }
2170
2101
  function getKfValueParts(kf) {
2171
- const v = kfValue(kf);
2102
+ const v = keyframeValue(kf);
2172
2103
  if (!v || typeof v !== "object" || Array.isArray(v)) return void 0;
2173
2104
  return v;
2174
2105
  }
@@ -2230,7 +2161,7 @@ var PixodeskAnimator = (() => {
2230
2161
  }
2231
2162
  function insertSharpCornerStepKfIfNeeded(out, prevKf, nextKf, prevPos, nextPos, rotationTol) {
2232
2163
  const lastKf = out[out.length - 1];
2233
- const lastV = kfValue(lastKf);
2164
+ const lastV = keyframeValue(lastKf);
2234
2165
  const prevExit = lastV == null ? void 0 : lastV.rotate;
2235
2166
  if (typeof prevExit !== "number") return;
2236
2167
  const boundaryV = getKfValueParts(prevKf);
@@ -2412,7 +2343,7 @@ var PixodeskAnimator = (() => {
2412
2343
  }
2413
2344
 
2414
2345
  // ../svg-animator-core/src/animation/PxDefinitions.ts
2415
- var LOOP_JUMP_SHIFT_MS = 1;
2346
+ var PX_LOOP_JUMP_SHIFT_MS = 1;
2416
2347
  function deepEqualValue(a, b) {
2417
2348
  if (a === b) return true;
2418
2349
  if (typeof a !== typeof b || a === null || b === null || typeof a !== "object") return false;
@@ -2588,7 +2519,7 @@ var PixodeskAnimator = (() => {
2588
2519
  const bPaths = (_b = b == null ? void 0 : b.paths) != null ? _b : Array.isArray(b) ? b : [];
2589
2520
  return { paths: interpolateBeziers(aPaths, bPaths, t) };
2590
2521
  }
2591
- if (COLOR_ATTR_NAMES.has(propName)) {
2522
+ if (PX_COLOR_ATTR_NAMES.has(propName)) {
2592
2523
  return interpolateColor(a || [0, 0, 0, 1], b || [0, 0, 0, 1], t);
2593
2524
  }
2594
2525
  if (propName === "transform" && typeof a === "object" && a !== null && !Array.isArray(a) && typeof b === "object" && b !== null && !Array.isArray(b)) {
@@ -2597,7 +2528,7 @@ var PixodeskAnimator = (() => {
2597
2528
  if (propName === "rotate" && typeof a === "number" && typeof b === "number") {
2598
2529
  return interpolateNum(a, b, t);
2599
2530
  }
2600
- if (TRANSFORM_FN_NAMES.has(propName) || propName === "stroke-dasharray" || propName === "strokeDasharray") {
2531
+ if (PX_TRANSFORM_FN_NAMES.has(propName) || propName === "stroke-dasharray" || propName === "strokeDasharray") {
2601
2532
  return interpolateVec(a || [], b || [], t);
2602
2533
  }
2603
2534
  return interpolateNum(+(a || 0), +(b || 0), t);
@@ -2649,8 +2580,8 @@ var PixodeskAnimator = (() => {
2649
2580
  relT: (kf.t - segStartT) / segDuration,
2650
2581
  v: kf.v,
2651
2582
  e: kf.e,
2652
- tangentIn: kfTangentIn(kf),
2653
- tangentOut: kfTangentOut(kf)
2583
+ tangentIn: keyframeTangentIn(kf),
2584
+ tangentOut: keyframeTangentOut(kf)
2654
2585
  }));
2655
2586
  const fullReps = Math.floor(fillDuration / segDuration);
2656
2587
  const remainder = fillDuration - fullReps * segDuration;
@@ -2716,7 +2647,7 @@ var PixodeskAnimator = (() => {
2716
2647
  }
2717
2648
  }
2718
2649
  const pushed = {
2719
- t: repStart + entry.relT * segDuration + (isBoundary ? LOOP_JUMP_SHIFT_MS : 0),
2650
+ t: repStart + entry.relT * segDuration + (isBoundary ? PX_LOOP_JUMP_SHIFT_MS : 0),
2720
2651
  v: entry.v,
2721
2652
  e: i < entries.length - 1 ? entry.e : void 0
2722
2653
  };
@@ -2803,14 +2734,14 @@ var PixodeskAnimator = (() => {
2803
2734
  const keyframes = propAnim.keyframes || [];
2804
2735
  const normalized = [];
2805
2736
  for (const kf of keyframes) {
2806
- const timePct = kfTime(kf);
2807
- let value = kfValue(kf);
2808
- const easing = kfEasing(kf);
2737
+ const timePct = keyframeTime(kf);
2738
+ let value = keyframeValue(kf);
2739
+ const easing = keyframeEasing(kf);
2809
2740
  if (propName === "d") {
2810
2741
  value = normalizePathValue(value);
2811
2742
  }
2812
2743
  const propNameKebab = isCamelCaseWord(propName) ? camelCaseToKebabWordIfNeeded(propName) : propName;
2813
- if (COLOR_ATTR_NAMES.has(propNameKebab)) {
2744
+ if (PX_COLOR_ATTR_NAMES.has(propNameKebab)) {
2814
2745
  value = (_a2 = parseColor(value)) != null ? _a2 : value;
2815
2746
  }
2816
2747
  const normKf = {
@@ -2818,8 +2749,8 @@ var PixodeskAnimator = (() => {
2818
2749
  v: value,
2819
2750
  e: resolveEasing(easing, defs)
2820
2751
  };
2821
- const tIn = kfTangentIn(kf);
2822
- const tOut = kfTangentOut(kf);
2752
+ const tIn = keyframeTangentIn(kf);
2753
+ const tOut = keyframeTangentOut(kf);
2823
2754
  if (tIn) normKf.tangentIn = tIn;
2824
2755
  if (tOut) normKf.tangentOut = tOut;
2825
2756
  normalized.push(normKf);
@@ -2851,17 +2782,17 @@ var PixodeskAnimator = (() => {
2851
2782
  const rawKfs = propAnim.keyframes;
2852
2783
  if (!Array.isArray(rawKfs) || rawKfs.length < 2) return propAnim;
2853
2784
  const propNameKebab = isCamelCaseWord(propName) ? camelCaseToKebabWordIfNeeded(propName) : propName;
2854
- const isColor = COLOR_ATTR_NAMES.has(propNameKebab);
2785
+ const isColor = PX_COLOR_ATTR_NAMES.has(propNameKebab);
2855
2786
  const kfs = rawKfs.map((kf) => {
2856
2787
  var _a2;
2857
- const t = kfTime(kf);
2858
- let v = kfValue(kf);
2788
+ const t = keyframeTime(kf);
2789
+ let v = keyframeValue(kf);
2859
2790
  if (propName === "d") v = normalizePathValue(v);
2860
2791
  if (isColor) v = (_a2 = parseColor(v)) != null ? _a2 : v;
2861
- const e = kfEasing(kf);
2792
+ const e = keyframeEasing(kf);
2862
2793
  const out2 = { t, v, e };
2863
- const tIn = kfTangentIn(kf);
2864
- const tOut = kfTangentOut(kf);
2794
+ const tIn = keyframeTangentIn(kf);
2795
+ const tOut = keyframeTangentOut(kf);
2865
2796
  if (tIn) out2.tangentIn = tIn;
2866
2797
  if (tOut) out2.tangentOut = tOut;
2867
2798
  return out2;
@@ -2926,7 +2857,7 @@ var PixodeskAnimator = (() => {
2926
2857
  }
2927
2858
  return animDef;
2928
2859
  }
2929
- const channels = Object.keys(animDef).filter((k) => TRANSFORM_FN_NAMES.has(k));
2860
+ const channels = Object.keys(animDef).filter((k) => PX_TRANSFORM_FN_NAMES.has(k));
2930
2861
  if (channels.length !== 1) return animDef;
2931
2862
  const ch = channels[0];
2932
2863
  const chAnim = animDef[ch];
@@ -2955,14 +2886,12 @@ var PixodeskAnimator = (() => {
2955
2886
  }
2956
2887
  return normalized;
2957
2888
  }
2958
- function getNormalizedBindings(doc, engine = PxTimelineEngine.native) {
2889
+ function normalizeBindings(doc, engine = PxTimelineEngine.native) {
2959
2890
  const animatorConfig = getAnimatorConfig(doc) || {};
2960
- const defs = getDefs(doc);
2891
+ const defs = getDefinitions(doc);
2961
2892
  const duration = animatorConfig.duration || 1e3;
2962
2893
  const bindings = [];
2963
- const processAnimation = (id, animate, staticTransform) => {
2964
- if (!animate) return null;
2965
- const animDefs = resolveElementAnimation(animate, defs);
2894
+ const processAnimation = (id, animDefs, staticTransform) => {
2966
2895
  if (animDefs.length === 0) return null;
2967
2896
  const merged = mergeStaticTransformIntoAnimDef(mergeAnimationDefinitions(animDefs), staticTransform);
2968
2897
  const normalizedAnim = normalizeAnimationDefinition(merged, duration, defs, engine);
@@ -2975,7 +2904,9 @@ var PixodeskAnimator = (() => {
2975
2904
  const docBindings = getBindings(doc);
2976
2905
  if (docBindings) {
2977
2906
  for (const binding of docBindings) {
2978
- const normalized = processAnimation(binding.id, binding.animate);
2907
+ const id = binding.target.startsWith("#") ? binding.target.slice(1) : binding.target;
2908
+ const animDefs = binding.animateWith.map((name) => resolveAnimation(name, defs)).filter((d) => !!d);
2909
+ const normalized = processAnimation(id, animDefs);
2979
2910
  if (normalized) bindings.push(normalized);
2980
2911
  }
2981
2912
  }
@@ -2984,7 +2915,7 @@ var PixodeskAnimator = (() => {
2984
2915
  if (inlineAnim && Object.keys(inlineAnim).length > 0) {
2985
2916
  const nodeId = node.id || generateElementId();
2986
2917
  node.id = nodeId;
2987
- const normalized = processAnimation(nodeId, inlineAnim, node.transform);
2918
+ const normalized = processAnimation(nodeId, resolveElementAnimation(inlineAnim, defs), node.transform);
2988
2919
  if (normalized) bindings.push(normalized);
2989
2920
  }
2990
2921
  if (node.children) {
@@ -3027,7 +2958,7 @@ var PixodeskAnimator = (() => {
3027
2958
  const { prevKf, nextKf } = getKeyframesPair(keyframes, progress);
3028
2959
  let localProgress = prevKf === nextKf ? 0 : remap(progress, (_a2 = prevKf.t) != null ? _a2 : 0, (_b = nextKf.t) != null ? _b : 0, 0, 1);
3029
2960
  localProgress = clamp(localProgress, 0, 1);
3030
- const easing = kfEasing(prevKf);
2961
+ const easing = keyframeEasing(prevKf);
3031
2962
  if (easing && Array.isArray(easing)) {
3032
2963
  try {
3033
2964
  localProgress = cubicBezier(easing)(localProgress);
@@ -3046,7 +2977,7 @@ var PixodeskAnimator = (() => {
3046
2977
  nextPaths,
3047
2978
  localProgress
3048
2979
  ).map((bz) => bezierToSvgPath(bz)).join("");
3049
- } else if (COLOR_ATTR_NAMES.has(cssAttrName)) {
2980
+ } else if (PX_COLOR_ATTR_NAMES.has(cssAttrName)) {
3050
2981
  cssValue = toRGBA(interpolateColor(
3051
2982
  prevV || [0, 0, 0, 1],
3052
2983
  nextV || [0, 0, 0, 1],
@@ -3127,7 +3058,7 @@ var PixodeskAnimator = (() => {
3127
3058
  );
3128
3059
  cssValue = num;
3129
3060
  }
3130
- if (PCT_BASED_ATTR_NAMES.has(cssAttrName) && typeof cssValue === "number") {
3061
+ if (PX_PCT_BASED_ATTR_NAMES.has(cssAttrName) && typeof cssValue === "number") {
3131
3062
  cssValue = cssValue * 100 + "%";
3132
3063
  }
3133
3064
  return { k: cssAttrName, v: cssValue === null ? "" : "" + cssValue };
@@ -3143,218 +3074,6 @@ var PixodeskAnimator = (() => {
3143
3074
  return result;
3144
3075
  }
3145
3076
 
3146
- // ../svg-animator-core/src/util/PxNodeCloneUtil.ts
3147
- function deepClonePxNode(value) {
3148
- if (value === null || typeof value !== "object") return value;
3149
- if (Array.isArray(value)) return value.map(deepClonePxNode);
3150
- const out = {};
3151
- for (const k of Object.keys(value)) out[k] = deepClonePxNode(value[k]);
3152
- return out;
3153
- }
3154
- function regenerateIdsAndRewriteRefs(root, genId3) {
3155
- const oldToNew = /* @__PURE__ */ new Map();
3156
- const walkAssign = (n) => {
3157
- var _a2;
3158
- if (typeof n.id === "string") {
3159
- const newId = genId3();
3160
- oldToNew.set(n.id, newId);
3161
- n.id = newId;
3162
- }
3163
- (_a2 = n.children) == null ? void 0 : _a2.forEach(walkAssign);
3164
- };
3165
- walkAssign(root);
3166
- const rewriteUrl = (s) => s.replace(/url\(#([^)]+)\)/g, (m, oldId) => {
3167
- const newId = oldToNew.get(oldId);
3168
- return newId ? "url(#" + newId + ")" : m;
3169
- });
3170
- const walkRewrite = (n) => {
3171
- var _a2;
3172
- if (typeof n.href === "string" && n.href.startsWith("#")) {
3173
- const newId = oldToNew.get(n.href.slice(1));
3174
- if (newId) n.href = "#" + newId;
3175
- }
3176
- for (const k of Object.keys(n)) {
3177
- if (k === "children" || k === "effects" || k === "meta" || k === "animate" || k === "href" || k === "id") continue;
3178
- const v = n[k];
3179
- if (typeof v === "string" && v.indexOf("url(#") !== -1) {
3180
- n[k] = rewriteUrl(v);
3181
- }
3182
- }
3183
- (_a2 = n.children) == null ? void 0 : _a2.forEach(walkRewrite);
3184
- };
3185
- walkRewrite(root);
3186
- return oldToNew;
3187
- }
3188
- function toFiniteNum(v) {
3189
- const n = typeof v === "number" ? v : typeof v === "string" ? parseFloat(v) : NaN;
3190
- return Number.isFinite(n) ? n : 0;
3191
- }
3192
- function applyUseOffsetToG(gNode) {
3193
- var _a2;
3194
- const x = toFiniteNum(gNode.x);
3195
- const y = toFiniteNum(gNode.y);
3196
- delete gNode.x;
3197
- delete gNode.y;
3198
- if (!x && !y) return gNode;
3199
- const offset = "translate(" + x + "," + y + ")";
3200
- const carriesTransform = gNode.transform !== void 0 || gNode.animate !== void 0;
3201
- if (carriesTransform) {
3202
- const inner = { type: "g", transform: offset, children: (_a2 = gNode.children) != null ? _a2 : [] };
3203
- gNode.children = [inner];
3204
- } else {
3205
- gNode.transform = offset;
3206
- }
3207
- return gNode;
3208
- }
3209
-
3210
- // ../svg-animator-core/src/materialize/PxAnimatorUseMaterializer.ts
3211
- function materializeAnimatedUseInstances(root) {
3212
- var _a2;
3213
- const idMap = buildIdMap(root);
3214
- const animatedIds = computeAnimatedSubtreeIds(root, idMap);
3215
- if (animatedIds.size === 0) return root;
3216
- let idCounter = 0;
3217
- const genId3 = () => "_lw_use_mat_" + ++idCounter;
3218
- const rootViewport = readRootViewport(root);
3219
- const defsCollector = [];
3220
- const walked = walkAndMaterialize2(root, idMap, animatedIds, genId3, defsCollector, rootViewport);
3221
- if (defsCollector.length === 0) return walked;
3222
- const defsNode = { type: "defs", children: defsCollector };
3223
- const newChildren = [...(_a2 = walked.children) != null ? _a2 : [], defsNode];
3224
- return __spreadProps(__spreadValues({}, walked), { children: newChildren });
3225
- }
3226
- function readRootViewport(root) {
3227
- const vb = parseViewBox(root.viewBox);
3228
- if (vb) return [vb[2], vb[3]];
3229
- const w = numericAttr(root.width);
3230
- const h = numericAttr(root.height);
3231
- if (w !== void 0 && h !== void 0) return [w, h];
3232
- return [1, 1];
3233
- }
3234
- function numericAttr(v) {
3235
- if (typeof v === "number") return v;
3236
- if (typeof v === "string") {
3237
- const n = parseFloat(v);
3238
- return Number.isFinite(n) ? n : void 0;
3239
- }
3240
- return void 0;
3241
- }
3242
- function buildIdMap(root) {
3243
- const map = /* @__PURE__ */ new Map();
3244
- const visit = (n) => {
3245
- var _a2;
3246
- if (typeof n.id === "string") map.set(n.id, n);
3247
- (_a2 = n.children) == null ? void 0 : _a2.forEach(visit);
3248
- };
3249
- visit(root);
3250
- return map;
3251
- }
3252
- function computeAnimatedSubtreeIds(root, idMap) {
3253
- const cache = /* @__PURE__ */ new WeakMap();
3254
- const result = /* @__PURE__ */ new Set();
3255
- const hasAnim = (n, visiting) => {
3256
- const cached = cache.get(n);
3257
- if (cached !== void 0) return cached;
3258
- if (visiting.has(n)) return false;
3259
- visiting.add(n);
3260
- let r = false;
3261
- if (n.animate && typeof n.animate === "object" && !Array.isArray(n.animate)) {
3262
- for (const _ in n.animate) {
3263
- r = true;
3264
- break;
3265
- }
3266
- }
3267
- if (!r && n.children) {
3268
- for (const ch of n.children) {
3269
- if (hasAnim(ch, visiting)) {
3270
- r = true;
3271
- break;
3272
- }
3273
- }
3274
- }
3275
- if (!r && n.type === "use" && typeof n.href === "string") {
3276
- const targetId = stripHash(n.href);
3277
- const target = targetId ? idMap.get(targetId) : void 0;
3278
- if (target) r = hasAnim(target, visiting);
3279
- }
3280
- visiting.delete(n);
3281
- cache.set(n, r);
3282
- return r;
3283
- };
3284
- for (const [id, node] of idMap) {
3285
- if (hasAnim(node, /* @__PURE__ */ new Set())) result.add(id);
3286
- }
3287
- return result;
3288
- }
3289
- function stripHash(href) {
3290
- if (typeof href !== "string") return void 0;
3291
- return href.startsWith("#") ? href.slice(1) : href;
3292
- }
3293
- function materializeOneUse(useNode, target, idMap, animatedIds, genId3, defsCollector, rootViewport) {
3294
- var _a2, _b, _c, _d;
3295
- const clone2 = deepClonePxNode(target);
3296
- regenerateIdsAndRewriteRefs(clone2, genId3);
3297
- const symbolViewBox = clone2.type === "symbol" ? parseViewBox(clone2.viewBox) : void 0;
3298
- const useW = (_b = (_a2 = numericAttr(useNode.width)) != null ? _a2 : symbolViewBox == null ? void 0 : symbolViewBox[2]) != null ? _b : rootViewport[0];
3299
- const useH = (_d = (_c = numericAttr(useNode.height)) != null ? _c : symbolViewBox == null ? void 0 : symbolViewBox[3]) != null ? _d : rootViewport[1];
3300
- const rewrittenClone = clone2.type === "symbol" ? rewriteSymbolRootToGroup(clone2, genId3, defsCollector, useW, useH) : clone2;
3301
- const materializedClone = walkAndMaterialize2(rewrittenClone, idMap, animatedIds, genId3, defsCollector, rootViewport);
3302
- const newNode = __spreadProps(__spreadValues({}, useNode), { type: "g", children: [materializedClone] });
3303
- delete newNode.href;
3304
- delete newNode.width;
3305
- delete newNode.height;
3306
- return applyUseOffsetToG(newNode);
3307
- }
3308
- function rewriteSymbolRootToGroup(symbolNode, genId3, defsCollector, useW, useH) {
3309
- const viewBox = parseViewBox(symbolNode.viewBox);
3310
- const g = __spreadProps(__spreadValues({}, symbolNode), { type: "g" });
3311
- delete g.viewBox;
3312
- delete g.preserveAspectRatio;
3313
- delete g.width;
3314
- delete g.height;
3315
- if (!viewBox) return g;
3316
- const [vbX, vbY, vbW, vbH] = viewBox;
3317
- const scale = vbW > 0 && vbH > 0 ? Math.min(useW / vbW, useH / vbH) : 1;
3318
- const xOff = (useW - vbW * scale) / 2;
3319
- const yOff = (useH - vbH * scale) / 2;
3320
- const parts = [];
3321
- if (xOff !== 0 || yOff !== 0) parts.push("translate(" + xOff + "," + yOff + ")");
3322
- if (scale !== 1) parts.push("scale(" + scale + ")");
3323
- if (vbX !== 0 || vbY !== 0) parts.push("translate(" + -vbX + "," + -vbY + ")");
3324
- if (parts.length) g.transform = parts.join("");
3325
- const clipId = genId3();
3326
- defsCollector.push({
3327
- type: "clipPath",
3328
- id: clipId,
3329
- children: [{ type: "rect", x: vbX, y: vbY, width: vbW, height: vbH }]
3330
- });
3331
- g.clipPath = "url(#" + clipId + ")";
3332
- return g;
3333
- }
3334
- function parseViewBox(v) {
3335
- if (typeof v !== "string") return void 0;
3336
- const parts = v.trim().split(/[\s,]+/).map(Number);
3337
- if (parts.length < 4 || parts.some((n) => !Number.isFinite(n))) return void 0;
3338
- return [parts[0], parts[1], parts[2], parts[3]];
3339
- }
3340
- function walkAndMaterialize2(node, idMap, animatedIds, genId3, defsCollector, rootViewport) {
3341
- if (node.type === "use" && typeof node.href === "string") {
3342
- const targetId = stripHash(node.href);
3343
- if (targetId && animatedIds.has(targetId)) {
3344
- const target = idMap.get(targetId);
3345
- if (target) return materializeOneUse(node, target, idMap, animatedIds, genId3, defsCollector, rootViewport);
3346
- }
3347
- }
3348
- if (!node.children) return node;
3349
- let changed = false;
3350
- const newChildren = node.children.map((ch) => {
3351
- const m = walkAndMaterialize2(ch, idMap, animatedIds, genId3, defsCollector, rootViewport);
3352
- if (m !== ch) changed = true;
3353
- return m;
3354
- });
3355
- return changed ? __spreadProps(__spreadValues({}, node), { children: newChildren }) : node;
3356
- }
3357
-
3358
3077
  // ../svg-animator-core/src/effects/shared/transformParts.ts
3359
3078
  function partsRecord(part, value, origin) {
3360
3079
  const rec = {};
@@ -3520,14 +3239,78 @@ var PixodeskAnimator = (() => {
3520
3239
  children: [inner]
3521
3240
  };
3522
3241
  }
3523
- return inner;
3242
+ return inner;
3243
+ }
3244
+
3245
+ // ../svg-animator-core/src/util/PxNodeCloneUtil.ts
3246
+ function deepClonePxNode(value) {
3247
+ if (value === null || typeof value !== "object") return value;
3248
+ if (Array.isArray(value)) return value.map(deepClonePxNode);
3249
+ const out = {};
3250
+ for (const k of Object.keys(value)) out[k] = deepClonePxNode(value[k]);
3251
+ return out;
3252
+ }
3253
+ function regenerateIdsAndRewriteRefs(root, genId3) {
3254
+ const oldToNew = /* @__PURE__ */ new Map();
3255
+ const walkAssign = (n) => {
3256
+ var _a2;
3257
+ if (typeof n.id === "string") {
3258
+ const newId = genId3();
3259
+ oldToNew.set(n.id, newId);
3260
+ n.id = newId;
3261
+ }
3262
+ (_a2 = n.children) == null ? void 0 : _a2.forEach(walkAssign);
3263
+ };
3264
+ walkAssign(root);
3265
+ const rewriteUrl = (s) => s.replace(/url\(#([^)]+)\)/g, (m, oldId) => {
3266
+ const newId = oldToNew.get(oldId);
3267
+ return newId ? "url(#" + newId + ")" : m;
3268
+ });
3269
+ const walkRewrite = (n) => {
3270
+ var _a2;
3271
+ if (typeof n.href === "string" && n.href.startsWith("#")) {
3272
+ const newId = oldToNew.get(n.href.slice(1));
3273
+ if (newId) n.href = "#" + newId;
3274
+ }
3275
+ for (const k of Object.keys(n)) {
3276
+ if (k === "children" || k === "effects" || k === "meta" || k === "animate" || k === "href" || k === "id") continue;
3277
+ const v = n[k];
3278
+ if (typeof v === "string" && v.indexOf("url(#") !== -1) {
3279
+ n[k] = rewriteUrl(v);
3280
+ }
3281
+ }
3282
+ (_a2 = n.children) == null ? void 0 : _a2.forEach(walkRewrite);
3283
+ };
3284
+ walkRewrite(root);
3285
+ return oldToNew;
3286
+ }
3287
+ function toFiniteNum(v) {
3288
+ const n = typeof v === "number" ? v : typeof v === "string" ? parseFloat(v) : NaN;
3289
+ return Number.isFinite(n) ? n : 0;
3290
+ }
3291
+ function applyUseOffsetToG(gNode) {
3292
+ var _a2;
3293
+ const x = toFiniteNum(gNode.x);
3294
+ const y = toFiniteNum(gNode.y);
3295
+ delete gNode.x;
3296
+ delete gNode.y;
3297
+ if (!x && !y) return gNode;
3298
+ const offset = "translate(" + x + "," + y + ")";
3299
+ const carriesTransform = gNode.transform !== void 0 || gNode.animate !== void 0;
3300
+ if (carriesTransform) {
3301
+ const inner = { type: "g", transform: offset, children: (_a2 = gNode.children) != null ? _a2 : [] };
3302
+ gNode.children = [inner];
3303
+ } else {
3304
+ gNode.transform = offset;
3305
+ }
3306
+ return gNode;
3524
3307
  }
3525
3308
 
3526
3309
  // ../svg-animator-core/src/effects/shared/util.ts
3527
3310
  function genId(ctx, prefix) {
3528
3311
  return "_lw_" + prefix + "_" + ctx.nextId++;
3529
3312
  }
3530
- function stripHash2(href) {
3313
+ function stripHash(href) {
3531
3314
  return typeof href === "string" ? href.replace(/^#/, "") : void 0;
3532
3315
  }
3533
3316
  function indexById(node, map) {
@@ -3549,7 +3332,7 @@ var PixodeskAnimator = (() => {
3549
3332
  function identifyContentRefTargets(node, ctx, allocator) {
3550
3333
  var _a2, _b, _c;
3551
3334
  if (node.type === "use" && ((_b = (_a2 = node.effects) == null ? void 0 : _a2.clone) == null ? void 0 : _b.without) === "translate") {
3552
- const sourceId = stripHash2(node.effects.clone.source);
3335
+ const sourceId = stripHash(node.effects.clone.source);
3553
3336
  if (typeof sourceId === "string" && sourceId && !ctx.contentRefInnerIds.has(sourceId)) {
3554
3337
  ctx.contentRefInnerIds.set(sourceId, allocator(sourceId));
3555
3338
  }
@@ -3840,11 +3623,11 @@ var PixodeskAnimator = (() => {
3840
3623
  const loopFromSource = read.loop;
3841
3624
  let stopCount = 0;
3842
3625
  for (const kf of kfs) {
3843
- const v = kfValue(kf);
3626
+ const v = keyframeValue(kf);
3844
3627
  if (Array.isArray(v) && v.length > stopCount) stopCount = v.length;
3845
3628
  }
3846
3629
  if (!stopCount) return [];
3847
- const firstKfValue = kfValue(kfs[0]);
3630
+ const firstKfValue = keyframeValue(kfs[0]);
3848
3631
  const baselineStops = [];
3849
3632
  for (let i = 0; i < stopCount; i++) {
3850
3633
  const s = (_b = (_a2 = firstKfValue == null ? void 0 : firstKfValue[i]) != null ? _a2 : prevDefinedStop(kfs, 0, i)) != null ? _b : { offset: i / Math.max(1, stopCount - 1), color: "#000000" };
@@ -3865,11 +3648,11 @@ var PixodeskAnimator = (() => {
3865
3648
  const offsetKfs = [];
3866
3649
  let offsetVaries = false;
3867
3650
  for (const kf of kfs) {
3868
- const t = kfTime(kf);
3869
- const arr = kfValue(kf);
3651
+ const t = keyframeTime(kf);
3652
+ const arr = keyframeValue(kf);
3870
3653
  const sliced = (_a2 = arr == null ? void 0 : arr[stopIdx]) != null ? _a2 : prevDefinedStop(kfs, kfs.indexOf(kf), stopIdx);
3871
3654
  if (!sliced) continue;
3872
- const easing = kfEasing(kf);
3655
+ const easing = keyframeEasing(kf);
3873
3656
  const colorOut = { time: t, value: sliced.color };
3874
3657
  if (easing !== void 0) colorOut.easing = easing;
3875
3658
  colorKfs.push(colorOut);
@@ -3897,11 +3680,11 @@ var PixodeskAnimator = (() => {
3897
3680
  }
3898
3681
  function prevDefinedStop(kfs, fromIdx, stopIdx) {
3899
3682
  for (let i = fromIdx; i >= 0; i--) {
3900
- const arr = kfValue(kfs[i]);
3683
+ const arr = keyframeValue(kfs[i]);
3901
3684
  if (arr == null ? void 0 : arr[stopIdx]) return arr[stopIdx];
3902
3685
  }
3903
3686
  for (let i = fromIdx + 1; i < kfs.length; i++) {
3904
- const arr = kfValue(kfs[i]);
3687
+ const arr = keyframeValue(kfs[i]);
3905
3688
  if (arr == null ? void 0 : arr[stopIdx]) return arr[stopIdx];
3906
3689
  }
3907
3690
  return void 0;
@@ -3938,7 +3721,7 @@ var PixodeskAnimator = (() => {
3938
3721
  // ../svg-animator-core/src/effects/clipping/maskedByEffect.ts
3939
3722
  function applyMaskedByEffect(node, fx, transformBy, ctx) {
3940
3723
  if (!fx) return node;
3941
- const sourceId = stripHash2(fx.source);
3724
+ const sourceId = stripHash(fx.source);
3942
3725
  if (!sourceId) {
3943
3726
  ctx.errors.push("maskedBy.source missing \u2014 cannot build mask");
3944
3727
  return node;
@@ -4215,7 +3998,7 @@ var PixodeskAnimator = (() => {
4215
3998
  const interestingNodes = /* @__PURE__ */ new Set();
4216
3999
  const collectInterestingNodes = (n) => {
4217
4000
  var _a2, _b;
4218
- const maskSourceId = stripHash2((_b = (_a2 = n.effects) == null ? void 0 : _a2.maskedBy) == null ? void 0 : _b.source);
4001
+ const maskSourceId = stripHash((_b = (_a2 = n.effects) == null ? void 0 : _a2.maskedBy) == null ? void 0 : _b.source);
4219
4002
  if (typeof maskSourceId === "string") {
4220
4003
  interestingNodes.add(n);
4221
4004
  const sourceNode = ctx.idMap.get(maskSourceId);
@@ -4295,7 +4078,7 @@ var PixodeskAnimator = (() => {
4295
4078
  // ../svg-animator-core/src/effects/reference/refEffect.ts
4296
4079
  function applyRefHref(node, clone2, ctx) {
4297
4080
  if (!clone2) return;
4298
- const sourceId = stripHash2(clone2.source);
4081
+ const sourceId = stripHash(clone2.source);
4299
4082
  if (!sourceId) {
4300
4083
  if (clone2.without === PxCloneWithout.translate) ctx.errors.push("clone: content ref missing `source`");
4301
4084
  return;
@@ -4441,7 +4224,7 @@ var PixodeskAnimator = (() => {
4441
4224
  if (!n) return;
4442
4225
  if (n !== site && readCloneRetime(n)) count++;
4443
4226
  if (n.type === "use" && n.href) {
4444
- const id = stripHash2(n.href);
4227
+ const id = stripHash(n.href);
4445
4228
  if (id && !visited.has(id)) {
4446
4229
  visited.add(id);
4447
4230
  walk(ctx.idMap.get(id));
@@ -4449,7 +4232,7 @@ var PixodeskAnimator = (() => {
4449
4232
  }
4450
4233
  (_a2 = n.children) == null ? void 0 : _a2.forEach(walk);
4451
4234
  };
4452
- const rootId = stripHash2(site.href);
4235
+ const rootId = stripHash(site.href);
4453
4236
  if (rootId) {
4454
4237
  visited.add(rootId);
4455
4238
  walk(ctx.idMap.get(rootId));
@@ -4470,7 +4253,7 @@ var PixodeskAnimator = (() => {
4470
4253
  }
4471
4254
  }
4472
4255
  function materializeRetime(useNode, retime, ctx) {
4473
- const targetId = stripHash2(useNode.href);
4256
+ const targetId = stripHash(useNode.href);
4474
4257
  if (!targetId) {
4475
4258
  ctx.errors.push("retime: <use> has no href to follow");
4476
4259
  return;
@@ -4507,7 +4290,7 @@ var PixodeskAnimator = (() => {
4507
4290
  }
4508
4291
  clearCloneRetime(cloneNode);
4509
4292
  if (target.type === "use" && target.href) {
4510
- const subId = stripHash2(target.href);
4293
+ const subId = stripHash(target.href);
4511
4294
  if (subId) {
4512
4295
  const innerRetime = readCloneRetime(target);
4513
4296
  const subAccum = innerRetime ? concatRetime(asRetime(innerRetime), accum) : accum;
@@ -4528,7 +4311,7 @@ var PixodeskAnimator = (() => {
4528
4311
  var _a2;
4529
4312
  const retime = readCloneRetime(n);
4530
4313
  if (n.type === "use" && retime && n.href) {
4531
- const subId = stripHash2(n.href);
4314
+ const subId = stripHash(n.href);
4532
4315
  if (subId) {
4533
4316
  const subAccum = concatRetime(asRetime(retime), accum);
4534
4317
  const subChain = new Set(chain);
@@ -4882,7 +4665,7 @@ var PixodeskAnimator = (() => {
4882
4665
  "stroke",
4883
4666
  "strokeWidth",
4884
4667
  "effects",
4885
- TEXT_CONTENT_ATTR,
4668
+ PX_TEXT_CONTENT_ATTR,
4886
4669
  "xml:space"
4887
4670
  ];
4888
4671
  var PAINT_STATIC_KEYS = [
@@ -4918,7 +4701,7 @@ var PixodeskAnimator = (() => {
4918
4701
  }
4919
4702
  return out;
4920
4703
  }
4921
- function resolveStyle2(node, parent) {
4704
+ function resolveStyle(node, parent) {
4922
4705
  var _a2, _b, _c, _d, _e, _f, _g, _h, _i, _j;
4923
4706
  const isTextRoot = node.type === "text";
4924
4707
  const nodeStyle = node.style;
@@ -5025,7 +4808,7 @@ var PixodeskAnimator = (() => {
5025
4808
  };
5026
4809
  const walk = (el, parentStyle) => {
5027
4810
  var _a3, _b2, _c2;
5028
- const s = resolveStyle2(el, parentStyle);
4811
+ const s = resolveStyle(el, parentStyle);
5029
4812
  const x = parseLen(el.x);
5030
4813
  const y = parseLen(el.y);
5031
4814
  if (x !== void 0) {
@@ -5036,13 +4819,13 @@ var PixodeskAnimator = (() => {
5036
4819
  if (y !== void 0) pen.y = y;
5037
4820
  pen.x += (_a3 = parseLen(el.dx)) != null ? _a3 : 0;
5038
4821
  pen.y += (_b2 = parseLen(el.dy)) != null ? _b2 : 0;
5039
- const content = str(el[TEXT_CONTENT_ATTR]);
4822
+ const content = str(el[PX_TEXT_CONTENT_ATTR]);
5040
4823
  if (content && !((_c2 = el.children) == null ? void 0 : _c2.length)) renderChars(content, s);
5041
4824
  if (el.children) for (const ch of el.children) walk(ch, s);
5042
4825
  };
5043
4826
  const rootStyle = rootStyleOf(node);
5044
4827
  if (node.children) for (const ch of node.children) walk(ch, rootStyle);
5045
- const rootContent = str(node[TEXT_CONTENT_ATTR]);
4828
+ const rootContent = str(node[PX_TEXT_CONTENT_ATTR]);
5046
4829
  if (rootContent && !((_c = node.children) == null ? void 0 : _c.length)) renderChars(rootContent, rootStyle);
5047
4830
  const anchor = str(node.textAnchor);
5048
4831
  if (anchor === "middle" || anchor === "end") {
@@ -5059,8 +4842,8 @@ var PixodeskAnimator = (() => {
5059
4842
  let adv = 0;
5060
4843
  const walk = (el, parentStyle) => {
5061
4844
  var _a2, _b;
5062
- const s = resolveStyle2(el, parentStyle);
5063
- const content = str(el[TEXT_CONTENT_ATTR]);
4845
+ const s = resolveStyle(el, parentStyle);
4846
+ const content = str(el[PX_TEXT_CONTENT_ATTR]);
5064
4847
  if (content && !((_a2 = el.children) == null ? void 0 : _a2.length)) {
5065
4848
  const gf = glyphFontFor(s, glyphs, soleFont, warnings);
5066
4849
  if (gf) {
@@ -5431,7 +5214,7 @@ var PixodeskAnimator = (() => {
5431
5214
  if (r.kind === "static" /* Static */) return [r.value];
5432
5215
  const out = [];
5433
5216
  for (const kf of r.keyframes) {
5434
- const v = kfValue(kf);
5217
+ const v = keyframeValue(kf);
5435
5218
  if (typeof v === "number") out.push(v);
5436
5219
  }
5437
5220
  return out;
@@ -5442,9 +5225,9 @@ var PixodeskAnimator = (() => {
5442
5225
  return {
5443
5226
  kind: "animated" /* Animated */,
5444
5227
  keyframes: read.keyframes.map((kf) => ({
5445
- time: kfTime(kf),
5446
- value: map(kfValue(kf)),
5447
- easing: kfEasing(kf)
5228
+ time: keyframeTime(kf),
5229
+ value: map(keyframeValue(kf)),
5230
+ easing: keyframeEasing(kf)
5448
5231
  })),
5449
5232
  loop: read.loop
5450
5233
  };
@@ -5462,7 +5245,7 @@ var PixodeskAnimator = (() => {
5462
5245
  let anyHide = false;
5463
5246
  let allHide = true;
5464
5247
  for (const kf of kfs) {
5465
- if (hide(kfValue(kf))) anyHide = true;
5248
+ if (hide(keyframeValue(kf))) anyHide = true;
5466
5249
  else allHide = false;
5467
5250
  }
5468
5251
  if (!anyHide) return void 0;
@@ -5472,10 +5255,10 @@ var PixodeskAnimator = (() => {
5472
5255
  const kf = kfs[i];
5473
5256
  const prevKf = i > 0 ? kfs[i - 1] : void 0;
5474
5257
  const nextKf = i < kfs.length - 1 ? kfs[i + 1] : void 0;
5475
- const t = kfTime(kf);
5476
- const thisHide = hide(kfValue(kf));
5477
- const prevHide = prevKf ? thisHide && hide(kfValue(prevKf)) : thisHide;
5478
- const nextHide = nextKf ? thisHide && hide(kfValue(nextKf)) : thisHide;
5258
+ const t = keyframeTime(kf);
5259
+ const thisHide = hide(keyframeValue(kf));
5260
+ const prevHide = prevKf ? thisHide && hide(keyframeValue(prevKf)) : thisHide;
5261
+ const nextHide = nextKf ? thisHide && hide(keyframeValue(nextKf)) : thisHide;
5479
5262
  if (prevHide && !nextHide) {
5480
5263
  out.push({ time: t, value: 0 });
5481
5264
  out.push({ time: t + OPACITY_STEP_MS, value: 1 });
@@ -5491,9 +5274,9 @@ var PixodeskAnimator = (() => {
5491
5274
  const r = readAnimatable(raw);
5492
5275
  if (r.kind !== "animated" /* Animated */) return r;
5493
5276
  const kfs = r.keyframes.map((kf) => ({
5494
- time: kfTime(kf),
5495
- value: kfValue(kf),
5496
- easing: kfEasing(kf)
5277
+ time: keyframeTime(kf),
5278
+ value: keyframeValue(kf),
5279
+ easing: keyframeEasing(kf)
5497
5280
  }));
5498
5281
  const hasReverse = kfs.some((kf) => kf.value[0] > kf.value[1]);
5499
5282
  if (!hasReverse) {
@@ -5621,7 +5404,7 @@ var PixodeskAnimator = (() => {
5621
5404
  }
5622
5405
 
5623
5406
  // ../svg-animator-core/src/effects/PlayerEffectsUtil.ts
5624
- function applyPlayerEffects(root) {
5407
+ function materializeNodeEffects(root) {
5625
5408
  var _a2, _b;
5626
5409
  const ctx = {
5627
5410
  defs: [],
@@ -5634,7 +5417,7 @@ var PixodeskAnimator = (() => {
5634
5417
  // Resolved engine: `frames` ONLY when explicitly set; auto/waapi/unset →
5635
5418
  // waapi (we're not 100% sure it's frames, and CSS/WAAPI need the inline form).
5636
5419
  engine: resolveTimelineEngine((_a2 = getAnimatorConfig(root)) == null ? void 0 : _a2.engine),
5637
- glyphs: (_b = getDefs(root)) == null ? void 0 : _b.fonts
5420
+ glyphs: (_b = getDefinitions(root)) == null ? void 0 : _b.fonts
5638
5421
  };
5639
5422
  const working = clone(root);
5640
5423
  indexById(working, ctx.idMap);
@@ -5718,11 +5501,11 @@ var PixodeskAnimator = (() => {
5718
5501
  if (propAnim.alongPathMode !== "offsetPath") return void 0;
5719
5502
  const kfs = propAnim.keyframes;
5720
5503
  if (!kfs || kfs.length < 2) return void 0;
5721
- const first = kfValue(kfs[0]);
5504
+ const first = keyframeValue(kfs[0]);
5722
5505
  const anchor = (first == null ? void 0 : first.origin) && first.origin.length >= 2 ? [first.origin[0], first.origin[1]] : [0, 0];
5723
5506
  const points = [];
5724
5507
  for (const kf of kfs) {
5725
- const v = kfValue(kf);
5508
+ const v = keyframeValue(kf);
5726
5509
  const tr = v == null ? void 0 : v.translate;
5727
5510
  if (!tr || tr.length < 2) return void 0;
5728
5511
  const parts = Object.keys(v);
@@ -5731,13 +5514,13 @@ var PixodeskAnimator = (() => {
5731
5514
  if (o[0] !== anchor[0] || o[1] !== anchor[1]) return void 0;
5732
5515
  points.push([tr[0] + anchor[0], tr[1] + anchor[1]]);
5733
5516
  }
5734
- if (!kfs.some((kf) => kfTangentIn(kf) || kfTangentOut(kf))) return void 0;
5517
+ if (!kfs.some((kf) => keyframeTangentIn(kf) || keyframeTangentOut(kf))) return void 0;
5735
5518
  let d = "M" + fmt2(points[0][0]) + "," + fmt2(points[0][1]);
5736
5519
  const segLens = [];
5737
5520
  for (let i = 0; i < points.length - 1; i++) {
5738
5521
  const p0 = points[i], p1 = points[i + 1];
5739
- const to = (_b = kfTangentOut(kfs[i])) != null ? _b : [0, 0];
5740
- const ti = (_c = kfTangentIn(kfs[i + 1])) != null ? _c : [0, 0];
5522
+ const to = (_b = keyframeTangentOut(kfs[i])) != null ? _b : [0, 0];
5523
+ const ti = (_c = keyframeTangentIn(kfs[i + 1])) != null ? _c : [0, 0];
5741
5524
  const c1 = [p0[0] + to[0], p0[1] + to[1]];
5742
5525
  const c2 = [p1[0] + ti[0], p1[1] + ti[1]];
5743
5526
  d += "C" + fmt2(c1[0]) + "," + fmt2(c1[1]) + "," + fmt2(c2[0]) + "," + fmt2(c2[1]) + "," + fmt2(p1[0]) + "," + fmt2(p1[1]);
@@ -5749,8 +5532,8 @@ var PixodeskAnimator = (() => {
5749
5532
  let cum = 0;
5750
5533
  for (let i = 0; i < kfs.length; i++) {
5751
5534
  if (i > 0) cum += segLens[i - 1];
5752
- const out = { t: kfTime(kfs[i]), v: cum / total };
5753
- const e = kfEasing(kfs[i]);
5535
+ const out = { t: keyframeTime(kfs[i]), v: cum / total };
5536
+ const e = keyframeEasing(kfs[i]);
5754
5537
  if (e !== void 0) out.e = e;
5755
5538
  distanceKfs.push(out);
5756
5539
  }
@@ -5800,15 +5583,163 @@ var PixodeskAnimator = (() => {
5800
5583
  return walk(root);
5801
5584
  }
5802
5585
 
5586
+ // ../svg-animator-core/src/materialize/PxAnimatorUseMaterializer.ts
5587
+ function materializeAnimatedUseInstances(root) {
5588
+ var _a2;
5589
+ const idMap = buildIdMap(root);
5590
+ const animatedIds = computeAnimatedSubtreeIds(root, idMap);
5591
+ if (animatedIds.size === 0) return root;
5592
+ let idCounter = 0;
5593
+ const genId3 = () => "_lw_use_mat_" + ++idCounter;
5594
+ const rootViewport = readRootViewport(root);
5595
+ const defsCollector = [];
5596
+ const walked = walkAndMaterialize2(root, idMap, animatedIds, genId3, defsCollector, rootViewport);
5597
+ if (defsCollector.length === 0) return walked;
5598
+ const defsNode = { type: "defs", children: defsCollector };
5599
+ const newChildren = [...(_a2 = walked.children) != null ? _a2 : [], defsNode];
5600
+ return __spreadProps(__spreadValues({}, walked), { children: newChildren });
5601
+ }
5602
+ function readRootViewport(root) {
5603
+ const vb = parseViewBox(root.viewBox);
5604
+ if (vb) return [vb[2], vb[3]];
5605
+ const w = numericAttr(root.width);
5606
+ const h = numericAttr(root.height);
5607
+ if (w !== void 0 && h !== void 0) return [w, h];
5608
+ return [1, 1];
5609
+ }
5610
+ function numericAttr(v) {
5611
+ if (typeof v === "number") return v;
5612
+ if (typeof v === "string") {
5613
+ const n = parseFloat(v);
5614
+ return Number.isFinite(n) ? n : void 0;
5615
+ }
5616
+ return void 0;
5617
+ }
5618
+ function buildIdMap(root) {
5619
+ const map = /* @__PURE__ */ new Map();
5620
+ const visit = (n) => {
5621
+ var _a2;
5622
+ if (typeof n.id === "string") map.set(n.id, n);
5623
+ (_a2 = n.children) == null ? void 0 : _a2.forEach(visit);
5624
+ };
5625
+ visit(root);
5626
+ return map;
5627
+ }
5628
+ function computeAnimatedSubtreeIds(root, idMap) {
5629
+ const cache = /* @__PURE__ */ new WeakMap();
5630
+ const result = /* @__PURE__ */ new Set();
5631
+ const hasAnim = (n, visiting) => {
5632
+ const cached = cache.get(n);
5633
+ if (cached !== void 0) return cached;
5634
+ if (visiting.has(n)) return false;
5635
+ visiting.add(n);
5636
+ let r = false;
5637
+ if (n.animate && typeof n.animate === "object" && !Array.isArray(n.animate)) {
5638
+ for (const _ in n.animate) {
5639
+ r = true;
5640
+ break;
5641
+ }
5642
+ }
5643
+ if (!r && n.children) {
5644
+ for (const ch of n.children) {
5645
+ if (hasAnim(ch, visiting)) {
5646
+ r = true;
5647
+ break;
5648
+ }
5649
+ }
5650
+ }
5651
+ if (!r && n.type === "use" && typeof n.href === "string") {
5652
+ const targetId = stripHash2(n.href);
5653
+ const target = targetId ? idMap.get(targetId) : void 0;
5654
+ if (target) r = hasAnim(target, visiting);
5655
+ }
5656
+ visiting.delete(n);
5657
+ cache.set(n, r);
5658
+ return r;
5659
+ };
5660
+ for (const [id, node] of idMap) {
5661
+ if (hasAnim(node, /* @__PURE__ */ new Set())) result.add(id);
5662
+ }
5663
+ return result;
5664
+ }
5665
+ function stripHash2(href) {
5666
+ if (typeof href !== "string") return void 0;
5667
+ return href.startsWith("#") ? href.slice(1) : href;
5668
+ }
5669
+ function materializeOneUse(useNode, target, idMap, animatedIds, genId3, defsCollector, rootViewport) {
5670
+ var _a2, _b, _c, _d;
5671
+ const clone2 = deepClonePxNode(target);
5672
+ regenerateIdsAndRewriteRefs(clone2, genId3);
5673
+ const symbolViewBox = clone2.type === "symbol" ? parseViewBox(clone2.viewBox) : void 0;
5674
+ const useW = (_b = (_a2 = numericAttr(useNode.width)) != null ? _a2 : symbolViewBox == null ? void 0 : symbolViewBox[2]) != null ? _b : rootViewport[0];
5675
+ const useH = (_d = (_c = numericAttr(useNode.height)) != null ? _c : symbolViewBox == null ? void 0 : symbolViewBox[3]) != null ? _d : rootViewport[1];
5676
+ const rewrittenClone = clone2.type === "symbol" ? rewriteSymbolRootToGroup(clone2, genId3, defsCollector, useW, useH) : clone2;
5677
+ const materializedClone = walkAndMaterialize2(rewrittenClone, idMap, animatedIds, genId3, defsCollector, rootViewport);
5678
+ const newNode = __spreadProps(__spreadValues({}, useNode), { type: "g", children: [materializedClone] });
5679
+ delete newNode.href;
5680
+ delete newNode.width;
5681
+ delete newNode.height;
5682
+ return applyUseOffsetToG(newNode);
5683
+ }
5684
+ function rewriteSymbolRootToGroup(symbolNode, genId3, defsCollector, useW, useH) {
5685
+ const viewBox = parseViewBox(symbolNode.viewBox);
5686
+ const g = __spreadProps(__spreadValues({}, symbolNode), { type: "g" });
5687
+ delete g.viewBox;
5688
+ delete g.preserveAspectRatio;
5689
+ delete g.width;
5690
+ delete g.height;
5691
+ if (!viewBox) return g;
5692
+ const [vbX, vbY, vbW, vbH] = viewBox;
5693
+ const scale = vbW > 0 && vbH > 0 ? Math.min(useW / vbW, useH / vbH) : 1;
5694
+ const xOff = (useW - vbW * scale) / 2;
5695
+ const yOff = (useH - vbH * scale) / 2;
5696
+ const parts = [];
5697
+ if (xOff !== 0 || yOff !== 0) parts.push("translate(" + xOff + "," + yOff + ")");
5698
+ if (scale !== 1) parts.push("scale(" + scale + ")");
5699
+ if (vbX !== 0 || vbY !== 0) parts.push("translate(" + -vbX + "," + -vbY + ")");
5700
+ if (parts.length) g.transform = parts.join("");
5701
+ const clipId = genId3();
5702
+ defsCollector.push({
5703
+ type: "clipPath",
5704
+ id: clipId,
5705
+ children: [{ type: "rect", x: vbX, y: vbY, width: vbW, height: vbH }]
5706
+ });
5707
+ g.clipPath = "url(#" + clipId + ")";
5708
+ return g;
5709
+ }
5710
+ function parseViewBox(v) {
5711
+ if (typeof v !== "string") return void 0;
5712
+ const parts = v.trim().split(/[\s,]+/).map(Number);
5713
+ if (parts.length < 4 || parts.some((n) => !Number.isFinite(n))) return void 0;
5714
+ return [parts[0], parts[1], parts[2], parts[3]];
5715
+ }
5716
+ function walkAndMaterialize2(node, idMap, animatedIds, genId3, defsCollector, rootViewport) {
5717
+ if (node.type === "use" && typeof node.href === "string") {
5718
+ const targetId = stripHash2(node.href);
5719
+ if (targetId && animatedIds.has(targetId)) {
5720
+ const target = idMap.get(targetId);
5721
+ if (target) return materializeOneUse(node, target, idMap, animatedIds, genId3, defsCollector, rootViewport);
5722
+ }
5723
+ }
5724
+ if (!node.children) return node;
5725
+ let changed = false;
5726
+ const newChildren = node.children.map((ch) => {
5727
+ const m = walkAndMaterialize2(ch, idMap, animatedIds, genId3, defsCollector, rootViewport);
5728
+ if (m !== ch) changed = true;
5729
+ return m;
5730
+ });
5731
+ return changed ? __spreadProps(__spreadValues({}, node), { children: newChildren }) : node;
5732
+ }
5733
+
5803
5734
  // ../svg-animator-core/src/materialize/PxAnimatorMaterializeAll.ts
5804
- function materializeAllInTree(doc, engine, opts) {
5735
+ function materializeAllInTree(doc, engine, options) {
5805
5736
  var _a2, _b;
5806
- let root = applyPlayerEffects(doc).root;
5737
+ let root = materializeNodeEffects(doc).root;
5807
5738
  root = materializeOffsetPathsInTree(root);
5808
- const duration = (_b = (_a2 = getAnimatorConfig(root)) == null ? void 0 : _a2.duration) != null ? _b : DEFAULT_DURATION_MS;
5739
+ const duration = (_b = (_a2 = getAnimatorConfig(root)) == null ? void 0 : _a2.duration) != null ? _b : PX_DEFAULT_DURATION_MS;
5809
5740
  root = materializeInternalLoopsInTree(root, duration);
5810
5741
  if (engine === PxTimelineEngine.native) {
5811
- root = materializeMotionPathsInTree(root, opts == null ? void 0 : opts.motionPath);
5742
+ root = materializeMotionPathsInTree(root, options == null ? void 0 : options.motionPath);
5812
5743
  root = materializeAnimatedUseInstances(root);
5813
5744
  root = pruneUnreferencedDefs(root);
5814
5745
  }
@@ -5892,16 +5823,16 @@ var PixodeskAnimator = (() => {
5892
5823
  }
5893
5824
  g.clearTimeout(handle);
5894
5825
  }
5895
- function createBasicFrameLoopAnimator(doc, adapter, callbacks) {
5826
+ function createAdapterAnimator(doc, adapter, callbacks) {
5896
5827
  var _a2;
5897
5828
  const config = getAnimatorConfig(doc) || {};
5898
- const bindings = getNormalizedBindings(doc, PxTimelineEngine.js);
5829
+ const bindings = normalizeBindings(doc, PxTimelineEngine.js);
5899
5830
  const _iterations = config.iterations;
5900
5831
  let iterations = 1;
5901
5832
  if (typeof _iterations === "number") iterations = _iterations || 1;
5902
5833
  if (_iterations === "infinite") iterations = Infinity;
5903
5834
  if (iterations < 1) iterations = 1;
5904
- const duration = +(config.duration || DEFAULT_DURATION_MS);
5835
+ const duration = +(config.duration || PX_DEFAULT_DURATION_MS);
5905
5836
  const totalDuration = duration && iterations ? duration * (iterations === Infinity ? Infinity : iterations) : duration ? (iterations != null ? iterations : 1) * duration : 0;
5906
5837
  const direction = config.direction || "normal";
5907
5838
  const fill = (_a2 = config.fill) != null ? _a2 : "forwards";
@@ -6175,10 +6106,6 @@ var PixodeskAnimator = (() => {
6175
6106
  function asError(error) {
6176
6107
  return typeof error === "string" ? new Error(error) : error;
6177
6108
  }
6178
- function isSilenced(silent, kind) {
6179
- if (!silent) return false;
6180
- return silent === true || silent.includes(kind);
6181
- }
6182
6109
  function createDiagnostics(config, prefix) {
6183
6110
  const tag = prefix ? prefix + " " : "";
6184
6111
  return {
@@ -6187,19 +6114,21 @@ var PixodeskAnimator = (() => {
6187
6114
  config.onWarn({ kind, message, detail });
6188
6115
  return;
6189
6116
  }
6190
- if (isSilenced(config == null ? void 0 : config.silent, kind)) return;
6117
+ if (config == null ? void 0 : config.muteWarn) return;
6191
6118
  const line = tag + kind + ": " + message;
6192
6119
  if (detail === void 0) console.warn(line);
6193
6120
  else console.warn(line, detail);
6194
6121
  },
6195
- error: (kind, error) => {
6122
+ error: (kind, error, detail) => {
6196
6123
  const err = asError(error);
6197
6124
  if (config == null ? void 0 : config.onError) {
6198
- config.onError({ kind, message: err.message, error: err });
6125
+ config.onError({ kind, message: err.message, error: err, detail });
6199
6126
  return;
6200
6127
  }
6201
- if (isSilenced(config == null ? void 0 : config.silent, kind)) return;
6202
- console.error(tag + kind + ": " + err.message);
6128
+ if (config == null ? void 0 : config.muteError) return;
6129
+ const line = tag + kind + ": " + err.message;
6130
+ if (detail === void 0) console.error(line);
6131
+ else console.error(line, detail);
6203
6132
  }
6204
6133
  };
6205
6134
  }
@@ -6218,7 +6147,7 @@ var PixodeskAnimator = (() => {
6218
6147
  "mode",
6219
6148
  "frameRate"
6220
6149
  ];
6221
- var CONTENT_KEYS = ["definitions", "animateById"];
6150
+ var CONTENT_KEYS = ["definitions", "bindings"];
6222
6151
  var isPlainObject = (v) => !!v && typeof v === "object" && !Array.isArray(v);
6223
6152
  var timelineTypeOf = (t) => isPlainObject(t) && typeof t.type === "string" ? t.type : "time";
6224
6153
  var isScrollish = (type) => type === "scroll" || type === "view";
@@ -6322,9 +6251,9 @@ var PixodeskAnimator = (() => {
6322
6251
  }
6323
6252
  return { config: out, warnings };
6324
6253
  }
6325
- function applyAnimatorConfig(doc, patch, opts) {
6254
+ function applyAnimatorConfig(doc, patch, options) {
6326
6255
  var _a2, _b;
6327
- const reset = !!(opts == null ? void 0 : opts.resetDefaults);
6256
+ const reset = !!(options == null ? void 0 : options.resetTimeline);
6328
6257
  if (!doc || (patch === void 0 || !reset && (patch === null || !isPlainObject(patch) || !Object.keys(patch).length))) {
6329
6258
  return { doc, warnings: [] };
6330
6259
  }
@@ -6375,9 +6304,65 @@ var PixodeskAnimator = (() => {
6375
6304
  );
6376
6305
  }
6377
6306
 
6307
+ // ../svg-animator-core/src/playback/PxScrollMath.ts
6308
+ function isScrollTimeline(config) {
6309
+ return (config == null ? void 0 : config.timelineSource) === "scroll";
6310
+ }
6311
+ function scrollTotalDurationMs(config) {
6312
+ const duration = typeof (config == null ? void 0 : config.duration) === "number" && config.duration > 0 ? config.duration : PX_DEFAULT_DURATION_MS;
6313
+ const iterations = typeof (config == null ? void 0 : config.iterations) === "number" && config.iterations > 0 ? config.iterations : 1;
6314
+ return duration * iterations;
6315
+ }
6316
+ function scrollPhaseInterval(phase, subjectSize, scrollportSize) {
6317
+ const s = subjectSize, vp = scrollportSize;
6318
+ switch (phase) {
6319
+ case "cover":
6320
+ return [0, s + vp];
6321
+ case "entry":
6322
+ return [0, Math.min(s, vp)];
6323
+ case "contain":
6324
+ return [Math.min(s, vp), Math.max(s, vp)];
6325
+ case "exit":
6326
+ return [Math.max(s, vp), s + vp];
6327
+ case "entry-crossing":
6328
+ return [0, s];
6329
+ case "exit-crossing":
6330
+ return [vp, s + vp];
6331
+ }
6332
+ }
6333
+ var DEFAULT_PHASE = "cover";
6334
+ function resolveRangePointU(point, defaultFraction, subjectSize, scrollportSize) {
6335
+ var _a2;
6336
+ const [u0, u1] = scrollPhaseInterval((_a2 = point == null ? void 0 : point.phase) != null ? _a2 : DEFAULT_PHASE, subjectSize, scrollportSize);
6337
+ const fraction = typeof (point == null ? void 0 : point.fraction) === "number" ? point.fraction : defaultFraction;
6338
+ return u0 + fraction * (u1 - u0);
6339
+ }
6340
+ function scrollViewProgress(subjectStart, subjectSize, scrollportSize, range) {
6341
+ const u = scrollportSize - subjectStart;
6342
+ const uStart = resolveRangePointU(range == null ? void 0 : range.start, 0, subjectSize, scrollportSize);
6343
+ const uEnd = resolveRangePointU(range == null ? void 0 : range.end, 1, subjectSize, scrollportSize);
6344
+ if (uEnd <= uStart) return u >= uEnd ? 1 : 0;
6345
+ return clamp((u - uStart) / (uEnd - uStart), 0, 1);
6346
+ }
6347
+ function scrollOffsetProgress(offset, maxOffset, range) {
6348
+ var _a2, _b;
6349
+ const raw = maxOffset > 0 ? clamp(offset / maxOffset, 0, 1) : 1;
6350
+ const start = typeof ((_a2 = range == null ? void 0 : range.start) == null ? void 0 : _a2.fraction) === "number" ? range.start.fraction : 0;
6351
+ const end = typeof ((_b = range == null ? void 0 : range.end) == null ? void 0 : _b.fraction) === "number" ? range.end.fraction : 1;
6352
+ if (end <= start) return raw >= end ? 1 : 0;
6353
+ return clamp((raw - start) / (end - start), 0, 1);
6354
+ }
6355
+ function scrollResolveAxis(axis, writingMode) {
6356
+ const a = axis != null ? axis : "block";
6357
+ if (a === "x" || a === "y") return a;
6358
+ const vertical = !!writingMode && writingMode.startsWith("vertical");
6359
+ if (a === "inline") return vertical ? "y" : "x";
6360
+ return vertical ? "x" : "y";
6361
+ }
6362
+
6378
6363
  // src/shared/PxAnimatorCallbacks.ts
6379
6364
  function toEngineCallbacks(inline) {
6380
- const { onPlay, onPause, onCancel, onFinish, onRemove, onStop, onWarn, onError, silent } = inline != null ? inline : {};
6365
+ const { onPlay, onPause, onCancel, onFinish, onRemove, onStop, onWarn, onError, muteWarn, muteError } = inline != null ? inline : {};
6381
6366
  const withStop = (own) => own || onStop ? () => {
6382
6367
  own == null ? void 0 : own();
6383
6368
  onStop == null ? void 0 : onStop();
@@ -6390,18 +6375,22 @@ var PixodeskAnimator = (() => {
6390
6375
  onRemove: withStop(onRemove),
6391
6376
  onWarn,
6392
6377
  onError,
6393
- silent
6378
+ muteWarn,
6379
+ muteError
6394
6380
  };
6395
6381
  }
6382
+ function asThrownError(e) {
6383
+ return e instanceof Error ? e : new Error(String(e));
6384
+ }
6396
6385
 
6397
6386
  // src/triggers/PxAnimatorTriggers.ts
6398
- function setupAnimationTriggers(api, config, diag) {
6387
+ function setupAnimationTriggers(api, trigger, diag) {
6399
6388
  const report = diag != null ? diag : createDiagnostics(void 0, "[PxAnimator]");
6400
6389
  const cleanups = [];
6401
6390
  const dispose = () => {
6402
6391
  for (const undo of cleanups.splice(0)) undo();
6403
6392
  };
6404
- const { startOn, outAction, scrollIntoViewThreshold } = resolveTrigger(config);
6393
+ const { startOn, outAction, scrollIntoViewThreshold } = resolveTrigger(trigger);
6405
6394
  const root = api.getRootElement();
6406
6395
  if (!root) {
6407
6396
  report.warn(PxDiagnosticKind.host, "setupAnimationTriggers: No root element found for animation.");
@@ -6528,7 +6517,7 @@ var PixodeskAnimator = (() => {
6528
6517
  diag.warn(PxDiagnosticKind.host, "createFrameLoopAnimator: No root element provided");
6529
6518
  }
6530
6519
  }
6531
- const basicApi = createBasicFrameLoopAnimator(
6520
+ const basicApi = createAdapterAnimator(
6532
6521
  doc,
6533
6522
  adapter || createDomAdapter(rootElement, diag),
6534
6523
  callbacks
@@ -6568,7 +6557,7 @@ var PixodeskAnimator = (() => {
6568
6557
  const element = elements[i];
6569
6558
  const effectiveAttrName = attrName === "transform" && element.tagName === "pattern" ? "patternTransform" : attrName;
6570
6559
  element.setAttribute(effectiveAttrName, value);
6571
- if (STYLE_ATTR_NAMES.has(attrName)) {
6560
+ if (PX_STYLE_ATTR_NAMES.has(attrName)) {
6572
6561
  element.style[attrName] = value;
6573
6562
  }
6574
6563
  }
@@ -6579,20 +6568,20 @@ var PixodeskAnimator = (() => {
6579
6568
 
6580
6569
  // src/engines/PxAnimatorWebApi.ts
6581
6570
  function createCssKf(kf, t, propName, unsupportedSet) {
6582
- let value = kfValue(kf);
6583
- const e = kfEasing(kf);
6571
+ let value = keyframeValue(kf);
6572
+ const e = keyframeEasing(kf);
6584
6573
  const cssKf = {
6585
6574
  offset: t,
6586
6575
  easing: e && Array.isArray(e) ? "cubic-bezier(" + e.join(",") + ")" : void 0
6587
6576
  };
6588
6577
  let cssValue;
6589
6578
  let cssKey = propName;
6590
- if (COLOR_ATTR_NAMES.has(propName) && Array.isArray(value)) {
6579
+ if (PX_COLOR_ATTR_NAMES.has(propName) && Array.isArray(value)) {
6591
6580
  cssValue = toRGBA(value);
6592
6581
  } else if (propName === "transform" && value !== null && typeof value === "object" && !Array.isArray(value)) {
6593
6582
  cssValue = composeTransformParts(value, { withUnits: true });
6594
6583
  cssKey = "transform";
6595
- } else if (TRANSFORM_FN_NAMES.has(propName)) {
6584
+ } else if (PX_TRANSFORM_FN_NAMES.has(propName)) {
6596
6585
  if (Array.isArray(value)) {
6597
6586
  if (propName === "translate") value = value.map((v) => v + "px");
6598
6587
  value = value.join(",");
@@ -6603,7 +6592,7 @@ var PixodeskAnimator = (() => {
6603
6592
  } else if (propName === "d") {
6604
6593
  const paths = value && typeof value === "object" && Array.isArray(value.paths) ? value.paths : [];
6605
6594
  cssValue = 'path("' + paths.map((bz) => bezierToSvgPath(bz, true)).join("") + '")';
6606
- } else if (PCT_BASED_ATTR_NAMES.has(propName) && typeof value === "number") {
6595
+ } else if (PX_PCT_BASED_ATTR_NAMES.has(propName) && typeof value === "number") {
6607
6596
  cssValue = value * 100 + "%";
6608
6597
  } else {
6609
6598
  cssValue = "" + value;
@@ -6686,7 +6675,7 @@ var PixodeskAnimator = (() => {
6686
6675
  diag.warn(PxDiagnosticKind.host, "createWebApiAnimator: No root element provided");
6687
6676
  }
6688
6677
  }
6689
- const bindings = getNormalizedBindings(doc, PxTimelineEngine.native);
6678
+ const bindings = normalizeBindings(doc, PxTimelineEngine.native);
6690
6679
  const animations = [];
6691
6680
  const _iterations = config.iterations;
6692
6681
  let iterations;
@@ -7168,7 +7157,7 @@ var PixodeskAnimator = (() => {
7168
7157
  unpin = () => {
7169
7158
  };
7170
7159
  }
7171
- const api = (animatorConfig.engine !== PxTimelineEngineExtra.js ? createWebApiAnimator(doc, cb, rootElement, isNativeForced(animatorConfig.engine)) : null) || createFrameLoopAnimator(doc, adapter, cb, rootElement);
7160
+ const api = (animatorConfig.engine !== PxTimelineEngineSetting.js ? createWebApiAnimator(doc, cb, rootElement, isNativeForced(animatorConfig.engine)) : null) || createFrameLoopAnimator(doc, adapter, cb, rootElement);
7172
7161
  const subject = ((_a2 = api.getRootElement) == null ? void 0 : _a2.call(api)) || rootElement;
7173
7162
  if (subject) {
7174
7163
  unpin = applyScrollPin(subject, animatorConfig.scroll);
@@ -7194,7 +7183,7 @@ var PixodeskAnimator = (() => {
7194
7183
  });
7195
7184
  }
7196
7185
  return finaliseAnimator(animatorConfig, callbacks, (cb) => {
7197
- if (animatorConfig.engine === PxTimelineEngineExtra.js) {
7186
+ if (animatorConfig.engine === PxTimelineEngineSetting.js) {
7198
7187
  return createFrameLoopAnimator(doc, adapter, cb, rootElement);
7199
7188
  }
7200
7189
  return createWebApiAnimator(
@@ -7209,7 +7198,7 @@ var PixodeskAnimator = (() => {
7209
7198
  // src/dom/PxAnimatorDOM.ts
7210
7199
  var SVG_NS = "http://www.w3.org/2000/svg";
7211
7200
  function createElement(tagName, normalizedProps, style, children, textContent, diag) {
7212
- if (DISALLOWED_SVG_TAGS_LOWER.has(tagName.toLowerCase())) {
7201
+ if (PX_DISALLOWED_SVG_TAGS_LOWER.has(tagName.toLowerCase())) {
7213
7202
  (diag != null ? diag : createDiagnostics(void 0, "[PxAnimator]")).warn(PxDiagnosticKind.document, "SVG tag blocked (dangerous): " + tagName);
7214
7203
  return null;
7215
7204
  }
@@ -7217,7 +7206,7 @@ var PixodeskAnimator = (() => {
7217
7206
  for (const propName in normalizedProps) {
7218
7207
  const sanitized = sanitizeAttributeValue(propName, normalizedProps[propName]);
7219
7208
  if (sanitized === void 0) continue;
7220
- if (CSS_ONLY_STYLE_PROPS.has(propName)) {
7209
+ if (PX_CSS_ONLY_STYLE_PROPS.has(propName)) {
7221
7210
  element.style[propName] = String(sanitized);
7222
7211
  continue;
7223
7212
  }
@@ -7242,8 +7231,8 @@ var PixodeskAnimator = (() => {
7242
7231
  const _a2 = node, { type, children, style } = _a2, props = __objRest(_a2, ["type", "children", "style"]);
7243
7232
  const domType = props.domType;
7244
7233
  if (domType !== void 0) delete props.domType;
7245
- const nodeDefs = getDefs(node) || defs;
7246
- const resolvedStyle = resolveStyle(style, nodeDefs);
7234
+ const nodeDefs = getDefinitions(node) || defs;
7235
+ const resolvedStyle = style;
7247
7236
  let childElements;
7248
7237
  if (children) {
7249
7238
  for (const ch of children) {
@@ -7256,10 +7245,10 @@ var PixodeskAnimator = (() => {
7256
7245
  }
7257
7246
  const element = createElement(
7258
7247
  type || "g",
7259
- getNormalizedProps(props),
7248
+ toDomProps(props),
7260
7249
  resolvedStyle,
7261
7250
  childElements,
7262
- props[TEXT_CONTENT_ATTR],
7251
+ props[PX_TEXT_CONTENT_ATTR],
7263
7252
  diag
7264
7253
  );
7265
7254
  if (element && domType !== void 0) element.setAttribute("type", domType);
@@ -7279,7 +7268,7 @@ var PixodeskAnimator = (() => {
7279
7268
  for (const w of effectsWarnings) diag.warn(PxDiagnosticKind.document, "effects shape: " + w);
7280
7269
  reportDocumentDiagnostics(doc, "[PxAnimator] createAnimator");
7281
7270
  if (patch !== void 0 || resetTimeline) {
7282
- const patched = applyAnimatorConfig(doc, patch != null ? patch : {}, { resetDefaults: !!resetTimeline });
7271
+ const patched = applyAnimatorConfig(doc, patch != null ? patch : {}, { resetTimeline: !!resetTimeline });
7283
7272
  for (const w of patched.warnings) diag.warn(PxDiagnosticKind.usage, "timeline override: " + w);
7284
7273
  doc = patched.doc;
7285
7274
  }
@@ -7308,12 +7297,16 @@ var PixodeskAnimator = (() => {
7308
7297
  }
7309
7298
  return api;
7310
7299
  }
7300
+ function isInternalOptions(options) {
7301
+ return "adapter" in options;
7302
+ }
7311
7303
  function resolveTimelineOption(options) {
7312
7304
  const { timeline, duration, delay, iterations, startOn } = options;
7313
7305
  return foldTimelineOverride(timeline, { duration, delay, iterations, startOn });
7314
7306
  }
7315
7307
  function createAnimator(options) {
7316
- const { src, doc, adapter, container, resetTimeline } = options;
7308
+ const { src, doc, container, resetTimeline } = options;
7309
+ const adapter = isInternalOptions(options) ? options.adapter : void 0;
7317
7310
  const patch = resolveTimelineOption(options);
7318
7311
  const callbacks = toEngineCallbacks(options);
7319
7312
  if (doc !== void 0 && src !== void 0) {
@@ -7322,9 +7315,6 @@ var PixodeskAnimator = (() => {
7322
7315
  if (doc === void 0 && src === void 0) {
7323
7316
  throw new Error("createAnimator: either `src` or `doc` is required");
7324
7317
  }
7325
- if (doc !== void 0) {
7326
- return createAnimatorImpl(doc, adapter, callbacks, container, patch, resetTimeline);
7327
- }
7328
7318
  let animator = null;
7329
7319
  let pending = [];
7330
7320
  let destroyed = false;
@@ -7335,28 +7325,37 @@ var PixodeskAnimator = (() => {
7335
7325
  pending.push(call);
7336
7326
  }
7337
7327
  };
7338
- const loadDiag = createDiagnostics(callbacks, "[PxAnimator]");
7339
- fetch(src).then((res) => res.json()).then((json) => {
7340
- if (destroyed) return;
7341
- if (isPxElementFileFormat(json)) {
7342
- animator = createAnimatorImpl(json, adapter, callbacks, container, patch, resetTimeline);
7343
- const queued = pending;
7344
- pending = null;
7345
- queued == null ? void 0 : queued.forEach((call) => call(animator));
7346
- } else {
7347
- loadDiag.error(
7348
- PxDiagnosticKind.document,
7349
- 'createAnimator: invalid animation document format at "' + src + '"'
7350
- );
7351
- }
7352
- }).catch((err) => {
7353
- var _a2;
7328
+ const diag = createDiagnostics(callbacks, "[PxAnimator]");
7329
+ const ready = (api) => {
7330
+ animator = api;
7331
+ const queued = pending;
7354
7332
  pending = null;
7355
- loadDiag.error(
7356
- PxDiagnosticKind.host,
7357
- 'createAnimator: failed to load "' + src + '" \u2014 ' + ((_a2 = err == null ? void 0 : err.message) != null ? _a2 : String(err))
7358
- );
7359
- });
7333
+ queued == null ? void 0 : queued.forEach((call) => call(api));
7334
+ };
7335
+ const failed = (kind, message, detail) => {
7336
+ pending = null;
7337
+ diag.error(kind, message, detail);
7338
+ };
7339
+ const build = (document2) => {
7340
+ try {
7341
+ ready(createAnimatorImpl(document2, adapter, callbacks, container, patch, resetTimeline));
7342
+ } catch (e) {
7343
+ const err = asThrownError(e);
7344
+ failed(PxDiagnosticKind.internal, "createAnimator: could not build the player \u2014 " + err.message, err);
7345
+ }
7346
+ };
7347
+ if (doc !== void 0) {
7348
+ build(doc);
7349
+ } else {
7350
+ fetch(src).then((res) => res.json()).then((json) => {
7351
+ if (destroyed) return;
7352
+ if (isPxDocument(json)) build(json);
7353
+ else failed(PxDiagnosticKind.document, 'createAnimator: invalid animation document format at "' + src + '"');
7354
+ }).catch((err) => {
7355
+ var _a2;
7356
+ failed(PxDiagnosticKind.host, 'createAnimator: failed to load "' + src + '" \u2014 ' + ((_a2 = err == null ? void 0 : err.message) != null ? _a2 : String(err)));
7357
+ });
7358
+ }
7360
7359
  return {
7361
7360
  "isReady": () => !!animator,
7362
7361
  "getRootElement": () => animator ? animator.getRootElement() : null,