@pixodesk/svg-animator-web 1.0.39 → 1.0.40

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.
@@ -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;
@@ -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
@@ -1450,9 +944,6 @@ var PixodeskAnimator = (() => {
1450
944
  var PxDefsSchema = 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({
@@ -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
1036
  definitions: PxDefsSchema.optional(),
1542
- animateById: px.record(PxElementAnimationSchema).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(),
@@ -1733,198 +1224,646 @@ var PixodeskAnimator = (() => {
1733
1224
  if (parseWireVersion(version) !== void 0) return [];
1734
1225
  return ["root.animator.version: " + JSON.stringify(version) + ' is not a version stamp ("a.b" or "a.b.c") \u2014 it reads as unstamped'];
1735
1226
  }
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
- }
1227
+ function validateDocument(doc, opts) {
1228
+ var _a2;
1229
+ const strict = (opts == null ? void 0 : opts.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 PxNodeBase = 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 (MINIFICATION-BOUNDARY-PLAN.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 `applyPlayerEffects` 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({}, PxNodeBase._shape), {
1282
+ children: px.lazy(() => px.array(PxNodeSchema), []).optional()
1283
+ }), PxAttrValueSchema);
1284
+ var PxSvgNodeExtra = 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({}, PxNodeBase._shape), PxSvgNodeExtra._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 COLOR_ATTR_NAMES = /* @__PURE__ */ new Set(["color", "fill", "flood-color", "lighting-color", "stop-color", "stroke"]);
1652
+ var TRANSFORM_FN_NAMES = /* @__PURE__ */ new Set(["translate", "rotate", "scale", "skew"]);
1653
+ var 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 STYLE_ATTR_NAMES = /* @__PURE__ */ new Set(["offset-distance", "offsetDistance"]);
1707
+ var 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));
1772
+ }
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
@@ -1990,14 +1929,6 @@ 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
1932
  function getNormalizedProps(props) {
2002
1933
  const propsCopy = {};
2003
1934
  for (const rawKey of Object.keys(props)) {
@@ -2960,9 +2891,7 @@ var PixodeskAnimator = (() => {
2960
2891
  const defs = getDefs(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) {
@@ -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
  }
@@ -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);
@@ -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) {
@@ -5059,7 +4842,7 @@ var PixodeskAnimator = (() => {
5059
4842
  let adv = 0;
5060
4843
  const walk = (el, parentStyle) => {
5061
4844
  var _a2, _b;
5062
- const s = resolveStyle2(el, parentStyle);
4845
+ const s = resolveStyle(el, parentStyle);
5063
4846
  const content = str(el[TEXT_CONTENT_ATTR]);
5064
4847
  if (content && !((_a2 = el.children) == null ? void 0 : _a2.length)) {
5065
4848
  const gf = glyphFontFor(s, glyphs, soleFont, warnings);
@@ -5800,6 +5583,154 @@ 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
5735
  function materializeAllInTree(doc, engine, opts) {
5805
5736
  var _a2, _b;
@@ -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";
@@ -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 : 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,9 +6375,13 @@ 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
6387
  function setupAnimationTriggers(api, config, diag) {
@@ -7243,7 +7232,7 @@ var PixodeskAnimator = (() => {
7243
7232
  const domType = props.domType;
7244
7233
  if (domType !== void 0) delete props.domType;
7245
7234
  const nodeDefs = getDefs(node) || defs;
7246
- const resolvedStyle = resolveStyle(style, nodeDefs);
7235
+ const resolvedStyle = style;
7247
7236
  let childElements;
7248
7237
  if (children) {
7249
7238
  for (const ch of children) {
@@ -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 (isPxElementFileFormat(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,