@pixodesk/svg-animator-web 1.0.30 → 1.0.35

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
@@ -58,12 +58,11 @@ __export(index_exports, {
58
58
  PxAnimatedSvgDocumentSchema: () => PxAnimatedSvgDocumentSchema,
59
59
  PxAnimationDefinitionSchema: () => PxAnimationDefinitionSchema,
60
60
  PxAnimatorConfigSchema: () => PxAnimatorConfigSchema,
61
- PxAnimatorEngine: () => PxAnimatorEngine,
62
- PxAnimatorMode: () => PxAnimatorMode,
63
61
  PxAttrValueSchema: () => PxAttrValueSchema,
64
62
  PxBezierPathSchema: () => PxBezierPathSchema,
65
63
  PxBindingSchema: () => PxBindingSchema,
66
64
  PxCloneEffectSchema: () => PxCloneEffectSchema,
65
+ PxCloneWithout: () => PxCloneWithout,
67
66
  PxDefsSchema: () => PxDefsSchema,
68
67
  PxEasingOrRefSchema: () => PxEasingOrRefSchema,
69
68
  PxEffectsSchema: () => PxEffectsSchema,
@@ -75,6 +74,8 @@ __export(index_exports, {
75
74
  PxGradientUnits: () => PxGradientUnits,
76
75
  PxKeyframeSchema: () => PxKeyframeSchema,
77
76
  PxKeyframeValueSchema: () => PxKeyframeValueSchema,
77
+ PxLoopDirection: () => PxLoopDirection,
78
+ PxLoopRepeatAt: () => PxLoopRepeatAt,
78
79
  PxLoopSchema: () => PxLoopSchema,
79
80
  PxMaskedByEffectSchema: () => PxMaskedByEffectSchema,
80
81
  PxNodeBase: () => PxNodeBase,
@@ -84,15 +85,19 @@ __export(index_exports, {
84
85
  PxRetimeEffectSchema: () => PxRetimeEffectSchema,
85
86
  PxStrokeGradientEffectSchema: () => PxStrokeGradientEffectSchema,
86
87
  PxStrokeTrimEffectSchema: () => PxStrokeTrimEffectSchema,
88
+ PxStrokeTrimSubPaths: () => PxStrokeTrimSubPaths,
87
89
  PxSvgNodeExtra: () => PxSvgNodeExtra,
88
90
  PxTextEffectSchema: () => PxTextEffectSchema,
89
91
  PxTextPathEffectSchema: () => PxTextPathEffectSchema,
92
+ PxTimelineEngine: () => PxTimelineEngine,
93
+ PxTimelineEngineExtra: () => PxTimelineEngineExtra,
90
94
  PxTransformByEffectSchema: () => PxTransformByEffectSchema,
91
95
  PxTransformPartsSchema: () => PxTransformPartsSchema,
92
96
  PxTransformValueSchema: () => PxTransformValueSchema,
93
97
  PxTriggerSchema: () => PxTriggerSchema,
94
98
  STYLE_ATTR_NAMES: () => STYLE_ATTR_NAMES,
95
99
  TRANSFORM_FN_NAMES: () => TRANSFORM_FN_NAMES,
100
+ applyAnimatorConfig: () => applyAnimatorConfig,
96
101
  applyPlayerEffects: () => applyPlayerEffects,
97
102
  calcAnimationValues: () => calcAnimationValues,
98
103
  camelCaseToKebabWordIfNeeded: () => camelCaseToKebabWordIfNeeded,
@@ -107,6 +112,7 @@ __export(index_exports, {
107
112
  diffInEffect: () => diffInEffect,
108
113
  evaluateMotionPathSegment: () => evaluateMotionPathSegment,
109
114
  extendedPathForBrowser: () => extendedPathForBrowser,
115
+ foldAnimatorConfigShortcuts: () => foldAnimatorConfigShortcuts,
110
116
  generateNewIds: () => generateNewIds,
111
117
  getAnimatorConfig: () => getAnimatorConfig,
112
118
  getBindings: () => getBindings,
@@ -127,6 +133,7 @@ __export(index_exports, {
127
133
  materialiseInternalLoopsInTree: () => materialiseInternalLoopsInTree,
128
134
  materialiseMotionPathInPropAnim: () => materialiseMotionPathInPropAnim,
129
135
  materialiseMotionPathsInTree: () => materialiseMotionPathsInTree,
136
+ mergeAnimatorConfig: () => mergeAnimatorConfig,
130
137
  normalizeDocument: () => getNormalisedBindings,
131
138
  propAnimIsMotionPath: () => propAnimIsMotionPath,
132
139
  px: () => px,
@@ -135,6 +142,7 @@ __export(index_exports, {
135
142
  setupAnimationTriggers: () => setupAnimationTriggers,
136
143
  shiftAnimatable: () => shiftAnimatable,
137
144
  toRGBA: () => toRGBA,
145
+ validateDocument: () => validateDocument,
138
146
  validateNodeEffects: () => validateNodeEffects,
139
147
  visualModelAt: () => visualModelAt
140
148
  });
@@ -174,7 +182,7 @@ var __objRest2 = (source, exclude) => {
174
182
  return target;
175
183
  };
176
184
  function bezierToSvgPath(path, forceCurves = false) {
177
- var _a, _b, _c, _d;
185
+ var _a2, _b, _c, _d;
178
186
  const v = path.v;
179
187
  const i = path.i;
180
188
  const o = path.o;
@@ -185,7 +193,7 @@ function bezierToSvgPath(path, forceCurves = false) {
185
193
  d.push("M" + v[0][0] + "," + v[0][1]);
186
194
  for (let idx = 1; idx < len; idx++) {
187
195
  const prevV = v[idx - 1];
188
- const prevO = (_a = o == null ? void 0 : o[idx - 1]) != null ? _a : prevV;
196
+ const prevO = (_a2 = o == null ? void 0 : o[idx - 1]) != null ? _a2 : prevV;
189
197
  const currI = (_b = i == null ? void 0 : i[idx]) != null ? _b : v[idx];
190
198
  const currV = v[idx];
191
199
  const isLine = !forceCurves && (prevO[0] === prevV[0] && prevO[1] === prevV[1]) && (currI[0] === currV[0] && currI[1] === currV[1]);
@@ -236,7 +244,7 @@ function interpolateBeziers(paths1, paths2, progress) {
236
244
  return res;
237
245
  }
238
246
  function interpolateBezier(path1, path2, progress) {
239
- var _a, _b, _c, _d, _e, _f, _g, _h, _i;
247
+ var _a2, _b, _c, _d, _e, _f, _g, _h, _i;
240
248
  if (!path1 || !path2) return path1 || path2 || { v: [] };
241
249
  const t = Math.min(Math.max(progress, 0), 1);
242
250
  const len = Math.min(path1.v.length, path2.v.length);
@@ -247,7 +255,7 @@ function interpolateBezier(path1, path2, progress) {
247
255
  const v1 = path1.v[idx];
248
256
  const v2 = path2.v[idx];
249
257
  v.push(interpolateVec(v1, v2, t));
250
- const i1 = (_b = (_a = path1.i) == null ? void 0 : _a[idx]) != null ? _b : v1;
258
+ const i1 = (_b = (_a2 = path1.i) == null ? void 0 : _a2[idx]) != null ? _b : v1;
251
259
  const i2 = (_d = (_c = path2.i) == null ? void 0 : _c[idx]) != null ? _d : v2;
252
260
  i.push(interpolateVec(i1, i2, t));
253
261
  const o1 = (_f = (_e = path1.o) == null ? void 0 : _e[idx]) != null ? _f : v1;
@@ -366,8 +374,8 @@ function toRGBA(color) {
366
374
  return color.length === 4 ? "rgba(" + r + "," + g + "," + b + "," + color[3] + ")" : "rgb(" + r + "," + g + "," + b + ")";
367
375
  }
368
376
  function parseRgba(s) {
369
- var _a;
370
- const inner = (_a = s.match(/rgba?\((.*)\)/)) == null ? void 0 : _a[1];
377
+ var _a2;
378
+ const inner = (_a2 = s.match(/rgba?\((.*)\)/)) == null ? void 0 : _a2[1];
371
379
  if (!inner) throw new Error("Invalid rgb/rgba format");
372
380
  const parts = inner.split(",").map((v) => +v.trim());
373
381
  return [parts[0] / 255, parts[1] / 255, parts[2] / 255, ...parts[3] !== void 0 ? [parts[3]] : []];
@@ -406,9 +414,9 @@ var COLOUR_ATTR_NAMES = /* @__PURE__ */ new Set(["color", "fill", "flood-color",
406
414
  var TRANSFORM_FN_NAMES = /* @__PURE__ */ new Set(["translate", "rotate", "scale", "skew"]);
407
415
  var PCT_BASED_ATTR_NAMES = /* @__PURE__ */ new Set(["offset-distance", "offsetDistance"]);
408
416
  function composeTransformParts(parts, opts) {
409
- var _a;
417
+ var _a2;
410
418
  if (!parts) return "";
411
- const withUnits = (_a = opts == null ? void 0 : opts.withUnits) != null ? _a : true;
419
+ const withUnits = (_a2 = opts == null ? void 0 : opts.withUnits) != null ? _a2 : true;
412
420
  const segs = [];
413
421
  const t = parts.translate;
414
422
  const o = parts.origin;
@@ -425,6 +433,38 @@ function composeTransformParts(parts, opts) {
425
433
  if (o) segs.push("translate(" + -o[0] + tu + "," + -o[1] + tu + ")");
426
434
  return segs.join("");
427
435
  }
436
+ function parseTransformParts(str2) {
437
+ var _a2, _b;
438
+ if (!str2 || typeof str2 !== "string") return void 0;
439
+ const out = {};
440
+ const re = /([a-zA-Z]+)\s*\(([^)]*)\)/g;
441
+ const order = ["translate", "rotate", "skewX", "scale"];
442
+ let lastIdx = -1;
443
+ let m;
444
+ while ((m = re.exec(str2)) !== null) {
445
+ const fn = m[1];
446
+ const idx = order.indexOf(fn);
447
+ if (idx < 0 || idx <= lastIdx) return void 0;
448
+ lastIdx = idx;
449
+ const nums = m[2].split(/[\s,]+/).filter(Boolean).map(Number);
450
+ if (nums.some((n) => Number.isNaN(n))) return void 0;
451
+ if (fn === "translate") {
452
+ if (nums.length < 1 || nums.length > 2) return void 0;
453
+ out.translate = [nums[0], (_a2 = nums[1]) != null ? _a2 : 0];
454
+ } else if (fn === "rotate") {
455
+ if (nums.length !== 1) return void 0;
456
+ out.rotate = nums[0];
457
+ } else if (fn === "skewX") {
458
+ if (nums.length !== 1) return void 0;
459
+ out.skew = nums[0];
460
+ } else {
461
+ if (nums.length < 1 || nums.length > 2) return void 0;
462
+ out.scale = [nums[0], (_b = nums[1]) != null ? _b : nums[0]];
463
+ }
464
+ }
465
+ if (str2.replace(/([a-zA-Z]+)\s*\(([^)]*)\)/g, "").replace(/[\s,]/g, "").length) return void 0;
466
+ return Object.keys(out).length ? out : void 0;
467
+ }
428
468
  var STYLE_ATTR_NAMES = /* @__PURE__ */ new Set(["offset-distance", "offsetDistance"]);
429
469
  var DEFAULT_DURATION_MS = 1e3;
430
470
  function kebabToCamelCaseWord(kebab) {
@@ -614,8 +654,8 @@ function scrollPhaseInterval(phase, subjectSize, scrollportSize) {
614
654
  }
615
655
  var DEFAULT_PHASE = "cover";
616
656
  function resolveRangePointU(point, defaultFraction, subjectSize, scrollportSize) {
617
- var _a;
618
- const [u0, u1] = scrollPhaseInterval((_a = point == null ? void 0 : point.phase) != null ? _a : DEFAULT_PHASE, subjectSize, scrollportSize);
657
+ var _a2;
658
+ const [u0, u1] = scrollPhaseInterval((_a2 = point == null ? void 0 : point.phase) != null ? _a2 : DEFAULT_PHASE, subjectSize, scrollportSize);
619
659
  const fraction = typeof (point == null ? void 0 : point.fraction) === "number" ? point.fraction : defaultFraction;
620
660
  return u0 + fraction * (u1 - u0);
621
661
  }
@@ -627,9 +667,9 @@ function scrollViewProgress(subjectStart, subjectSize, scrollportSize, range) {
627
667
  return clamp((u - uStart) / (uEnd - uStart), 0, 1);
628
668
  }
629
669
  function scrollOffsetProgress(offset, maxOffset, range) {
630
- var _a, _b;
670
+ var _a2, _b;
631
671
  const raw = maxOffset > 0 ? clamp(offset / maxOffset, 0, 1) : 1;
632
- const start = typeof ((_a = range == null ? void 0 : range.start) == null ? void 0 : _a.fraction) === "number" ? range.start.fraction : 0;
672
+ const start = typeof ((_a2 = range == null ? void 0 : range.start) == null ? void 0 : _a2.fraction) === "number" ? range.start.fraction : 0;
633
673
  const end = typeof ((_b = range == null ? void 0 : range.end) == null ? void 0 : _b.fraction) === "number" ? range.end.fraction : 1;
634
674
  if (end <= start) return raw >= end ? 1 : 0;
635
675
  return clamp((raw - start) / (end - start), 0, 1);
@@ -641,6 +681,7 @@ function scrollResolveAxis(axis, writingMode) {
641
681
  if (a === "inline") return vertical ? "y" : "x";
642
682
  return vertical ? "x" : "y";
643
683
  }
684
+ var PX_UNKNOWN_KEY_ERROR = "unexpected extra key";
644
685
  function pathStr(path) {
645
686
  if (!path.length) return ".";
646
687
  let result = "";
@@ -752,6 +793,7 @@ var Union = class extends Base {
752
793
  constructor(schemas, defaultVal) {
753
794
  super();
754
795
  this.schemas = schemas;
796
+ this._kind = "union";
755
797
  this._default = defaultVal != null ? defaultVal : schemas[0]._default;
756
798
  }
757
799
  sanitize(raw) {
@@ -761,10 +803,10 @@ var Union = class extends Base {
761
803
  return this._default;
762
804
  }
763
805
  isValid(raw, ctx, path) {
764
- var _a;
806
+ var _a2;
765
807
  const probe = ctx && { errors: [], warnings: [], strict: ctx.strict };
766
808
  if (this.schemas.some((s) => s.isValid(raw, probe, path ? [...path] : void 0))) return true;
767
- ctx == null ? void 0 : ctx.errors.push(pathStr(path != null ? path : []) + ": no union member matched for value " + ((_a = JSON.stringify(raw)) != null ? _a : "").slice(0, 240));
809
+ ctx == null ? void 0 : ctx.errors.push(pathStr(path != null ? path : []) + ": no union member matched for value " + ((_a2 = JSON.stringify(raw)) != null ? _a2 : "").slice(0, 240));
768
810
  return false;
769
811
  }
770
812
  _canSanitize(raw) {
@@ -773,25 +815,30 @@ var Union = class extends Base {
773
815
  };
774
816
  var DiscriminatedUnion = class extends Base {
775
817
  constructor(_key, _schemas, defaultVal) {
818
+ var _a2;
776
819
  super();
777
820
  this._key = _key;
778
821
  this._schemas = _schemas;
822
+ this._kind = "discriminatedUnion";
779
823
  this._default = defaultVal != null ? defaultVal : _schemas[0]._default;
780
824
  this._map = /* @__PURE__ */ new Map();
781
825
  for (const s of _schemas) {
782
826
  const keySchema = s._shape[_key];
783
- if (keySchema) this._map.set(keySchema._default, s);
827
+ if (!keySchema) continue;
828
+ const literal = (_a2 = keySchema.inner) != null ? _a2 : keySchema;
829
+ this._map.set(literal._default, s);
830
+ if (keySchema.inner) this._absentMember = s;
784
831
  }
785
832
  }
786
833
  _findSchema(raw) {
787
834
  if (raw === null || typeof raw !== "object" || Array.isArray(raw)) return void 0;
788
835
  const val = raw[this._key];
789
- if (val === void 0 || val === null) return void 0;
836
+ if (val === void 0 || val === null) return this._absentMember;
790
837
  return this._map.get(val);
791
838
  }
792
839
  sanitize(raw) {
793
- var _a;
794
- return ((_a = this._findSchema(raw)) != null ? _a : this._schemas[0]).sanitize(raw);
840
+ var _a2;
841
+ return ((_a2 = this._findSchema(raw)) != null ? _a2 : this._schemas[0]).sanitize(raw);
795
842
  }
796
843
  isValid(raw, ctx, path) {
797
844
  const schema = this._findSchema(raw);
@@ -820,7 +867,8 @@ var Obj = class extends Base {
820
867
  const src = raw && typeof raw === "object" && !Array.isArray(raw) ? raw : {};
821
868
  const out = {};
822
869
  for (const key of Object.keys(this._shape)) {
823
- out[key] = this._shape[key].sanitize(src[key]);
870
+ const v = this._shape[key].sanitize(src[key]);
871
+ if (v !== void 0) out[key] = v;
824
872
  }
825
873
  return out;
826
874
  }
@@ -842,7 +890,7 @@ var Obj = class extends Base {
842
890
  if (key in this._shape) continue;
843
891
  if (obj[key] === void 0) continue;
844
892
  p.push(key);
845
- ctx.errors.push(pathStr(p) + ": unexpected extra key");
893
+ ctx.errors.push(pathStr(p) + ": " + PX_UNKNOWN_KEY_ERROR);
846
894
  p.pop();
847
895
  ok = false;
848
896
  }
@@ -866,7 +914,8 @@ var OpenObj = class extends Base {
866
914
  const src = raw && typeof raw === "object" && !Array.isArray(raw) ? raw : {};
867
915
  const out = __spreadValues2({}, src);
868
916
  for (const key of Object.keys(this._shape)) {
869
- out[key] = this._shape[key].sanitize(src[key]);
917
+ const v = this._shape[key].sanitize(src[key]);
918
+ if (v !== void 0) out[key] = v;
870
919
  }
871
920
  if (this._openSchema) {
872
921
  for (const key of Object.keys(src)) {
@@ -938,6 +987,7 @@ var Rec = class extends Base {
938
987
  constructor(value) {
939
988
  super();
940
989
  this.value = value;
990
+ this._kind = "record";
941
991
  this._default = {};
942
992
  }
943
993
  sanitize(raw) {
@@ -1006,8 +1056,8 @@ var Lazy = class extends Base {
1006
1056
  this.resolved = null;
1007
1057
  }
1008
1058
  get schema() {
1009
- var _a;
1010
- return (_a = this.resolved) != null ? _a : this.resolved = this.fn();
1059
+ var _a2;
1060
+ return (_a2 = this.resolved) != null ? _a2 : this.resolved = this.fn();
1011
1061
  }
1012
1062
  sanitize(raw) {
1013
1063
  return this.schema.sanitize(raw);
@@ -1023,6 +1073,7 @@ var Tuple = class extends Base {
1023
1073
  constructor(schemas) {
1024
1074
  super();
1025
1075
  this.schemas = schemas;
1076
+ this._kind = "tuple";
1026
1077
  this._default = schemas.map((s) => s._default);
1027
1078
  }
1028
1079
  sanitize(raw) {
@@ -1057,12 +1108,22 @@ function schemaKeys(schema) {
1057
1108
  );
1058
1109
  }
1059
1110
  function describeSchema(schema) {
1060
- var _a;
1111
+ var _a2;
1061
1112
  const s = schema;
1062
- if ("_shape" in s) return { kind: "shape", shape: s._shape };
1113
+ switch (s._kind) {
1114
+ case "union":
1115
+ return { kind: "union", members: s.schemas };
1116
+ case "discriminatedUnion":
1117
+ return { kind: "discriminatedUnion", key: s._key, members: s._schemas };
1118
+ case "record":
1119
+ return { kind: "record", value: s.value };
1120
+ case "tuple":
1121
+ return { kind: "tuple", items: s.schemas };
1122
+ }
1123
+ if ("_shape" in s) return { kind: "shape", shape: s._shape, openValue: s._openSchema };
1063
1124
  if ("item" in s) return { kind: "array", item: s.item };
1064
1125
  if ("inner" in s) return { kind: "optional", inner: s.inner };
1065
- if ("fn" in s) return { kind: "lazy", resolved: (_a = s.resolved) != null ? _a : s.fn() };
1126
+ if ("fn" in s) return { kind: "lazy", resolved: (_a2 = s.resolved) != null ? _a2 : s.resolved = s.fn() };
1066
1127
  return { kind: "leaf" };
1067
1128
  }
1068
1129
  var px = {
@@ -1116,24 +1177,49 @@ var px = {
1116
1177
  /** Defers schema creation — required for recursive types. Must supply a default value. */
1117
1178
  lazy: (fn, defaultVal) => new Lazy(fn, defaultVal)
1118
1179
  };
1180
+ var PX_PLAYER_SCHEMA_VERSION = "1.1";
1181
+ var VERSION_RE = /^(\d+)\.(\d+)(?:\.(\d+))?$/;
1182
+ function parseWireVersion(raw) {
1183
+ if (typeof raw !== "string") return void 0;
1184
+ const m = VERSION_RE.exec(raw.trim());
1185
+ if (!m) return void 0;
1186
+ return { a: Number(m[1]), b: Number(m[2]), c: m[3] === void 0 ? 0 : Number(m[3]) };
1187
+ }
1188
+ var _a;
1189
+ var PLAYER_WIRE_VERSION = (_a = parseWireVersion(PX_PLAYER_SCHEMA_VERSION)) != null ? _a : { a: 1, b: 1, c: 0 };
1119
1190
  var PX_ANIM_SRC_ATTR_NAME = "data-px-animation-src";
1120
1191
  var PX_ANIM_ATTR_NAME = "_px_animator";
1121
- var PxAnimatorMode = {
1122
- auto: "auto",
1123
- waapi: "waapi",
1124
- frames: "frames"
1192
+ var PX_TIMELINE_SHARED_KEYS = ["duration", "iterations", "engine", "frameRate"];
1193
+ var PX_TIME_ONLY_TIMELINE_KEYS = ["trigger", "delay", "fillMode", "direction"];
1194
+ var PxTimelineEngine = {
1195
+ native: "native",
1196
+ js: "js"
1125
1197
  };
1126
- var PxAnimatorEngine = {
1127
- waapi: PxAnimatorMode.waapi,
1128
- frames: PxAnimatorMode.frames
1198
+ var PxTimelineEngineExtra = __spreadProps2(__spreadValues2({}, PxTimelineEngine), {
1199
+ auto: "auto"
1200
+ });
1201
+ function resolveTimelineEngine(engine) {
1202
+ return engine === PxTimelineEngineExtra.js ? PxTimelineEngine.js : PxTimelineEngine.native;
1203
+ }
1204
+ function isNativeForced(engine) {
1205
+ return engine === PxTimelineEngineExtra.native;
1206
+ }
1207
+ function mayUseNativeScrollTimeline(engine) {
1208
+ return engine !== PxTimelineEngineExtra.js;
1209
+ }
1210
+ var PxLoopRepeatAt = {
1211
+ /** Segment from the START; the repetition runs BEFORE the first keyframe
1212
+ * (intro loops that play until the main timeline begins). */
1213
+ start: "start",
1214
+ /** DEFAULT — segment from the END; the repetition runs AFTER the last keyframe
1215
+ * (idle/outro loops that continue once the main timeline has finished). */
1216
+ end: "end"
1129
1217
  };
1130
- var PxLoopExtend = {
1131
- /** Segment from the START; the animation is extended BEFORE the first keyframe
1132
- * (intro loops that run before the main timeline begins). */
1133
- before: "before",
1134
- /** DEFAULT — segment from the END; extended AFTER the last keyframe (idle/outro
1135
- * loops that continue once the main timeline has finished). */
1136
- after: "after"
1218
+ var PxLoopDirection = {
1219
+ /** DEFAULT — cycle: every repetition replays the segment the same way round. */
1220
+ normal: "normal",
1221
+ /** Ping-pong: repetitions alternate forward / backward. */
1222
+ alternate: "alternate"
1137
1223
  };
1138
1224
  var PxMaskType = {
1139
1225
  luminance: "luminance",
@@ -1143,8 +1229,9 @@ var PxUnits = {
1143
1229
  userSpaceOnUse: "userSpaceOnUse",
1144
1230
  objectBoundingBox: "objectBoundingBox"
1145
1231
  };
1146
- var PxCloneType = {
1147
- content: "content"
1232
+ var PxCloneWithout = {
1233
+ translate: "translate"
1234
+ // transform: 'transform', // future: drop rotate/scale too (content only)
1148
1235
  };
1149
1236
  var PxPathOverflow = {
1150
1237
  clip: "clip",
@@ -1168,6 +1255,9 @@ var PxStrokeTrimSubPaths = {
1168
1255
  };
1169
1256
  var TEXT_ATTR = "text";
1170
1257
  var TEXT_CONTENT_ATTR = "textContent";
1258
+ var CLASS_ATTR = "class";
1259
+ var TRANSFORM_ATTR = "transform";
1260
+ var OFFSET_DISTANCE_ATTR = "offsetDistance";
1171
1261
  var INTERNAL_ATTRS = /* @__PURE__ */ new Set([
1172
1262
  "type",
1173
1263
  "children",
@@ -1178,7 +1268,18 @@ var INTERNAL_ATTRS = /* @__PURE__ */ new Set([
1178
1268
  TEXT_ATTR,
1179
1269
  TEXT_CONTENT_ATTR
1180
1270
  ]);
1181
- var PX_TRANSFORM_PART_KEYS = ["translate", "rotate", "scale", "origin"];
1271
+ var TRANSFORM_PART = {
1272
+ translate: "translate",
1273
+ rotate: "rotate",
1274
+ scale: "scale",
1275
+ origin: "origin"
1276
+ };
1277
+ var PX_TRANSFORM_PART_KEYS = [
1278
+ TRANSFORM_PART.translate,
1279
+ TRANSFORM_PART.rotate,
1280
+ TRANSFORM_PART.scale,
1281
+ TRANSFORM_PART.origin
1282
+ ];
1182
1283
  var PxGradientUnits = {
1183
1284
  userSpaceOnUse: "userSpaceOnUse",
1184
1285
  objectBoundingBox: "objectBoundingBox"
@@ -1196,23 +1297,68 @@ function isPxElementFileFormat(fileJson) {
1196
1297
  if (!(fileJson && typeof fileJson === "object" && !Array.isArray(fileJson))) {
1197
1298
  return false;
1198
1299
  }
1199
- return fileJson["type"] === "svg";
1300
+ return fileJson.type === "svg";
1200
1301
  }
1201
1302
  function getAnimatorConfig(doc) {
1202
- var _a;
1203
- return (doc == null ? void 0 : doc.animator) || ((_a = doc == null ? void 0 : doc.meta) == null ? void 0 : _a.animator);
1303
+ var _a2;
1304
+ const cfg = (doc == null ? void 0 : doc.animator) || ((_a2 = doc == null ? void 0 : doc.meta) == null ? void 0 : _a2.animator);
1305
+ return cfg ? flattenAnimatorTimeline(cfg) : void 0;
1306
+ }
1307
+ var flattenMemo = /* @__PURE__ */ new WeakMap();
1308
+ function flattenAnimatorTimeline(cfg) {
1309
+ const timeline = cfg.timeline;
1310
+ if (timeline === void 0 || timeline === null || typeof timeline !== "object") return cfg;
1311
+ const memoised = flattenMemo.get(cfg);
1312
+ if (memoised) return memoised;
1313
+ const _a2 = cfg, { timeline: _dropped } = _a2, flat = __objRest2(_a2, ["timeline"]);
1314
+ if (timeline.engine !== void 0) flat.engine = timeline.engine;
1315
+ if (timeline.frameRate !== void 0) flat.frameRate = timeline.frameRate;
1316
+ if (timeline.type === "scroll" || timeline.type === "view") {
1317
+ flat.timelineSource = "scroll";
1318
+ if (timeline.duration !== void 0) flat.duration = timeline.duration;
1319
+ if (timeline.iterations !== void 0) flat.iterations = timeline.iterations;
1320
+ const scroll = __spreadValues2({}, flat.scroll || {});
1321
+ scroll.kind = timeline.type;
1322
+ if (timeline.axis !== void 0) scroll.axis = timeline.axis;
1323
+ if (timeline.source !== void 0) scroll.source = timeline.source;
1324
+ if (timeline.subject !== void 0) scroll.subject = timeline.subject;
1325
+ if (timeline.smoothing !== void 0) scroll.smoothing = timeline.smoothing;
1326
+ if (timeline.range !== void 0) scroll.range = timeline.range;
1327
+ const pin = timeline.pin;
1328
+ if (typeof pin === "boolean") scroll.pin = pin;
1329
+ else if (pin && typeof pin === "object") {
1330
+ scroll.pin = true;
1331
+ if (pin.align !== void 0) scroll.pinAlign = pin.align;
1332
+ if (pin.top !== void 0) scroll.pinTop = pin.top;
1333
+ if (pin.distance !== void 0) scroll.pinDistance = pin.distance;
1334
+ }
1335
+ flat.scroll = scroll;
1336
+ } else {
1337
+ if (timeline.duration !== void 0) flat.duration = timeline.duration;
1338
+ if (timeline.trigger !== void 0) {
1339
+ const _b = timeline.trigger, { finishAction } = _b, restTrigger = __objRest2(_b, ["finishAction"]);
1340
+ if (Object.keys(restTrigger).length) flat.trigger = restTrigger;
1341
+ if (finishAction !== void 0) flat.resetOnFinish = finishAction === "reset";
1342
+ }
1343
+ if (timeline.delay !== void 0) flat.delay = timeline.delay;
1344
+ if (timeline.iterations !== void 0) flat.iterations = timeline.iterations;
1345
+ if (timeline.direction !== void 0) flat.direction = timeline.direction;
1346
+ if (timeline.fillMode !== void 0) flat.fill = timeline.fillMode;
1347
+ }
1348
+ flattenMemo.set(cfg, flat);
1349
+ return flat;
1204
1350
  }
1205
1351
  function getDefs(doc) {
1206
- var _a;
1352
+ var _a2;
1207
1353
  if (!doc) return void 0;
1208
- return (_a = getAnimatorConfig(doc)) == null ? void 0 : _a.definitions;
1354
+ return (_a2 = getAnimatorConfig(doc)) == null ? void 0 : _a2.definitions;
1209
1355
  }
1210
1356
  function getBindings(doc) {
1211
- var _a;
1357
+ var _a2;
1212
1358
  if (!doc) return void 0;
1213
- const animateById = (_a = getAnimatorConfig(doc)) == null ? void 0 : _a.animateById;
1359
+ const animateById = (_a2 = getAnimatorConfig(doc)) == null ? void 0 : _a2.animateById;
1214
1360
  if (!animateById) return void 0;
1215
- return Object.entries(animateById).map(([id, anim]) => ({ id, animate: anim }));
1361
+ return Object.entries(animateById).map(([id, anim]) => ({ id: id.startsWith("#") ? id.slice(1) : id, animate: anim }));
1216
1362
  }
1217
1363
  function getChildren(doc) {
1218
1364
  return doc == null ? void 0 : doc.children;
@@ -1226,39 +1372,54 @@ var PxKeyframeValueSchema = implementsInterface()(px.union([
1226
1372
  // e.g. for colors
1227
1373
  px.number(),
1228
1374
  px.array(px.number()),
1229
- px.lazy(() => PxTransformPartsSchema, {}),
1375
+ // ORDER LAW: the key-discriminated object shapes (`{path}`, `{paths}`) come BEFORE the
1376
+ // all-optional transform-parts record. In default (non-strict) mode that record accepts
1377
+ // ANY object (every key optional, unknown keys ignored), so listing it earlier made
1378
+ // Union.sanitize route `{path}`/`{paths}` values into it and strip them to `{}` —
1379
+ // silent morph-data loss (repro: the editor's keyframeValueSanitize spec). Validity is
1380
+ // order-independent (`some()`); only sanitize routing depends on this order.
1230
1381
  px.object({ path: px.string() }),
1231
1382
  px.lazy(() => px.object({ paths: px.array(PxBezierPathSchema) }), { paths: [] }),
1232
1383
  // Gradient `stops` timeline — each kf value is the full stops-array snapshot.
1233
- px.lazy(() => px.array(PxGradientStopSchema), [])
1384
+ px.lazy(() => px.array(PxGradientStopSchema), []),
1385
+ px.lazy(() => PxTransformPartsSchema, {})
1234
1386
  ]));
1235
1387
  var PxKeyframeSchema = implementsInterface()(px.object({
1236
1388
  time: px.number().optional(),
1237
- t: px.number().optional(),
1238
1389
  value: PxKeyframeValueSchema.optional(),
1239
- v: PxKeyframeValueSchema.optional(),
1240
1390
  easing: PxEasingOrRefSchema.optional(),
1241
- e: PxEasingOrRefSchema.optional(),
1242
1391
  tangentOut: px.tuple([px.number(), px.number()]).optional(),
1243
- to: px.tuple([px.number(), px.number()]).optional(),
1244
- // short alias
1245
- tangentIn: px.tuple([px.number(), px.number()]).optional(),
1246
- ti: px.tuple([px.number(), px.number()]).optional(),
1247
- // short alias
1248
- selected: px.boolean().optional()
1249
- // editor-side UI state (Player ignores it)
1392
+ tangentIn: px.tuple([px.number(), px.number()]).optional()
1393
+ // (`selected` — editor timeline-selection UI state — was REMOVED from the wire
1394
+ // (review §1.3): editor data lives under `meta`. The editor still carries it on
1395
+ // its internal COPY-PASTE payload, which never validates against this schema.)
1250
1396
  }));
1397
+ var anyKf = (kf) => kf;
1398
+ var kfTime = (kf) => {
1399
+ var _a2, _b;
1400
+ return (_b = (_a2 = anyKf(kf).time) != null ? _a2 : anyKf(kf).t) != null ? _b : 0;
1401
+ };
1402
+ var kfValue = (kf) => {
1403
+ var _a2;
1404
+ return (_a2 = anyKf(kf).value) != null ? _a2 : anyKf(kf).v;
1405
+ };
1406
+ var kfEasing = (kf) => {
1407
+ var _a2;
1408
+ return (_a2 = anyKf(kf).easing) != null ? _a2 : anyKf(kf).e;
1409
+ };
1410
+ var kfTangentIn = (kf) => anyKf(kf).tangentIn;
1411
+ var kfTangentOut = (kf) => anyKf(kf).tangentOut;
1251
1412
  var PxLoopSchema = implementsInterface()(px.object({
1252
1413
  segmentCount: px.number().optional(),
1253
- extend: px.enum([PxLoopExtend.before, PxLoopExtend.after]).optional(),
1254
- alternate: px.boolean().optional()
1414
+ repeatAt: px.enum([PxLoopRepeatAt.start, PxLoopRepeatAt.end]).optional(),
1415
+ direction: px.enum([PxLoopDirection.normal, PxLoopDirection.alternate]).optional()
1255
1416
  }));
1256
1417
  var PxPropertyAnimationSchema = implementsInterface()(px.object({
1257
1418
  value: PxKeyframeValueSchema.optional(),
1258
1419
  keyframes: px.array(PxKeyframeSchema).optional(),
1259
- kfs: px.array(PxKeyframeSchema).optional(),
1260
1420
  loop: px.union([PxLoopSchema, px.boolean()]).optional(),
1261
- autoOrient: px.boolean().optional()
1421
+ autoOrient: px.boolean().optional(),
1422
+ alongPathMode: px.enum(["sampled", "offsetPath"]).optional()
1262
1423
  }));
1263
1424
  var PxTransformPartsSchema = implementsInterface()(px.object({
1264
1425
  translate: px.tuple([px.number(), px.number()]).optional(),
@@ -1284,6 +1445,10 @@ var PxElementAnimationSchema = implementsInterface()(px.union([
1284
1445
  var PxTriggerSchema = implementsInterface()(px.object({
1285
1446
  startOn: px.enum(["load", "mouseOver", "click", "scrollIntoView", "programmatic"]).optional(),
1286
1447
  outAction: px.enum(["continue", "pause", "reset", "reverse"]).optional(),
1448
+ // What happens after a NATURAL finish — `'hold'` (default: keep the end state per
1449
+ // `fill`) or `'reset'` (snap back to the start state). Pairs with `outAction` ("what
1450
+ // happens when the trigger condition ends"); both end-of-life knobs now read alike.
1451
+ finishAction: px.enum(["hold", "reset"]).optional(),
1287
1452
  scrollIntoViewThreshold: px.number().optional()
1288
1453
  }));
1289
1454
  var PxGlyphSchema = implementsInterface()(px.object({
@@ -1291,8 +1456,8 @@ var PxGlyphSchema = implementsInterface()(px.object({
1291
1456
  d: px.string()
1292
1457
  }));
1293
1458
  var PxGlyphFontSchema = implementsInterface()(px.object({
1294
- fFamily: px.string(),
1295
- style: px.string(),
1459
+ fontFamily: px.string(),
1460
+ fontStyle: px.string(),
1296
1461
  ascent: px.number(),
1297
1462
  unitsPerEm: px.number(),
1298
1463
  glyphs: px.record(PxGlyphSchema)
@@ -1300,8 +1465,10 @@ var PxGlyphFontSchema = implementsInterface()(px.object({
1300
1465
  var PxDefsSchema = implementsInterface()(px.object({
1301
1466
  easings: px.record(px.tuple([px.number(), px.number(), px.number(), px.number()])).optional(),
1302
1467
  animations: px.record(PxAnimationDefinitionSchema).optional(),
1303
- styles: px.record(px.any()).optional(),
1304
- glyphs: px.record(PxGlyphFontSchema).optional()
1468
+ // Review §2.6: the schema now matches the declared type — a style preset is a flat
1469
+ // record of string|number attribute values, nothing nested.
1470
+ styles: px.record(px.record(px.union([px.string(), px.number()]))).optional(),
1471
+ fonts: px.record(PxGlyphFontSchema).optional()
1305
1472
  }));
1306
1473
  var PX_SCROLL_PHASES = ["cover", "contain", "entry", "exit", "entry-crossing", "exit-crossing"];
1307
1474
  var PxScrollRangePointSchema = implementsInterface()(px.object({
@@ -1313,7 +1480,6 @@ var PxScrollRangeSchema = px.object({
1313
1480
  end: PxScrollRangePointSchema.optional()
1314
1481
  });
1315
1482
  var PxScrollSchema = implementsInterface()(px.object({
1316
- driver: px.enum(["custom", "native"]).optional(),
1317
1483
  kind: px.enum(["view", "scroll"]).optional(),
1318
1484
  axis: px.enum(["block", "inline", "x", "y"]).optional(),
1319
1485
  source: px.enum(["nearest", "root"]).optional(),
@@ -1326,23 +1492,67 @@ var PxScrollSchema = implementsInterface()(px.object({
1326
1492
  pinDistance: px.number().optional(),
1327
1493
  range: PxScrollRangeSchema.optional()
1328
1494
  }));
1329
- var PxAnimatorConfigSchema = implementsInterface()(px.object({
1330
- mode: px.enum([PxAnimatorMode.auto, PxAnimatorMode.waapi, PxAnimatorMode.frames]).optional(),
1495
+ var PxTimelinePinSchema = implementsInterface()(px.object({
1496
+ align: px.enum(["top", "center", "bottom"]).optional(),
1497
+ top: px.number().optional(),
1498
+ distance: px.number().optional()
1499
+ }));
1500
+ var PxTimelineEngineSchema = px.enum([PxTimelineEngineExtra.auto, PxTimelineEngineExtra.native, PxTimelineEngineExtra.js]).optional();
1501
+ var PxTimeTimelineSchema = implementsInterface()(px.object({
1502
+ type: px.literal("time").optional(),
1503
+ engine: PxTimelineEngineSchema,
1504
+ frameRate: px.number().optional(),
1505
+ // §2.8: duration is a property of the TIMELINE — how long one pass takes.
1331
1506
  duration: px.number().optional(),
1507
+ trigger: PxTriggerSchema.optional(),
1332
1508
  delay: px.number().optional(),
1333
- // LAW (SCHEMA-DESIGN R3, S10): the ONE sanctioned string-in-number union
1334
- // (CSS animation-iteration-count familiarity) — do not add more mixed unions.
1335
1509
  iterations: px.union([px.number(), px.literal("infinite")]).optional(),
1336
- fill: px.enum(["forwards", "backwards", "both", "none"]).optional(),
1337
- direction: px.enum(["normal", "reverse", "alternate", "alternate-reverse"]).optional(),
1510
+ // `fillMode` on the wire (CSS `animation-fill-mode`; the runtime view calls it `fill`)
1511
+ // — never `fill`, which is paint everywhere else in the format.
1512
+ fillMode: px.enum(["forwards", "backwards", "both", "none"]).optional(),
1513
+ direction: px.enum(["normal", "reverse", "alternate", "alternate-reverse"]).optional()
1514
+ }));
1515
+ var scrollishTimelineShape = {
1516
+ // §2.8: duration is a property of the TIMELINE — under scrubbing it is the keyframe
1517
+ // span the scroll range maps onto.
1518
+ duration: px.number().optional(),
1519
+ // Finite repeat count IS meaningful when scrubbing — the scroll range maps onto
1520
+ // duration × iterations (rule D4; `'infinite'` cannot map to a range, so no literal here).
1521
+ iterations: px.number().optional(),
1522
+ engine: PxTimelineEngineSchema,
1338
1523
  frameRate: px.number().optional(),
1339
- trigger: PxTriggerSchema.optional(),
1340
- resetOnFinish: px.boolean().optional(),
1524
+ axis: px.enum(["block", "inline", "x", "y"]).optional(),
1525
+ source: px.enum(["nearest", "root"]).optional(),
1526
+ subject: px.string().optional(),
1527
+ // 'parent' | 'scroller' | any CSS selector
1528
+ smoothing: px.number().optional(),
1529
+ // ms
1530
+ pin: px.union([px.boolean(), PxTimelinePinSchema]).optional(),
1531
+ range: PxScrollRangeSchema.optional()
1532
+ };
1533
+ var PxScrollTimelineSchema = implementsInterface()(
1534
+ px.object(__spreadValues2({ type: px.literal("scroll") }, scrollishTimelineShape))
1535
+ );
1536
+ var PxViewTimelineSchema = implementsInterface()(
1537
+ px.object(__spreadValues2({ type: px.literal("view") }, scrollishTimelineShape))
1538
+ );
1539
+ var PxTimelineSchema = px.discriminatedUnion("type", [
1540
+ PxTimeTimelineSchema,
1541
+ // first = the member an absent `type` selects
1542
+ PxScrollTimelineSchema,
1543
+ PxViewTimelineSchema
1544
+ ]);
1545
+ var PxAnimatorConfigSchema = implementsInterface()(px.object({
1546
+ // (`mode`, `duration` and `frameRate` live INSIDE `timeline` on the wire — §2.8; they exist
1547
+ // at this level only on the runtime view, like the rest of the playback dynamics.)
1548
+ // THE spelling of "what advances progress" — clock / scroll / view (review §2.1).
1549
+ timeline: PxTimelineSchema.optional(),
1341
1550
  definitions: PxDefsSchema.optional(),
1342
1551
  animateById: px.record(PxElementAnimationSchema).optional(),
1343
- timelineSource: px.string().optional(),
1344
- scroll: PxScrollSchema.optional(),
1345
- debugInstName: px.string().optional()
1552
+ debugGlobalName: px.string().optional(),
1553
+ // Declared HERE because this is a closed object: an undeclared key would be stripped by
1554
+ // `sanitize` and flagged by strict validation on our own files.
1555
+ version: px.string().optional()
1346
1556
  }));
1347
1557
  var PxBindingSchema = implementsInterface()(px.object({
1348
1558
  id: px.string(),
@@ -1360,18 +1570,18 @@ var PxAttrValueSchema = px.union([
1360
1570
  ]);
1361
1571
  var PxAnimatableNumberSchema = px.union([
1362
1572
  px.number(),
1363
- px.object({ value: px.number() }),
1364
- PxPropertyAnimationSchema
1573
+ PxPropertyAnimationSchema,
1574
+ px.object({ value: px.number() })
1365
1575
  ]);
1366
1576
  var PxAnimatableVec2Schema = px.union([
1367
1577
  px.tuple([px.number(), px.number()]),
1368
- px.object({ value: px.tuple([px.number(), px.number()]) }),
1369
- PxPropertyAnimationSchema
1578
+ PxPropertyAnimationSchema,
1579
+ px.object({ value: px.tuple([px.number(), px.number()]) })
1370
1580
  ]);
1371
1581
  var PxAnimatableStringSchema = px.union([
1372
1582
  px.string(),
1373
- px.object({ value: px.string() }),
1374
- PxPropertyAnimationSchema
1583
+ PxPropertyAnimationSchema,
1584
+ px.object({ value: px.string() })
1375
1585
  ]);
1376
1586
  var PxTransformByEffectSchema = implementsInterface()(px.object({
1377
1587
  translate: PxAnimatableVec2Schema.optional(),
@@ -1391,7 +1601,7 @@ var PxRepeaterEffectSchema = implementsInterface()(px.object({
1391
1601
  origin: PxAnimatableVec2Schema.optional()
1392
1602
  }));
1393
1603
  var PxMaskedByEffectSchema = implementsInterface()(px.object({
1394
- sourceId: px.string().optional(),
1604
+ source: px.string().optional(),
1395
1605
  maskType: px.enum([PxMaskType.luminance, PxMaskType.alpha]).optional(),
1396
1606
  maskUnits: px.enum([PxUnits.userSpaceOnUse, PxUnits.objectBoundingBox]).optional(),
1397
1607
  maskContentUnits: px.enum([PxUnits.userSpaceOnUse, PxUnits.objectBoundingBox]).optional(),
@@ -1401,8 +1611,7 @@ var PxMaskedByEffectSchema = implementsInterface()(px.object({
1401
1611
  height: px.number().optional()
1402
1612
  }));
1403
1613
  var PxClipPathEffectSchema = implementsInterface()(px.object({
1404
- d: PxAnimatableStringSchema.optional(),
1405
- animate: PxPropertyAnimationSchema.optional()
1614
+ d: PxAnimatableStringSchema.optional()
1406
1615
  }));
1407
1616
  var PxStrokeTrimEffectSchema = implementsInterface()(px.object({
1408
1617
  offset: PxAnimatableNumberSchema.optional(),
@@ -1410,15 +1619,15 @@ var PxStrokeTrimEffectSchema = implementsInterface()(px.object({
1410
1619
  subPaths: px.enum([PxStrokeTrimSubPaths.separate, PxStrokeTrimSubPaths.combined]).optional()
1411
1620
  }));
1412
1621
  var PxRetimeEffectSchema = implementsInterface()(px.object({
1413
- sourceId: px.string().optional(),
1414
1622
  start: px.number().optional(),
1415
1623
  stretch: px.number().optional(),
1416
1624
  timeCrop: px.tuple([px.number(), px.number()]).optional()
1417
1625
  }));
1418
1626
  var PxCloneEffectSchema = implementsInterface()(px.object({
1419
- // Contextual kind — the `type` convention, see `PxNodeBase.type`.
1420
- type: px.enum([PxCloneType.content]).optional(),
1421
- sourceId: px.string().optional(),
1627
+ // Subtractive on purpose: the `<use>` can only point at one wrapper layer of the
1628
+ // source, so the choices form a ladder — 'translate' now, maybe 'transform' later.
1629
+ without: px.enum([PxCloneWithout.translate]).optional(),
1630
+ source: px.string().optional(),
1422
1631
  retime: PxRetimeEffectSchema.optional()
1423
1632
  }));
1424
1633
  var PxGradientStopSchema = implementsInterface()(px.object({
@@ -1433,11 +1642,11 @@ var PxAnimatableGradientStopsSchema = px.union([
1433
1642
  var PxFillGradientEffectSchema = implementsInterface()(px.object({
1434
1643
  // Contextual kind — the `type` convention, see `PxNodeBase.type`.
1435
1644
  type: px.enum([PxGradientType.linear, PxGradientType.radial]),
1436
- p1: PxAnimatableVec2Schema.optional(),
1437
- p2: PxAnimatableVec2Schema.optional(),
1438
- c: PxAnimatableVec2Schema.optional(),
1439
- r: PxAnimatableNumberSchema.optional(),
1440
- fp: PxAnimatableVec2Schema.optional(),
1645
+ start: PxAnimatableVec2Schema.optional(),
1646
+ end: PxAnimatableVec2Schema.optional(),
1647
+ center: PxAnimatableVec2Schema.optional(),
1648
+ radius: PxAnimatableNumberSchema.optional(),
1649
+ focal: PxAnimatableVec2Schema.optional(),
1441
1650
  stops: PxAnimatableGradientStopsSchema.optional(),
1442
1651
  gradientUnits: px.enum([PxGradientUnits.userSpaceOnUse, PxGradientUnits.objectBoundingBox]).optional(),
1443
1652
  spreadMethod: px.enum([PxGradientSpreadMethod.pad, PxGradientSpreadMethod.reflect, PxGradientSpreadMethod.repeat]).optional(),
@@ -1445,7 +1654,7 @@ var PxFillGradientEffectSchema = implementsInterface()(px.object({
1445
1654
  }));
1446
1655
  var PxStrokeGradientEffectSchema = PxFillGradientEffectSchema;
1447
1656
  var PxTextPathEffectSchema = implementsInterface()(px.object({
1448
- path: px.string(),
1657
+ pathData: px.string(),
1449
1658
  pathOverflow: px.enum([PxPathOverflow.clip, PxPathOverflow.extend]).optional(),
1450
1659
  lengthAdjust: px.enum([PxLengthAdjust.spacing, PxLengthAdjust.spacingAndGlyphs]).optional(),
1451
1660
  method: px.enum([PxTextPathMethod.align, PxTextPathMethod.stretch]).optional(),
@@ -1485,16 +1694,33 @@ function validateNodeEffects(root, opts) {
1485
1694
  walk(root, "root");
1486
1695
  return warnings;
1487
1696
  }
1697
+ function validateDocument(doc) {
1698
+ const ctx = { errors: [], warnings: [], strict: true };
1699
+ const problems = PxAnimatedSvgDocumentSchema.isValid(doc, ctx, ["root"]) ? [] : [...ctx.errors];
1700
+ if (doc && typeof doc === "object") {
1701
+ for (const w of validateNodeEffects(doc, { strict: true })) {
1702
+ if (!problems.includes(w)) problems.push(w);
1703
+ }
1704
+ }
1705
+ return problems;
1706
+ }
1488
1707
  var PxNodeBase = px.openObject({
1489
1708
  // CONVENTION (SCHEMA-DESIGN R1 / issues N4): `type` is the ONE word for "what
1490
1709
  // kind of thing is this", discriminated by its CARRIER — here the node TAG
1491
- // (`rect`, `text`), and inside a sub-object that object's kind (`clone.type`,
1710
+ // (`rect`, `text`), and inside a sub-object that object's kind (`fillGradient.type`,
1492
1711
  // `fillGradient.type`, editor `preset.type`). Each sits in its own object, so
1493
1712
  // the carrier disambiguates completely; synonyms (`cloneKind`, `presetShape`)
1494
1713
  // would add words that all mean "type" and still need the carrier to read.
1495
1714
  // Guarding a `type` SLOT against a wrong VALUE is the job of strict enums
1496
1715
  // (issues V3), never of distinct key names.
1497
1716
  type: px.string(),
1717
+ // The escape hatch for elements that carry a REAL `type` attribute — `<feTurbulence
1718
+ // type="fractalNoise">`, `<feFuncR type="table">`, `<feColorMatrix type="saturate">`.
1719
+ // `type` is taken by the tag name, so the attribute travels here and the renderer puts
1720
+ // it back (`PxAnimatorDOM.renderNode`, `PxRnRender`). Declared here — not merely
1721
+ // documented — because a wire key that is not in a schema is invisible to the
1722
+ // minifier's reserve list and gets renamed (MINIFICATION-BOUNDARY-PLAN.md §1.1).
1723
+ domType: px.string().optional(),
1498
1724
  id: px.string().optional(),
1499
1725
  meta: px.any().optional(),
1500
1726
  // Player-effects bucket emitted by the Editor's lightweight design format.
@@ -1551,7 +1777,7 @@ function deepClone(value) {
1551
1777
  return cloned;
1552
1778
  }
1553
1779
  function generateNewIds(doc) {
1554
- var _a, _b;
1780
+ var _a2, _b;
1555
1781
  const cloned = deepClone(doc);
1556
1782
  const idMap = /* @__PURE__ */ new Map();
1557
1783
  const hashRefAttrs = /* @__PURE__ */ new Set(["href", "xlink:href"]);
@@ -1569,7 +1795,8 @@ function generateNewIds(doc) {
1569
1795
  "flood-color",
1570
1796
  "lighting-color"
1571
1797
  ]);
1572
- const directIdRefAttrs = /* @__PURE__ */ new Set(["sourceId", "targetId", "boundElementId"]);
1798
+ const directIdRefAttrs = /* @__PURE__ */ new Set(["targetId", "boundElementId"]);
1799
+ const isEffectSourceRef = (key, parentKey) => key === "source" && (parentKey === "maskedBy" || parentKey === "clone");
1573
1800
  function collectIds(node) {
1574
1801
  if (!node || typeof node !== "object") return;
1575
1802
  if (node.id && typeof node.id === "string") {
@@ -1586,7 +1813,7 @@ function generateNewIds(doc) {
1586
1813
  }
1587
1814
  }
1588
1815
  }
1589
- function updateRefs(node) {
1816
+ function updateRefs(node, parentKey) {
1590
1817
  if (!node || typeof node !== "object") return;
1591
1818
  for (const [key, value] of Object.entries(node)) {
1592
1819
  if (key === "children") {
@@ -1606,7 +1833,7 @@ function generateNewIds(doc) {
1606
1833
  }
1607
1834
  } else if (urlRefAttrs.has(key)) {
1608
1835
  node[key] = replaceUrlRefs(value, idMap);
1609
- } else if (directIdRefAttrs.has(key)) {
1836
+ } else if (directIdRefAttrs.has(key) || isEffectSourceRef(key, parentKey)) {
1610
1837
  const hasHash = value.startsWith("#");
1611
1838
  const newId = idMap.get(hasHash ? value.slice(1) : value);
1612
1839
  if (newId) {
@@ -1622,18 +1849,20 @@ function generateNewIds(doc) {
1622
1849
  }
1623
1850
  }
1624
1851
  } else if (typeof value === "object" && value !== null) {
1625
- updateRefs(value);
1852
+ updateRefs(value, key);
1626
1853
  }
1627
1854
  }
1628
1855
  }
1629
1856
  collectIds(cloned);
1630
1857
  updateRefs(cloned);
1631
- const docAnimate = (_a = cloned.animator) == null ? void 0 : _a.animateById;
1858
+ const docAnimate = (_a2 = cloned.animator) == null ? void 0 : _a2.animateById;
1632
1859
  if (docAnimate && typeof docAnimate === "object") {
1633
1860
  const updatedAnimate = {};
1634
- for (const [id, anim] of Object.entries(docAnimate)) {
1861
+ for (const [key, anim] of Object.entries(docAnimate)) {
1862
+ const hashed = key.startsWith("#");
1863
+ const id = hashed ? key.slice(1) : key;
1635
1864
  const newId = (_b = idMap.get(id)) != null ? _b : id;
1636
- updatedAnimate[newId] = anim;
1865
+ updatedAnimate[hashed ? "#" + newId : newId] = anim;
1637
1866
  }
1638
1867
  cloned.animator = __spreadProps2(__spreadValues2({}, cloned.animator), { animateById: updatedAnimate });
1639
1868
  }
@@ -1708,10 +1937,10 @@ function sanitiseAttributeValue(name, value) {
1708
1937
  return value;
1709
1938
  }
1710
1939
  function resolveStyle(style, defs) {
1711
- var _a;
1940
+ var _a2;
1712
1941
  if (!style) return void 0;
1713
1942
  if (typeof style === "string") {
1714
- return (_a = defs == null ? void 0 : defs.styles) == null ? void 0 : _a[style];
1943
+ return (_a2 = defs == null ? void 0 : defs.styles) == null ? void 0 : _a2[style];
1715
1944
  }
1716
1945
  return style;
1717
1946
  }
@@ -1724,16 +1953,16 @@ function getNormalizedProps(props) {
1724
1953
  let value = props[rawKey];
1725
1954
  if (COLOUR_ATTR_NAMES.has(key) && Array.isArray(value)) {
1726
1955
  propsCopy[key] = toRGBA(value);
1727
- } else if (key === "transform" && value !== null && typeof value === "object" && !Array.isArray(value) && !value.keyframes && !value.kfs) {
1956
+ } else if (key === "transform" && value !== null && typeof value === "object" && !Array.isArray(value) && !value.keyframes) {
1728
1957
  const parts = value.value && typeof value.value === "object" ? value.value : value;
1729
- propsCopy["transform"] = composeTransformParts(parts, { withUnits: false });
1958
+ propsCopy[TRANSFORM_ATTR] = composeTransformParts(parts, { withUnits: false });
1730
1959
  } else if (TRANSFORM_FN_NAMES.has(key)) {
1731
1960
  if (Array.isArray(value)) {
1732
1961
  if (key === "translate") value = value.map((v) => v + "px");
1733
1962
  value = value.join(",");
1734
1963
  }
1735
1964
  if (key === "rotate") value = value + "deg";
1736
- propsCopy["transform"] = key + "(" + value + ")";
1965
+ propsCopy[TRANSFORM_ATTR] = key + "(" + value + ")";
1737
1966
  } else if (Array.isArray(value)) {
1738
1967
  propsCopy[key] = value.join(",");
1739
1968
  } else if (value !== void 0 && value !== null) {
@@ -1743,8 +1972,7 @@ function getNormalizedProps(props) {
1743
1972
  return propsCopy;
1744
1973
  }
1745
1974
  function getKfTranslate(kf) {
1746
- var _a;
1747
- const v = (_a = kf.value) != null ? _a : kf.v;
1975
+ const v = kfValue(kf);
1748
1976
  if (!v) return void 0;
1749
1977
  if (Array.isArray(v) && v.length >= 2 && typeof v[0] === "number" && typeof v[1] === "number") {
1750
1978
  return [v[0], v[1]];
@@ -1754,31 +1982,27 @@ function getKfTranslate(kf) {
1754
1982
  return void 0;
1755
1983
  }
1756
1984
  function getKfTime(kf) {
1757
- var _a, _b;
1758
- return (_b = (_a = kf.time) != null ? _a : kf.t) != null ? _b : 0;
1985
+ return kfTime(kf);
1759
1986
  }
1760
1987
  function getKfEasing(kf) {
1761
- var _a;
1762
- return (_a = kf.easing) != null ? _a : kf.e;
1988
+ return kfEasing(kf);
1763
1989
  }
1764
1990
  function propAnimIsMotionPath(anim) {
1765
- var _a, _b, _c;
1766
- const kfs = (_a = anim.keyframes) != null ? _a : anim.kfs;
1991
+ const kfs = anim.keyframes;
1767
1992
  if (!Array.isArray(kfs)) return false;
1768
1993
  if (anim.autoOrient) return true;
1769
1994
  for (const kf of kfs) {
1770
- if (((_b = kf.tangentIn) != null ? _b : kf.ti) || ((_c = kf.tangentOut) != null ? _c : kf.to)) return true;
1995
+ if (kfTangentIn(kf) || kfTangentOut(kf)) return true;
1771
1996
  }
1772
1997
  return false;
1773
1998
  }
1774
1999
  var _segmentCache = /* @__PURE__ */ new WeakMap();
1775
2000
  function getSegmentCache(prevKf, nextKf, prevPos, nextPos) {
1776
- var _a, _b;
1777
2001
  let byNext = _segmentCache.get(prevKf);
1778
2002
  const existing = byNext == null ? void 0 : byNext.get(nextKf);
1779
2003
  if (existing) return existing;
1780
- const to = (_a = prevKf.tangentOut) != null ? _a : prevKf.to;
1781
- const ti = (_b = nextKf.tangentIn) != null ? _b : nextKf.ti;
2004
+ const to = kfTangentOut(prevKf);
2005
+ const ti = kfTangentIn(nextKf);
1782
2006
  const P1 = [prevPos[0] + (to ? to[0] : 0), prevPos[1] + (to ? to[1] : 0)];
1783
2007
  const P2 = [nextPos[0] + (ti ? ti[0] : 0), nextPos[1] + (ti ? ti[1] : 0)];
1784
2008
  const lut = bezier2D_arcLengthLUT(prevPos, P1, P2, nextPos);
@@ -1828,14 +2052,14 @@ var DEFAULT_FLATNESS_TOL = 0.5;
1828
2052
  var DEFAULT_ROTATION_TOL = 5;
1829
2053
  var DEFAULT_MAX_SAMPLES = 32;
1830
2054
  function materialiseMotionPathInPropAnim(anim, opts) {
1831
- var _a, _b, _c, _d;
2055
+ var _a2, _b, _c;
1832
2056
  if (!propAnimIsMotionPath(anim)) return anim;
1833
- const kfs = (_a = anim.keyframes) != null ? _a : anim.kfs;
2057
+ const kfs = anim.keyframes;
1834
2058
  if (!Array.isArray(kfs) || kfs.length < 2) return anim;
1835
2059
  const autoOrient = !!anim.autoOrient;
1836
- const flatnessTol = (_b = opts == null ? void 0 : opts.flatnessTolerance) != null ? _b : DEFAULT_FLATNESS_TOL;
1837
- const rotationTol = (_c = opts == null ? void 0 : opts.rotationTolerance) != null ? _c : DEFAULT_ROTATION_TOL;
1838
- const maxSamples = (_d = opts == null ? void 0 : opts.maxSamplesPerSegment) != null ? _d : DEFAULT_MAX_SAMPLES;
2060
+ const flatnessTol = (_a2 = opts == null ? void 0 : opts.flatnessTolerance) != null ? _a2 : DEFAULT_FLATNESS_TOL;
2061
+ const rotationTol = (_b = opts == null ? void 0 : opts.rotationTolerance) != null ? _b : DEFAULT_ROTATION_TOL;
2062
+ const maxSamples = (_c = opts == null ? void 0 : opts.maxSamplesPerSegment) != null ? _c : DEFAULT_MAX_SAMPLES;
1839
2063
  const out = [];
1840
2064
  const firstPos = getKfTranslate(kfs[0]);
1841
2065
  if (!firstPos) return anim;
@@ -1864,15 +2088,14 @@ function materialiseMotionPathInPropAnim(anim, opts) {
1864
2088
  const lastInE = getKfEasing(kfs[kfs.length - 1]);
1865
2089
  if (lastInE) out[out.length - 1].e = lastInE;
1866
2090
  if (autoOrient) unwrapAutoOrientRotations(out);
1867
- const result = { kfs: out };
2091
+ const result = { keyframes: out };
1868
2092
  if (anim.loop !== void 0) result.loop = anim.loop;
1869
2093
  return result;
1870
2094
  }
1871
2095
  function unwrapAutoOrientRotations(kfs) {
1872
- var _a;
1873
2096
  let prev;
1874
2097
  for (const kf of kfs) {
1875
- const v = (_a = kf.v) != null ? _a : kf.value;
2098
+ const v = kfValue(kf);
1876
2099
  if (!v || typeof v.rotate !== "number") continue;
1877
2100
  if (prev === void 0) {
1878
2101
  prev = v.rotate;
@@ -1889,8 +2112,7 @@ function makeOutKf(time, value) {
1889
2112
  return { t: time, v: value };
1890
2113
  }
1891
2114
  function getKfValueParts(kf) {
1892
- var _a;
1893
- const v = (_a = kf.value) != null ? _a : kf.v;
2115
+ const v = kfValue(kf);
1894
2116
  if (!v || typeof v !== "object" || Array.isArray(v)) return void 0;
1895
2117
  return v;
1896
2118
  }
@@ -1951,9 +2173,8 @@ function wrappedAngleDelta(a, b) {
1951
2173
  return d;
1952
2174
  }
1953
2175
  function insertSharpCornerStepKfIfNeeded(out, prevKf, nextKf, prevPos, nextPos, rotationTol) {
1954
- var _a;
1955
2176
  const lastKf = out[out.length - 1];
1956
- const lastV = (_a = lastKf.v) != null ? _a : lastKf.value;
2177
+ const lastV = kfValue(lastKf);
1957
2178
  const prevExit = lastV == null ? void 0 : lastV.rotate;
1958
2179
  if (typeof prevExit !== "number") return;
1959
2180
  const boundaryV = getKfValueParts(prevKf);
@@ -2264,21 +2485,21 @@ function normalizePathValue(value) {
2264
2485
  return value;
2265
2486
  }
2266
2487
  function resolveEasing(easing, defs) {
2267
- var _a;
2488
+ var _a2;
2268
2489
  if (!easing) return void 0;
2269
2490
  if (Array.isArray(easing)) {
2270
2491
  return easing;
2271
2492
  }
2272
- if ((_a = defs == null ? void 0 : defs.easings) == null ? void 0 : _a[easing]) {
2493
+ if ((_a2 = defs == null ? void 0 : defs.easings) == null ? void 0 : _a2[easing]) {
2273
2494
  return defs.easings[easing];
2274
2495
  }
2275
2496
  console.warn("Unknown easing name: " + easing);
2276
2497
  return void 0;
2277
2498
  }
2278
2499
  function resolveAnimation(animRef, defs) {
2279
- var _a;
2500
+ var _a2;
2280
2501
  if (typeof animRef === "string") {
2281
- const resolved = (_a = defs == null ? void 0 : defs.animations) == null ? void 0 : _a[animRef];
2502
+ const resolved = (_a2 = defs == null ? void 0 : defs.animations) == null ? void 0 : _a2[animRef];
2282
2503
  if (!resolved) {
2283
2504
  console.warn("Unknown animation name: " + animRef);
2284
2505
  }
@@ -2303,9 +2524,9 @@ function resolveElementAnimation(animate, defs) {
2303
2524
  return results;
2304
2525
  }
2305
2526
  function interpolateValue(propName, a, b, t) {
2306
- var _a, _b;
2527
+ var _a2, _b;
2307
2528
  if (propName === "d") {
2308
- const aPaths = (_a = a == null ? void 0 : a.paths) != null ? _a : Array.isArray(a) ? a : [];
2529
+ const aPaths = (_a2 = a == null ? void 0 : a.paths) != null ? _a2 : Array.isArray(a) ? a : [];
2309
2530
  const bPaths = (_b = b == null ? void 0 : b.paths) != null ? _b : Array.isArray(b) ? b : [];
2310
2531
  return { paths: interpolateBeziers(aPaths, bPaths, t) };
2311
2532
  }
@@ -2341,11 +2562,11 @@ function interpolateTransformParts(a, b, t) {
2341
2562
  return out;
2342
2563
  }
2343
2564
  function expandLoopKeyframes(propName, keyframes, loop, duration) {
2344
- var _a, _b, _c, _d, _e;
2565
+ var _a2, _b, _c, _d, _e;
2345
2566
  const totalIntervals = keyframes.length - 1;
2346
- const segCount = clamp((_a = loop.segmentCount) != null ? _a : totalIntervals, 1, totalIntervals);
2567
+ const segCount = clamp((_a2 = loop.segmentCount) != null ? _a2 : totalIntervals, 1, totalIntervals);
2347
2568
  let segKfs;
2348
- if (loop.extend === PxLoopExtend.before) {
2569
+ if (loop.repeatAt === PxLoopRepeatAt.start) {
2349
2570
  segKfs = keyframes.slice(0, segCount + 1);
2350
2571
  } else {
2351
2572
  segKfs = keyframes.slice(totalIntervals - segCount);
@@ -2353,7 +2574,7 @@ function expandLoopKeyframes(propName, keyframes, loop, duration) {
2353
2574
  const firstT = (_b = keyframes[0].t) != null ? _b : 0;
2354
2575
  const lastT = (_c = keyframes[keyframes.length - 1].t) != null ? _c : 0;
2355
2576
  let fillStart, fillEnd;
2356
- if (loop.extend === PxLoopExtend.before) {
2577
+ if (loop.repeatAt === PxLoopRepeatAt.start) {
2357
2578
  fillStart = 0;
2358
2579
  fillEnd = firstT;
2359
2580
  } else {
@@ -2366,26 +2587,23 @@ function expandLoopKeyframes(propName, keyframes, loop, duration) {
2366
2587
  const segEndT = (_e = segKfs[segKfs.length - 1].t) != null ? _e : 0;
2367
2588
  const segDuration = segEndT - segStartT;
2368
2589
  if (segDuration <= 0) return keyframes;
2369
- const template = segKfs.map((kf) => {
2370
- var _a2, _b2;
2371
- return {
2372
- relT: (kf.t - segStartT) / segDuration,
2373
- v: kf.v,
2374
- e: kf.e,
2375
- tangentIn: (_a2 = kf.tangentIn) != null ? _a2 : kf.ti,
2376
- tangentOut: (_b2 = kf.tangentOut) != null ? _b2 : kf.to
2377
- };
2378
- });
2590
+ const template = segKfs.map((kf) => ({
2591
+ relT: (kf.t - segStartT) / segDuration,
2592
+ v: kf.v,
2593
+ e: kf.e,
2594
+ tangentIn: kfTangentIn(kf),
2595
+ tangentOut: kfTangentOut(kf)
2596
+ }));
2379
2597
  const fullReps = Math.floor(fillDuration / segDuration);
2380
2598
  const remainder = fillDuration - fullReps * segDuration;
2381
2599
  const partialFraction = remainder / segDuration;
2382
2600
  const looped = [];
2383
- const separateBoundary = loop.extend !== PxLoopExtend.before;
2601
+ const separateBoundary = loop.repeatAt !== PxLoopRepeatAt.start;
2384
2602
  const originalTerminalKf = keyframes[keyframes.length - 1];
2385
2603
  let terminalEasingOverride;
2386
2604
  let hasTerminalEasingOverride = false;
2387
2605
  function appendRep(repStart, isReversed, partial) {
2388
- var _a2;
2606
+ var _a3;
2389
2607
  let entries;
2390
2608
  if (isReversed) {
2391
2609
  entries = [];
@@ -2422,7 +2640,7 @@ function expandLoopKeyframes(propName, keyframes, loop, duration) {
2422
2640
  return;
2423
2641
  }
2424
2642
  const prevKf = looped.length > 0 ? looped[looped.length - 1] : originalTerminalKf;
2425
- const isBoundary = separateBoundary && i === 0 && prevKf !== void 0 && Math.abs(((_a2 = prevKf.t) != null ? _a2 : 0) - (repStart + entry.relT * segDuration)) < 1e-9;
2643
+ const isBoundary = separateBoundary && i === 0 && prevKf !== void 0 && Math.abs(((_a3 = prevKf.t) != null ? _a3 : 0) - (repStart + entry.relT * segDuration)) < 1e-9;
2426
2644
  if (isBoundary) {
2427
2645
  if (deepEqualValue(prevKf.v, entry.v)) {
2428
2646
  if (looped.length > 0) {
@@ -2488,30 +2706,30 @@ function expandLoopKeyframes(propName, keyframes, loop, duration) {
2488
2706
  looped.push(pushed);
2489
2707
  }
2490
2708
  }
2491
- if (loop.extend === PxLoopExtend.before) {
2709
+ if (loop.repeatAt === PxLoopRepeatAt.start) {
2492
2710
  if (partialFraction > 1e-9) {
2493
- const isReversed = !!loop.alternate && fullReps % 2 === 0;
2711
+ const isReversed = loop.direction === PxLoopDirection.alternate && fullReps % 2 === 0;
2494
2712
  appendRepTail(fillStart, isReversed, partialFraction);
2495
2713
  }
2496
2714
  for (let rep = 0; rep < fullReps; rep++) {
2497
2715
  const distFromBoundary = fullReps - 1 - rep;
2498
- const isReversed = !!loop.alternate && distFromBoundary % 2 === 0;
2716
+ const isReversed = loop.direction === PxLoopDirection.alternate && distFromBoundary % 2 === 0;
2499
2717
  const repStart = fillStart + remainder + rep * segDuration;
2500
2718
  appendRep(repStart, isReversed);
2501
2719
  }
2502
2720
  } else {
2503
2721
  for (let rep = 0; rep < fullReps; rep++) {
2504
- const isReversed = !!loop.alternate && rep % 2 === 0;
2722
+ const isReversed = loop.direction === PxLoopDirection.alternate && rep % 2 === 0;
2505
2723
  const repStart = fillStart + rep * segDuration;
2506
2724
  appendRep(repStart, isReversed);
2507
2725
  }
2508
2726
  if (partialFraction > 1e-9) {
2509
- const isReversed = !!loop.alternate && fullReps % 2 === 0;
2727
+ const isReversed = loop.direction === PxLoopDirection.alternate && fullReps % 2 === 0;
2510
2728
  const repStart = fillStart + fullReps * segDuration;
2511
2729
  appendRep(repStart, isReversed, partialFraction);
2512
2730
  }
2513
2731
  }
2514
- if (loop.extend === PxLoopExtend.before) {
2732
+ if (loop.repeatAt === PxLoopRepeatAt.start) {
2515
2733
  return [...looped, ...keyframes];
2516
2734
  } else {
2517
2735
  if (hasTerminalEasingOverride && keyframes.length > 0) {
@@ -2523,34 +2741,34 @@ function expandLoopKeyframes(propName, keyframes, loop, duration) {
2523
2741
  }
2524
2742
  }
2525
2743
  function normalizeKeyframes(propName, propAnim, duration, defs) {
2526
- var _a, _b, _c, _d, _e, _f, _g;
2527
- const keyframes = propAnim.keyframes || propAnim.kfs || [];
2744
+ var _a2;
2745
+ const keyframes = propAnim.keyframes || [];
2528
2746
  const normalized = [];
2529
2747
  for (const kf of keyframes) {
2530
- const timePct = (_b = (_a = kf.time) != null ? _a : kf.t) != null ? _b : 0;
2531
- let value = (_c = kf.value) != null ? _c : kf.v;
2532
- const easing = (_d = kf.easing) != null ? _d : kf.e;
2748
+ const timePct = kfTime(kf);
2749
+ let value = kfValue(kf);
2750
+ const easing = kfEasing(kf);
2533
2751
  if (propName === "d") {
2534
2752
  value = normalizePathValue(value);
2535
2753
  }
2536
2754
  const propNameKebab = isCamelCaseWord(propName) ? camelCaseToKebabWordIfNeeded(propName) : propName;
2537
2755
  if (COLOUR_ATTR_NAMES.has(propNameKebab)) {
2538
- value = (_e = parseColor(value)) != null ? _e : value;
2756
+ value = (_a2 = parseColor(value)) != null ? _a2 : value;
2539
2757
  }
2540
2758
  const normKf = {
2541
2759
  t: timePct,
2542
2760
  v: value,
2543
2761
  e: resolveEasing(easing, defs)
2544
2762
  };
2545
- const tIn = (_f = kf.tangentIn) != null ? _f : kf.ti;
2546
- const tOut = (_g = kf.tangentOut) != null ? _g : kf.to;
2763
+ const tIn = kfTangentIn(kf);
2764
+ const tOut = kfTangentOut(kf);
2547
2765
  if (tIn) normKf.tangentIn = tIn;
2548
2766
  if (tOut) normKf.tangentOut = tOut;
2549
2767
  normalized.push(normKf);
2550
2768
  }
2551
2769
  normalized.sort((a, b) => {
2552
- var _a2, _b2;
2553
- return ((_a2 = a.t) != null ? _a2 : 0) - ((_b2 = b.t) != null ? _b2 : 0);
2770
+ var _a3, _b;
2771
+ return ((_a3 = a.t) != null ? _a3 : 0) - ((_b = b.t) != null ? _b : 0);
2554
2772
  });
2555
2773
  const loopRaw = propAnim.loop;
2556
2774
  const loop = loopRaw === true ? {} : loopRaw || void 0;
@@ -2569,28 +2787,29 @@ function mergeAnimationDefinitions(animations) {
2569
2787
  return merged;
2570
2788
  }
2571
2789
  function materialiseInternalLoopsInPropAnim(propName, propAnim, duration) {
2572
- var _a;
2573
2790
  const loopRaw = propAnim.loop;
2574
2791
  if (loopRaw === void 0 || loopRaw === null || loopRaw === false) return propAnim;
2575
2792
  const loop = loopRaw === true ? {} : loopRaw;
2576
- const rawKfs = (_a = propAnim.keyframes) != null ? _a : propAnim.kfs;
2793
+ const rawKfs = propAnim.keyframes;
2577
2794
  if (!Array.isArray(rawKfs) || rawKfs.length < 2) return propAnim;
2578
2795
  const propNameKebab = isCamelCaseWord(propName) ? camelCaseToKebabWordIfNeeded(propName) : propName;
2579
2796
  const isColour = COLOUR_ATTR_NAMES.has(propNameKebab);
2580
2797
  const kfs = rawKfs.map((kf) => {
2581
- var _a2, _b, _c, _d, _e, _f, _g, _h;
2582
- const t = (_a2 = kf.t) != null ? _a2 : kf.time;
2583
- let v = (_b = kf.v) != null ? _b : kf.value;
2798
+ var _a2;
2799
+ const t = kfTime(kf);
2800
+ let v = kfValue(kf);
2584
2801
  if (propName === "d") v = normalizePathValue(v);
2585
- if (isColour) v = (_c = parseColor(v)) != null ? _c : v;
2586
- const e = (_d = kf.e) != null ? _d : kf.easing;
2802
+ if (isColour) v = (_a2 = parseColor(v)) != null ? _a2 : v;
2803
+ const e = kfEasing(kf);
2587
2804
  const out2 = { t, v, e };
2588
- if ((_e = kf.tangentIn) != null ? _e : kf.ti) out2.tangentIn = (_f = kf.tangentIn) != null ? _f : kf.ti;
2589
- if ((_g = kf.tangentOut) != null ? _g : kf.to) out2.tangentOut = (_h = kf.tangentOut) != null ? _h : kf.to;
2805
+ const tIn = kfTangentIn(kf);
2806
+ const tOut = kfTangentOut(kf);
2807
+ if (tIn) out2.tangentIn = tIn;
2808
+ if (tOut) out2.tangentOut = tOut;
2590
2809
  return out2;
2591
2810
  });
2592
2811
  const expanded = expandLoopKeyframes(propName, kfs, loop, duration);
2593
- const out = { kfs: expanded };
2812
+ const out = { keyframes: expanded };
2594
2813
  if (propAnim.autoOrient !== void 0) out.autoOrient = propAnim.autoOrient;
2595
2814
  return out;
2596
2815
  }
@@ -2632,7 +2851,37 @@ var _elementIdCounter = 0;
2632
2851
  function generateElementId() {
2633
2852
  return "_px_el_" + ++_elementIdCounter;
2634
2853
  }
2635
- function normalizeAnimationDefinition(animDef, duration, defs, engine = PxAnimatorEngine.waapi) {
2854
+ function mergeStaticTransformIntoAnimDef(animDef, staticTransform) {
2855
+ if (!animDef) return animDef;
2856
+ const staticParts = staticTransform && typeof staticTransform === "object" && !Array.isArray(staticTransform) ? staticTransform : parseTransformParts(staticTransform);
2857
+ if (!staticParts || !Object.keys(staticParts).length) return animDef;
2858
+ const mergeKfValue = (v) => v && typeof v === "object" && !Array.isArray(v) ? __spreadValues2(__spreadValues2({}, staticParts), v) : v;
2859
+ const transformAnim = animDef[TRANSFORM_ATTR];
2860
+ if (transformAnim && typeof transformAnim === "object") {
2861
+ const anim = transformAnim;
2862
+ if (Array.isArray(anim.keyframes)) {
2863
+ const out = __spreadProps2(__spreadValues2({}, anim), {
2864
+ keyframes: anim.keyframes.map((kf) => __spreadProps2(__spreadValues2({}, kf), { value: mergeKfValue(kf.value) }))
2865
+ });
2866
+ if (out.value !== void 0) out.value = mergeKfValue(out.value);
2867
+ return __spreadProps2(__spreadValues2({}, animDef), { transform: out });
2868
+ }
2869
+ return animDef;
2870
+ }
2871
+ const channels = Object.keys(animDef).filter((k) => TRANSFORM_FN_NAMES.has(k));
2872
+ if (channels.length !== 1) return animDef;
2873
+ const ch = channels[0];
2874
+ const chAnim = animDef[ch];
2875
+ if (!chAnim || typeof chAnim !== "object" || !Array.isArray(chAnim.keyframes)) return animDef;
2876
+ const lifted = __spreadProps2(__spreadValues2({}, chAnim), {
2877
+ keyframes: chAnim.keyframes.map((kf) => __spreadProps2(__spreadValues2({}, kf), { value: __spreadProps2(__spreadValues2({}, staticParts), { [ch]: kf.value }) }))
2878
+ });
2879
+ if (lifted.value !== void 0) lifted.value = __spreadProps2(__spreadValues2({}, staticParts), { [ch]: lifted.value });
2880
+ const rest = __spreadValues2({}, animDef);
2881
+ delete rest[ch];
2882
+ return __spreadProps2(__spreadValues2({}, rest), { transform: lifted });
2883
+ }
2884
+ function normalizeAnimationDefinition(animDef, duration, defs, engine = PxTimelineEngine.native) {
2636
2885
  const normalized = {};
2637
2886
  for (const [propName, propAnim] of Object.entries(animDef)) {
2638
2887
  if (propName === "transform" && propAnim.alongPathMode === "offsetPath" && animDef["offsetDistance"] !== void 0) {
@@ -2640,24 +2889,24 @@ function normalizeAnimationDefinition(animDef, duration, defs, engine = PxAnimat
2640
2889
  }
2641
2890
  const normalizedKfs = normalizeKeyframes(propName, propAnim, duration, defs);
2642
2891
  if (normalizedKfs.length > 0) {
2643
- const out = { kfs: normalizedKfs };
2892
+ const out = { keyframes: normalizedKfs };
2644
2893
  if (propAnim.autoOrient !== void 0) out.autoOrient = propAnim.autoOrient;
2645
2894
  if (propAnim.loop !== void 0) out.loop = propAnim.loop;
2646
- normalized[propName] = engine === PxAnimatorEngine.waapi && propName === "transform" ? materialiseMotionPathInPropAnim(out) : out;
2895
+ normalized[propName] = engine === PxTimelineEngine.native && propName === "transform" ? materialiseMotionPathInPropAnim(out) : out;
2647
2896
  }
2648
2897
  }
2649
2898
  return normalized;
2650
2899
  }
2651
- function getNormalisedBindings(doc, engine = PxAnimatorEngine.waapi) {
2900
+ function getNormalisedBindings(doc, engine = PxTimelineEngine.native) {
2652
2901
  const animatorConfig = getAnimatorConfig(doc) || {};
2653
2902
  const defs = getDefs(doc);
2654
2903
  const duration = animatorConfig.duration || 1e3;
2655
2904
  const bindings = [];
2656
- const processAnimation = (id, animate) => {
2905
+ const processAnimation = (id, animate, staticTransform) => {
2657
2906
  if (!animate) return null;
2658
2907
  const animDefs = resolveElementAnimation(animate, defs);
2659
2908
  if (animDefs.length === 0) return null;
2660
- const merged = mergeAnimationDefinitions(animDefs);
2909
+ const merged = mergeStaticTransformIntoAnimDef(mergeAnimationDefinitions(animDefs), staticTransform);
2661
2910
  const normalizedAnim = normalizeAnimationDefinition(merged, duration, defs, engine);
2662
2911
  if (Object.keys(normalizedAnim).length === 0) return null;
2663
2912
  return {
@@ -2677,7 +2926,7 @@ function getNormalisedBindings(doc, engine = PxAnimatorEngine.waapi) {
2677
2926
  if (inlineAnim && Object.keys(inlineAnim).length > 0) {
2678
2927
  const nodeId = node.id || generateElementId();
2679
2928
  node.id = nodeId;
2680
- const normalized = processAnimation(nodeId, inlineAnim);
2929
+ const normalized = processAnimation(nodeId, inlineAnim, node.transform);
2681
2930
  if (normalized) bindings.push(normalized);
2682
2931
  }
2683
2932
  if (node.children) {
@@ -2694,12 +2943,12 @@ function getNormalisedBindings(doc, engine = PxAnimatorEngine.waapi) {
2694
2943
  return bindings;
2695
2944
  }
2696
2945
  function getKeyframesPair(keyframes, progress) {
2697
- var _a, _b;
2946
+ var _a2, _b;
2698
2947
  const last = keyframes.length - 1;
2699
2948
  let prevKf = keyframes[0];
2700
2949
  let nextKf = keyframes[last > 0 ? 1 : 0];
2701
2950
  for (let j = 0; j < last; j++) {
2702
- const aOff = (_a = keyframes[j].t) != null ? _a : 0;
2951
+ const aOff = (_a2 = keyframes[j].t) != null ? _a2 : 0;
2703
2952
  const bOff = (_b = keyframes[j + 1].t) != null ? _b : 0;
2704
2953
  if (aOff <= progress && progress <= bOff) {
2705
2954
  prevKf = keyframes[j];
@@ -2714,13 +2963,13 @@ function getKeyframesPair(keyframes, progress) {
2714
2963
  return { prevKf, nextKf };
2715
2964
  }
2716
2965
  function calcPropertyValue(propName, propAnim, progress) {
2717
- var _a, _b, _c, _d, _e, _f, _g;
2718
- const keyframes = propAnim.kfs || propAnim.keyframes || [];
2966
+ var _a2, _b, _c, _d;
2967
+ const keyframes = propAnim.keyframes || [];
2719
2968
  if (keyframes.length === 0) return null;
2720
2969
  const { prevKf, nextKf } = getKeyframesPair(keyframes, progress);
2721
- let localProgress = prevKf === nextKf ? 0 : remap(progress, (_a = prevKf.t) != null ? _a : 0, (_b = nextKf.t) != null ? _b : 0, 0, 1);
2970
+ let localProgress = prevKf === nextKf ? 0 : remap(progress, (_a2 = prevKf.t) != null ? _a2 : 0, (_b = nextKf.t) != null ? _b : 0, 0, 1);
2722
2971
  localProgress = clamp(localProgress, 0, 1);
2723
- const easing = (_c = prevKf.e) != null ? _c : prevKf.easing;
2972
+ const easing = kfEasing(prevKf);
2724
2973
  if (easing && Array.isArray(easing)) {
2725
2974
  try {
2726
2975
  localProgress = cubicBezier(easing)(localProgress);
@@ -2729,11 +2978,11 @@ function calcPropertyValue(propName, propAnim, progress) {
2729
2978
  }
2730
2979
  let cssAttrName = isCamelCaseWord(propName) ? camelCaseToKebabWordIfNeeded(propName) : propName;
2731
2980
  let cssValue = null;
2732
- const prevV = (_d = prevKf == null ? void 0 : prevKf.v) != null ? _d : prevKf == null ? void 0 : prevKf.value;
2733
- const nextV = (_e = nextKf == null ? void 0 : nextKf.v) != null ? _e : nextKf == null ? void 0 : nextKf.value;
2981
+ const prevV = prevKf == null ? void 0 : prevKf.v;
2982
+ const nextV = nextKf == null ? void 0 : nextKf.v;
2734
2983
  if (cssAttrName === "d") {
2735
- const prevPaths = (_f = prevV == null ? void 0 : prevV.paths) != null ? _f : Array.isArray(prevV) ? prevV : [];
2736
- const nextPaths = (_g = nextV == null ? void 0 : nextV.paths) != null ? _g : Array.isArray(nextV) ? nextV : [];
2984
+ const prevPaths = (_c = prevV == null ? void 0 : prevV.paths) != null ? _c : Array.isArray(prevV) ? prevV : [];
2985
+ const nextPaths = (_d = nextV == null ? void 0 : nextV.paths) != null ? _d : Array.isArray(nextV) ? nextV : [];
2737
2986
  cssValue = interpolateBeziers(
2738
2987
  prevPaths,
2739
2988
  nextPaths,
@@ -2845,13 +3094,13 @@ function deepClonePxNode(value) {
2845
3094
  function regenerateIdsAndRewriteRefs(root, genId3) {
2846
3095
  const oldToNew = /* @__PURE__ */ new Map();
2847
3096
  const walkAssign = (n) => {
2848
- var _a;
3097
+ var _a2;
2849
3098
  if (typeof n.id === "string") {
2850
3099
  const newId = genId3();
2851
3100
  oldToNew.set(n.id, newId);
2852
3101
  n.id = newId;
2853
3102
  }
2854
- (_a = n.children) == null ? void 0 : _a.forEach(walkAssign);
3103
+ (_a2 = n.children) == null ? void 0 : _a2.forEach(walkAssign);
2855
3104
  };
2856
3105
  walkAssign(root);
2857
3106
  const rewriteUrl = (s) => s.replace(/url\(#([^)]+)\)/g, (m, oldId) => {
@@ -2859,7 +3108,7 @@ function regenerateIdsAndRewriteRefs(root, genId3) {
2859
3108
  return newId ? "url(#" + newId + ")" : m;
2860
3109
  });
2861
3110
  const walkRewrite = (n) => {
2862
- var _a;
3111
+ var _a2;
2863
3112
  if (typeof n.href === "string" && n.href.startsWith("#")) {
2864
3113
  const newId = oldToNew.get(n.href.slice(1));
2865
3114
  if (newId) n.href = "#" + newId;
@@ -2871,7 +3120,7 @@ function regenerateIdsAndRewriteRefs(root, genId3) {
2871
3120
  n[k] = rewriteUrl(v);
2872
3121
  }
2873
3122
  }
2874
- (_a = n.children) == null ? void 0 : _a.forEach(walkRewrite);
3123
+ (_a2 = n.children) == null ? void 0 : _a2.forEach(walkRewrite);
2875
3124
  };
2876
3125
  walkRewrite(root);
2877
3126
  return oldToNew;
@@ -2881,7 +3130,7 @@ function toFiniteNum(v) {
2881
3130
  return Number.isFinite(n) ? n : 0;
2882
3131
  }
2883
3132
  function applyUseOffsetToG(gNode) {
2884
- var _a;
3133
+ var _a2;
2885
3134
  const x = toFiniteNum(gNode.x);
2886
3135
  const y = toFiniteNum(gNode.y);
2887
3136
  delete gNode.x;
@@ -2890,7 +3139,7 @@ function applyUseOffsetToG(gNode) {
2890
3139
  const offset = "translate(" + x + "," + y + ")";
2891
3140
  const carriesTransform = gNode.transform !== void 0 || gNode.animate !== void 0;
2892
3141
  if (carriesTransform) {
2893
- const inner = { type: "g", transform: offset, children: (_a = gNode.children) != null ? _a : [] };
3142
+ const inner = { type: "g", transform: offset, children: (_a2 = gNode.children) != null ? _a2 : [] };
2894
3143
  gNode.children = [inner];
2895
3144
  } else {
2896
3145
  gNode.transform = offset;
@@ -2898,7 +3147,7 @@ function applyUseOffsetToG(gNode) {
2898
3147
  return gNode;
2899
3148
  }
2900
3149
  function materialiseAnimatedUseInstances(root) {
2901
- var _a;
3150
+ var _a2;
2902
3151
  const idMap = buildIdMap(root);
2903
3152
  const animatedIds = computeAnimatedSubtreeIds(root, idMap);
2904
3153
  if (animatedIds.size === 0) return root;
@@ -2909,7 +3158,7 @@ function materialiseAnimatedUseInstances(root) {
2909
3158
  const walked = walkAndMaterialise2(root, idMap, animatedIds, genId3, defsCollector, rootViewport);
2910
3159
  if (defsCollector.length === 0) return walked;
2911
3160
  const defsNode = { type: "defs", children: defsCollector };
2912
- const newChildren = [...(_a = walked.children) != null ? _a : [], defsNode];
3161
+ const newChildren = [...(_a2 = walked.children) != null ? _a2 : [], defsNode];
2913
3162
  return __spreadProps2(__spreadValues2({}, walked), { children: newChildren });
2914
3163
  }
2915
3164
  function readRootViewport(root) {
@@ -2931,9 +3180,9 @@ function numericAttr(v) {
2931
3180
  function buildIdMap(root) {
2932
3181
  const map = /* @__PURE__ */ new Map();
2933
3182
  const visit = (n) => {
2934
- var _a;
3183
+ var _a2;
2935
3184
  if (typeof n.id === "string") map.set(n.id, n);
2936
- (_a = n.children) == null ? void 0 : _a.forEach(visit);
3185
+ (_a2 = n.children) == null ? void 0 : _a2.forEach(visit);
2937
3186
  };
2938
3187
  visit(root);
2939
3188
  return map;
@@ -2980,11 +3229,11 @@ function stripHash(href) {
2980
3229
  return href.startsWith("#") ? href.slice(1) : href;
2981
3230
  }
2982
3231
  function materialiseOneUse(useNode, target, idMap, animatedIds, genId3, defsCollector, rootViewport) {
2983
- var _a, _b, _c, _d;
3232
+ var _a2, _b, _c, _d;
2984
3233
  const clone2 = deepClonePxNode(target);
2985
3234
  regenerateIdsAndRewriteRefs(clone2, genId3);
2986
3235
  const symbolViewBox = clone2.type === "symbol" ? parseViewBox(clone2.viewBox) : void 0;
2987
- const useW = (_b = (_a = numericAttr(useNode.width)) != null ? _a : symbolViewBox == null ? void 0 : symbolViewBox[2]) != null ? _b : rootViewport[0];
3236
+ const useW = (_b = (_a2 = numericAttr(useNode.width)) != null ? _a2 : symbolViewBox == null ? void 0 : symbolViewBox[2]) != null ? _b : rootViewport[0];
2988
3237
  const useH = (_d = (_c = numericAttr(useNode.height)) != null ? _c : symbolViewBox == null ? void 0 : symbolViewBox[3]) != null ? _d : rootViewport[1];
2989
3238
  const rewrittenClone = clone2.type === "symbol" ? rewriteSymbolRootToGroup(clone2, genId3, defsCollector, useW, useH) : clone2;
2990
3239
  const materialisedClone = walkAndMaterialise2(rewrittenClone, idMap, animatedIds, genId3, defsCollector, rootViewport);
@@ -3053,7 +3302,7 @@ function partsRecord(part, value, origin) {
3053
3302
  return rec;
3054
3303
  }
3055
3304
  function readAnimatable(raw) {
3056
- var _a, _b, _c;
3305
+ var _a2, _b;
3057
3306
  if (raw === void 0) return {
3058
3307
  kind: "absent"
3059
3308
  /* Absent */
@@ -3061,20 +3310,20 @@ function readAnimatable(raw) {
3061
3310
  if (Array.isArray(raw)) return { kind: "static", value: raw };
3062
3311
  if (typeof raw === "object") {
3063
3312
  const obj = raw;
3064
- const kfs = (_a = obj.keyframes) != null ? _a : obj.kfs;
3313
+ const kfs = obj.keyframes;
3065
3314
  if (kfs) {
3066
3315
  const out = { kind: "animated", keyframes: kfs.map(normaliseKeyframe), autoOrient: obj.autoOrient, loop: obj.loop };
3067
- const base = (_b = obj.value) != null ? _b : obj.v;
3316
+ const base = (_a2 = obj.value) != null ? _a2 : obj.v;
3068
3317
  if (base !== void 0 && out.kind === "animated") out.base = base;
3069
3318
  return out;
3070
3319
  }
3071
- const staticValue = (_c = obj.value) != null ? _c : obj.v;
3320
+ const staticValue = (_b = obj.value) != null ? _b : obj.v;
3072
3321
  if (staticValue !== void 0) return { kind: "static", value: staticValue };
3073
3322
  }
3074
3323
  return { kind: "static", value: raw };
3075
3324
  }
3076
3325
  function writeAnimatableChannel(node, attrName, read, opts) {
3077
- var _a, _b, _c, _d;
3326
+ var _a2, _b, _c, _d;
3078
3327
  const toOut = (v) => (opts == null ? void 0 : opts.asString) && v !== void 0 && v !== null ? String(v) : v;
3079
3328
  if (read.kind === "absent") return;
3080
3329
  if (read.kind === "static") {
@@ -3088,7 +3337,7 @@ function writeAnimatableChannel(node, attrName, read, opts) {
3088
3337
  if (read.autoOrient !== void 0) block.autoOrient = read.autoOrient;
3089
3338
  animate[attrName] = block;
3090
3339
  node.animate = animate;
3091
- const baseline = (_d = (_b = read.base) != null ? _b : (_a = read.keyframes[0]) == null ? void 0 : _a.value) != null ? _d : (_c = read.keyframes[0]) == null ? void 0 : _c.v;
3340
+ const baseline = (_d = (_b = read.base) != null ? _b : (_a2 = read.keyframes[0]) == null ? void 0 : _a2.value) != null ? _d : (_c = read.keyframes[0]) == null ? void 0 : _c.v;
3092
3341
  if (baseline !== void 0) node[attrName] = toOut(baseline);
3093
3342
  }
3094
3343
  function normaliseKeyframe(kf) {
@@ -3106,12 +3355,12 @@ function normaliseKeyframe(kf) {
3106
3355
  return out;
3107
3356
  }
3108
3357
  function readStaticOrigin(raw, ctx) {
3109
- var _a;
3358
+ var _a2;
3110
3359
  const o = readAnimatable(raw);
3111
3360
  if (o.kind === "absent") return void 0;
3112
3361
  if (o.kind === "static") return o.value;
3113
3362
  ctx.warnings.push("transformBy.origin: animated origin approximated by its first keyframe");
3114
- return (_a = o.keyframes[0]) == null ? void 0 : _a.value;
3363
+ return (_a2 = o.keyframes[0]) == null ? void 0 : _a2.value;
3115
3364
  }
3116
3365
  function keyframeWith(kf, value) {
3117
3366
  const out = { value };
@@ -3217,9 +3466,9 @@ function stripHash2(href) {
3217
3466
  return typeof href === "string" ? href.replace(/^#/, "") : void 0;
3218
3467
  }
3219
3468
  function indexById(node, map) {
3220
- var _a;
3469
+ var _a2;
3221
3470
  if (typeof node.id === "string") map.set(node.id, node);
3222
- (_a = node.children) == null ? void 0 : _a.forEach((child) => indexById(child, map));
3471
+ (_a2 = node.children) == null ? void 0 : _a2.forEach((child) => indexById(child, map));
3223
3472
  }
3224
3473
  function spliceDefs(root, defs) {
3225
3474
  if (!defs.length) return;
@@ -3231,9 +3480,9 @@ function regenerateIdsInClone(root, ctx) {
3231
3480
  return regenerateIdsAndRewriteRefs(root, () => genId(ctx, "retimed"));
3232
3481
  }
3233
3482
  function identifyContentRefTargets(node, ctx, allocator) {
3234
- var _a, _b, _c;
3235
- if (node.type === "use" && ((_b = (_a = node.effects) == null ? void 0 : _a.clone) == null ? void 0 : _b.type) === "content") {
3236
- const sourceId = stripHash2(node.effects.clone.sourceId);
3483
+ var _a2, _b, _c;
3484
+ if (node.type === "use" && ((_b = (_a2 = node.effects) == null ? void 0 : _a2.clone) == null ? void 0 : _b.without) === "translate") {
3485
+ const sourceId = stripHash2(node.effects.clone.source);
3237
3486
  if (typeof sourceId === "string" && sourceId && !ctx.contentRefInnerIds.has(sourceId)) {
3238
3487
  ctx.contentRefInnerIds.set(sourceId, allocator(sourceId));
3239
3488
  }
@@ -3258,10 +3507,10 @@ function splitForContentRef(node, transformBy, originalId, innerId, ctx) {
3258
3507
  return outerWrapper;
3259
3508
  }
3260
3509
  function liftBodyTranslate(node, transformBy) {
3261
- var _a, _b, _c;
3510
+ var _a2, _b, _c;
3262
3511
  const out = {};
3263
3512
  let didLiftAnimate = false;
3264
- const animTr = (_a = node.animate) == null ? void 0 : _a.transform;
3513
+ const animTr = (_a2 = node.animate) == null ? void 0 : _a2.transform;
3265
3514
  if (animTr && typeof animTr === "object" && Array.isArray(animTr.keyframes)) {
3266
3515
  const kfs = animTr.keyframes;
3267
3516
  const hasTranslate = kfs.some((kf) => kf.value && kf.value.translate);
@@ -3330,7 +3579,7 @@ function liftBodyTranslate(node, transformBy) {
3330
3579
  if (split.rest) node.transform = split.rest;
3331
3580
  else delete node.transform;
3332
3581
  }
3333
- } else if (node.transform && typeof node.transform === "object" && !Array.isArray(node.transform) && !node.transform.keyframes && !node.transform.kfs) {
3582
+ } else if (node.transform && typeof node.transform === "object" && !Array.isArray(node.transform) && !node.transform.keyframes) {
3334
3583
  const wrapped = node.transform.value;
3335
3584
  const isWrapped = !!(wrapped && typeof wrapped === "object");
3336
3585
  const value = isWrapped ? wrapped : node.transform;
@@ -3463,12 +3712,12 @@ function synthesiseGradientDef(fx, id, ctx) {
3463
3712
  id
3464
3713
  };
3465
3714
  if (fx.type === PxGradientType.linear) {
3466
- applyGeomVec(out, "x1", "y1", fx.p1);
3467
- applyGeomVec(out, "x2", "y2", fx.p2);
3715
+ applyGeomVec(out, "x1", "y1", fx.start);
3716
+ applyGeomVec(out, "x2", "y2", fx.end);
3468
3717
  } else {
3469
- applyGeomVec(out, "cx", "cy", fx.c);
3470
- applyGeomNumber(out, "r", fx.r);
3471
- applyGeomVec(out, "fx", "fy", fx.fp);
3718
+ applyGeomVec(out, "cx", "cy", fx.center);
3719
+ applyGeomNumber(out, "r", fx.radius);
3720
+ applyGeomVec(out, "fx", "fy", fx.focal);
3472
3721
  }
3473
3722
  if (fx.gradientUnits) out.gradientUnits = fx.gradientUnits;
3474
3723
  if (fx.spreadMethod) out.spreadMethod = fx.spreadMethod;
@@ -3477,7 +3726,7 @@ function synthesiseGradientDef(fx, id, ctx) {
3477
3726
  return out;
3478
3727
  }
3479
3728
  function applyGeomVec(out, xAttr, yAttr, raw) {
3480
- var _a, _b, _c;
3729
+ var _a2, _b, _c;
3481
3730
  const read = readAnimatable(raw);
3482
3731
  if (read.kind === "absent") return;
3483
3732
  if (read.kind === "static") {
@@ -3496,7 +3745,7 @@ function applyGeomVec(out, xAttr, yAttr, raw) {
3496
3745
  if (read.loop !== void 0) block.loop = read.loop;
3497
3746
  return block;
3498
3747
  };
3499
- const animate = (_a = out.animate) != null ? _a : {};
3748
+ const animate = (_a2 = out.animate) != null ? _a2 : {};
3500
3749
  animate[xAttr] = axisChannel(0);
3501
3750
  animate[yAttr] = axisChannel(1);
3502
3751
  out.animate = animate;
@@ -3512,7 +3761,7 @@ function applyGeomNumber(out, attrName, raw) {
3512
3761
  writeAnimatableChannel(out, attrName, read, { asString: true });
3513
3762
  }
3514
3763
  function buildStopChildren(stops, ctx) {
3515
- var _a, _b, _c, _d;
3764
+ var _a2, _b;
3516
3765
  if (!stops) return [];
3517
3766
  const read = readAnimatable(stops);
3518
3767
  if (read.kind === "absent") return [];
@@ -3522,14 +3771,14 @@ function buildStopChildren(stops, ctx) {
3522
3771
  const loopFromSource = read.loop;
3523
3772
  let stopCount = 0;
3524
3773
  for (const kf of kfs) {
3525
- const v = (_a = kf.value) != null ? _a : kf.v;
3774
+ const v = kfValue(kf);
3526
3775
  if (Array.isArray(v) && v.length > stopCount) stopCount = v.length;
3527
3776
  }
3528
3777
  if (!stopCount) return [];
3529
- const firstKfValue = (_b = kfs[0].value) != null ? _b : kfs[0].v;
3778
+ const firstKfValue = kfValue(kfs[0]);
3530
3779
  const baselineStops = [];
3531
3780
  for (let i = 0; i < stopCount; i++) {
3532
- const s = (_d = (_c = firstKfValue == null ? void 0 : firstKfValue[i]) != null ? _c : prevDefinedStop(kfs, 0, i)) != null ? _d : { offset: i / Math.max(1, stopCount - 1), color: "#000000" };
3781
+ const s = (_b = (_a2 = firstKfValue == null ? void 0 : firstKfValue[i]) != null ? _a2 : prevDefinedStop(kfs, 0, i)) != null ? _b : { offset: i / Math.max(1, stopCount - 1), color: "#000000" };
3533
3782
  baselineStops.push({ offset: s.offset, color: s.color });
3534
3783
  }
3535
3784
  return baselineStops.map((bs, i) => animatedStopNode(bs, kfs, i, ctx, loopFromSource));
@@ -3542,16 +3791,16 @@ function staticStopNode(s) {
3542
3791
  };
3543
3792
  }
3544
3793
  function animatedStopNode(baseline, kfs, stopIdx, _ctx, loop) {
3545
- var _a, _b, _c, _d, _e;
3794
+ var _a2;
3546
3795
  const colorKfs = [];
3547
3796
  const offsetKfs = [];
3548
3797
  let offsetVaries = false;
3549
3798
  for (const kf of kfs) {
3550
- const t = (_b = (_a = kf.time) != null ? _a : kf.t) != null ? _b : 0;
3551
- const arr = (_c = kf.value) != null ? _c : kf.v;
3552
- const sliced = (_d = arr == null ? void 0 : arr[stopIdx]) != null ? _d : prevDefinedStop(kfs, kfs.indexOf(kf), stopIdx);
3799
+ const t = kfTime(kf);
3800
+ const arr = kfValue(kf);
3801
+ const sliced = (_a2 = arr == null ? void 0 : arr[stopIdx]) != null ? _a2 : prevDefinedStop(kfs, kfs.indexOf(kf), stopIdx);
3553
3802
  if (!sliced) continue;
3554
- const easing = (_e = kf.easing) != null ? _e : kf.e;
3803
+ const easing = kfEasing(kf);
3555
3804
  const colorOut = { time: t, value: sliced.color };
3556
3805
  if (easing !== void 0) colorOut.easing = easing;
3557
3806
  colorKfs.push(colorOut);
@@ -3578,13 +3827,12 @@ function animatedStopNode(baseline, kfs, stopIdx, _ctx, loop) {
3578
3827
  return stop;
3579
3828
  }
3580
3829
  function prevDefinedStop(kfs, fromIdx, stopIdx) {
3581
- var _a, _b;
3582
3830
  for (let i = fromIdx; i >= 0; i--) {
3583
- const arr = (_a = kfs[i].value) != null ? _a : kfs[i].v;
3831
+ const arr = kfValue(kfs[i]);
3584
3832
  if (arr == null ? void 0 : arr[stopIdx]) return arr[stopIdx];
3585
3833
  }
3586
3834
  for (let i = fromIdx + 1; i < kfs.length; i++) {
3587
- const arr = (_b = kfs[i].value) != null ? _b : kfs[i].v;
3835
+ const arr = kfValue(kfs[i]);
3588
3836
  if (arr == null ? void 0 : arr[stopIdx]) return arr[stopIdx];
3589
3837
  }
3590
3838
  return void 0;
@@ -3594,8 +3842,7 @@ function formatOffset(o) {
3594
3842
  return pct + "%";
3595
3843
  }
3596
3844
  function applyClipPathEffect(node, fx, ctx) {
3597
- var _a, _b;
3598
- if (!fx || !fx.d && !fx.animate) return node;
3845
+ if (!(fx == null ? void 0 : fx.d)) return node;
3599
3846
  const clipId = genId(ctx, "clip");
3600
3847
  const pathChild = { type: "path" };
3601
3848
  const read = readAnimatable(fx.d);
@@ -3607,11 +3854,6 @@ function applyClipPathEffect(node, fx, ctx) {
3607
3854
  if (pathChild.d !== void 0) pathChild.d = pathString(pathChild.d);
3608
3855
  }
3609
3856
  }
3610
- if (fx.animate && !((_a = pathChild.animate) == null ? void 0 : _a.d)) {
3611
- const animate = (_b = pathChild.animate) != null ? _b : {};
3612
- animate.d = fx.animate;
3613
- pathChild.animate = animate;
3614
- }
3615
3857
  ctx.defs.push({ type: "clipPath", id: clipId, children: [pathChild] });
3616
3858
  node.clipPath = "url(#" + clipId + ")";
3617
3859
  return node;
@@ -3623,9 +3865,9 @@ function pathString(v) {
3623
3865
  }
3624
3866
  function applyMaskedByEffect(node, fx, transformBy, ctx) {
3625
3867
  if (!fx) return node;
3626
- const sourceId = stripHash2(fx.sourceId);
3868
+ const sourceId = stripHash2(fx.source);
3627
3869
  if (!sourceId) {
3628
- ctx.errors.push("maskedBy.sourceId missing \u2014 cannot build mask");
3870
+ ctx.errors.push("maskedBy.source missing \u2014 cannot build mask");
3629
3871
  return node;
3630
3872
  }
3631
3873
  const maskId = genId(ctx, "mask");
@@ -3688,16 +3930,16 @@ function invertPartValue(part, value) {
3688
3930
  return [1 / value[0], 1 / value[1]];
3689
3931
  }
3690
3932
  function negatedSpatialTangents(kf) {
3691
- var _a, _b;
3933
+ var _a2, _b;
3692
3934
  const out = {};
3693
- const to = (_a = kf.tangentOut) != null ? _a : kf.to;
3935
+ const to = (_a2 = kf.tangentOut) != null ? _a2 : kf.to;
3694
3936
  const ti = (_b = kf.tangentIn) != null ? _b : kf.ti;
3695
3937
  if (Array.isArray(to)) out.tangentOut = [-to[0], -to[1]];
3696
3938
  if (Array.isArray(ti)) out.tangentIn = [-ti[0], -ti[1]];
3697
3939
  return out;
3698
3940
  }
3699
3941
  function wrapInverseAnimatedBodyTransform(inner, node, _ctx) {
3700
- var _a;
3942
+ var _a2;
3701
3943
  const animate = node.animate && typeof node.animate === "object" && !Array.isArray(node.animate) ? node.animate : void 0;
3702
3944
  const animTr = animate == null ? void 0 : animate.transform;
3703
3945
  const kfs = animTr && typeof animTr === "object" && Array.isArray(animTr.keyframes) ? animTr.keyframes : void 0;
@@ -3706,7 +3948,7 @@ function wrapInverseAnimatedBodyTransform(inner, node, _ctx) {
3706
3948
  const rotateKfs = [];
3707
3949
  const scaleKfs = [];
3708
3950
  for (const kf of kfs) {
3709
- const v = ((_a = kf.value) != null ? _a : kf.v) || {};
3951
+ const v = ((_a2 = kf.value) != null ? _a2 : kf.v) || {};
3710
3952
  const baseKf = keyframeWith(kf, void 0);
3711
3953
  if (Array.isArray(v.translate)) {
3712
3954
  translateKfs.push(__spreadProps2(__spreadValues2(__spreadValues2({}, baseKf), negatedSpatialTangents(kf)), { value: { translate: [-v.translate[0], -v.translate[1]] } }));
@@ -3754,7 +3996,7 @@ function readTransformationFromBody(node) {
3754
3996
  if (parts.origin) out.origin = parts.origin;
3755
3997
  return Object.keys(out).length ? out : void 0;
3756
3998
  }
3757
- if (node.transform && typeof node.transform === "object" && !node.transform.keyframes && !node.transform.kfs) {
3999
+ if (node.transform && typeof node.transform === "object" && !node.transform.keyframes) {
3758
4000
  const wrapped = node.transform.value;
3759
4001
  const value = wrapped && typeof wrapped === "object" ? wrapped : node.transform;
3760
4002
  if (value && typeof value === "object") {
@@ -3770,7 +4012,7 @@ function readTransformationFromBody(node) {
3770
4012
  return void 0;
3771
4013
  }
3772
4014
  function parseTransformStringToParts(s) {
3773
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m;
4015
+ var _a2, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m;
3774
4016
  const re = /([a-zA-Z]+)\s*\(([^)]*)\)/g;
3775
4017
  let m;
3776
4018
  const ops = [];
@@ -3784,7 +4026,7 @@ function parseTransformStringToParts(s) {
3784
4026
  for (let j = ops.length - 2; j >= 0; j--) {
3785
4027
  const cand = ops[j];
3786
4028
  if (cand.name !== "translate") continue;
3787
- const ox = (_a = cand.args[0]) != null ? _a : 0;
4029
+ const ox = (_a2 = cand.args[0]) != null ? _a2 : 0;
3788
4030
  const oy = (_b = cand.args[1]) != null ? _b : 0;
3789
4031
  const lx = (_c = last.args[0]) != null ? _c : 0;
3790
4032
  const ly = (_d = last.args[1]) != null ? _d : 0;
@@ -3899,8 +4141,8 @@ function interpKfs(kfs, t) {
3899
4141
  function collectMaskAncestorChains(root, ctx) {
3900
4142
  const interestingNodes = /* @__PURE__ */ new Set();
3901
4143
  const collectInterestingNodes = (n) => {
3902
- var _a, _b;
3903
- const maskSourceId = stripHash2((_b = (_a = n.effects) == null ? void 0 : _a.maskedBy) == null ? void 0 : _b.sourceId);
4144
+ var _a2, _b;
4145
+ const maskSourceId = stripHash2((_b = (_a2 = n.effects) == null ? void 0 : _a2.maskedBy) == null ? void 0 : _b.source);
3904
4146
  if (typeof maskSourceId === "string") {
3905
4147
  interestingNodes.add(n);
3906
4148
  const sourceNode = ctx.idMap.get(maskSourceId);
@@ -3921,7 +4163,7 @@ function collectMaskAncestorChains(root, ctx) {
3921
4163
  walk(root, []);
3922
4164
  }
3923
4165
  function extractTranslateOnly(node, ctx) {
3924
- var _a, _b, _c;
4166
+ var _a2, _b, _c;
3925
4167
  const tr = node.transform;
3926
4168
  const animateBlock = node.animate && typeof node.animate === "object" && !Array.isArray(node.animate) ? node.animate.transform : void 0;
3927
4169
  if (tr === void 0 && !animateBlock) return void 0;
@@ -3929,7 +4171,7 @@ function extractTranslateOnly(node, ctx) {
3929
4171
  if (typeof tr === "string") {
3930
4172
  const parts = parseTranslateOnlyFromString(tr, ctx);
3931
4173
  if (parts) out.translate = parts;
3932
- } else if (tr && typeof tr === "object" && !tr.keyframes && !tr.kfs) {
4174
+ } else if (tr && typeof tr === "object" && !tr.keyframes) {
3933
4175
  const wrapped = tr.value;
3934
4176
  const value = wrapped && typeof wrapped === "object" ? wrapped : tr;
3935
4177
  if (value && typeof value === "object" && Array.isArray(value.translate)) {
@@ -3943,7 +4185,7 @@ function extractTranslateOnly(node, ctx) {
3943
4185
  const kfs = animateBlock.keyframes;
3944
4186
  const translateKfs = [];
3945
4187
  for (const kf of kfs) {
3946
- const v = (_a = kf.value) != null ? _a : kf.v;
4188
+ const v = (_a2 = kf.value) != null ? _a2 : kf.v;
3947
4189
  const t = (_c = (_b = kf.time) != null ? _b : kf.t) != null ? _c : 0;
3948
4190
  if (v && typeof v === "object" && Array.isArray(v.translate)) {
3949
4191
  translateKfs.push({ time: t, value: [v.translate[0] || 0, v.translate[1] || 0] });
@@ -3976,15 +4218,14 @@ function parseTranslateOnlyFromString(s, ctx) {
3976
4218
  if (droppedNonTranslate) ctx.warnings.push("maskedBy ancestor: non-translate transform in string ignored: " + s);
3977
4219
  return seen ? [x, y] : void 0;
3978
4220
  }
3979
- var CONTENT_SUBREF = "content";
3980
4221
  function applyRefHref(node, clone2, ctx) {
3981
4222
  if (!clone2) return;
3982
- const sourceId = stripHash2(clone2.sourceId);
4223
+ const sourceId = stripHash2(clone2.source);
3983
4224
  if (!sourceId) {
3984
- if (clone2.type === CONTENT_SUBREF) ctx.errors.push("clone: content ref missing sourceId");
4225
+ if (clone2.without === PxCloneWithout.translate) ctx.errors.push("clone: content ref missing `source`");
3985
4226
  return;
3986
4227
  }
3987
- const targetId = clone2.type === CONTENT_SUBREF ? ctx.contentRefInnerIds.get(sourceId) || sourceId : sourceId;
4228
+ const targetId = clone2.without === PxCloneWithout.translate ? ctx.contentRefInnerIds.get(sourceId) || sourceId : sourceId;
3988
4229
  node.href = "#" + targetId;
3989
4230
  }
3990
4231
  function applyRefAndTransformationEffect(node, clone2, transformBy, ctx) {
@@ -3992,9 +4233,9 @@ function applyRefAndTransformationEffect(node, clone2, transformBy, ctx) {
3992
4233
  return applyTransformByEffect(node, transformBy, ctx);
3993
4234
  }
3994
4235
  function applyRepeaterEffect(node, fx, ctx) {
3995
- var _a, _b;
4236
+ var _a2, _b;
3996
4237
  if (!fx) return node;
3997
- const copies = (_a = fx.copies) != null ? _a : 1;
4238
+ const copies = (_a2 = fx.copies) != null ? _a2 : 1;
3998
4239
  if (copies < 1) {
3999
4240
  ctx.errors.push("repeater.copies invalid: " + fx.copies);
4000
4241
  return node;
@@ -4062,8 +4303,8 @@ function synthesiseScale(raw, i) {
4062
4303
  }
4063
4304
  var RETIME_MATERIALISATION_MODE_INLINE_G = false;
4064
4305
  function asRetime(r) {
4065
- var _a, _b;
4066
- return { start: (_a = r.start) != null ? _a : 0, stretch: (_b = r.stretch) != null ? _b : 1 };
4306
+ var _a2, _b;
4307
+ return { start: (_a2 = r.start) != null ? _a2 : 0, stretch: (_b = r.stretch) != null ? _b : 1 };
4067
4308
  }
4068
4309
  var CROP_EDGE_MS = 1;
4069
4310
  function applyTimeCrop(useNode, crop, ctx) {
@@ -4091,12 +4332,12 @@ function concatRetime(child, parent) {
4091
4332
  };
4092
4333
  }
4093
4334
  function readCloneRetime(n) {
4094
- var _a, _b;
4095
- return (_b = (_a = n.effects) == null ? void 0 : _a.clone) == null ? void 0 : _b.retime;
4335
+ var _a2, _b;
4336
+ return (_b = (_a2 = n.effects) == null ? void 0 : _a2.clone) == null ? void 0 : _b.retime;
4096
4337
  }
4097
4338
  function clearCloneRetime(n) {
4098
- var _a;
4099
- const clone2 = (_a = n.effects) == null ? void 0 : _a.clone;
4339
+ var _a2;
4340
+ const clone2 = (_a2 = n.effects) == null ? void 0 : _a2.clone;
4100
4341
  if (!clone2) return;
4101
4342
  delete clone2.retime;
4102
4343
  if (Object.keys(clone2).length === 0) delete n.effects.clone;
@@ -4107,9 +4348,9 @@ function applyAllRetimeEffects(root, ctx) {
4107
4348
  indexById(root, ctx.idMap);
4108
4349
  const sites = [];
4109
4350
  const collect = (n) => {
4110
- var _a;
4351
+ var _a2;
4111
4352
  if (readCloneRetime(n)) sites.push(n);
4112
- (_a = n.children) == null ? void 0 : _a.forEach(collect);
4353
+ (_a2 = n.children) == null ? void 0 : _a2.forEach(collect);
4113
4354
  };
4114
4355
  collect(root);
4115
4356
  const reachCount = /* @__PURE__ */ new Map();
@@ -4117,7 +4358,7 @@ function applyAllRetimeEffects(root, ctx) {
4117
4358
  let count = 0;
4118
4359
  const visited = /* @__PURE__ */ new Set();
4119
4360
  const walk = (n) => {
4120
- var _a;
4361
+ var _a2;
4121
4362
  if (!n) return;
4122
4363
  if (n !== site && readCloneRetime(n)) count++;
4123
4364
  if (n.type === "use" && n.href) {
@@ -4127,7 +4368,7 @@ function applyAllRetimeEffects(root, ctx) {
4127
4368
  walk(ctx.idMap.get(id));
4128
4369
  }
4129
4370
  }
4130
- (_a = n.children) == null ? void 0 : _a.forEach(walk);
4371
+ (_a2 = n.children) == null ? void 0 : _a2.forEach(walk);
4131
4372
  };
4132
4373
  const rootId = stripHash2(site.href);
4133
4374
  if (rootId) {
@@ -4137,8 +4378,8 @@ function applyAllRetimeEffects(root, ctx) {
4137
4378
  reachCount.set(site, count);
4138
4379
  }
4139
4380
  sites.sort((a, b) => {
4140
- var _a, _b;
4141
- return ((_a = reachCount.get(b)) != null ? _a : 0) - ((_b = reachCount.get(a)) != null ? _b : 0);
4381
+ var _a2, _b;
4382
+ return ((_a2 = reachCount.get(b)) != null ? _a2 : 0) - ((_b = reachCount.get(a)) != null ? _b : 0);
4142
4383
  });
4143
4384
  for (const useNode of sites) {
4144
4385
  const retime = readCloneRetime(useNode);
@@ -4205,7 +4446,7 @@ function buildChainClone(targetId, accum, ctx, chain) {
4205
4446
  }
4206
4447
  function materialiseNestedRetimeUses(node, accum, ctx, chain, parentTargetId) {
4207
4448
  const visit = (n) => {
4208
- var _a;
4449
+ var _a2;
4209
4450
  const retime = readCloneRetime(n);
4210
4451
  if (n.type === "use" && retime && n.href) {
4211
4452
  const subId = stripHash2(n.href);
@@ -4218,14 +4459,14 @@ function materialiseNestedRetimeUses(node, accum, ctx, chain, parentTargetId) {
4218
4459
  }
4219
4460
  clearCloneRetime(n);
4220
4461
  }
4221
- (_a = n.children) == null ? void 0 : _a.forEach(visit);
4462
+ (_a2 = n.children) == null ? void 0 : _a2.forEach(visit);
4222
4463
  };
4223
4464
  visit(node);
4224
4465
  }
4225
4466
  function remapKeyframeTimes(node, start, stretch) {
4226
- var _a;
4467
+ var _a2;
4227
4468
  remapKeyframeTimesOnly(node, start, stretch);
4228
- (_a = node.children) == null ? void 0 : _a.forEach((c) => remapKeyframeTimes(c, start, stretch));
4469
+ (_a2 = node.children) == null ? void 0 : _a2.forEach((c) => remapKeyframeTimes(c, start, stretch));
4229
4470
  }
4230
4471
  function remapKeyframeTimesOnly(node, start, stretch) {
4231
4472
  const remap2 = (kfs) => {
@@ -4400,8 +4641,8 @@ function numRange(v) {
4400
4641
  function estimateTextAdvance(node) {
4401
4642
  let chars = 0, maxFont = 16;
4402
4643
  const walk = (el) => {
4403
- var _a, _b;
4404
- const fs = parseFloat(String((_a = el.fontSize) != null ? _a : "")) || 0;
4644
+ var _a2, _b;
4645
+ const fs = parseFloat(String((_a2 = el.fontSize) != null ? _a2 : "")) || 0;
4405
4646
  if (fs) maxFont = Math.max(maxFont, fs);
4406
4647
  const t = (_b = el.text) != null ? _b : el.textContent;
4407
4648
  if (typeof t === "string") chars += t.length;
@@ -4425,14 +4666,14 @@ function shiftAnimatable(v, by) {
4425
4666
  return out;
4426
4667
  }
4427
4668
  function extendedPathForBrowser(pathD, opts) {
4428
- var _a;
4669
+ var _a2;
4429
4670
  if (opts.pathOverflow === "clip") return { d: pathD, startShift: 0 };
4430
4671
  const sampler = createPathSampler(pathD);
4431
4672
  if (!sampler || sampler.closed || sampler.totalLength <= 0) return { d: pathD, startShift: 0 };
4432
4673
  const L = sampler.totalLength;
4433
4674
  const margin = EXTEND_MARGIN_FRAC * L;
4434
4675
  const so = numRange(opts.startOffset);
4435
- const runWidth = numRange(opts.textLength).max || ((_a = opts.advance) != null ? _a : 0);
4676
+ const runWidth = numRange(opts.textLength).max || ((_a2 = opts.advance) != null ? _a2 : 0);
4436
4677
  const startOverflow = Math.max(0, -so.min);
4437
4678
  const endOverflow = Math.max(0, so.max + runWidth - L);
4438
4679
  const startExt = startOverflow > 0 ? startOverflow + margin : 0;
@@ -4453,10 +4694,10 @@ function extendedPathForBrowser(pathD, opts) {
4453
4694
  return { d, startShift: startExt };
4454
4695
  }
4455
4696
  function applyTextPathEffect(node, fx, ctx) {
4456
- var _a;
4457
- if (!fx || typeof fx.path !== "string" || !fx.path) return node;
4697
+ var _a2;
4698
+ if (!fx || typeof fx.pathData !== "string" || !fx.pathData) return node;
4458
4699
  const pathId = genId(ctx, "tpath");
4459
- const { d, startShift } = extendedPathForBrowser(fx.path, {
4700
+ const { d, startShift } = extendedPathForBrowser(fx.pathData, {
4460
4701
  pathOverflow: fx.pathOverflow,
4461
4702
  startOffset: fx.startOffset,
4462
4703
  textLength: fx.textLength,
@@ -4466,7 +4707,7 @@ function applyTextPathEffect(node, fx, ctx) {
4466
4707
  const textPath = {
4467
4708
  type: "textPath",
4468
4709
  href: "#" + pathId,
4469
- children: (_a = node.children) != null ? _a : []
4710
+ children: (_a2 = node.children) != null ? _a2 : []
4470
4711
  };
4471
4712
  if (fx.lengthAdjust !== void 0) textPath.lengthAdjust = fx.lengthAdjust;
4472
4713
  if (fx.method !== void 0) textPath.method = fx.method;
@@ -4590,15 +4831,15 @@ function paintAnimateOf(node) {
4590
4831
  return out;
4591
4832
  }
4592
4833
  function resolveStyle2(node, parent) {
4593
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
4834
+ var _a2, _b, _c, _d, _e, _f, _g, _h, _i, _j;
4594
4835
  const isTextRoot = node.type === "text";
4595
4836
  const nodeStyle = node.style;
4596
4837
  const own = (key) => {
4597
- var _a2;
4598
- return isTextRoot ? void 0 : (_a2 = node[key]) != null ? _a2 : nodeStyle == null ? void 0 : nodeStyle[key];
4838
+ var _a3;
4839
+ return isTextRoot ? void 0 : (_a3 = node[key]) != null ? _a3 : nodeStyle == null ? void 0 : nodeStyle[key];
4599
4840
  };
4600
4841
  const res = {
4601
- fontFamily: (_a = str(node.fontFamily)) != null ? _a : parent.fontFamily,
4842
+ fontFamily: (_a2 = str(node.fontFamily)) != null ? _a2 : parent.fontFamily,
4602
4843
  fontSize: (_b = parseLen(node.fontSize)) != null ? _b : parent.fontSize,
4603
4844
  fill: (_c = node.fill) != null ? _c : parent.fill,
4604
4845
  stroke: (_d = node.stroke) != null ? _d : parent.stroke,
@@ -4615,10 +4856,10 @@ function resolveStyle2(node, parent) {
4615
4856
  return res;
4616
4857
  }
4617
4858
  function rootStyleOf(node) {
4618
- var _a, _b, _c;
4859
+ var _a2, _b, _c;
4619
4860
  return {
4620
4861
  fontFamily: str(node.fontFamily),
4621
- fontSize: (_a = parseLen(node.fontSize)) != null ? _a : DEFAULT_FONT_SIZE,
4862
+ fontSize: (_a2 = parseLen(node.fontSize)) != null ? _a2 : DEFAULT_FONT_SIZE,
4622
4863
  fill: node.fill,
4623
4864
  stroke: node.stroke,
4624
4865
  strokeWidth: node.strokeWidth,
@@ -4639,9 +4880,9 @@ function paintOf(s) {
4639
4880
  return p;
4640
4881
  }
4641
4882
  function glyphFontFor(s, glyphs, soleFont, warnings) {
4642
- var _a;
4883
+ var _a2;
4643
4884
  const gf = s.fontFamily ? glyphs[s.fontFamily] : soleFont;
4644
- if (!gf) warnings == null ? void 0 : warnings.push('textGlyphs: no glyphs for font "' + ((_a = s.fontFamily) != null ? _a : "") + '"');
4885
+ if (!gf) warnings == null ? void 0 : warnings.push('textGlyphs: no glyphs for font "' + ((_a2 = s.fontFamily) != null ? _a2 : "") + '"');
4645
4886
  return gf;
4646
4887
  }
4647
4888
  function soleFontOf(glyphs) {
@@ -4663,19 +4904,19 @@ function missingGlyphBoxEm(advanceEm, ascentEm) {
4663
4904
  return outer + "M" + ix0 + " " + iyb + "L" + ix0 + " " + iyt + "L" + ix1 + " " + iyt + "L" + ix1 + " " + iyb + "Z";
4664
4905
  }
4665
4906
  function materialiseGlyphTextHorizontal(node, opts) {
4666
- var _a, _b, _c, _d;
4907
+ var _a2, _b, _c, _d;
4667
4908
  const { glyphs, create = jsonElementFactory, warnings } = opts;
4668
4909
  const soleFont = soleFontOf(glyphs);
4669
- const pen = { x: (_a = parseLen(node.x)) != null ? _a : 0, y: (_b = parseLen(node.y)) != null ? _b : 0 };
4910
+ const pen = { x: (_a2 = parseLen(node.x)) != null ? _a2 : 0, y: (_b = parseLen(node.y)) != null ? _b : 0 };
4670
4911
  const placements = [];
4671
4912
  const lines = [{ start: pen.x, end: pen.x }];
4672
4913
  let line = 0;
4673
4914
  const renderChars = (content, s) => {
4674
- var _a2;
4915
+ var _a3;
4675
4916
  const gf = glyphFontFor(s, glyphs, soleFont, warnings);
4676
4917
  const upm = (gf == null ? void 0 : gf.unitsPerEm) || 1e3;
4677
4918
  const scale = s.fontSize / upm;
4678
- const ascentEm = (_a2 = gf == null ? void 0 : gf.ascent) != null ? _a2 : 0.9 * upm;
4919
+ const ascentEm = (_a3 = gf == null ? void 0 : gf.ascent) != null ? _a3 : 0.9 * upm;
4679
4920
  const paint = paintOf(s);
4680
4921
  for (let i = 0; i < content.length; i++) {
4681
4922
  const ch = content.charAt(i);
@@ -4695,7 +4936,7 @@ function materialiseGlyphTextHorizontal(node, opts) {
4695
4936
  }
4696
4937
  };
4697
4938
  const walk = (el, parentStyle) => {
4698
- var _a2, _b2, _c2, _d2;
4939
+ var _a3, _b2, _c2, _d2;
4699
4940
  const s = resolveStyle2(el, parentStyle);
4700
4941
  const x = parseLen(el.x);
4701
4942
  const y = parseLen(el.y);
@@ -4705,7 +4946,7 @@ function materialiseGlyphTextHorizontal(node, opts) {
4705
4946
  lines.push({ start: pen.x, end: pen.x });
4706
4947
  }
4707
4948
  if (y !== void 0) pen.y = y;
4708
- pen.x += (_a2 = parseLen(el.dx)) != null ? _a2 : 0;
4949
+ pen.x += (_a3 = parseLen(el.dx)) != null ? _a3 : 0;
4709
4950
  pen.y += (_b2 = parseLen(el.dy)) != null ? _b2 : 0;
4710
4951
  const content = (_c2 = str(el[TEXT_CONTENT_ATTR])) != null ? _c2 : str(el[TEXT_ATTR]);
4711
4952
  if (content && !((_d2 = el.children) == null ? void 0 : _d2.length)) renderChars(content, s);
@@ -4726,8 +4967,8 @@ function materialiseGlyphTextHorizontal(node, opts) {
4726
4967
  return toGroup(node, buildPaths(placements, create, warnings), create);
4727
4968
  }
4728
4969
  function layoutGlyphTextChars(node, opts) {
4729
- var _a, _b, _c, _d, _e, _f;
4730
- if ((_a = opts.alongPath) == null ? void 0 : _a.pathD) return layoutGlyphTextCharsAlongPath(node, opts.alongPath.pathD, opts);
4970
+ var _a2, _b, _c, _d, _e, _f;
4971
+ if ((_a2 = opts.alongPath) == null ? void 0 : _a2.pathD) return layoutGlyphTextCharsAlongPath(node, opts.alongPath.pathD, opts);
4731
4972
  const { glyphs, warnings } = opts;
4732
4973
  const soleFont = soleFontOf(glyphs);
4733
4974
  const pen = { x: (_b = parseLen(node.x)) != null ? _b : 0, y: (_c = parseLen(node.y)) != null ? _c : 0 };
@@ -4735,11 +4976,11 @@ function layoutGlyphTextChars(node, opts) {
4735
4976
  const lines = [{ start: pen.x, end: pen.x }];
4736
4977
  let line = 0;
4737
4978
  const renderChars = (content, s) => {
4738
- var _a2;
4979
+ var _a3;
4739
4980
  const gf = glyphFontFor(s, glyphs, soleFont, warnings);
4740
4981
  const upm = (gf == null ? void 0 : gf.unitsPerEm) || 1e3;
4741
4982
  const scale = s.fontSize / upm;
4742
- const ascent = ((_a2 = gf == null ? void 0 : gf.ascent) != null ? _a2 : 0.9 * upm) * scale;
4983
+ const ascent = ((_a3 = gf == null ? void 0 : gf.ascent) != null ? _a3 : 0.9 * upm) * scale;
4743
4984
  for (let i = 0; i < content.length; i++) {
4744
4985
  const ch = content.charAt(i);
4745
4986
  const g = gf == null ? void 0 : gf.glyphs[ch];
@@ -4750,7 +4991,7 @@ function layoutGlyphTextChars(node, opts) {
4750
4991
  }
4751
4992
  };
4752
4993
  const walk = (el, parentStyle) => {
4753
- var _a2, _b2, _c2, _d2;
4994
+ var _a3, _b2, _c2, _d2;
4754
4995
  const s = resolveStyle2(el, parentStyle);
4755
4996
  const x = parseLen(el.x);
4756
4997
  const y = parseLen(el.y);
@@ -4760,7 +5001,7 @@ function layoutGlyphTextChars(node, opts) {
4760
5001
  lines.push({ start: pen.x, end: pen.x });
4761
5002
  }
4762
5003
  if (y !== void 0) pen.y = y;
4763
- pen.x += (_a2 = parseLen(el.dx)) != null ? _a2 : 0;
5004
+ pen.x += (_a3 = parseLen(el.dx)) != null ? _a3 : 0;
4764
5005
  pen.y += (_b2 = parseLen(el.dy)) != null ? _b2 : 0;
4765
5006
  const content = (_c2 = str(el[TEXT_CONTENT_ATTR])) != null ? _c2 : str(el[TEXT_ATTR]);
4766
5007
  if (content && !((_d2 = el.children) == null ? void 0 : _d2.length)) renderChars(content, s);
@@ -4792,7 +5033,7 @@ function layoutGlyphTextChars(node, opts) {
4792
5033
  });
4793
5034
  }
4794
5035
  function layoutGlyphTextCharsAlongPath(node, pathD, opts) {
4795
- var _a, _b;
5036
+ var _a2, _b;
4796
5037
  const { glyphs, warnings, alongPath } = opts;
4797
5038
  const sampler = createPathSampler(pathD);
4798
5039
  if (!sampler) {
@@ -4803,9 +5044,9 @@ function layoutGlyphTextCharsAlongPath(node, pathD, opts) {
4803
5044
  const chars = [];
4804
5045
  let adv = 0;
4805
5046
  const walk = (el, parentStyle) => {
4806
- var _a2, _b2, _c;
5047
+ var _a3, _b2, _c;
4807
5048
  const s = resolveStyle2(el, parentStyle);
4808
- const content = (_a2 = str(el[TEXT_CONTENT_ATTR])) != null ? _a2 : str(el[TEXT_ATTR]);
5049
+ const content = (_a3 = str(el[TEXT_CONTENT_ATTR])) != null ? _a3 : str(el[TEXT_ATTR]);
4809
5050
  if (content && !((_b2 = el.children) == null ? void 0 : _b2.length)) {
4810
5051
  const gf = glyphFontFor(s, glyphs, soleFont, warnings);
4811
5052
  const upm = (gf == null ? void 0 : gf.unitsPerEm) || 1e3;
@@ -4825,7 +5066,7 @@ function layoutGlyphTextCharsAlongPath(node, pathD, opts) {
4825
5066
  walk(node, rootStyleOf(node));
4826
5067
  const width = adv;
4827
5068
  const tlr = readAnimatable(alongPath == null ? void 0 : alongPath.textLength);
4828
- const tlv = tlr.kind === "animated" ? Number((_a = tlr.keyframes[0]) == null ? void 0 : _a.value) || 0 : tlr.kind === "static" ? Number(tlr.value) || 0 : 0;
5069
+ const tlv = tlr.kind === "animated" ? Number((_a2 = tlr.keyframes[0]) == null ? void 0 : _a2.value) || 0 : tlr.kind === "static" ? Number(tlr.value) || 0 : 0;
4829
5070
  const k = tlv > 0 && width > 0 ? tlv / width : 1;
4830
5071
  const so = readAnimatable(alongPath == null ? void 0 : alongPath.startOffset);
4831
5072
  const { along: alongOffset, perp } = alongPathNodeOffsets(node);
@@ -4857,9 +5098,9 @@ function collectAlongPathCells(node, glyphs, soleFont, warnings) {
4857
5098
  const cells = [];
4858
5099
  let adv = 0;
4859
5100
  const walk = (el, parentStyle) => {
4860
- var _a, _b, _c;
5101
+ var _a2, _b, _c;
4861
5102
  const s = resolveStyle2(el, parentStyle);
4862
- const content = (_a = str(el[TEXT_CONTENT_ATTR])) != null ? _a : str(el[TEXT_ATTR]);
5103
+ const content = (_a2 = str(el[TEXT_CONTENT_ATTR])) != null ? _a2 : str(el[TEXT_ATTR]);
4863
5104
  if (content && !((_b = el.children) == null ? void 0 : _b.length)) {
4864
5105
  const gf = glyphFontFor(s, glyphs, soleFont, warnings);
4865
5106
  if (gf) {
@@ -4896,9 +5137,9 @@ function alongAffine(sampler, dist, scale, widthEm, perp = 0) {
4896
5137
  return [scale * cos, scale * sin, -scale * sin, scale * cos, x - scale * cos * hw - perp * sin, y - scale * sin * hw + perp * cos];
4897
5138
  }
4898
5139
  function alongPathNodeOffsets(node) {
4899
- var _a, _b, _c;
5140
+ var _a2, _b, _c;
4900
5141
  return {
4901
- along: ((_a = parseLen(node.x)) != null ? _a : 0) + ((_b = parseLen(node.dx)) != null ? _b : 0),
5142
+ along: ((_a2 = parseLen(node.x)) != null ? _a2 : 0) + ((_b = parseLen(node.dx)) != null ? _b : 0),
4902
5143
  perp: (_c = parseLen(node.dy)) != null ? _c : 0
4903
5144
  };
4904
5145
  }
@@ -4938,7 +5179,7 @@ function materialiseGlyphTextAlongPath(node, pathD, startOffset, opts, textLengt
4938
5179
  return toGroup(node, buildPaths(placements, create, warnings), create);
4939
5180
  }
4940
5181
  function numTrackOf(raw) {
4941
- var _a;
5182
+ var _a2;
4942
5183
  const r = readAnimatable(raw);
4943
5184
  if (r.kind === "animated" && r.keyframes.length >= 2) {
4944
5185
  const kfs = [...r.keyframes].sort((k1, k2) => (Number(k1.time) || 0) - (Number(k2.time) || 0));
@@ -4961,7 +5202,7 @@ function numTrackOf(raw) {
4961
5202
  }
4962
5203
  };
4963
5204
  }
4964
- const v = r.kind === "animated" ? Number((_a = r.keyframes[0]) == null ? void 0 : _a.value) || 0 : r.kind === "static" ? Number(r.value) || 0 : 0;
5205
+ const v = r.kind === "animated" ? Number((_a2 = r.keyframes[0]) == null ? void 0 : _a2.value) || 0 : r.kind === "static" ? Number(r.value) || 0 : 0;
4965
5206
  return { animated: false, times: [], at: () => v };
4966
5207
  }
4967
5208
  function mergeTrackTimes(a, b) {
@@ -5043,7 +5284,7 @@ function paintProps(paint) {
5043
5284
  return p;
5044
5285
  }
5045
5286
  function missingGlyphProps(isMissing) {
5046
- return isMissing ? { class: MISSING_GLYPH_CLASS_NAME } : {};
5287
+ return isMissing ? { [CLASS_ATTR]: MISSING_GLYPH_CLASS_NAME } : {};
5047
5288
  }
5048
5289
  function buildPaths(placements, create, warnings) {
5049
5290
  if (!placements.length) {
@@ -5087,14 +5328,14 @@ function materialiseGlyphText(node, opts) {
5087
5328
  function applyTextGlyphsEffect(node, fx, ctx) {
5088
5329
  if (!(fx == null ? void 0 : fx.useGlyphs)) return node;
5089
5330
  if (!ctx.glyphs) {
5090
- ctx.warnings.push("textGlyphs: no definitions.glyphs \u2014 left as native <text>");
5331
+ ctx.warnings.push("textGlyphs: no definitions.fonts \u2014 left as native <text>");
5091
5332
  return node;
5092
5333
  }
5093
5334
  return materialiseGlyphTextHorizontal(node, { glyphs: ctx.glyphs, warnings: ctx.warnings });
5094
5335
  }
5095
5336
  function applyTextGlyphsAlongPath(node, ctx, pathD, startOffset, textLength, pathOverflow) {
5096
5337
  if (!ctx.glyphs) {
5097
- ctx.warnings.push("textGlyphs: no definitions.glyphs");
5338
+ ctx.warnings.push("textGlyphs: no definitions.fonts");
5098
5339
  return null;
5099
5340
  }
5100
5341
  return materialiseGlyphTextAlongPath(node, pathD, startOffset, { glyphs: ctx.glyphs, warnings: ctx.warnings }, textLength, pathOverflow);
@@ -5234,12 +5475,11 @@ function getOffsetIndexRange(minMaxOffset) {
5234
5475
  ];
5235
5476
  }
5236
5477
  function readScalarValues(r) {
5237
- var _a;
5238
5478
  if (r.kind === "absent") return [];
5239
5479
  if (r.kind === "static") return [r.value];
5240
5480
  const out = [];
5241
5481
  for (const kf of r.keyframes) {
5242
- const v = (_a = kf.value) != null ? _a : kf.v;
5482
+ const v = kfValue(kf);
5243
5483
  if (typeof v === "number") out.push(v);
5244
5484
  }
5245
5485
  return out;
@@ -5249,14 +5489,11 @@ function computeAnimAttr(read, map) {
5249
5489
  if (read.kind === "static") return { kind: "static", value: map(read.value) };
5250
5490
  return {
5251
5491
  kind: "animated",
5252
- keyframes: read.keyframes.map((kf) => {
5253
- var _a, _b, _c, _d;
5254
- return {
5255
- time: (_b = (_a = kf.time) != null ? _a : kf.t) != null ? _b : 0,
5256
- value: map((_c = kf.value) != null ? _c : kf.v),
5257
- easing: (_d = kf.easing) != null ? _d : kf.e
5258
- };
5259
- }),
5492
+ keyframes: read.keyframes.map((kf) => ({
5493
+ time: kfTime(kf),
5494
+ value: map(kfValue(kf)),
5495
+ easing: kfEasing(kf)
5496
+ })),
5260
5497
  loop: read.loop
5261
5498
  };
5262
5499
  }
@@ -5266,7 +5503,6 @@ function applyAttr(node, attrName, attr) {
5266
5503
  }
5267
5504
  var OPACITY_STEP_MS = 10;
5268
5505
  function computeOpacityFromRange(rangeRead) {
5269
- var _a, _b, _c, _d, _e, _f;
5270
5506
  const hide = (v) => v[0] === v[1];
5271
5507
  if (rangeRead.kind === "absent") return void 0;
5272
5508
  if (rangeRead.kind === "static") return hide(rangeRead.value) ? { kind: "static", value: 0 } : void 0;
@@ -5274,7 +5510,7 @@ function computeOpacityFromRange(rangeRead) {
5274
5510
  let anyHide = false;
5275
5511
  let allHide = true;
5276
5512
  for (const kf of kfs) {
5277
- if (hide((_a = kf.value) != null ? _a : kf.v)) anyHide = true;
5513
+ if (hide(kfValue(kf))) anyHide = true;
5278
5514
  else allHide = false;
5279
5515
  }
5280
5516
  if (!anyHide) return void 0;
@@ -5284,10 +5520,10 @@ function computeOpacityFromRange(rangeRead) {
5284
5520
  const kf = kfs[i];
5285
5521
  const prevKf = i > 0 ? kfs[i - 1] : void 0;
5286
5522
  const nextKf = i < kfs.length - 1 ? kfs[i + 1] : void 0;
5287
- const t = (_c = (_b = kf.time) != null ? _b : kf.t) != null ? _c : 0;
5288
- const thisHide = hide((_d = kf.value) != null ? _d : kf.v);
5289
- const prevHide = prevKf ? thisHide && hide((_e = prevKf.value) != null ? _e : prevKf.v) : thisHide;
5290
- const nextHide = nextKf ? thisHide && hide((_f = nextKf.value) != null ? _f : nextKf.v) : thisHide;
5523
+ const t = kfTime(kf);
5524
+ const thisHide = hide(kfValue(kf));
5525
+ const prevHide = prevKf ? thisHide && hide(kfValue(prevKf)) : thisHide;
5526
+ const nextHide = nextKf ? thisHide && hide(kfValue(nextKf)) : thisHide;
5291
5527
  if (prevHide && !nextHide) {
5292
5528
  out.push({ time: t, value: 0 });
5293
5529
  out.push({ time: t + OPACITY_STEP_MS, value: 1 });
@@ -5302,14 +5538,11 @@ function computeOpacityFromRange(rangeRead) {
5302
5538
  function readRangeWithCrossings(raw) {
5303
5539
  const r = readAnimatable(raw);
5304
5540
  if (r.kind !== "animated") return r;
5305
- const kfs = r.keyframes.map((kf) => {
5306
- var _a, _b, _c, _d;
5307
- return {
5308
- time: (_b = (_a = kf.time) != null ? _a : kf.t) != null ? _b : 0,
5309
- value: (_c = kf.value) != null ? _c : kf.v,
5310
- easing: (_d = kf.easing) != null ? _d : kf.e
5311
- };
5312
- });
5541
+ const kfs = r.keyframes.map((kf) => ({
5542
+ time: kfTime(kf),
5543
+ value: kfValue(kf),
5544
+ easing: kfEasing(kf)
5545
+ }));
5313
5546
  const hasReverse = kfs.some((kf) => kf.value[0] > kf.value[1]);
5314
5547
  if (!hasReverse) {
5315
5548
  return {
@@ -5406,20 +5639,20 @@ function pxBezierPathLength(path) {
5406
5639
  return total;
5407
5640
  }
5408
5641
  function segmentLength(path, from, to) {
5409
- var _a, _b, _c, _d;
5642
+ var _a2, _b, _c, _d;
5410
5643
  const v = path.v;
5411
5644
  const p0 = v[from];
5412
5645
  const p3 = v[to];
5413
- const p1 = (_b = (_a = path.o) == null ? void 0 : _a[from]) != null ? _b : p0;
5646
+ const p1 = (_b = (_a2 = path.o) == null ? void 0 : _a2[from]) != null ? _b : p0;
5414
5647
  const p2 = (_d = (_c = path.i) == null ? void 0 : _c[to]) != null ? _d : p3;
5415
5648
  const lut = bezier2D_arcLengthLUT(p0, p1, p2, p3);
5416
5649
  return lut.ds[lut.ds.length - 1];
5417
5650
  }
5418
5651
  var ARC_KAPPA = 0.5522847498307936;
5419
5652
  function shapeToPathD(node) {
5420
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
5653
+ var _a2, _b, _c, _d, _e, _f, _g, _h, _i, _j;
5421
5654
  if (node.type === "rect") {
5422
- const x = Number((_a = node.x) != null ? _a : 0), y = Number((_b = node.y) != null ? _b : 0);
5655
+ const x = Number((_a2 = node.x) != null ? _a2 : 0), y = Number((_b = node.y) != null ? _b : 0);
5423
5656
  const w = Number((_c = node.width) != null ? _c : 0), h = Number((_d = node.height) != null ? _d : 0);
5424
5657
  return "M" + (x + w) + "," + y + "L" + (x + w) + "," + (y + h) + "L" + x + "," + (y + h) + "L" + x + "," + y + "L" + (x + w) + "," + y + "z";
5425
5658
  }
@@ -5435,7 +5668,7 @@ function shapeToPathD(node) {
5435
5668
  return void 0;
5436
5669
  }
5437
5670
  function applyPlayerEffects(root) {
5438
- var _a, _b;
5671
+ var _a2, _b;
5439
5672
  const ctx = {
5440
5673
  defs: [],
5441
5674
  warnings: [],
@@ -5446,8 +5679,8 @@ function applyPlayerEffects(root) {
5446
5679
  maskAncestorChains: /* @__PURE__ */ new Map(),
5447
5680
  // Resolved engine: `frames` ONLY when explicitly set; auto/waapi/unset →
5448
5681
  // waapi (we're not 100% sure it's frames, and CSS/WAAPI need the inline form).
5449
- engine: ((_a = getAnimatorConfig(root)) == null ? void 0 : _a.mode) === PxAnimatorMode.frames ? PxAnimatorEngine.frames : PxAnimatorEngine.waapi,
5450
- glyphs: (_b = getDefs(root)) == null ? void 0 : _b.glyphs
5682
+ engine: resolveTimelineEngine((_a2 = getAnimatorConfig(root)) == null ? void 0 : _a2.engine),
5683
+ glyphs: (_b = getDefs(root)) == null ? void 0 : _b.fonts
5451
5684
  };
5452
5685
  const working = clone(root);
5453
5686
  indexById(working, ctx.idMap);
@@ -5470,7 +5703,7 @@ function applyPlayerEffects_exceptRetime(node, ctx) {
5470
5703
  let consumedByGlyphs = false;
5471
5704
  if (text == null ? void 0 : text.useGlyphs) {
5472
5705
  if (textPath) {
5473
- const pathD = typeof textPath.path === "string" ? textPath.path : void 0;
5706
+ const pathD = typeof textPath.pathData === "string" ? textPath.pathData : void 0;
5474
5707
  const glyphed = applyTextGlyphsAlongPath(n, ctx, pathD, textPath.startOffset, textPath.textLength, textPath.pathOverflow);
5475
5708
  if (glyphed) {
5476
5709
  n = glyphed;
@@ -5502,26 +5735,6 @@ function applyPlayerEffects_retime(node, ctx) {
5502
5735
  applyAllRetimeEffects(node, ctx);
5503
5736
  return node;
5504
5737
  }
5505
- var kfTime = (kf) => {
5506
- var _a, _b;
5507
- return (_b = (_a = kf.t) != null ? _a : kf.time) != null ? _b : 0;
5508
- };
5509
- var kfValue = (kf) => {
5510
- var _a;
5511
- return (_a = kf.v) != null ? _a : kf.value;
5512
- };
5513
- var kfEasing = (kf) => {
5514
- var _a;
5515
- return (_a = kf.e) != null ? _a : kf.easing;
5516
- };
5517
- var kfTangentIn = (kf) => {
5518
- var _a;
5519
- return (_a = kf.tangentIn) != null ? _a : kf.ti;
5520
- };
5521
- var kfTangentOut = (kf) => {
5522
- var _a;
5523
- return (_a = kf.tangentOut) != null ? _a : kf.to;
5524
- };
5525
5738
  function cubicAt(p0, c1, c2, p1, t) {
5526
5739
  const u = 1 - t;
5527
5740
  const a = u * u * u, b = 3 * u * u * t, c = 3 * u * t * t, d = t * t * t;
@@ -5545,9 +5758,9 @@ var fmt2 = (n) => {
5545
5758
  return Object.is(r, -0) ? "0" : String(r);
5546
5759
  };
5547
5760
  function buildOffsetPath(propAnim) {
5548
- var _a, _b, _c, _d;
5761
+ var _a2, _b, _c;
5549
5762
  if (propAnim.alongPathMode !== "offsetPath") return void 0;
5550
- const kfs = (_a = propAnim.keyframes) != null ? _a : propAnim.kfs;
5763
+ const kfs = propAnim.keyframes;
5551
5764
  if (!kfs || kfs.length < 2) return void 0;
5552
5765
  const first = kfValue(kfs[0]);
5553
5766
  const anchor = (first == null ? void 0 : first.origin) && first.origin.length >= 2 ? [first.origin[0], first.origin[1]] : [0, 0];
@@ -5558,7 +5771,7 @@ function buildOffsetPath(propAnim) {
5558
5771
  if (!tr || tr.length < 2) return void 0;
5559
5772
  const parts = Object.keys(v);
5560
5773
  if (parts.some((p) => p !== "translate" && p !== "origin")) return void 0;
5561
- const o = (_b = v == null ? void 0 : v.origin) != null ? _b : [0, 0];
5774
+ const o = (_a2 = v == null ? void 0 : v.origin) != null ? _a2 : [0, 0];
5562
5775
  if (o[0] !== anchor[0] || o[1] !== anchor[1]) return void 0;
5563
5776
  points.push([tr[0] + anchor[0], tr[1] + anchor[1]]);
5564
5777
  }
@@ -5567,8 +5780,8 @@ function buildOffsetPath(propAnim) {
5567
5780
  const segLens = [];
5568
5781
  for (let i = 0; i < points.length - 1; i++) {
5569
5782
  const p0 = points[i], p1 = points[i + 1];
5570
- const to = (_c = kfTangentOut(kfs[i])) != null ? _c : [0, 0];
5571
- const ti = (_d = kfTangentIn(kfs[i + 1])) != null ? _d : [0, 0];
5783
+ const to = (_b = kfTangentOut(kfs[i])) != null ? _b : [0, 0];
5784
+ const ti = (_c = kfTangentIn(kfs[i + 1])) != null ? _c : [0, 0];
5572
5785
  const c1 = [p0[0] + to[0], p0[1] + to[1]];
5573
5786
  const c2 = [p1[0] + ti[0], p1[1] + ti[1]];
5574
5787
  d += "C" + fmt2(c1[0]) + "," + fmt2(c1[1]) + "," + fmt2(c2[0]) + "," + fmt2(c2[1]) + "," + fmt2(p1[0]) + "," + fmt2(p1[1]);
@@ -5589,7 +5802,7 @@ function buildOffsetPath(propAnim) {
5589
5802
  }
5590
5803
  function materialiseOffsetPathsInTree(root) {
5591
5804
  const walk = (node) => {
5592
- var _a;
5805
+ var _a2;
5593
5806
  let out = node;
5594
5807
  const anim = node.animate;
5595
5808
  const transform = anim == null ? void 0 : anim["transform"];
@@ -5597,16 +5810,16 @@ function materialiseOffsetPathsInTree(root) {
5597
5810
  const built = buildOffsetPath(transform);
5598
5811
  if (built) {
5599
5812
  const newAnimate = __spreadValues2({}, anim);
5600
- delete newAnimate["transform"];
5813
+ delete newAnimate[TRANSFORM_ATTR];
5601
5814
  const distance = { keyframes: built.distanceKfs };
5602
5815
  if (transform.loop !== void 0) distance.loop = transform.loop;
5603
- newAnimate["offsetDistance"] = distance;
5816
+ newAnimate[OFFSET_DISTANCE_ATTR] = distance;
5604
5817
  const staticTr = node.transform;
5605
5818
  let newTransform = staticTr;
5606
5819
  if (staticTr && typeof staticTr === "object") {
5607
5820
  const t = __spreadValues2({}, staticTr);
5608
- delete t["translate"];
5609
- delete t["origin"];
5821
+ delete t[TRANSFORM_PART.translate];
5822
+ delete t[TRANSFORM_PART.origin];
5610
5823
  newTransform = Object.keys(t).length ? t : void 0;
5611
5824
  }
5612
5825
  out = __spreadProps2(__spreadValues2({}, node), {
@@ -5622,7 +5835,7 @@ function materialiseOffsetPathsInTree(root) {
5622
5835
  else delete out.transform;
5623
5836
  }
5624
5837
  }
5625
- if ((_a = out.children) == null ? void 0 : _a.length) {
5838
+ if ((_a2 = out.children) == null ? void 0 : _a2.length) {
5626
5839
  const children = out.children.map(walk);
5627
5840
  if (children.some((c, i) => c !== out.children[i])) out = __spreadProps2(__spreadValues2({}, out), { children });
5628
5841
  }
@@ -5631,12 +5844,12 @@ function materialiseOffsetPathsInTree(root) {
5631
5844
  return walk(root);
5632
5845
  }
5633
5846
  function materialiseAllInTree(doc, engine, opts) {
5634
- var _a, _b;
5847
+ var _a2, _b;
5635
5848
  let root = applyPlayerEffects(doc).root;
5636
5849
  root = materialiseOffsetPathsInTree(root);
5637
- const duration = (_b = (_a = getAnimatorConfig(root)) == null ? void 0 : _a.duration) != null ? _b : DEFAULT_DURATION_MS;
5850
+ const duration = (_b = (_a2 = getAnimatorConfig(root)) == null ? void 0 : _a2.duration) != null ? _b : DEFAULT_DURATION_MS;
5638
5851
  root = materialiseInternalLoopsInTree(root, duration);
5639
- if (engine === PxAnimatorEngine.waapi) {
5852
+ if (engine === PxTimelineEngine.native) {
5640
5853
  root = materialiseMotionPathsInTree(root, opts == null ? void 0 : opts.motionPath);
5641
5854
  root = materialiseAnimatedUseInstances(root);
5642
5855
  root = pruneUnreferencedDefs(root);
@@ -5646,9 +5859,9 @@ function materialiseAllInTree(doc, engine, opts) {
5646
5859
  function pruneUnreferencedDefs(root) {
5647
5860
  const stripHash3 = (h) => h.startsWith("#") ? h.slice(1) : h;
5648
5861
  const walk = (n, fn) => {
5649
- var _a;
5862
+ var _a2;
5650
5863
  fn(n);
5651
- (_a = n.children) == null ? void 0 : _a.forEach((c) => walk(c, fn));
5864
+ (_a2 = n.children) == null ? void 0 : _a2.forEach((c) => walk(c, fn));
5652
5865
  };
5653
5866
  let changed = true;
5654
5867
  while (changed) {
@@ -5686,9 +5899,9 @@ function cancelFrame(handle) {
5686
5899
  g.clearTimeout(handle);
5687
5900
  }
5688
5901
  function createBasicFrameLoopAnimator(doc, adapter, callbacks) {
5689
- var _a;
5902
+ var _a2;
5690
5903
  const config = getAnimatorConfig(doc) || {};
5691
- const bindings = getNormalisedBindings(doc, PxAnimatorEngine.frames);
5904
+ const bindings = getNormalisedBindings(doc, PxTimelineEngine.js);
5692
5905
  const _iterations = config.iterations;
5693
5906
  let iterations = 1;
5694
5907
  if (typeof _iterations === "number") iterations = _iterations || 1;
@@ -5697,7 +5910,7 @@ function createBasicFrameLoopAnimator(doc, adapter, callbacks) {
5697
5910
  const duration = +(config.duration || DEFAULT_DURATION_MS);
5698
5911
  const totalDuration = duration && iterations ? duration * (iterations === Infinity ? Infinity : iterations) : duration ? (iterations != null ? iterations : 1) * duration : 0;
5699
5912
  const direction = config.direction || "normal";
5700
- const fill = (_a = config.fill) != null ? _a : "forwards";
5913
+ const fill = (_a2 = config.fill) != null ? _a2 : "forwards";
5701
5914
  const fillsForwards = fill === "forwards" || fill === "both";
5702
5915
  const fillsBackwards = fill === "backwards" || fill === "both";
5703
5916
  let timerId = null;
@@ -5759,7 +5972,7 @@ function createBasicFrameLoopAnimator(doc, adapter, callbacks) {
5759
5972
  }
5760
5973
  }
5761
5974
  const tick = () => {
5762
- var _a2, _b;
5975
+ var _a3, _b;
5763
5976
  if (!adapter.isConnected()) {
5764
5977
  pauseAnim();
5765
5978
  return;
@@ -5775,7 +5988,7 @@ function createBasicFrameLoopAnimator(doc, adapter, callbacks) {
5775
5988
  renderFrame(0);
5776
5989
  if (!finishCalled) {
5777
5990
  finishCalled = true;
5778
- (_a2 = callbacks == null ? void 0 : callbacks.onFinish) == null ? void 0 : _a2.call(callbacks);
5991
+ (_a3 = callbacks == null ? void 0 : callbacks.onFinish) == null ? void 0 : _a3.call(callbacks);
5779
5992
  }
5780
5993
  return;
5781
5994
  }
@@ -5867,17 +6080,17 @@ function createBasicFrameLoopAnimator(doc, adapter, callbacks) {
5867
6080
  }
5868
6081
  };
5869
6082
  const cancelAnim = () => {
5870
- var _a2;
6083
+ var _a3;
5871
6084
  pauseAnim();
5872
6085
  timeBeforeLastStartMs = 0;
5873
6086
  lastStartedTs = 0;
5874
6087
  playing = false;
5875
6088
  finishCalled = false;
5876
6089
  renderFrame(timeBeforeLastStartMs);
5877
- (_a2 = callbacks == null ? void 0 : callbacks.onCancel) == null ? void 0 : _a2.call(callbacks);
6090
+ (_a3 = callbacks == null ? void 0 : callbacks.onCancel) == null ? void 0 : _a3.call(callbacks);
5878
6091
  };
5879
6092
  const finishAnim = (callOnFinish = true) => {
5880
- var _a2;
6093
+ var _a3;
5881
6094
  if (Number.isFinite(totalDuration)) {
5882
6095
  timeBeforeLastStartMs = totalDuration;
5883
6096
  } else {
@@ -5892,7 +6105,7 @@ function createBasicFrameLoopAnimator(doc, adapter, callbacks) {
5892
6105
  renderFrame(fillsForwards ? timeBeforeLastStartMs : 0);
5893
6106
  if (callOnFinish && !finishCalled) {
5894
6107
  finishCalled = true;
5895
- (_a2 = callbacks == null ? void 0 : callbacks.onFinish) == null ? void 0 : _a2.call(callbacks);
6108
+ (_a3 = callbacks == null ? void 0 : callbacks.onFinish) == null ? void 0 : _a3.call(callbacks);
5896
6109
  }
5897
6110
  };
5898
6111
  const api = {
@@ -5902,14 +6115,14 @@ function createBasicFrameLoopAnimator(doc, adapter, callbacks) {
5902
6115
  return _isPlaying();
5903
6116
  },
5904
6117
  "play": () => {
5905
- var _a2;
6118
+ var _a3;
5906
6119
  startAnim();
5907
- (_a2 = callbacks == null ? void 0 : callbacks.onPlay) == null ? void 0 : _a2.call(callbacks);
6120
+ (_a3 = callbacks == null ? void 0 : callbacks.onPlay) == null ? void 0 : _a3.call(callbacks);
5908
6121
  },
5909
6122
  "pause": () => {
5910
- var _a2;
6123
+ var _a3;
5911
6124
  pauseAnim();
5912
- (_a2 = callbacks == null ? void 0 : callbacks.onPause) == null ? void 0 : _a2.call(callbacks);
6125
+ (_a3 = callbacks == null ? void 0 : callbacks.onPause) == null ? void 0 : _a3.call(callbacks);
5913
6126
  },
5914
6127
  "cancel": () => {
5915
6128
  cancelAnim();
@@ -5941,9 +6154,9 @@ function createBasicFrameLoopAnimator(doc, adapter, callbacks) {
5941
6154
  renderFrame(getAnimCurrentTime());
5942
6155
  },
5943
6156
  "destroy": () => {
5944
- var _a2;
6157
+ var _a3;
5945
6158
  api.cancel();
5946
- (_a2 = callbacks == null ? void 0 : callbacks.onRemove) == null ? void 0 : _a2.call(callbacks);
6159
+ (_a3 = callbacks == null ? void 0 : callbacks.onRemove) == null ? void 0 : _a3.call(callbacks);
5947
6160
  }
5948
6161
  };
5949
6162
  return api;
@@ -5997,9 +6210,9 @@ function lerp(a, b, f) {
5997
6210
  return a + (b - a) * f;
5998
6211
  }
5999
6212
  function interpParts(kfs, t) {
6000
- var _a, _b, _c, _d, _e, _f, _g;
6213
+ var _a2, _b, _c, _d, _e, _f, _g;
6001
6214
  if (!kfs.length) return {};
6002
- if (t <= ((_a = kfs[0].time) != null ? _a : 0)) return kfs[0].value || {};
6215
+ if (t <= ((_a2 = kfs[0].time) != null ? _a2 : 0)) return kfs[0].value || {};
6003
6216
  if (t >= ((_b = kfs[kfs.length - 1].time) != null ? _b : 0)) return kfs[kfs.length - 1].value || {};
6004
6217
  let i = 0;
6005
6218
  while (i < kfs.length - 1 && ((_c = kfs[i + 1].time) != null ? _c : 0) < t) i++;
@@ -6030,10 +6243,10 @@ function nodeMatrix(node, t) {
6030
6243
  return IDENTITY;
6031
6244
  }
6032
6245
  function evalScalar(animated, staticVal, fallback, t) {
6033
- var _a, _b, _c, _d, _e, _f;
6246
+ var _a2, _b, _c, _d, _e, _f;
6034
6247
  if (animated && animated.keyframes && animated.keyframes.length) {
6035
6248
  const kfs = animated.keyframes;
6036
- if (t <= ((_a = kfs[0].time) != null ? _a : 0)) return kfs[0].value;
6249
+ if (t <= ((_a2 = kfs[0].time) != null ? _a2 : 0)) return kfs[0].value;
6037
6250
  if (t >= ((_b = kfs[kfs.length - 1].time) != null ? _b : 0)) return kfs[kfs.length - 1].value;
6038
6251
  let i = 0;
6039
6252
  while (i < kfs.length - 1 && ((_c = kfs[i + 1].time) != null ? _c : 0) < t) i++;
@@ -6046,9 +6259,9 @@ function evalScalar(animated, staticVal, fallback, t) {
6046
6259
  var CONTAINER_TYPES = /* @__PURE__ */ new Set(["svg", "g", "symbol"]);
6047
6260
  var SKIP_TYPES = /* @__PURE__ */ new Set(["defs", "mask", "clipPath", "title"]);
6048
6261
  function buildIdMap2(node, map) {
6049
- var _a;
6262
+ var _a2;
6050
6263
  if (typeof node.id === "string") map.set(node.id, node);
6051
- (_a = node.children) == null ? void 0 : _a.forEach((c) => buildIdMap2(c, map));
6264
+ (_a2 = node.children) == null ? void 0 : _a2.forEach((c) => buildIdMap2(c, map));
6052
6265
  }
6053
6266
  function num(v) {
6054
6267
  return v === void 0 || v === null ? 0 : Number(v);
@@ -6057,7 +6270,7 @@ function round(n) {
6057
6270
  return Math.round(n * 100) / 100 + 0;
6058
6271
  }
6059
6272
  function geomKey(node) {
6060
- var _a;
6273
+ var _a2;
6061
6274
  switch (node.type) {
6062
6275
  case "rect":
6063
6276
  return num(node.width) + "," + num(node.height) + "," + num(node.x) + "," + num(node.y);
@@ -6066,14 +6279,14 @@ function geomKey(node) {
6066
6279
  case "circle":
6067
6280
  return num(node.r) + "," + num(node.cx) + "," + num(node.cy);
6068
6281
  case "path":
6069
- return String((_a = node.d) != null ? _a : "");
6282
+ return String((_a2 = node.d) != null ? _a2 : "");
6070
6283
  default:
6071
6284
  return "";
6072
6285
  }
6073
6286
  }
6074
6287
  function describePrimitive(node, m, t) {
6075
- var _a, _b, _c, _d, _e;
6076
- const fill = (_a = node.fill) != null ? _a : "";
6288
+ var _a2, _b, _c, _d, _e;
6289
+ const fill = (_a2 = node.fill) != null ? _a2 : "";
6077
6290
  const stroke = (_b = node.stroke) != null ? _b : "";
6078
6291
  const sw = (_d = (_c = node["stroke-width"]) != null ? _c : node.strokeWidth) != null ? _d : "";
6079
6292
  const opacity = round(evalScalar((_e = node.animate) == null ? void 0 : _e.opacity, node.opacity, 1, t));
@@ -6082,7 +6295,7 @@ function describePrimitive(node, m, t) {
6082
6295
  return node.type + "|" + geomKey(node) + "|[" + mat + "]|f:" + fill + "|s:" + stroke + "|sw:" + (num(sw) || "") + "|o:" + opacity + "|m:" + masked;
6083
6296
  }
6084
6297
  function flatten(node, parent, t, idMap, out) {
6085
- var _a;
6298
+ var _a2;
6086
6299
  const type = node.type || "";
6087
6300
  if (SKIP_TYPES.has(type)) return;
6088
6301
  const m = mul(parent, nodeMatrix(node, t));
@@ -6095,33 +6308,33 @@ function flatten(node, parent, t, idMap, out) {
6095
6308
  return;
6096
6309
  }
6097
6310
  if (CONTAINER_TYPES.has(type)) {
6098
- (_a = node.children) == null ? void 0 : _a.forEach((c) => flatten(c, m, t, idMap, out));
6311
+ (_a2 = node.children) == null ? void 0 : _a2.forEach((c) => flatten(c, m, t, idMap, out));
6099
6312
  return;
6100
6313
  }
6101
6314
  out.push(describePrimitive(node, m, t));
6102
6315
  }
6103
6316
  function collectSampleTimes(node, into) {
6104
- var _a;
6317
+ var _a2;
6105
6318
  into.add(0);
6106
6319
  const scanAnim = (anim) => {
6107
- var _a2;
6320
+ var _a3;
6108
6321
  if (!anim || typeof anim !== "object") return;
6109
6322
  for (const key of Object.keys(anim)) {
6110
- const kfs = (_a2 = anim[key]) == null ? void 0 : _a2.keyframes;
6323
+ const kfs = (_a3 = anim[key]) == null ? void 0 : _a3.keyframes;
6111
6324
  if (Array.isArray(kfs)) kfs.forEach((kf) => {
6112
- var _a3;
6113
- return into.add((_a3 = kf.time) != null ? _a3 : 0);
6325
+ var _a4;
6326
+ return into.add((_a4 = kf.time) != null ? _a4 : 0);
6114
6327
  });
6115
6328
  }
6116
6329
  };
6117
6330
  scanAnim(node.animate);
6118
6331
  if (node.transform && typeof node.transform === "object" && node.transform.keyframes) {
6119
6332
  node.transform.keyframes.forEach((kf) => {
6120
- var _a2;
6121
- return into.add((_a2 = kf.time) != null ? _a2 : 0);
6333
+ var _a3;
6334
+ return into.add((_a3 = kf.time) != null ? _a3 : 0);
6122
6335
  });
6123
6336
  }
6124
- (_a = node.children) == null ? void 0 : _a.forEach((c) => collectSampleTimes(c, into));
6337
+ (_a2 = node.children) == null ? void 0 : _a2.forEach((c) => collectSampleTimes(c, into));
6125
6338
  }
6126
6339
  function visualModelAt(root, t) {
6127
6340
  const idMap = /* @__PURE__ */ new Map();
@@ -6155,8 +6368,191 @@ function subtractMultiset(a, b) {
6155
6368
  }
6156
6369
  return extra;
6157
6370
  }
6371
+ var FLAT_ONLY_KEYS = [
6372
+ "timelineSource",
6373
+ "scroll",
6374
+ "trigger",
6375
+ "delay",
6376
+ "iterations",
6377
+ "direction",
6378
+ "fill",
6379
+ "resetOnFinish",
6380
+ "duration",
6381
+ "mode",
6382
+ "frameRate"
6383
+ ];
6384
+ var CONTENT_KEYS = ["definitions", "animateById"];
6385
+ var isPlainObject = (v) => !!v && typeof v === "object" && !Array.isArray(v);
6386
+ var timelineTypeOf = (t) => isPlainObject(t) && typeof t.type === "string" ? t.type : "time";
6387
+ var isScrollish = (type) => type === "scroll" || type === "view";
6388
+ function mergePlain(base, patch) {
6389
+ const out = isPlainObject(base) ? __spreadValues2({}, base) : {};
6390
+ for (const key of Object.keys(patch)) {
6391
+ const value = patch[key];
6392
+ if (value === null) {
6393
+ delete out[key];
6394
+ continue;
6395
+ }
6396
+ if (isPlainObject(value)) {
6397
+ out[key] = mergePlain(out[key], value);
6398
+ continue;
6399
+ }
6400
+ out[key] = value;
6401
+ }
6402
+ return out;
6403
+ }
6404
+ function mergeTimeline(base, patch, warn) {
6405
+ const baseType = timelineTypeOf(base);
6406
+ const patchNamesType = isPlainObject(patch) && typeof patch.type === "string";
6407
+ const patchType = patchNamesType ? String(patch.type) : baseType;
6408
+ let merged;
6409
+ if (patchType !== baseType) {
6410
+ const carried = {};
6411
+ if (isPlainObject(base)) {
6412
+ for (const k of PX_TIMELINE_SHARED_KEYS) {
6413
+ if (base[k] !== void 0) carried[k] = base[k];
6414
+ }
6415
+ }
6416
+ merged = mergePlain(carried, patch);
6417
+ } else {
6418
+ merged = mergePlain(base, patch);
6419
+ }
6420
+ if (isScrollish(patchType)) {
6421
+ for (const k of PX_TIME_ONLY_TIMELINE_KEYS) {
6422
+ if (merged[k] === void 0) continue;
6423
+ warn("animator.timeline." + k + ": no slot on a '" + patchType + "' timeline \u2014 dropped");
6424
+ delete merged[k];
6425
+ }
6426
+ if (merged.iterations === "infinite") {
6427
+ warn("animator.timeline.iterations: 'infinite' cannot map onto a scroll range \u2014 dropped");
6428
+ delete merged.iterations;
6429
+ }
6430
+ }
6431
+ return merged;
6432
+ }
6433
+ function foldAnimatorConfigShortcuts(config, shortcuts) {
6434
+ let base;
6435
+ if (typeof config === "string") {
6436
+ try {
6437
+ base = JSON.parse(config);
6438
+ } catch (e) {
6439
+ console.warn("animator config: not valid JSON \u2014 ignored", e);
6440
+ base = void 0;
6441
+ }
6442
+ } else {
6443
+ base = config != null ? config : void 0;
6444
+ }
6445
+ const { duration, delay, iterations, startOn } = shortcuts;
6446
+ if (duration === void 0 && delay === void 0 && iterations === void 0 && startOn === void 0) {
6447
+ return base;
6448
+ }
6449
+ const out = isPlainObject(base) ? __spreadValues2({}, base) : {};
6450
+ const timeline = __spreadValues2({}, out.timeline);
6451
+ if (duration !== void 0) timeline.duration = duration;
6452
+ if (delay !== void 0) timeline.delay = delay;
6453
+ if (iterations !== void 0) timeline.iterations = iterations;
6454
+ if (startOn !== void 0) {
6455
+ timeline.trigger = __spreadProps2(__spreadValues2({}, timeline.trigger), { startOn });
6456
+ }
6457
+ out.timeline = timeline;
6458
+ return out;
6459
+ }
6460
+ function mergeAnimatorConfig(base, patch) {
6461
+ const warnings = [];
6462
+ const warn = (m) => warnings.push(m);
6463
+ if (patch === null) return { config: void 0, warnings };
6464
+ if (!isPlainObject(patch) || Object.keys(patch).length === 0) {
6465
+ return { config: base, warnings };
6466
+ }
6467
+ const flatInBase = isPlainObject(base) ? FLAT_ONLY_KEYS.filter((k) => base[k] !== void 0) : [];
6468
+ if (flatInBase.length) {
6469
+ warn("animator: the base carries the flat runtime spelling (" + flatInBase.join(", ") + "); the patch merges the wire spelling only");
6470
+ }
6471
+ const out = isPlainObject(base) ? __spreadValues2({}, base) : {};
6472
+ for (const key of Object.keys(patch)) {
6473
+ const value = patch[key];
6474
+ if (value === null) {
6475
+ delete out[key];
6476
+ continue;
6477
+ }
6478
+ if (key === "timeline") {
6479
+ out.timeline = isPlainObject(value) ? mergeTimeline(out.timeline, value, warn) : value;
6480
+ continue;
6481
+ }
6482
+ if (isPlainObject(value)) {
6483
+ out[key] = mergePlain(out[key], value);
6484
+ continue;
6485
+ }
6486
+ out[key] = value;
6487
+ }
6488
+ return { config: out, warnings };
6489
+ }
6490
+ function applyAnimatorConfig(doc, patch, opts) {
6491
+ var _a2, _b;
6492
+ const reset = !!(opts == null ? void 0 : opts.resetDefaults);
6493
+ if (!doc || (patch === void 0 || !reset && (patch === null || !isPlainObject(patch) || !Object.keys(patch).length))) {
6494
+ return { doc, warnings: [] };
6495
+ }
6496
+ const anyDoc = doc;
6497
+ const atRoot = isPlainObject(anyDoc.animator);
6498
+ const atMeta = !atRoot && isPlainObject((_a2 = anyDoc.meta) == null ? void 0 : _a2.animator);
6499
+ const current = atRoot ? anyDoc.animator : atMeta ? anyDoc.meta.animator : void 0;
6500
+ const warnings = [];
6501
+ if (atRoot && isPlainObject((_b = anyDoc.meta) == null ? void 0 : _b.animator)) {
6502
+ warnings.push("animator: doc.meta.animator is shadowed by doc.animator and was not patched");
6503
+ }
6504
+ let base = current;
6505
+ if (reset) {
6506
+ const kept = {};
6507
+ for (const k of CONTENT_KEYS) {
6508
+ if (isPlainObject(current) && current[k] !== void 0) kept[k] = current[k];
6509
+ }
6510
+ base = kept;
6511
+ }
6512
+ const merged = mergeAnimatorConfig(base, patch != null ? patch : {});
6513
+ warnings.push(...merged.warnings);
6514
+ if (merged.config === current) return { doc, warnings };
6515
+ if (atMeta) {
6516
+ return {
6517
+ doc: __spreadProps2(__spreadValues2({}, anyDoc), { meta: __spreadProps2(__spreadValues2({}, anyDoc.meta), { animator: merged.config }) }),
6518
+ warnings
6519
+ };
6520
+ }
6521
+ return { doc: __spreadProps2(__spreadValues2({}, anyDoc), { animator: merged.config }), warnings };
6522
+ }
6523
+ var MAX_REPORTED = 6;
6524
+ var LEGACY_FLAT_KEYS = [
6525
+ ...PX_TIMELINE_SHARED_KEYS,
6526
+ ...PX_TIME_ONLY_TIMELINE_KEYS,
6527
+ "fill",
6528
+ "resetOnFinish",
6529
+ "timelineSource",
6530
+ "scroll"
6531
+ ];
6532
+ var isLegacyFlatAnimatorKey = (w) => LEGACY_FLAT_KEYS.some((k) => w.indexOf("animator." + k + ":") >= 0);
6533
+ function diagnoseDocument(doc) {
6534
+ let all;
6535
+ try {
6536
+ all = validateDocument(doc);
6537
+ } catch (e) {
6538
+ return { problems: [], legacy: [] };
6539
+ }
6540
+ const problems = [];
6541
+ const legacy = [];
6542
+ for (const w of all) (isLegacyFlatAnimatorKey(w) ? legacy : problems).push(w);
6543
+ return { problems, legacy };
6544
+ }
6545
+ function reportDocumentDiagnostics(doc, where) {
6546
+ const { problems } = diagnoseDocument(doc);
6547
+ if (!problems.length) return;
6548
+ const shown = problems.slice(0, MAX_REPORTED);
6549
+ const more = problems.length - shown.length;
6550
+ console.warn(
6551
+ where + ": this document does not match the animation schema in " + problems.length + " place" + (problems.length === 1 ? "" : "s") + ".\n" + shown.map((p) => " - " + p).join("\n") + (more > 0 ? "\n \u2026 and " + more + " more" : "") + "\n\nIf you did not author these keys, the usual cause is a build that MANGLES PROPERTY NAMES. An animation document is data loaded at runtime, so renaming the property reads inside the player stops them matching the keys in the JSON, and the animation silently does nothing. Feed the published reserved-name list to your minifier \u2014 @pixodesk/svg-animator-web/mangle-reserved.json \u2014 see docs/library/minification.md."
6552
+ );
6553
+ }
6158
6554
 
6159
- // src/PxAnimatorTriggers.ts
6555
+ // src/triggers/PxAnimatorTriggers.ts
6160
6556
  function setupAnimationTriggers(api, config) {
6161
6557
  const { startOn, outAction = "continue", scrollIntoViewThreshold = 0 } = config;
6162
6558
  const root = api.getRootElement();
@@ -6226,12 +6622,12 @@ function setupAnimationTriggers(api, config) {
6226
6622
  }
6227
6623
  case "scrollIntoView": {
6228
6624
  const effectiveRatio = (entry) => {
6229
- var _a, _b;
6625
+ var _a2, _b;
6230
6626
  const target = entry.boundingClientRect;
6231
6627
  const visible = entry.intersectionRect;
6232
6628
  if (!(target == null ? void 0 : target.height) || !visible) return entry.intersectionRatio;
6233
6629
  const live = typeof window !== "undefined" && window.innerHeight ? window.innerHeight : Infinity;
6234
- const declared = (_b = (_a = entry.rootBounds) == null ? void 0 : _a.height) != null ? _b : Infinity;
6630
+ const declared = (_b = (_a2 = entry.rootBounds) == null ? void 0 : _a2.height) != null ? _b : Infinity;
6235
6631
  const viewport = Math.min(live, declared);
6236
6632
  const denom = Math.min(target.height, Number.isFinite(viewport) ? viewport : target.height);
6237
6633
  return denom > 0 ? visible.height / denom : entry.intersectionRatio;
@@ -6261,7 +6657,7 @@ function setupAnimationTriggers(api, config) {
6261
6657
  return api;
6262
6658
  }
6263
6659
 
6264
- // src/PxAnimatorFrameLoop.ts
6660
+ // src/engines/PxAnimatorFrameLoop.ts
6265
6661
  function getSelector(id) {
6266
6662
  return "#" + id;
6267
6663
  }
@@ -6321,11 +6717,10 @@ function createDomAdapter(rootElement) {
6321
6717
  return adapter;
6322
6718
  }
6323
6719
 
6324
- // src/PxAnimatorWebApi.ts
6720
+ // src/engines/PxAnimatorWebApi.ts
6325
6721
  function createCssKf(kf, t, propName, unsupportedSet) {
6326
- var _a, _b;
6327
- let value = (_a = kf.v) != null ? _a : kf.value;
6328
- const e = (_b = kf.e) != null ? _b : kf.easing;
6722
+ let value = kfValue(kf);
6723
+ const e = kfEasing(kf);
6329
6724
  const cssKf = {
6330
6725
  offset: t,
6331
6726
  easing: e && Array.isArray(e) ? "cubic-bezier(" + e.join(",") + ")" : void 0
@@ -6359,11 +6754,11 @@ function createCssKf(kf, t, propName, unsupportedSet) {
6359
6754
  return cssKf;
6360
6755
  }
6361
6756
  function clipKeyframesToDuration(propName, keyframes, duration) {
6362
- var _a, _b, _c, _d, _e;
6757
+ var _a2, _b, _c, _d, _e;
6363
6758
  const result = [];
6364
6759
  for (let i = 0; i < keyframes.length; i++) {
6365
6760
  const kf = keyframes[i];
6366
- const t = (_a = kf.t) != null ? _a : 0;
6761
+ const t = (_a2 = kf.t) != null ? _a2 : 0;
6367
6762
  if (t < 0) {
6368
6763
  const next = keyframes[i + 1];
6369
6764
  if (next && ((_b = next.t) != null ? _b : 0) >= 0) {
@@ -6392,15 +6787,15 @@ function clipKeyframesToDuration(propName, keyframes, duration) {
6392
6787
  return result;
6393
6788
  }
6394
6789
  function convertToWebApiKeyframes(animDef, unsupportedSet, config) {
6395
- var _a;
6790
+ var _a2;
6396
6791
  const result = /* @__PURE__ */ new Map();
6397
6792
  for (const [propName, propAnim] of Object.entries(animDef)) {
6398
6793
  const duration = config.duration || 1;
6399
- const clippedKeyframes = clipKeyframesToDuration(propName, propAnim.kfs || propAnim.keyframes || [], duration);
6794
+ const clippedKeyframes = clipKeyframesToDuration(propName, propAnim.keyframes || [], duration);
6400
6795
  const cssKeyframes = [];
6401
6796
  for (let i = 0; i < clippedKeyframes.length; i++) {
6402
6797
  const kf = clippedKeyframes[i];
6403
- const t = clamp(((_a = kf.t) != null ? _a : 0) / duration, 0, 1);
6798
+ const t = clamp(((_a2 = kf.t) != null ? _a2 : 0) / duration, 0, 1);
6404
6799
  const cssKf = createCssKf(kf, t, propName, unsupportedSet);
6405
6800
  if (i === 0 && (cssKf.offset || 0) > 0) {
6406
6801
  cssKeyframes.push(__spreadProps(__spreadValues({}, cssKf), { offset: 0 }));
@@ -6419,7 +6814,7 @@ function convertToWebApiKeyframes(animDef, unsupportedSet, config) {
6419
6814
  return result;
6420
6815
  }
6421
6816
  function createWebApiAnimator(doc, callbacks, rootElement, forceEvenIfHasUnsupportedAttrs, scrollTimeline) {
6422
- var _a;
6817
+ var _a2;
6423
6818
  const config = getAnimatorConfig(doc) || {};
6424
6819
  if (!rootElement) {
6425
6820
  if (doc.id) {
@@ -6430,7 +6825,7 @@ function createWebApiAnimator(doc, callbacks, rootElement, forceEvenIfHasUnsuppo
6430
6825
  console.warn("createFrameLoopAnimator: No root element provided");
6431
6826
  }
6432
6827
  }
6433
- const bindings = getNormalisedBindings(doc, PxAnimatorEngine.waapi);
6828
+ const bindings = getNormalisedBindings(doc, PxTimelineEngine.native);
6434
6829
  const animations = [];
6435
6830
  const _iterations = config.iterations;
6436
6831
  let iterations;
@@ -6467,7 +6862,7 @@ function createWebApiAnimator(doc, callbacks, rootElement, forceEvenIfHasUnsuppo
6467
6862
  // animation ends — consistent with Lottie and other animation runtimes.
6468
6863
  // Without this, seeking to the last frame reverts elements to their
6469
6864
  // pre-animation state (the Web Animations API "after" phase with fill:'none').
6470
- fill: (_a = config.fill) != null ? _a : "forwards",
6865
+ fill: (_a2 = config.fill) != null ? _a2 : "forwards",
6471
6866
  direction: config.direction,
6472
6867
  iterations
6473
6868
  };
@@ -6484,16 +6879,16 @@ function createWebApiAnimator(doc, callbacks, rootElement, forceEvenIfHasUnsuppo
6484
6879
  if (scrollTimeline.rangeEnd) a.rangeEnd = scrollTimeline.rangeEnd;
6485
6880
  }
6486
6881
  if (callbacks == null ? void 0 : callbacks.onFinish) anim.onfinish = () => {
6487
- var _a2;
6882
+ var _a3;
6488
6883
  if (finishNotified) return;
6489
6884
  finishNotified = true;
6490
- (_a2 = callbacks.onFinish) == null ? void 0 : _a2.call(callbacks);
6885
+ (_a3 = callbacks.onFinish) == null ? void 0 : _a3.call(callbacks);
6491
6886
  };
6492
6887
  if (callbacks == null ? void 0 : callbacks.onRemove) anim.onremove = () => {
6493
- var _a2;
6888
+ var _a3;
6494
6889
  if (removeCalled) return;
6495
6890
  removeCalled = true;
6496
- (_a2 = callbacks.onRemove) == null ? void 0 : _a2.call(callbacks);
6891
+ (_a3 = callbacks.onRemove) == null ? void 0 : _a3.call(callbacks);
6497
6892
  };
6498
6893
  if (seekPosition !== void 0) {
6499
6894
  anim.currentTime = seekPosition;
@@ -6514,31 +6909,31 @@ function createWebApiAnimator(doc, callbacks, rootElement, forceEvenIfHasUnsuppo
6514
6909
  "isReady": () => true,
6515
6910
  "getRootElement": () => rootElement || null,
6516
6911
  "isPlaying": () => {
6517
- var _a2;
6518
- return ((_a2 = animations[0]) == null ? void 0 : _a2.playState) === "running";
6912
+ var _a3;
6913
+ return ((_a3 = animations[0]) == null ? void 0 : _a3.playState) === "running";
6519
6914
  },
6520
6915
  "play": () => {
6521
- var _a2;
6916
+ var _a3;
6522
6917
  finishNotified = false;
6523
6918
  animations.forEach((a) => a.play());
6524
- (_a2 = callbacks == null ? void 0 : callbacks.onPlay) == null ? void 0 : _a2.call(callbacks);
6919
+ (_a3 = callbacks == null ? void 0 : callbacks.onPlay) == null ? void 0 : _a3.call(callbacks);
6525
6920
  },
6526
6921
  "pause": () => {
6527
- var _a2;
6922
+ var _a3;
6528
6923
  animations.forEach((a) => a.pause());
6529
- (_a2 = callbacks == null ? void 0 : callbacks.onPause) == null ? void 0 : _a2.call(callbacks);
6924
+ (_a3 = callbacks == null ? void 0 : callbacks.onPause) == null ? void 0 : _a3.call(callbacks);
6530
6925
  },
6531
6926
  "cancel": () => {
6532
- var _a2;
6927
+ var _a3;
6533
6928
  finishNotified = false;
6534
6929
  animations.forEach((a) => a.cancel());
6535
- (_a2 = callbacks == null ? void 0 : callbacks.onCancel) == null ? void 0 : _a2.call(callbacks);
6930
+ (_a3 = callbacks == null ? void 0 : callbacks.onCancel) == null ? void 0 : _a3.call(callbacks);
6536
6931
  },
6537
6932
  "finish": () => {
6538
- var _a2;
6933
+ var _a3;
6539
6934
  for (const a of animations) {
6540
6935
  try {
6541
- if (((_a2 = a.effect) == null ? void 0 : _a2.getTiming().iterations) === Infinity) {
6936
+ if (((_a3 = a.effect) == null ? void 0 : _a3.getTiming().iterations) === Infinity) {
6542
6937
  a.effect.updateTiming({ iterations: 1 });
6543
6938
  a.finish();
6544
6939
  a.effect.updateTiming({ iterations: Infinity });
@@ -6555,8 +6950,8 @@ function createWebApiAnimator(doc, callbacks, rootElement, forceEvenIfHasUnsuppo
6555
6950
  return api;
6556
6951
  },
6557
6952
  "getCurrentTime": () => {
6558
- var _a2, _b;
6559
- const res = (_b = (_a2 = animations[0]) == null ? void 0 : _a2.currentTime) != null ? _b : null;
6953
+ var _a3, _b;
6954
+ const res = (_b = (_a3 = animations[0]) == null ? void 0 : _a3.currentTime) != null ? _b : null;
6560
6955
  return res !== null ? +res : null;
6561
6956
  },
6562
6957
  "setCurrentTime": (time) => {
@@ -6566,12 +6961,12 @@ function createWebApiAnimator(doc, callbacks, rootElement, forceEvenIfHasUnsuppo
6566
6961
  });
6567
6962
  },
6568
6963
  "destroy": () => {
6569
- var _a2;
6964
+ var _a3;
6570
6965
  api.cancel();
6571
6966
  animations.splice(0, animations.length);
6572
6967
  if (!removeCalled) {
6573
6968
  removeCalled = true;
6574
- (_a2 = callbacks == null ? void 0 : callbacks.onRemove) == null ? void 0 : _a2.call(callbacks);
6969
+ (_a3 = callbacks == null ? void 0 : callbacks.onRemove) == null ? void 0 : _a3.call(callbacks);
6575
6970
  }
6576
6971
  }
6577
6972
  };
@@ -6588,21 +6983,21 @@ function createWebApiAnimator(doc, callbacks, rootElement, forceEvenIfHasUnsuppo
6588
6983
  return api;
6589
6984
  }
6590
6985
 
6591
- // src/PxScrollDriver.ts
6986
+ // src/scroll/PxScrollDriver.ts
6592
6987
  function nativeRangeOffset(point, defaultFraction, view) {
6593
- var _a, _b, _c;
6988
+ var _a2, _b, _c;
6594
6989
  const fraction = typeof (point == null ? void 0 : point.fraction) === "number" ? point.fraction : defaultFraction;
6595
- const pct = (_b = (_a = globalThis.CSS) == null ? void 0 : _a.percent) == null ? void 0 : _b.call(_a, fraction * 100);
6990
+ const pct = (_b = (_a2 = globalThis.CSS) == null ? void 0 : _a2.percent) == null ? void 0 : _b.call(_a2, fraction * 100);
6596
6991
  if (pct === void 0) return void 0;
6597
6992
  return view ? { rangeName: (_c = point == null ? void 0 : point.phase) != null ? _c : "cover", offset: pct } : { offset: pct };
6598
6993
  }
6599
6994
  function createNativeScrollTimeline(subject, config) {
6600
- var _a, _b, _c, _d;
6995
+ var _a2, _b, _c, _d;
6601
6996
  if (!config || !isScrollTimeline(config)) return null;
6602
6997
  const scroll = config.scroll || {};
6603
- const kind = (_a = scroll.kind) != null ? _a : "view";
6998
+ const kind = (_a2 = scroll.kind) != null ? _a2 : "view";
6604
6999
  if (scroll.smoothing) {
6605
- console.warn('scroll timeline: `smoothing` needs the built-in driver \u2014 ignoring `driver: "native"`');
7000
+ console.warn("scroll timeline: `smoothing` needs the built-in driver \u2014 using the built-in driver instead of the browser timeline");
6606
7001
  return null;
6607
7002
  }
6608
7003
  const g = globalThis;
@@ -6619,7 +7014,7 @@ function createNativeScrollTimeline(subject, config) {
6619
7014
  timeline = new Ctor({ source, axis });
6620
7015
  }
6621
7016
  } catch (e) {
6622
- console.warn("scroll timeline: native timeline construction failed \u2014 falling back to the custom driver", e);
7017
+ console.warn("scroll timeline: native timeline construction failed \u2014 falling back to the player measuring progress itself", e);
6623
7018
  return null;
6624
7019
  }
6625
7020
  return {
@@ -6647,7 +7042,7 @@ function documentScroller() {
6647
7042
  var SUBJECT_PARENT = "parent";
6648
7043
  var SUBJECT_SCROLLER = "scroller";
6649
7044
  function resolveScrollSubject(svgRoot, subject) {
6650
- var _a, _b;
7045
+ var _a2, _b;
6651
7046
  const spec = subject == null ? void 0 : subject.trim();
6652
7047
  if (!spec) return svgRoot;
6653
7048
  if (spec === SUBJECT_PARENT) {
@@ -6656,7 +7051,7 @@ function resolveScrollSubject(svgRoot, subject) {
6656
7051
  const position = getComputedStyle(p).position;
6657
7052
  if (position === "sticky" || position === "fixed") outermostPinned = p;
6658
7053
  }
6659
- return (_b = (_a = outermostPinned == null ? void 0 : outermostPinned.parentElement) != null ? _a : svgRoot.parentElement) != null ? _b : svgRoot;
7054
+ return (_b = (_a2 = outermostPinned == null ? void 0 : outermostPinned.parentElement) != null ? _a2 : svgRoot.parentElement) != null ? _b : svgRoot;
6660
7055
  }
6661
7056
  if (spec === SUBJECT_SCROLLER) {
6662
7057
  return findNearestScroller(svgRoot, "y") || findNearestScroller(svgRoot, "x") || documentScroller();
@@ -6675,10 +7070,10 @@ function resolveScrollSubject(svgRoot, subject) {
6675
7070
  return found;
6676
7071
  }
6677
7072
  function createScrollDriver(subject, config, onProgress) {
6678
- var _a, _b;
7073
+ var _a2, _b;
6679
7074
  if (!config || !isScrollTimeline(config)) return null;
6680
7075
  const scroll = config.scroll || {};
6681
- const kind = (_a = scroll.kind) != null ? _a : "view";
7076
+ const kind = (_a2 = scroll.kind) != null ? _a2 : "view";
6682
7077
  const measured = resolveScrollSubject(subject, scroll.subject);
6683
7078
  const nearest = findNearestScroller(subject, "y") || findNearestScroller(subject, "x");
6684
7079
  const scroller = kind === "scroll" && scroll.source === "root" ? documentScroller() : nearest || documentScroller();
@@ -6797,8 +7192,8 @@ function applyScrollPin(svgRoot, scroll) {
6797
7192
  style.position = "sticky";
6798
7193
  const alignFactor = scroll.pinAlign === "center" ? 0.5 : scroll.pinAlign === "bottom" ? 1 : 0;
6799
7194
  const applyTop = () => {
6800
- var _a;
6801
- const extra = (_a = scroll.pinTop) != null ? _a : 0;
7195
+ var _a2;
7196
+ const extra = (_a2 = scroll.pinTop) != null ? _a2 : 0;
6802
7197
  if (!alignFactor) {
6803
7198
  style.top = extra + "px";
6804
7199
  return;
@@ -6838,23 +7233,23 @@ function applyScrollPin(svgRoot, scroll) {
6838
7233
  };
6839
7234
  }
6840
7235
 
6841
- // src/PxAnimatorBind.ts
7236
+ // src/engines/PxAnimatorBind.ts
6842
7237
  function finaliseAnimator(animatorConfig, callbacks, make) {
6843
7238
  let apiRef;
6844
7239
  let effectiveCallbacks = callbacks;
6845
7240
  if (animatorConfig.resetOnFinish) {
6846
7241
  effectiveCallbacks = __spreadProps(__spreadValues({}, callbacks), {
6847
7242
  onFinish: () => {
6848
- var _a;
6849
- (_a = callbacks == null ? void 0 : callbacks.onFinish) == null ? void 0 : _a.call(callbacks);
7243
+ var _a2;
7244
+ (_a2 = callbacks == null ? void 0 : callbacks.onFinish) == null ? void 0 : _a2.call(callbacks);
6850
7245
  apiRef == null ? void 0 : apiRef.cancel();
6851
7246
  }
6852
7247
  });
6853
7248
  }
6854
7249
  const res = make(effectiveCallbacks);
6855
7250
  apiRef = res;
6856
- if (animatorConfig.debugInstName) {
6857
- window[animatorConfig.debugInstName] = res;
7251
+ if (animatorConfig.debugGlobalName) {
7252
+ window[animatorConfig.debugGlobalName] = res;
6858
7253
  }
6859
7254
  return res;
6860
7255
  }
@@ -6862,10 +7257,10 @@ function bindWithEngineChoice(doc, adapter, callbacks, rootElement) {
6862
7257
  const animatorConfig = getAnimatorConfig(doc) || {};
6863
7258
  if (isScrollTimeline(animatorConfig)) {
6864
7259
  return finaliseAnimator(animatorConfig, callbacks, (cb) => {
6865
- var _a, _b;
7260
+ var _a2;
6866
7261
  let unpin = () => {
6867
7262
  };
6868
- if (animatorConfig.mode !== PxAnimatorMode.frames && ((_a = animatorConfig.scroll) == null ? void 0 : _a.driver) === "native" && rootElement) {
7263
+ if (mayUseNativeScrollTimeline(animatorConfig.engine) && rootElement) {
6869
7264
  unpin = applyScrollPin(rootElement, animatorConfig.scroll);
6870
7265
  const native = createNativeScrollTimeline(rootElement, animatorConfig);
6871
7266
  if (native) {
@@ -6873,7 +7268,7 @@ function bindWithEngineChoice(doc, adapter, callbacks, rootElement) {
6873
7268
  doc,
6874
7269
  cb,
6875
7270
  rootElement,
6876
- animatorConfig.mode === PxAnimatorMode.waapi,
7271
+ isNativeForced(animatorConfig.engine),
6877
7272
  native
6878
7273
  );
6879
7274
  if (api2) {
@@ -6889,8 +7284,8 @@ function bindWithEngineChoice(doc, adapter, callbacks, rootElement) {
6889
7284
  unpin = () => {
6890
7285
  };
6891
7286
  }
6892
- const api = (animatorConfig.mode !== PxAnimatorMode.frames ? createWebApiAnimator(doc, cb, rootElement, animatorConfig.mode === PxAnimatorMode.waapi) : null) || createFrameLoopAnimator(doc, adapter, cb, rootElement);
6893
- const subject = ((_b = api.getRootElement) == null ? void 0 : _b.call(api)) || rootElement;
7287
+ const api = (animatorConfig.engine !== PxTimelineEngineExtra.js ? createWebApiAnimator(doc, cb, rootElement, isNativeForced(animatorConfig.engine)) : null) || createFrameLoopAnimator(doc, adapter, cb, rootElement);
7288
+ const subject = ((_a2 = api.getRootElement) == null ? void 0 : _a2.call(api)) || rootElement;
6894
7289
  if (subject) {
6895
7290
  unpin = applyScrollPin(subject, animatorConfig.scroll);
6896
7291
  const totalMs = scrollTotalDurationMs(animatorConfig);
@@ -6914,20 +7309,19 @@ function bindWithEngineChoice(doc, adapter, callbacks, rootElement) {
6914
7309
  });
6915
7310
  }
6916
7311
  return finaliseAnimator(animatorConfig, callbacks, (cb) => {
6917
- if (animatorConfig.mode === PxAnimatorMode.frames) {
7312
+ if (animatorConfig.engine === PxTimelineEngineExtra.js) {
6918
7313
  return createFrameLoopAnimator(doc, adapter, cb, rootElement);
6919
7314
  }
6920
7315
  return createWebApiAnimator(
6921
7316
  doc,
6922
7317
  cb,
6923
7318
  rootElement,
6924
- animatorConfig.mode === PxAnimatorMode.waapi
6925
- // forcing waapi
7319
+ isNativeForced(animatorConfig.engine)
6926
7320
  ) || createFrameLoopAnimator(doc, adapter, cb, rootElement);
6927
7321
  });
6928
7322
  }
6929
7323
 
6930
- // src/PxAnimatorDOM.ts
7324
+ // src/dom/PxAnimatorDOM.ts
6931
7325
  var SVG_NS = "http://www.w3.org/2000/svg";
6932
7326
  function createElement(tagName, normalisedProps, style, children, textContent) {
6933
7327
  if (DISALLOWED_SVG_TAGS_LOWER.has(tagName.toLowerCase())) {
@@ -6959,7 +7353,7 @@ function createElement(tagName, normalisedProps, style, children, textContent) {
6959
7353
  }
6960
7354
  function renderNode(node, defs) {
6961
7355
  if (!node) return null;
6962
- const _a = node, { type, children, style } = _a, props = __objRest(_a, ["type", "children", "style"]);
7356
+ const _a2 = node, { type, children, style } = _a2, props = __objRest(_a2, ["type", "children", "style"]);
6963
7357
  const domType = props.domType;
6964
7358
  if (domType !== void 0) delete props.domType;
6965
7359
  const nodeDefs = getDefs(node) || defs;
@@ -6985,18 +7379,24 @@ function renderNode(node, defs) {
6985
7379
  return element;
6986
7380
  }
6987
7381
 
6988
- // src/PxAnimatorKeys.ts
7382
+ // src/shared/PxAnimatorKeys.ts
6989
7383
  var PX_ANIMATOR_DATA_KEY = "data";
6990
7384
 
6991
- // src/PxAnimator.ts
7385
+ // src/animator/PxAnimator.ts
6992
7386
  function createAnimatorFromConfig(doc, adapter, callbacks, rootElement) {
6993
7387
  return bindWithEngineChoice(doc, adapter, callbacks, rootElement);
6994
7388
  }
6995
- function createAnimatorImpl(doc, adapter, callbacks, containerElement) {
7389
+ function createAnimatorImpl(doc, adapter, callbacks, containerElement, config, resetDocDefaults) {
6996
7390
  const effectsWarnings = validateNodeEffects(doc);
6997
7391
  for (const w of effectsWarnings) console.warn("[PxAnimator] effects shape warning:", w);
7392
+ reportDocumentDiagnostics(doc, "[PxAnimator] createAnimator");
7393
+ if (config !== void 0 || resetDocDefaults) {
7394
+ const patched = applyAnimatorConfig(doc, config != null ? config : {}, { resetDefaults: !!resetDocDefaults });
7395
+ for (const w of patched.warnings) console.warn("[PxAnimator] config override:", w);
7396
+ doc = patched.doc;
7397
+ }
6998
7398
  const animatorConfig = getAnimatorConfig(doc) || {};
6999
- const engine = animatorConfig.mode === PxAnimatorMode.frames ? PxAnimatorEngine.frames : PxAnimatorEngine.waapi;
7399
+ const engine = resolveTimelineEngine(animatorConfig.engine);
7000
7400
  doc = materialiseAllInTree(doc, engine);
7001
7401
  let rootElement = null;
7002
7402
  if (containerElement) {
@@ -7009,10 +7409,24 @@ function createAnimatorImpl(doc, adapter, callbacks, containerElement) {
7009
7409
  }
7010
7410
  }
7011
7411
  }
7012
- return createAnimatorFromConfig(doc, adapter, callbacks, rootElement);
7412
+ const api = createAnimatorFromConfig(doc, adapter, callbacks, rootElement);
7413
+ if (containerElement && rootElement) {
7414
+ const rendered = rootElement;
7415
+ const destroyNative = api.destroy.bind(api);
7416
+ api.destroy = () => {
7417
+ destroyNative();
7418
+ rendered.remove();
7419
+ };
7420
+ }
7421
+ return api;
7422
+ }
7423
+ function resolveAnimatorConfigOption(options) {
7424
+ const { config, duration, delay, iterations, startOn } = options;
7425
+ return foldAnimatorConfigShortcuts(config, { duration, delay, iterations, startOn });
7013
7426
  }
7014
7427
  function createAnimator(options) {
7015
- const { src, data, adapter, callbacks, container } = options;
7428
+ const { src, data, adapter, callbacks, container, resetDocDefaults } = options;
7429
+ const config = resolveAnimatorConfigOption(options);
7016
7430
  if (data !== void 0 && src !== void 0) {
7017
7431
  throw new Error("createAnimator: provide either `src` or `data`, not both");
7018
7432
  }
@@ -7020,7 +7434,7 @@ function createAnimator(options) {
7020
7434
  throw new Error("createAnimator: either `src` or `data` is required");
7021
7435
  }
7022
7436
  if (data !== void 0) {
7023
- return createAnimatorImpl(data, adapter, callbacks, container);
7437
+ return createAnimatorImpl(data, adapter, callbacks, container, config, resetDocDefaults);
7024
7438
  }
7025
7439
  let animator = null;
7026
7440
  let pending = [];
@@ -7035,7 +7449,7 @@ function createAnimator(options) {
7035
7449
  fetch(src).then((res) => res.json()).then((json) => {
7036
7450
  if (destroyed) return;
7037
7451
  if (isPxElementFileFormat(json)) {
7038
- animator = createAnimatorImpl(json, adapter, callbacks, container);
7452
+ animator = createAnimatorImpl(json, adapter, callbacks, container, config, resetDocDefaults);
7039
7453
  const queued = pending;
7040
7454
  pending = null;
7041
7455
  queued == null ? void 0 : queued.forEach((call) => call(animator));
@@ -7104,12 +7518,11 @@ if (typeof window !== "undefined") {
7104
7518
  PxAnimatedSvgDocumentSchema,
7105
7519
  PxAnimationDefinitionSchema,
7106
7520
  PxAnimatorConfigSchema,
7107
- PxAnimatorEngine,
7108
- PxAnimatorMode,
7109
7521
  PxAttrValueSchema,
7110
7522
  PxBezierPathSchema,
7111
7523
  PxBindingSchema,
7112
7524
  PxCloneEffectSchema,
7525
+ PxCloneWithout,
7113
7526
  PxDefsSchema,
7114
7527
  PxEasingOrRefSchema,
7115
7528
  PxEffectsSchema,
@@ -7121,6 +7534,8 @@ if (typeof window !== "undefined") {
7121
7534
  PxGradientUnits,
7122
7535
  PxKeyframeSchema,
7123
7536
  PxKeyframeValueSchema,
7537
+ PxLoopDirection,
7538
+ PxLoopRepeatAt,
7124
7539
  PxLoopSchema,
7125
7540
  PxMaskedByEffectSchema,
7126
7541
  PxNodeBase,
@@ -7130,15 +7545,19 @@ if (typeof window !== "undefined") {
7130
7545
  PxRetimeEffectSchema,
7131
7546
  PxStrokeGradientEffectSchema,
7132
7547
  PxStrokeTrimEffectSchema,
7548
+ PxStrokeTrimSubPaths,
7133
7549
  PxSvgNodeExtra,
7134
7550
  PxTextEffectSchema,
7135
7551
  PxTextPathEffectSchema,
7552
+ PxTimelineEngine,
7553
+ PxTimelineEngineExtra,
7136
7554
  PxTransformByEffectSchema,
7137
7555
  PxTransformPartsSchema,
7138
7556
  PxTransformValueSchema,
7139
7557
  PxTriggerSchema,
7140
7558
  STYLE_ATTR_NAMES,
7141
7559
  TRANSFORM_FN_NAMES,
7560
+ applyAnimatorConfig,
7142
7561
  applyPlayerEffects,
7143
7562
  calcAnimationValues,
7144
7563
  camelCaseToKebabWordIfNeeded,
@@ -7153,6 +7572,7 @@ if (typeof window !== "undefined") {
7153
7572
  diffInEffect,
7154
7573
  evaluateMotionPathSegment,
7155
7574
  extendedPathForBrowser,
7575
+ foldAnimatorConfigShortcuts,
7156
7576
  generateNewIds,
7157
7577
  getAnimatorConfig,
7158
7578
  getBindings,
@@ -7173,6 +7593,7 @@ if (typeof window !== "undefined") {
7173
7593
  materialiseInternalLoopsInTree,
7174
7594
  materialiseMotionPathInPropAnim,
7175
7595
  materialiseMotionPathsInTree,
7596
+ mergeAnimatorConfig,
7176
7597
  normalizeDocument,
7177
7598
  propAnimIsMotionPath,
7178
7599
  px,
@@ -7181,6 +7602,7 @@ if (typeof window !== "undefined") {
7181
7602
  setupAnimationTriggers,
7182
7603
  shiftAnimatable,
7183
7604
  toRGBA,
7605
+ validateDocument,
7184
7606
  validateNodeEffects,
7185
7607
  visualModelAt
7186
7608
  });