@pixodesk/svg-animator-core 1.0.26 → 1.0.27

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -88,6 +88,9 @@ __export(index_exports, {
88
88
  PxPropertyAnimationSchema: () => PxPropertyAnimationSchema,
89
89
  PxRepeaterEffectSchema: () => PxRepeaterEffectSchema,
90
90
  PxRetimeEffectSchema: () => PxRetimeEffectSchema,
91
+ PxScrollRangePointSchema: () => PxScrollRangePointSchema,
92
+ PxScrollRangeSchema: () => PxScrollRangeSchema,
93
+ PxScrollSchema: () => PxScrollSchema,
91
94
  PxStrokeGradientEffectSchema: () => PxStrokeGradientEffectSchema,
92
95
  PxSvgNodeExtra: () => PxSvgNodeExtra,
93
96
  PxTextEffectSchema: () => PxTextEffectSchema,
@@ -129,6 +132,7 @@ __export(index_exports, {
129
132
  interpolateValue: () => interpolateValue,
130
133
  isPxElementFileFormat: () => isPxElementFileFormat,
131
134
  isPxElementFileFormatDeep: () => isPxElementFileFormatDeep,
135
+ isScrollTimeline: () => isScrollTimeline,
132
136
  jsonElementFactory: () => jsonElementFactory,
133
137
  kebabToCamelCaseWord: () => kebabToCamelCaseWord,
134
138
  layoutGlyphTextChars: () => layoutGlyphTextChars,
@@ -147,6 +151,11 @@ __export(index_exports, {
147
151
  reverseEasing: () => reverseEasing,
148
152
  sanitiseAttributeValue: () => sanitiseAttributeValue,
149
153
  schemaKeys: () => schemaKeys,
154
+ scrollOffsetProgress: () => scrollOffsetProgress,
155
+ scrollPhaseInterval: () => scrollPhaseInterval,
156
+ scrollResolveAxis: () => scrollResolveAxis,
157
+ scrollTotalDurationMs: () => scrollTotalDurationMs,
158
+ scrollViewProgress: () => scrollViewProgress,
150
159
  shiftAnimatable: () => shiftAnimatable,
151
160
  splitEasing: () => splitEasing,
152
161
  subdivideCubicBezier: () => subdivideCubicBezier,
@@ -156,111 +165,583 @@ __export(index_exports, {
156
165
  });
157
166
  module.exports = __toCommonJS(index_exports);
158
167
 
159
- // src/PxSchema.ts
160
- function pathStr(path) {
161
- if (!path.length) return ".";
162
- let result = "";
163
- for (const seg of path) {
164
- if (seg.startsWith("[")) result += seg;
165
- else result += (result ? "." : "") + seg;
168
+ // src/PxAnimatorUtil.ts
169
+ function bezierToSvgPath(path, forceCurves = false) {
170
+ var _a, _b, _c, _d;
171
+ const v = path.v;
172
+ const i = path.i;
173
+ const o = path.o;
174
+ const c = path.c;
175
+ if (!v.length) return "";
176
+ const d = [];
177
+ const len = v.length;
178
+ d.push("M" + v[0][0] + "," + v[0][1]);
179
+ for (let idx = 1; idx < len; idx++) {
180
+ const prevV = v[idx - 1];
181
+ const prevO = (_a = o == null ? void 0 : o[idx - 1]) != null ? _a : prevV;
182
+ const currI = (_b = i == null ? void 0 : i[idx]) != null ? _b : v[idx];
183
+ const currV = v[idx];
184
+ const isLine = !forceCurves && (prevO[0] === prevV[0] && prevO[1] === prevV[1]) && (currI[0] === currV[0] && currI[1] === currV[1]);
185
+ if (isLine) {
186
+ d.push("L" + currV[0] + "," + currV[1]);
187
+ } else {
188
+ d.push("C" + prevO[0] + "," + prevO[1] + "," + currI[0] + "," + currI[1] + "," + currV[0] + "," + currV[1]);
189
+ }
166
190
  }
167
- return result;
168
- }
169
- var Base = class {
170
- _canSanitize(raw) {
171
- return this.isValid(raw);
191
+ if (c && len > 0) {
192
+ const lastV = v[len - 1];
193
+ const lastO = (_c = o == null ? void 0 : o[len - 1]) != null ? _c : lastV;
194
+ const firstI = (_d = i == null ? void 0 : i[0]) != null ? _d : v[0];
195
+ const firstV = v[0];
196
+ const isLine = !forceCurves && (lastO[0] === lastV[0] && lastO[1] === lastV[1]) && (firstI[0] === firstV[0] && firstI[1] === firstV[1]);
197
+ if (!isLine) {
198
+ d.push("C" + lastO[0] + "," + lastO[1] + "," + firstI[0] + "," + firstI[1] + "," + firstV[0] + "," + firstV[1]);
199
+ }
200
+ d.push("z");
172
201
  }
173
- optional() {
174
- return new Optional(this);
202
+ return d.join("");
203
+ }
204
+ function interpolateNum(a, b, t) {
205
+ return a + (b - a) * t;
206
+ }
207
+ function interpolateVec(a, b, t) {
208
+ const res = [];
209
+ const count = Math.max(a.length, b.length);
210
+ for (let i = 0; i < count; i++) {
211
+ res[i] = interpolateNum(a[i] || 0, b[i] || 0, t);
175
212
  }
176
- };
177
- var Optional = class extends Base {
178
- constructor(inner) {
179
- super();
180
- this.inner = inner;
181
- this._default = void 0;
213
+ return res;
214
+ }
215
+ function interpolateColor(a, b, t) {
216
+ return [
217
+ interpolateNum(a[0] || 0, b[0] || 0, t),
218
+ interpolateNum(a[1] || 0, b[1] || 0, t),
219
+ interpolateNum(a[2] || 0, b[2] || 0, t),
220
+ interpolateNum(a[3] === void 0 ? 1 : a[3], b[3] === void 0 ? 1 : b[3], t)
221
+ ];
222
+ }
223
+ function interpolateBeziers(paths1, paths2, progress) {
224
+ const count = Math.max(paths1.length, paths2.length);
225
+ const res = [];
226
+ for (let i = 0; i < count; i++) {
227
+ res.push(interpolateBezier(paths1[i], paths2[i], progress));
182
228
  }
183
- sanitize(raw) {
184
- if (raw === void 0 || raw === null) return void 0;
185
- return this.inner._canSanitize(raw) ? this.inner.sanitize(raw) : void 0;
229
+ return res;
230
+ }
231
+ function interpolateBezier(path1, path2, progress) {
232
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i;
233
+ if (!path1 || !path2) return path1 || path2 || { v: [] };
234
+ const t = Math.min(Math.max(progress, 0), 1);
235
+ const len = Math.min(path1.v.length, path2.v.length);
236
+ const v = [];
237
+ const i = [];
238
+ const o = [];
239
+ for (let idx = 0; idx < len; idx++) {
240
+ const v1 = path1.v[idx];
241
+ const v2 = path2.v[idx];
242
+ v.push(interpolateVec(v1, v2, t));
243
+ const i1 = (_b = (_a = path1.i) == null ? void 0 : _a[idx]) != null ? _b : v1;
244
+ const i2 = (_d = (_c = path2.i) == null ? void 0 : _c[idx]) != null ? _d : v2;
245
+ i.push(interpolateVec(i1, i2, t));
246
+ const o1 = (_f = (_e = path1.o) == null ? void 0 : _e[idx]) != null ? _f : v1;
247
+ const o2 = (_h = (_g = path2.o) == null ? void 0 : _g[idx]) != null ? _h : v2;
248
+ o.push(interpolateVec(o1, o2, t));
186
249
  }
187
- isValid(raw, ctx, path) {
188
- if (raw === void 0 || raw === null) return true;
189
- return this.inner.isValid(raw, ctx, path);
250
+ return { v, i: i.length ? i : void 0, o: o.length ? o : void 0, c: (_i = path1.c) != null ? _i : path2.c };
251
+ }
252
+ function remap(value, inMin, inMax, outMin, outMax) {
253
+ if (inMax === inMin) return outMin;
254
+ const t = (value - inMin) / (inMax - inMin);
255
+ return outMin + t * (outMax - outMin);
256
+ }
257
+ function solveCubicBezierX(p1x, p2x, x) {
258
+ if (x <= 0) return 0;
259
+ if (x >= 1) return 1;
260
+ const cx = 3 * p1x;
261
+ const bx = 3 * (p2x - p1x) - cx;
262
+ const ax = 1 - cx - bx;
263
+ function sampleX(t) {
264
+ return ((ax * t + bx) * t + cx) * t;
190
265
  }
191
- _canSanitize(raw) {
192
- return raw === void 0 || raw === null || this.inner._canSanitize(raw);
266
+ function sampleDX(t) {
267
+ return (3 * ax * t + 2 * bx) * t + cx;
193
268
  }
194
- };
195
- var Str = class extends Base {
196
- constructor(_default = "") {
197
- super();
198
- this._default = _default;
269
+ let t2 = x;
270
+ let t0 = 0;
271
+ let t1 = 1;
272
+ for (let i = 0; i < 8; i++) {
273
+ const x2 = sampleX(t2) - x;
274
+ if (Math.abs(x2) < 1e-6) return t2;
275
+ const d2 = sampleDX(t2);
276
+ if (Math.abs(d2) < 1e-6) break;
277
+ t2 -= x2 / d2;
199
278
  }
200
- sanitize(raw) {
201
- return typeof raw === "string" ? raw : this._default;
279
+ t2 = x;
280
+ while (t0 < t1) {
281
+ const x2 = sampleX(t2);
282
+ if (Math.abs(x2 - x) < 1e-6) return t2;
283
+ if (x > x2) t0 = t2;
284
+ else t1 = t2;
285
+ t2 = (t1 + t0) / 2;
202
286
  }
203
- isValid(raw, ctx, path) {
204
- if (typeof raw === "string") return true;
205
- ctx == null ? void 0 : ctx.errors.push(pathStr(path != null ? path : []) + ": expected string, got " + typeof raw);
206
- return false;
287
+ return t2;
288
+ }
289
+ function cubicBezier(easing) {
290
+ const [p1x, p1y, p2x, p2y] = easing;
291
+ const cy = 3 * p1y;
292
+ const by = 3 * (p2y - p1y) - cy;
293
+ const ay = 1 - cy - by;
294
+ function sampleCurveY(t) {
295
+ return ((ay * t + by) * t + cy) * t;
207
296
  }
208
- };
209
- var Num = class extends Base {
210
- constructor(_default = 0) {
211
- super();
212
- this._default = _default;
297
+ return function(x) {
298
+ return sampleCurveY(solveCubicBezierX(p1x, p2x, x));
299
+ };
300
+ }
301
+ function lerp2(a, b, t) {
302
+ return [a[0] + (b[0] - a[0]) * t, a[1] + (b[1] - a[1]) * t];
303
+ }
304
+ function subdivideCubicBezier(p0, p1, p2, p3, t) {
305
+ const q0 = lerp2(p0, p1, t);
306
+ const q1 = lerp2(p1, p2, t);
307
+ const q2 = lerp2(p2, p3, t);
308
+ const r0 = lerp2(q0, q1, t);
309
+ const r1 = lerp2(q1, q2, t);
310
+ const s = lerp2(r0, r1, t);
311
+ return {
312
+ left: [p0, q0, r0, s],
313
+ right: [s, r1, q2, p3]
314
+ };
315
+ }
316
+ function splitEasing(easing, xFraction) {
317
+ if (!easing) return { left: void 0, right: void 0 };
318
+ if (xFraction <= 0) return { left: void 0, right: easing };
319
+ if (xFraction >= 1) return { left: easing, right: void 0 };
320
+ const [x1, y1, x2, y2] = easing;
321
+ const t = solveCubicBezierX(x1, x2, xFraction);
322
+ const p0 = [0, 0];
323
+ const p1 = [x1, y1];
324
+ const p2 = [x2, y2];
325
+ const p3 = [1, 1];
326
+ const { left, right } = subdivideCubicBezier(p0, p1, p2, p3, t);
327
+ const sx = left[3][0];
328
+ const sy = left[3][1];
329
+ let leftEasing;
330
+ if (sx > 1e-9 && Math.abs(sy) > 1e-9) {
331
+ leftEasing = [
332
+ left[1][0] / sx,
333
+ left[1][1] / sy,
334
+ left[2][0] / sx,
335
+ left[2][1] / sy
336
+ ];
213
337
  }
214
- sanitize(raw) {
215
- return typeof raw === "number" && isFinite(raw) ? raw : this._default;
338
+ let rightEasing;
339
+ const rx = 1 - sx;
340
+ const ry = 1 - sy;
341
+ if (rx > 1e-9 && Math.abs(ry) > 1e-9) {
342
+ rightEasing = [
343
+ (right[1][0] - sx) / rx,
344
+ (right[1][1] - sy) / ry,
345
+ (right[2][0] - sx) / rx,
346
+ (right[2][1] - sy) / ry
347
+ ];
216
348
  }
217
- isValid(raw, ctx, path) {
218
- if (typeof raw === "number" && isFinite(raw)) return true;
219
- ctx == null ? void 0 : ctx.errors.push(pathStr(path != null ? path : []) + ": expected finite number, got " + JSON.stringify(raw));
220
- return false;
349
+ return { left: leftEasing, right: rightEasing };
350
+ }
351
+ function reverseEasing(easing) {
352
+ if (!easing) return void 0;
353
+ return [1 - easing[2], 1 - easing[3], 1 - easing[0], 1 - easing[1]];
354
+ }
355
+ function toRGBA(color) {
356
+ const r = Math.round(color[0] * 255);
357
+ const g = Math.round(color[1] * 255);
358
+ const b = Math.round(color[2] * 255);
359
+ return color.length === 4 ? "rgba(" + r + "," + g + "," + b + "," + color[3] + ")" : "rgb(" + r + "," + g + "," + b + ")";
360
+ }
361
+ function parseRgba(s) {
362
+ var _a;
363
+ const inner = (_a = s.match(/rgba?\((.*)\)/)) == null ? void 0 : _a[1];
364
+ if (!inner) throw new Error("Invalid rgb/rgba format");
365
+ const parts = inner.split(",").map((v) => +v.trim());
366
+ return [parts[0] / 255, parts[1] / 255, parts[2] / 255, ...parts[3] !== void 0 ? [parts[3]] : []];
367
+ }
368
+ function parseHex(s) {
369
+ const hex = s.slice(1);
370
+ const isShort = hex.length <= 4;
371
+ const r = isShort ? hex[0] + hex[0] : hex.slice(0, 2);
372
+ const g = isShort ? hex[1] + hex[1] : hex.slice(2, 4);
373
+ const b = isShort ? hex[2] + hex[2] : hex.slice(4, 6);
374
+ const a = hex.length === 4 ? hex[3] + hex[3] : hex.length === 8 ? hex.slice(6, 8) : null;
375
+ const result = [
376
+ parseInt(r, 16) / 255,
377
+ parseInt(g, 16) / 255,
378
+ parseInt(b, 16) / 255
379
+ ];
380
+ if (a !== null) {
381
+ result.push(parseInt(a, 16) / 255);
221
382
  }
222
- };
223
- var Bool = class extends Base {
224
- constructor(_default = false) {
225
- super();
226
- this._default = _default;
383
+ return result;
384
+ }
385
+ function parseColor(s) {
386
+ if (!s) return void 0;
387
+ if (Array.isArray(s)) return s;
388
+ if (typeof s !== "string") return void 0;
389
+ if (s.startsWith("#")) {
390
+ return parseHex(s);
391
+ } else if (s.startsWith("rgb")) {
392
+ return parseRgba(s);
393
+ } else {
394
+ console.warn("Unsupported color format: " + s);
227
395
  }
228
- sanitize(raw) {
229
- return typeof raw === "boolean" ? raw : this._default;
396
+ return void 0;
397
+ }
398
+ var COLOUR_ATTR_NAMES = /* @__PURE__ */ new Set(["color", "fill", "flood-color", "lighting-color", "stop-color", "stroke"]);
399
+ var TRANSFORM_FN_NAMES = /* @__PURE__ */ new Set(["translate", "rotate", "scale", "skew"]);
400
+ var PCT_BASED_ATTR_NAMES = /* @__PURE__ */ new Set(["offset-distance", "offsetDistance"]);
401
+ function composeTransformParts(parts, opts) {
402
+ var _a;
403
+ if (!parts) return "";
404
+ const withUnits = (_a = opts == null ? void 0 : opts.withUnits) != null ? _a : true;
405
+ const segs = [];
406
+ const t = parts.translate;
407
+ const o = parts.origin;
408
+ const r = parts.rotate;
409
+ const k = parts.skew;
410
+ const s = parts.scale;
411
+ const tu = withUnits ? "px" : "";
412
+ const ru = withUnits ? "deg" : "";
413
+ if (t) segs.push("translate(" + t[0] + tu + "," + t[1] + tu + ")");
414
+ if (o) segs.push("translate(" + o[0] + tu + "," + o[1] + tu + ")");
415
+ if (r !== void 0 && r !== null) segs.push("rotate(" + r + ru + ")");
416
+ if (k !== void 0 && k !== null) segs.push("skewX(" + k + ru + ")");
417
+ if (s) segs.push("scale(" + s[0] + "," + s[1] + ")");
418
+ if (o) segs.push("translate(" + -o[0] + tu + "," + -o[1] + tu + ")");
419
+ return segs.join("");
420
+ }
421
+ var STYLE_ATTR_NAMES = /* @__PURE__ */ new Set(["offset-distance", "offsetDistance"]);
422
+ var DEFAULT_DURATION_MS = 1e3;
423
+ function kebabToCamelCaseWord(kebab) {
424
+ return kebab.includes("-") ? kebab.replace(/-([a-z])/g, (_, letter) => letter.toUpperCase()) : kebab;
425
+ }
426
+ function isCamelCaseWord(word) {
427
+ return !word.includes("-") && /[a-z][A-Z]/.test(word);
428
+ }
429
+ var SVG_CAMEL_CASE_ATTRS = /* @__PURE__ */ new Set([
430
+ // Transform/positioning
431
+ "viewBox",
432
+ "preserveAspectRatio",
433
+ // Gradient
434
+ "gradientUnits",
435
+ "gradientTransform",
436
+ "spreadMethod",
437
+ // Pattern
438
+ "patternUnits",
439
+ "patternContentUnits",
440
+ "patternTransform",
441
+ // Clipping/masking
442
+ "clipPathUnits",
443
+ "maskUnits",
444
+ "maskContentUnits",
445
+ // Marker (SVG spec keeps these camelCase, like viewBox)
446
+ "markerUnits",
447
+ "markerWidth",
448
+ "markerHeight",
449
+ "refX",
450
+ "refY",
451
+ // Text
452
+ "textLength",
453
+ "lengthAdjust",
454
+ "startOffset",
455
+ // Filter
456
+ "filterUnits",
457
+ "primitiveUnits",
458
+ "tableValues",
459
+ // feFuncR/G/B/A transfer table (type="table")
460
+ "stdDeviation",
461
+ "baseFrequency",
462
+ "numOctaves",
463
+ "surfaceScale",
464
+ "diffuseConstant",
465
+ "specularConstant",
466
+ "specularExponent",
467
+ "kernelMatrix",
468
+ "kernelUnitLength",
469
+ "edgeMode",
470
+ "preserveAlpha",
471
+ "targetX",
472
+ "targetY"
473
+ // // Animation
474
+ // 'attributeName',
475
+ // 'attributeType',
476
+ // 'calcMode',
477
+ // 'keyTimes',
478
+ // 'keySplines',
479
+ // 'repeatCount',
480
+ // 'repeatDur'
481
+ ]);
482
+ function camelCaseToKebabWordIfNeeded(camel) {
483
+ return SVG_CAMEL_CASE_ATTRS.has(camel) ? camel : camel.replace(/([a-z0-9])([A-Z])/g, "$1-$2").toLowerCase();
484
+ }
485
+ function clamp(value, min, max) {
486
+ return Math.max(min, Math.min(value, max));
487
+ }
488
+ function bezier2D_pointAt(P0, P1, P2, P3, t) {
489
+ if (t <= 0) return [P0[0], P0[1]];
490
+ if (t >= 1) return [P3[0], P3[1]];
491
+ const u = 1 - t;
492
+ const u2 = u * u;
493
+ const u3 = u2 * u;
494
+ const t2 = t * t;
495
+ const t3 = t2 * t;
496
+ const w0 = u3;
497
+ const w1 = 3 * t * u2;
498
+ const w2 = 3 * t2 * u;
499
+ const w3 = t3;
500
+ return [
501
+ w0 * P0[0] + w1 * P1[0] + w2 * P2[0] + w3 * P3[0],
502
+ w0 * P0[1] + w1 * P1[1] + w2 * P2[1] + w3 * P3[1]
503
+ ];
504
+ }
505
+ var BEZIER_T_NUDGE = 1e-4;
506
+ function bezier2D_derivativeAt(P0, P1, P2, P3, t) {
507
+ const result = _bezier2D_derivativeAtRaw(P0, P1, P2, P3, t);
508
+ if (result[0] === 0 && result[1] === 0) {
509
+ const nudgedT = t < 0.5 ? t + BEZIER_T_NUDGE : t - BEZIER_T_NUDGE;
510
+ return _bezier2D_derivativeAtRaw(P0, P1, P2, P3, nudgedT);
230
511
  }
231
- isValid(raw, ctx, path) {
232
- if (typeof raw === "boolean") return true;
233
- ctx == null ? void 0 : ctx.errors.push(pathStr(path != null ? path : []) + ": expected boolean, got " + typeof raw);
234
- return false;
512
+ return result;
513
+ }
514
+ function _bezier2D_derivativeAtRaw(P0, P1, P2, P3, t) {
515
+ const u = 1 - t;
516
+ const a = 3 * u * u;
517
+ const b = 6 * t * u;
518
+ const c = 3 * t * t;
519
+ return [
520
+ a * (P1[0] - P0[0]) + b * (P2[0] - P1[0]) + c * (P3[0] - P2[0]),
521
+ a * (P1[1] - P0[1]) + b * (P2[1] - P1[1]) + c * (P3[1] - P2[1])
522
+ ];
523
+ }
524
+ function bezier2D_arcLengthLUT(P0, P1, P2, P3, steps = 100) {
525
+ const n = steps + 1;
526
+ const ts = new Float64Array(n);
527
+ const ds = new Float64Array(n);
528
+ let prev = bezier2D_pointAt(P0, P1, P2, P3, 0);
529
+ ts[0] = 0;
530
+ ds[0] = 0;
531
+ let cum = 0;
532
+ for (let i = 1; i < n; i++) {
533
+ const t = i / steps;
534
+ const cur = bezier2D_pointAt(P0, P1, P2, P3, t);
535
+ const dx = cur[0] - prev[0];
536
+ const dy = cur[1] - prev[1];
537
+ cum += Math.sqrt(dx * dx + dy * dy);
538
+ ts[i] = t;
539
+ ds[i] = cum;
540
+ prev = cur;
541
+ }
542
+ return { ts, ds };
543
+ }
544
+ function bezier2D_tForDistance(lut, distance) {
545
+ const { ts, ds } = lut;
546
+ const last = ds.length - 1;
547
+ if (distance <= 0) return ts[0];
548
+ if (distance >= ds[last]) return ts[last];
549
+ let lo = 1;
550
+ let hi = last;
551
+ while (lo < hi) {
552
+ const mid = lo + hi >>> 1;
553
+ if (ds[mid] < distance) lo = mid + 1;
554
+ else hi = mid;
555
+ }
556
+ const dPrev = ds[hi - 1];
557
+ const dCur = ds[hi];
558
+ const span = dCur - dPrev;
559
+ const frac = span > 0 ? (distance - dPrev) / span : 0;
560
+ return ts[hi - 1] + frac * (ts[hi] - ts[hi - 1]);
561
+ }
562
+ function bezier2D_arcAtT(lut, t) {
563
+ const { ts, ds } = lut;
564
+ const last = ts.length - 1;
565
+ if (t <= ts[0]) return ds[0];
566
+ if (t >= ts[last]) return ds[last];
567
+ let lo = 1, hi = last;
568
+ while (lo < hi) {
569
+ const mid = lo + hi >>> 1;
570
+ if (ts[mid] < t) lo = mid + 1;
571
+ else hi = mid;
572
+ }
573
+ const tPrev = ts[hi - 1];
574
+ const span = ts[hi] - tPrev;
575
+ const frac = span > 0 ? (t - tPrev) / span : 0;
576
+ return ds[hi - 1] + frac * (ds[hi] - ds[hi - 1]);
577
+ }
578
+ function invertEasing(easing) {
579
+ if (!easing) return (y) => y;
580
+ const flipped = [easing[1], easing[0], easing[3], easing[2]];
581
+ return cubicBezier(flipped);
582
+ }
583
+
584
+ // src/PxScrollMath.ts
585
+ function isScrollTimeline(config) {
586
+ return (config == null ? void 0 : config.timelineSource) === "scroll";
587
+ }
588
+ function scrollTotalDurationMs(config) {
589
+ const duration = typeof (config == null ? void 0 : config.duration) === "number" && config.duration > 0 ? config.duration : DEFAULT_DURATION_MS;
590
+ const iterations = typeof (config == null ? void 0 : config.iterations) === "number" && config.iterations > 0 ? config.iterations : 1;
591
+ return duration * iterations;
592
+ }
593
+ function scrollPhaseInterval(phase, subjectSize, scrollportSize) {
594
+ const s = subjectSize, vp = scrollportSize;
595
+ switch (phase) {
596
+ case "cover":
597
+ return [0, s + vp];
598
+ case "entry":
599
+ return [0, Math.min(s, vp)];
600
+ case "contain":
601
+ return [Math.min(s, vp), Math.max(s, vp)];
602
+ case "exit":
603
+ return [Math.max(s, vp), s + vp];
604
+ case "entry-crossing":
605
+ return [0, s];
606
+ case "exit-crossing":
607
+ return [vp, s + vp];
608
+ }
609
+ }
610
+ var DEFAULT_PHASE = "cover";
611
+ function resolveRangePointU(point, defaultFraction, subjectSize, scrollportSize) {
612
+ var _a;
613
+ const [u0, u1] = scrollPhaseInterval((_a = point == null ? void 0 : point.phase) != null ? _a : DEFAULT_PHASE, subjectSize, scrollportSize);
614
+ const fraction = typeof (point == null ? void 0 : point.fraction) === "number" ? point.fraction : defaultFraction;
615
+ return u0 + fraction * (u1 - u0);
616
+ }
617
+ function scrollViewProgress(subjectStart, subjectSize, scrollportSize, range) {
618
+ const u = scrollportSize - subjectStart;
619
+ const uStart = resolveRangePointU(range == null ? void 0 : range.start, 0, subjectSize, scrollportSize);
620
+ const uEnd = resolveRangePointU(range == null ? void 0 : range.end, 1, subjectSize, scrollportSize);
621
+ if (uEnd <= uStart) return u >= uEnd ? 1 : 0;
622
+ return clamp((u - uStart) / (uEnd - uStart), 0, 1);
623
+ }
624
+ function scrollOffsetProgress(offset, maxOffset, range) {
625
+ var _a, _b;
626
+ const raw = maxOffset > 0 ? clamp(offset / maxOffset, 0, 1) : 1;
627
+ const start = typeof ((_a = range == null ? void 0 : range.start) == null ? void 0 : _a.fraction) === "number" ? range.start.fraction : 0;
628
+ const end = typeof ((_b = range == null ? void 0 : range.end) == null ? void 0 : _b.fraction) === "number" ? range.end.fraction : 1;
629
+ if (end <= start) return raw >= end ? 1 : 0;
630
+ return clamp((raw - start) / (end - start), 0, 1);
631
+ }
632
+ function scrollResolveAxis(axis, writingMode) {
633
+ const a = axis != null ? axis : "block";
634
+ if (a === "x" || a === "y") return a;
635
+ const vertical = !!writingMode && writingMode.startsWith("vertical");
636
+ if (a === "inline") return vertical ? "y" : "x";
637
+ return vertical ? "x" : "y";
638
+ }
639
+
640
+ // src/PxSchema.ts
641
+ function pathStr(path) {
642
+ if (!path.length) return ".";
643
+ let result = "";
644
+ for (const seg of path) {
645
+ if (seg.startsWith("[")) result += seg;
646
+ else result += (result ? "." : "") + seg;
647
+ }
648
+ return result;
649
+ }
650
+ var Base = class {
651
+ _canSanitize(raw) {
652
+ return this.isValid(raw);
653
+ }
654
+ optional() {
655
+ return new Optional(this);
235
656
  }
236
657
  };
237
- var Literal = class extends Base {
238
- constructor(value) {
658
+ var Optional = class extends Base {
659
+ constructor(inner) {
239
660
  super();
240
- this.value = value;
241
- this._default = value;
661
+ this.inner = inner;
662
+ this._default = void 0;
242
663
  }
243
664
  sanitize(raw) {
244
- return raw === this.value ? this.value : this._default;
665
+ if (raw === void 0 || raw === null) return void 0;
666
+ return this.inner._canSanitize(raw) ? this.inner.sanitize(raw) : void 0;
245
667
  }
246
668
  isValid(raw, ctx, path) {
247
- if (raw === this.value) return true;
248
- ctx == null ? void 0 : ctx.errors.push(pathStr(path != null ? path : []) + ": expected " + JSON.stringify(this.value) + ", got " + JSON.stringify(raw));
249
- return false;
669
+ if (raw === void 0 || raw === null) return true;
670
+ return this.inner.isValid(raw, ctx, path);
671
+ }
672
+ _canSanitize(raw) {
673
+ return raw === void 0 || raw === null || this.inner._canSanitize(raw);
250
674
  }
251
675
  };
252
- var Enum = class extends Base {
253
- constructor(values, defaultVal) {
676
+ var Str = class extends Base {
677
+ constructor(_default = "") {
254
678
  super();
255
- this.values = values;
256
- this._default = defaultVal != null ? defaultVal : values[0];
679
+ this._default = _default;
257
680
  }
258
681
  sanitize(raw) {
259
- return this.values.includes(raw) ? raw : this._default;
682
+ return typeof raw === "string" ? raw : this._default;
260
683
  }
261
684
  isValid(raw, ctx, path) {
262
- if (this.values.includes(raw)) return true;
263
- ctx == null ? void 0 : ctx.errors.push(pathStr(path != null ? path : []) + ": expected one of " + this.values.map((v) => JSON.stringify(v)).join(" | ") + ", got " + JSON.stringify(raw));
685
+ if (typeof raw === "string") return true;
686
+ ctx == null ? void 0 : ctx.errors.push(pathStr(path != null ? path : []) + ": expected string, got " + typeof raw);
687
+ return false;
688
+ }
689
+ };
690
+ var Num = class extends Base {
691
+ constructor(_default = 0) {
692
+ super();
693
+ this._default = _default;
694
+ }
695
+ sanitize(raw) {
696
+ return typeof raw === "number" && isFinite(raw) ? raw : this._default;
697
+ }
698
+ isValid(raw, ctx, path) {
699
+ if (typeof raw === "number" && isFinite(raw)) return true;
700
+ ctx == null ? void 0 : ctx.errors.push(pathStr(path != null ? path : []) + ": expected finite number, got " + JSON.stringify(raw));
701
+ return false;
702
+ }
703
+ };
704
+ var Bool = class extends Base {
705
+ constructor(_default = false) {
706
+ super();
707
+ this._default = _default;
708
+ }
709
+ sanitize(raw) {
710
+ return typeof raw === "boolean" ? raw : this._default;
711
+ }
712
+ isValid(raw, ctx, path) {
713
+ if (typeof raw === "boolean") return true;
714
+ ctx == null ? void 0 : ctx.errors.push(pathStr(path != null ? path : []) + ": expected boolean, got " + typeof raw);
715
+ return false;
716
+ }
717
+ };
718
+ var Literal = class extends Base {
719
+ constructor(value) {
720
+ super();
721
+ this.value = value;
722
+ this._default = value;
723
+ }
724
+ sanitize(raw) {
725
+ return raw === this.value ? this.value : this._default;
726
+ }
727
+ isValid(raw, ctx, path) {
728
+ if (raw === this.value) return true;
729
+ ctx == null ? void 0 : ctx.errors.push(pathStr(path != null ? path : []) + ": expected " + JSON.stringify(this.value) + ", got " + JSON.stringify(raw));
730
+ return false;
731
+ }
732
+ };
733
+ var Enum = class extends Base {
734
+ constructor(values, defaultVal) {
735
+ super();
736
+ this.values = values;
737
+ this._default = defaultVal != null ? defaultVal : values[0];
738
+ }
739
+ sanitize(raw) {
740
+ return this.values.includes(raw) ? raw : this._default;
741
+ }
742
+ isValid(raw, ctx, path) {
743
+ if (this.values.includes(raw)) return true;
744
+ ctx == null ? void 0 : ctx.errors.push(pathStr(path != null ? path : []) + ": expected one of " + this.values.map((v) => JSON.stringify(v)).join(" | ") + ", got " + JSON.stringify(raw));
264
745
  return false;
265
746
  }
266
747
  };
@@ -823,6 +1304,22 @@ var PxDefsSchema = implementsInterface()(px.object({
823
1304
  styles: px.record(px.any()).optional(),
824
1305
  glyphs: px.record(PxGlyphFontSchema).optional()
825
1306
  }));
1307
+ var PX_SCROLL_PHASES = ["cover", "contain", "entry", "exit", "entry-crossing", "exit-crossing"];
1308
+ var PxScrollRangePointSchema = implementsInterface()(px.object({
1309
+ phase: px.enum(PX_SCROLL_PHASES).optional(),
1310
+ fraction: px.number().optional()
1311
+ }));
1312
+ var PxScrollRangeSchema = px.object({
1313
+ start: PxScrollRangePointSchema.optional(),
1314
+ end: PxScrollRangePointSchema.optional()
1315
+ });
1316
+ var PxScrollSchema = implementsInterface()(px.object({
1317
+ driver: px.enum(["custom", "native"]).optional(),
1318
+ kind: px.enum(["view", "scroll"]).optional(),
1319
+ axis: px.enum(["block", "inline", "x", "y"]).optional(),
1320
+ source: px.enum(["nearest", "root"]).optional(),
1321
+ range: PxScrollRangeSchema.optional()
1322
+ }));
826
1323
  var PxAnimatorConfigSchema = implementsInterface()(px.object({
827
1324
  mode: px.enum([PxAnimatorMode.auto, PxAnimatorMode.waapi, PxAnimatorMode.frames]).optional(),
828
1325
  duration: px.number().optional(),
@@ -838,6 +1335,7 @@ var PxAnimatorConfigSchema = implementsInterface()(px.object({
838
1335
  definitions: PxDefsSchema.optional(),
839
1336
  animateById: px.record(PxElementAnimationSchema).optional(),
840
1337
  timelineSource: px.string().optional(),
1338
+ scroll: PxScrollSchema.optional(),
841
1339
  debugInstName: px.string().optional()
842
1340
  }));
843
1341
  var PxBindingSchema = implementsInterface()(px.object({
@@ -1030,422 +1528,6 @@ function isPxElementFileFormatDeep(fileJson) {
1030
1528
  return { valid, errors: valid ? [] : ["Document failed schema validation"] };
1031
1529
  }
1032
1530
 
1033
- // src/PxAnimatorUtil.ts
1034
- function bezierToSvgPath(path, forceCurves = false) {
1035
- var _a, _b, _c, _d;
1036
- const v = path.v;
1037
- const i = path.i;
1038
- const o = path.o;
1039
- const c = path.c;
1040
- if (!v.length) return "";
1041
- const d = [];
1042
- const len = v.length;
1043
- d.push("M" + v[0][0] + "," + v[0][1]);
1044
- for (let idx = 1; idx < len; idx++) {
1045
- const prevV = v[idx - 1];
1046
- const prevO = (_a = o == null ? void 0 : o[idx - 1]) != null ? _a : prevV;
1047
- const currI = (_b = i == null ? void 0 : i[idx]) != null ? _b : v[idx];
1048
- const currV = v[idx];
1049
- const isLine = !forceCurves && (prevO[0] === prevV[0] && prevO[1] === prevV[1]) && (currI[0] === currV[0] && currI[1] === currV[1]);
1050
- if (isLine) {
1051
- d.push("L" + currV[0] + "," + currV[1]);
1052
- } else {
1053
- d.push("C" + prevO[0] + "," + prevO[1] + "," + currI[0] + "," + currI[1] + "," + currV[0] + "," + currV[1]);
1054
- }
1055
- }
1056
- if (c && len > 0) {
1057
- const lastV = v[len - 1];
1058
- const lastO = (_c = o == null ? void 0 : o[len - 1]) != null ? _c : lastV;
1059
- const firstI = (_d = i == null ? void 0 : i[0]) != null ? _d : v[0];
1060
- const firstV = v[0];
1061
- const isLine = !forceCurves && (lastO[0] === lastV[0] && lastO[1] === lastV[1]) && (firstI[0] === firstV[0] && firstI[1] === firstV[1]);
1062
- if (!isLine) {
1063
- d.push("C" + lastO[0] + "," + lastO[1] + "," + firstI[0] + "," + firstI[1] + "," + firstV[0] + "," + firstV[1]);
1064
- }
1065
- d.push("z");
1066
- }
1067
- return d.join("");
1068
- }
1069
- function interpolateNum(a, b, t) {
1070
- return a + (b - a) * t;
1071
- }
1072
- function interpolateVec(a, b, t) {
1073
- const res = [];
1074
- const count = Math.max(a.length, b.length);
1075
- for (let i = 0; i < count; i++) {
1076
- res[i] = interpolateNum(a[i] || 0, b[i] || 0, t);
1077
- }
1078
- return res;
1079
- }
1080
- function interpolateColor(a, b, t) {
1081
- return [
1082
- interpolateNum(a[0] || 0, b[0] || 0, t),
1083
- interpolateNum(a[1] || 0, b[1] || 0, t),
1084
- interpolateNum(a[2] || 0, b[2] || 0, t),
1085
- interpolateNum(a[3] === void 0 ? 1 : a[3], b[3] === void 0 ? 1 : b[3], t)
1086
- ];
1087
- }
1088
- function interpolateBeziers(paths1, paths2, progress) {
1089
- const count = Math.max(paths1.length, paths2.length);
1090
- const res = [];
1091
- for (let i = 0; i < count; i++) {
1092
- res.push(interpolateBezier(paths1[i], paths2[i], progress));
1093
- }
1094
- return res;
1095
- }
1096
- function interpolateBezier(path1, path2, progress) {
1097
- var _a, _b, _c, _d, _e, _f, _g, _h, _i;
1098
- if (!path1 || !path2) return path1 || path2 || { v: [] };
1099
- const t = Math.min(Math.max(progress, 0), 1);
1100
- const len = Math.min(path1.v.length, path2.v.length);
1101
- const v = [];
1102
- const i = [];
1103
- const o = [];
1104
- for (let idx = 0; idx < len; idx++) {
1105
- const v1 = path1.v[idx];
1106
- const v2 = path2.v[idx];
1107
- v.push(interpolateVec(v1, v2, t));
1108
- const i1 = (_b = (_a = path1.i) == null ? void 0 : _a[idx]) != null ? _b : v1;
1109
- const i2 = (_d = (_c = path2.i) == null ? void 0 : _c[idx]) != null ? _d : v2;
1110
- i.push(interpolateVec(i1, i2, t));
1111
- const o1 = (_f = (_e = path1.o) == null ? void 0 : _e[idx]) != null ? _f : v1;
1112
- const o2 = (_h = (_g = path2.o) == null ? void 0 : _g[idx]) != null ? _h : v2;
1113
- o.push(interpolateVec(o1, o2, t));
1114
- }
1115
- return { v, i: i.length ? i : void 0, o: o.length ? o : void 0, c: (_i = path1.c) != null ? _i : path2.c };
1116
- }
1117
- function remap(value, inMin, inMax, outMin, outMax) {
1118
- if (inMax === inMin) return outMin;
1119
- const t = (value - inMin) / (inMax - inMin);
1120
- return outMin + t * (outMax - outMin);
1121
- }
1122
- function solveCubicBezierX(p1x, p2x, x) {
1123
- if (x <= 0) return 0;
1124
- if (x >= 1) return 1;
1125
- const cx = 3 * p1x;
1126
- const bx = 3 * (p2x - p1x) - cx;
1127
- const ax = 1 - cx - bx;
1128
- function sampleX(t) {
1129
- return ((ax * t + bx) * t + cx) * t;
1130
- }
1131
- function sampleDX(t) {
1132
- return (3 * ax * t + 2 * bx) * t + cx;
1133
- }
1134
- let t2 = x;
1135
- let t0 = 0;
1136
- let t1 = 1;
1137
- for (let i = 0; i < 8; i++) {
1138
- const x2 = sampleX(t2) - x;
1139
- if (Math.abs(x2) < 1e-6) return t2;
1140
- const d2 = sampleDX(t2);
1141
- if (Math.abs(d2) < 1e-6) break;
1142
- t2 -= x2 / d2;
1143
- }
1144
- t2 = x;
1145
- while (t0 < t1) {
1146
- const x2 = sampleX(t2);
1147
- if (Math.abs(x2 - x) < 1e-6) return t2;
1148
- if (x > x2) t0 = t2;
1149
- else t1 = t2;
1150
- t2 = (t1 + t0) / 2;
1151
- }
1152
- return t2;
1153
- }
1154
- function cubicBezier(easing) {
1155
- const [p1x, p1y, p2x, p2y] = easing;
1156
- const cy = 3 * p1y;
1157
- const by = 3 * (p2y - p1y) - cy;
1158
- const ay = 1 - cy - by;
1159
- function sampleCurveY(t) {
1160
- return ((ay * t + by) * t + cy) * t;
1161
- }
1162
- return function(x) {
1163
- return sampleCurveY(solveCubicBezierX(p1x, p2x, x));
1164
- };
1165
- }
1166
- function lerp2(a, b, t) {
1167
- return [a[0] + (b[0] - a[0]) * t, a[1] + (b[1] - a[1]) * t];
1168
- }
1169
- function subdivideCubicBezier(p0, p1, p2, p3, t) {
1170
- const q0 = lerp2(p0, p1, t);
1171
- const q1 = lerp2(p1, p2, t);
1172
- const q2 = lerp2(p2, p3, t);
1173
- const r0 = lerp2(q0, q1, t);
1174
- const r1 = lerp2(q1, q2, t);
1175
- const s = lerp2(r0, r1, t);
1176
- return {
1177
- left: [p0, q0, r0, s],
1178
- right: [s, r1, q2, p3]
1179
- };
1180
- }
1181
- function splitEasing(easing, xFraction) {
1182
- if (!easing) return { left: void 0, right: void 0 };
1183
- if (xFraction <= 0) return { left: void 0, right: easing };
1184
- if (xFraction >= 1) return { left: easing, right: void 0 };
1185
- const [x1, y1, x2, y2] = easing;
1186
- const t = solveCubicBezierX(x1, x2, xFraction);
1187
- const p0 = [0, 0];
1188
- const p1 = [x1, y1];
1189
- const p2 = [x2, y2];
1190
- const p3 = [1, 1];
1191
- const { left, right } = subdivideCubicBezier(p0, p1, p2, p3, t);
1192
- const sx = left[3][0];
1193
- const sy = left[3][1];
1194
- let leftEasing;
1195
- if (sx > 1e-9 && Math.abs(sy) > 1e-9) {
1196
- leftEasing = [
1197
- left[1][0] / sx,
1198
- left[1][1] / sy,
1199
- left[2][0] / sx,
1200
- left[2][1] / sy
1201
- ];
1202
- }
1203
- let rightEasing;
1204
- const rx = 1 - sx;
1205
- const ry = 1 - sy;
1206
- if (rx > 1e-9 && Math.abs(ry) > 1e-9) {
1207
- rightEasing = [
1208
- (right[1][0] - sx) / rx,
1209
- (right[1][1] - sy) / ry,
1210
- (right[2][0] - sx) / rx,
1211
- (right[2][1] - sy) / ry
1212
- ];
1213
- }
1214
- return { left: leftEasing, right: rightEasing };
1215
- }
1216
- function reverseEasing(easing) {
1217
- if (!easing) return void 0;
1218
- return [1 - easing[2], 1 - easing[3], 1 - easing[0], 1 - easing[1]];
1219
- }
1220
- function toRGBA(color) {
1221
- const r = Math.round(color[0] * 255);
1222
- const g = Math.round(color[1] * 255);
1223
- const b = Math.round(color[2] * 255);
1224
- return color.length === 4 ? "rgba(" + r + "," + g + "," + b + "," + color[3] + ")" : "rgb(" + r + "," + g + "," + b + ")";
1225
- }
1226
- function parseRgba(s) {
1227
- var _a;
1228
- const inner = (_a = s.match(/rgba?\((.*)\)/)) == null ? void 0 : _a[1];
1229
- if (!inner) throw new Error("Invalid rgb/rgba format");
1230
- const parts = inner.split(",").map((v) => +v.trim());
1231
- return [parts[0] / 255, parts[1] / 255, parts[2] / 255, ...parts[3] !== void 0 ? [parts[3]] : []];
1232
- }
1233
- function parseHex(s) {
1234
- const hex = s.slice(1);
1235
- const isShort = hex.length <= 4;
1236
- const r = isShort ? hex[0] + hex[0] : hex.slice(0, 2);
1237
- const g = isShort ? hex[1] + hex[1] : hex.slice(2, 4);
1238
- const b = isShort ? hex[2] + hex[2] : hex.slice(4, 6);
1239
- const a = hex.length === 4 ? hex[3] + hex[3] : hex.length === 8 ? hex.slice(6, 8) : null;
1240
- const result = [
1241
- parseInt(r, 16) / 255,
1242
- parseInt(g, 16) / 255,
1243
- parseInt(b, 16) / 255
1244
- ];
1245
- if (a !== null) {
1246
- result.push(parseInt(a, 16) / 255);
1247
- }
1248
- return result;
1249
- }
1250
- function parseColor(s) {
1251
- if (!s) return void 0;
1252
- if (Array.isArray(s)) return s;
1253
- if (typeof s !== "string") return void 0;
1254
- if (s.startsWith("#")) {
1255
- return parseHex(s);
1256
- } else if (s.startsWith("rgb")) {
1257
- return parseRgba(s);
1258
- } else {
1259
- console.warn("Unsupported color format: " + s);
1260
- }
1261
- return void 0;
1262
- }
1263
- var COLOUR_ATTR_NAMES = /* @__PURE__ */ new Set(["color", "fill", "flood-color", "lighting-color", "stop-color", "stroke"]);
1264
- var TRANSFORM_FN_NAMES = /* @__PURE__ */ new Set(["translate", "rotate", "scale", "skew"]);
1265
- var PCT_BASED_ATTR_NAMES = /* @__PURE__ */ new Set(["offset-distance", "offsetDistance"]);
1266
- function composeTransformParts(parts, opts) {
1267
- var _a;
1268
- if (!parts) return "";
1269
- const withUnits = (_a = opts == null ? void 0 : opts.withUnits) != null ? _a : true;
1270
- const segs = [];
1271
- const t = parts.translate;
1272
- const o = parts.origin;
1273
- const r = parts.rotate;
1274
- const k = parts.skew;
1275
- const s = parts.scale;
1276
- const tu = withUnits ? "px" : "";
1277
- const ru = withUnits ? "deg" : "";
1278
- if (t) segs.push("translate(" + t[0] + tu + "," + t[1] + tu + ")");
1279
- if (o) segs.push("translate(" + o[0] + tu + "," + o[1] + tu + ")");
1280
- if (r !== void 0 && r !== null) segs.push("rotate(" + r + ru + ")");
1281
- if (k !== void 0 && k !== null) segs.push("skewX(" + k + ru + ")");
1282
- if (s) segs.push("scale(" + s[0] + "," + s[1] + ")");
1283
- if (o) segs.push("translate(" + -o[0] + tu + "," + -o[1] + tu + ")");
1284
- return segs.join("");
1285
- }
1286
- var STYLE_ATTR_NAMES = /* @__PURE__ */ new Set(["offset-distance", "offsetDistance"]);
1287
- var DEFAULT_DURATION_MS = 1e3;
1288
- function kebabToCamelCaseWord(kebab) {
1289
- return kebab.includes("-") ? kebab.replace(/-([a-z])/g, (_, letter) => letter.toUpperCase()) : kebab;
1290
- }
1291
- function isCamelCaseWord(word) {
1292
- return !word.includes("-") && /[a-z][A-Z]/.test(word);
1293
- }
1294
- var SVG_CAMEL_CASE_ATTRS = /* @__PURE__ */ new Set([
1295
- // Transform/positioning
1296
- "viewBox",
1297
- "preserveAspectRatio",
1298
- // Gradient
1299
- "gradientUnits",
1300
- "gradientTransform",
1301
- "spreadMethod",
1302
- // Pattern
1303
- "patternUnits",
1304
- "patternContentUnits",
1305
- "patternTransform",
1306
- // Clipping/masking
1307
- "clipPathUnits",
1308
- "maskUnits",
1309
- "maskContentUnits",
1310
- // Marker (SVG spec keeps these camelCase, like viewBox)
1311
- "markerUnits",
1312
- "markerWidth",
1313
- "markerHeight",
1314
- "refX",
1315
- "refY",
1316
- // Text
1317
- "textLength",
1318
- "lengthAdjust",
1319
- "startOffset",
1320
- // Filter
1321
- "filterUnits",
1322
- "primitiveUnits",
1323
- "tableValues",
1324
- // feFuncR/G/B/A transfer table (type="table")
1325
- "stdDeviation",
1326
- "baseFrequency",
1327
- "numOctaves",
1328
- "surfaceScale",
1329
- "diffuseConstant",
1330
- "specularConstant",
1331
- "specularExponent",
1332
- "kernelMatrix",
1333
- "kernelUnitLength",
1334
- "edgeMode",
1335
- "preserveAlpha",
1336
- "targetX",
1337
- "targetY"
1338
- // // Animation
1339
- // 'attributeName',
1340
- // 'attributeType',
1341
- // 'calcMode',
1342
- // 'keyTimes',
1343
- // 'keySplines',
1344
- // 'repeatCount',
1345
- // 'repeatDur'
1346
- ]);
1347
- function camelCaseToKebabWordIfNeeded(camel) {
1348
- return SVG_CAMEL_CASE_ATTRS.has(camel) ? camel : camel.replace(/([a-z0-9])([A-Z])/g, "$1-$2").toLowerCase();
1349
- }
1350
- function clamp(value, min, max) {
1351
- return Math.max(min, Math.min(value, max));
1352
- }
1353
- function bezier2D_pointAt(P0, P1, P2, P3, t) {
1354
- if (t <= 0) return [P0[0], P0[1]];
1355
- if (t >= 1) return [P3[0], P3[1]];
1356
- const u = 1 - t;
1357
- const u2 = u * u;
1358
- const u3 = u2 * u;
1359
- const t2 = t * t;
1360
- const t3 = t2 * t;
1361
- const w0 = u3;
1362
- const w1 = 3 * t * u2;
1363
- const w2 = 3 * t2 * u;
1364
- const w3 = t3;
1365
- return [
1366
- w0 * P0[0] + w1 * P1[0] + w2 * P2[0] + w3 * P3[0],
1367
- w0 * P0[1] + w1 * P1[1] + w2 * P2[1] + w3 * P3[1]
1368
- ];
1369
- }
1370
- var BEZIER_T_NUDGE = 1e-4;
1371
- function bezier2D_derivativeAt(P0, P1, P2, P3, t) {
1372
- const result = _bezier2D_derivativeAtRaw(P0, P1, P2, P3, t);
1373
- if (result[0] === 0 && result[1] === 0) {
1374
- const nudgedT = t < 0.5 ? t + BEZIER_T_NUDGE : t - BEZIER_T_NUDGE;
1375
- return _bezier2D_derivativeAtRaw(P0, P1, P2, P3, nudgedT);
1376
- }
1377
- return result;
1378
- }
1379
- function _bezier2D_derivativeAtRaw(P0, P1, P2, P3, t) {
1380
- const u = 1 - t;
1381
- const a = 3 * u * u;
1382
- const b = 6 * t * u;
1383
- const c = 3 * t * t;
1384
- return [
1385
- a * (P1[0] - P0[0]) + b * (P2[0] - P1[0]) + c * (P3[0] - P2[0]),
1386
- a * (P1[1] - P0[1]) + b * (P2[1] - P1[1]) + c * (P3[1] - P2[1])
1387
- ];
1388
- }
1389
- function bezier2D_arcLengthLUT(P0, P1, P2, P3, steps = 100) {
1390
- const n = steps + 1;
1391
- const ts = new Float64Array(n);
1392
- const ds = new Float64Array(n);
1393
- let prev = bezier2D_pointAt(P0, P1, P2, P3, 0);
1394
- ts[0] = 0;
1395
- ds[0] = 0;
1396
- let cum = 0;
1397
- for (let i = 1; i < n; i++) {
1398
- const t = i / steps;
1399
- const cur = bezier2D_pointAt(P0, P1, P2, P3, t);
1400
- const dx = cur[0] - prev[0];
1401
- const dy = cur[1] - prev[1];
1402
- cum += Math.sqrt(dx * dx + dy * dy);
1403
- ts[i] = t;
1404
- ds[i] = cum;
1405
- prev = cur;
1406
- }
1407
- return { ts, ds };
1408
- }
1409
- function bezier2D_tForDistance(lut, distance) {
1410
- const { ts, ds } = lut;
1411
- const last = ds.length - 1;
1412
- if (distance <= 0) return ts[0];
1413
- if (distance >= ds[last]) return ts[last];
1414
- let lo = 1;
1415
- let hi = last;
1416
- while (lo < hi) {
1417
- const mid = lo + hi >>> 1;
1418
- if (ds[mid] < distance) lo = mid + 1;
1419
- else hi = mid;
1420
- }
1421
- const dPrev = ds[hi - 1];
1422
- const dCur = ds[hi];
1423
- const span = dCur - dPrev;
1424
- const frac = span > 0 ? (distance - dPrev) / span : 0;
1425
- return ts[hi - 1] + frac * (ts[hi] - ts[hi - 1]);
1426
- }
1427
- function bezier2D_arcAtT(lut, t) {
1428
- const { ts, ds } = lut;
1429
- const last = ts.length - 1;
1430
- if (t <= ts[0]) return ds[0];
1431
- if (t >= ts[last]) return ds[last];
1432
- let lo = 1, hi = last;
1433
- while (lo < hi) {
1434
- const mid = lo + hi >>> 1;
1435
- if (ts[mid] < t) lo = mid + 1;
1436
- else hi = mid;
1437
- }
1438
- const tPrev = ts[hi - 1];
1439
- const span = ts[hi] - tPrev;
1440
- const frac = span > 0 ? (t - tPrev) / span : 0;
1441
- return ds[hi - 1] + frac * (ds[hi] - ds[hi - 1]);
1442
- }
1443
- function invertEasing(easing) {
1444
- if (!easing) return (y) => y;
1445
- const flipped = [easing[1], easing[0], easing[3], easing[2]];
1446
- return cubicBezier(flipped);
1447
- }
1448
-
1449
1531
  // src/PxIdUtil.ts
1450
1532
  var _idCounter = 0;
1451
1533
  function generateUniqueId() {
@@ -6099,6 +6181,9 @@ function subtractMultiset(a, b) {
6099
6181
  PxPropertyAnimationSchema,
6100
6182
  PxRepeaterEffectSchema,
6101
6183
  PxRetimeEffectSchema,
6184
+ PxScrollRangePointSchema,
6185
+ PxScrollRangeSchema,
6186
+ PxScrollSchema,
6102
6187
  PxStrokeGradientEffectSchema,
6103
6188
  PxSvgNodeExtra,
6104
6189
  PxTextEffectSchema,
@@ -6140,6 +6225,7 @@ function subtractMultiset(a, b) {
6140
6225
  interpolateValue,
6141
6226
  isPxElementFileFormat,
6142
6227
  isPxElementFileFormatDeep,
6228
+ isScrollTimeline,
6143
6229
  jsonElementFactory,
6144
6230
  kebabToCamelCaseWord,
6145
6231
  layoutGlyphTextChars,
@@ -6158,6 +6244,11 @@ function subtractMultiset(a, b) {
6158
6244
  reverseEasing,
6159
6245
  sanitiseAttributeValue,
6160
6246
  schemaKeys,
6247
+ scrollOffsetProgress,
6248
+ scrollPhaseInterval,
6249
+ scrollResolveAxis,
6250
+ scrollTotalDurationMs,
6251
+ scrollViewProgress,
6161
6252
  shiftAnimatable,
6162
6253
  splitEasing,
6163
6254
  subdivideCubicBezier,