@pixodesk/svg-animator-web 1.0.34 → 1.0.39

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.js CHANGED
@@ -64,7 +64,7 @@ var __objRest2 = (source, exclude) => {
64
64
  return target;
65
65
  };
66
66
  function bezierToSvgPath(path, forceCurves = false) {
67
- var _a, _b, _c, _d;
67
+ var _a2, _b, _c, _d;
68
68
  const v = path.v;
69
69
  const i = path.i;
70
70
  const o = path.o;
@@ -75,7 +75,7 @@ function bezierToSvgPath(path, forceCurves = false) {
75
75
  d.push("M" + v[0][0] + "," + v[0][1]);
76
76
  for (let idx = 1; idx < len; idx++) {
77
77
  const prevV = v[idx - 1];
78
- const prevO = (_a = o == null ? void 0 : o[idx - 1]) != null ? _a : prevV;
78
+ const prevO = (_a2 = o == null ? void 0 : o[idx - 1]) != null ? _a2 : prevV;
79
79
  const currI = (_b = i == null ? void 0 : i[idx]) != null ? _b : v[idx];
80
80
  const currV = v[idx];
81
81
  const isLine = !forceCurves && (prevO[0] === prevV[0] && prevO[1] === prevV[1]) && (currI[0] === currV[0] && currI[1] === currV[1]);
@@ -126,7 +126,7 @@ function interpolateBeziers(paths1, paths2, progress) {
126
126
  return res;
127
127
  }
128
128
  function interpolateBezier(path1, path2, progress) {
129
- var _a, _b, _c, _d, _e, _f, _g, _h, _i;
129
+ var _a2, _b, _c, _d, _e, _f, _g, _h, _i;
130
130
  if (!path1 || !path2) return path1 || path2 || { v: [] };
131
131
  const t = Math.min(Math.max(progress, 0), 1);
132
132
  const len = Math.min(path1.v.length, path2.v.length);
@@ -137,7 +137,7 @@ function interpolateBezier(path1, path2, progress) {
137
137
  const v1 = path1.v[idx];
138
138
  const v2 = path2.v[idx];
139
139
  v.push(interpolateVec(v1, v2, t));
140
- const i1 = (_b = (_a = path1.i) == null ? void 0 : _a[idx]) != null ? _b : v1;
140
+ const i1 = (_b = (_a2 = path1.i) == null ? void 0 : _a2[idx]) != null ? _b : v1;
141
141
  const i2 = (_d = (_c = path2.i) == null ? void 0 : _c[idx]) != null ? _d : v2;
142
142
  i.push(interpolateVec(i1, i2, t));
143
143
  const o1 = (_f = (_e = path1.o) == null ? void 0 : _e[idx]) != null ? _f : v1;
@@ -256,8 +256,8 @@ function toRGBA(color) {
256
256
  return color.length === 4 ? "rgba(" + r + "," + g + "," + b + "," + color[3] + ")" : "rgb(" + r + "," + g + "," + b + ")";
257
257
  }
258
258
  function parseRgba(s) {
259
- var _a;
260
- const inner = (_a = s.match(/rgba?\((.*)\)/)) == null ? void 0 : _a[1];
259
+ var _a2;
260
+ const inner = (_a2 = s.match(/rgba?\((.*)\)/)) == null ? void 0 : _a2[1];
261
261
  if (!inner) throw new Error("Invalid rgb/rgba format");
262
262
  const parts = inner.split(",").map((v) => +v.trim());
263
263
  return [parts[0] / 255, parts[1] / 255, parts[2] / 255, ...parts[3] !== void 0 ? [parts[3]] : []];
@@ -292,13 +292,13 @@ function parseColor(s) {
292
292
  }
293
293
  return void 0;
294
294
  }
295
- var COLOUR_ATTR_NAMES = /* @__PURE__ */ new Set(["color", "fill", "flood-color", "lighting-color", "stop-color", "stroke"]);
295
+ var COLOR_ATTR_NAMES = /* @__PURE__ */ new Set(["color", "fill", "flood-color", "lighting-color", "stop-color", "stroke"]);
296
296
  var TRANSFORM_FN_NAMES = /* @__PURE__ */ new Set(["translate", "rotate", "scale", "skew"]);
297
297
  var PCT_BASED_ATTR_NAMES = /* @__PURE__ */ new Set(["offset-distance", "offsetDistance"]);
298
298
  function composeTransformParts(parts, opts) {
299
- var _a;
299
+ var _a2;
300
300
  if (!parts) return "";
301
- const withUnits = (_a = opts == null ? void 0 : opts.withUnits) != null ? _a : true;
301
+ const withUnits = (_a2 = opts == null ? void 0 : opts.withUnits) != null ? _a2 : true;
302
302
  const segs = [];
303
303
  const t = parts.translate;
304
304
  const o = parts.origin;
@@ -316,7 +316,7 @@ function composeTransformParts(parts, opts) {
316
316
  return segs.join("");
317
317
  }
318
318
  function parseTransformParts(str2) {
319
- var _a, _b;
319
+ var _a2, _b;
320
320
  if (!str2 || typeof str2 !== "string") return void 0;
321
321
  const out = {};
322
322
  const re = /([a-zA-Z]+)\s*\(([^)]*)\)/g;
@@ -332,7 +332,7 @@ function parseTransformParts(str2) {
332
332
  if (nums.some((n) => Number.isNaN(n))) return void 0;
333
333
  if (fn === "translate") {
334
334
  if (nums.length < 1 || nums.length > 2) return void 0;
335
- out.translate = [nums[0], (_a = nums[1]) != null ? _a : 0];
335
+ out.translate = [nums[0], (_a2 = nums[1]) != null ? _a2 : 0];
336
336
  } else if (fn === "rotate") {
337
337
  if (nums.length !== 1) return void 0;
338
338
  out.rotate = nums[0];
@@ -536,8 +536,8 @@ function scrollPhaseInterval(phase, subjectSize, scrollportSize) {
536
536
  }
537
537
  var DEFAULT_PHASE = "cover";
538
538
  function resolveRangePointU(point, defaultFraction, subjectSize, scrollportSize) {
539
- var _a;
540
- const [u0, u1] = scrollPhaseInterval((_a = point == null ? void 0 : point.phase) != null ? _a : DEFAULT_PHASE, subjectSize, scrollportSize);
539
+ var _a2;
540
+ const [u0, u1] = scrollPhaseInterval((_a2 = point == null ? void 0 : point.phase) != null ? _a2 : DEFAULT_PHASE, subjectSize, scrollportSize);
541
541
  const fraction = typeof (point == null ? void 0 : point.fraction) === "number" ? point.fraction : defaultFraction;
542
542
  return u0 + fraction * (u1 - u0);
543
543
  }
@@ -549,9 +549,9 @@ function scrollViewProgress(subjectStart, subjectSize, scrollportSize, range) {
549
549
  return clamp((u - uStart) / (uEnd - uStart), 0, 1);
550
550
  }
551
551
  function scrollOffsetProgress(offset, maxOffset, range) {
552
- var _a, _b;
552
+ var _a2, _b;
553
553
  const raw = maxOffset > 0 ? clamp(offset / maxOffset, 0, 1) : 1;
554
- const start = typeof ((_a = range == null ? void 0 : range.start) == null ? void 0 : _a.fraction) === "number" ? range.start.fraction : 0;
554
+ const start = typeof ((_a2 = range == null ? void 0 : range.start) == null ? void 0 : _a2.fraction) === "number" ? range.start.fraction : 0;
555
555
  const end = typeof ((_b = range == null ? void 0 : range.end) == null ? void 0 : _b.fraction) === "number" ? range.end.fraction : 1;
556
556
  if (end <= start) return raw >= end ? 1 : 0;
557
557
  return clamp((raw - start) / (end - start), 0, 1);
@@ -563,6 +563,7 @@ function scrollResolveAxis(axis, writingMode) {
563
563
  if (a === "inline") return vertical ? "y" : "x";
564
564
  return vertical ? "x" : "y";
565
565
  }
566
+ var PX_UNKNOWN_KEY_ERROR = "unexpected extra key";
566
567
  function pathStr(path) {
567
568
  if (!path.length) return ".";
568
569
  let result = "";
@@ -670,6 +671,7 @@ var Enum = class extends Base {
670
671
  return false;
671
672
  }
672
673
  };
674
+ var UNION_MEMBER_ERROR_LIMIT = 4;
673
675
  var Union = class extends Base {
674
676
  constructor(schemas, defaultVal) {
675
677
  super();
@@ -684,10 +686,38 @@ var Union = class extends Base {
684
686
  return this._default;
685
687
  }
686
688
  isValid(raw, ctx, path) {
687
- var _a;
689
+ var _a2;
688
690
  const probe = ctx && { errors: [], warnings: [], strict: ctx.strict };
689
691
  if (this.schemas.some((s) => s.isValid(raw, probe, path ? [...path] : void 0))) return true;
690
- 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));
692
+ if (!ctx) return false;
693
+ const base = pathStr(path != null ? path : []);
694
+ ctx.errors.push(base + ": no union member matched for value " + ((_a2 = JSON.stringify(raw)) != null ? _a2 : "").slice(0, 240));
695
+ let best;
696
+ let bestDepth = -1;
697
+ const leafExpectations = [];
698
+ for (const member of this.schemas) {
699
+ const sink = { errors: [], warnings: [], strict: ctx.strict };
700
+ member.isValid(raw, sink, path ? [...path] : void 0);
701
+ if (!sink.errors.length) continue;
702
+ const depth = Math.max(...sink.errors.map((e) => e.slice(0, e.indexOf(":")).length));
703
+ if (depth > bestDepth || depth === bestDepth && best && sink.errors.length < best.length) {
704
+ bestDepth = depth;
705
+ best = sink.errors;
706
+ }
707
+ if (depth <= base.length) {
708
+ for (const e of sink.errors) {
709
+ const m = /: expected (.+?), got /.exec(e);
710
+ if (m && !leafExpectations.includes(m[1])) leafExpectations.push(m[1]);
711
+ }
712
+ }
713
+ }
714
+ if (best && bestDepth > base.length) {
715
+ for (const e of best.slice(0, UNION_MEMBER_ERROR_LIMIT)) {
716
+ if (!ctx.errors.includes(e)) ctx.errors.push(e);
717
+ }
718
+ } else if (leafExpectations.length) {
719
+ ctx.errors.push(base + ": expected " + leafExpectations.join(" | "));
720
+ }
691
721
  return false;
692
722
  }
693
723
  _canSanitize(raw) {
@@ -696,6 +726,7 @@ var Union = class extends Base {
696
726
  };
697
727
  var DiscriminatedUnion = class extends Base {
698
728
  constructor(_key, _schemas, defaultVal) {
729
+ var _a2;
699
730
  super();
700
731
  this._key = _key;
701
732
  this._schemas = _schemas;
@@ -704,18 +735,21 @@ var DiscriminatedUnion = class extends Base {
704
735
  this._map = /* @__PURE__ */ new Map();
705
736
  for (const s of _schemas) {
706
737
  const keySchema = s._shape[_key];
707
- if (keySchema) this._map.set(keySchema._default, s);
738
+ if (!keySchema) continue;
739
+ const literal = (_a2 = keySchema.inner) != null ? _a2 : keySchema;
740
+ this._map.set(literal._default, s);
741
+ if (keySchema.inner) this._absentMember = s;
708
742
  }
709
743
  }
710
744
  _findSchema(raw) {
711
745
  if (raw === null || typeof raw !== "object" || Array.isArray(raw)) return void 0;
712
746
  const val = raw[this._key];
713
- if (val === void 0 || val === null) return void 0;
747
+ if (val === void 0 || val === null) return this._absentMember;
714
748
  return this._map.get(val);
715
749
  }
716
750
  sanitize(raw) {
717
- var _a;
718
- return ((_a = this._findSchema(raw)) != null ? _a : this._schemas[0]).sanitize(raw);
751
+ var _a2;
752
+ return ((_a2 = this._findSchema(raw)) != null ? _a2 : this._schemas[0]).sanitize(raw);
719
753
  }
720
754
  isValid(raw, ctx, path) {
721
755
  const schema = this._findSchema(raw);
@@ -744,7 +778,8 @@ var Obj = class extends Base {
744
778
  const src = raw && typeof raw === "object" && !Array.isArray(raw) ? raw : {};
745
779
  const out = {};
746
780
  for (const key of Object.keys(this._shape)) {
747
- out[key] = this._shape[key].sanitize(src[key]);
781
+ const v = this._shape[key].sanitize(src[key]);
782
+ if (v !== void 0) out[key] = v;
748
783
  }
749
784
  return out;
750
785
  }
@@ -766,7 +801,7 @@ var Obj = class extends Base {
766
801
  if (key in this._shape) continue;
767
802
  if (obj[key] === void 0) continue;
768
803
  p.push(key);
769
- ctx.errors.push(pathStr(p) + ": unexpected extra key");
804
+ ctx.errors.push(pathStr(p) + ": " + PX_UNKNOWN_KEY_ERROR);
770
805
  p.pop();
771
806
  ok = false;
772
807
  }
@@ -790,7 +825,8 @@ var OpenObj = class extends Base {
790
825
  const src = raw && typeof raw === "object" && !Array.isArray(raw) ? raw : {};
791
826
  const out = __spreadValues2({}, src);
792
827
  for (const key of Object.keys(this._shape)) {
793
- out[key] = this._shape[key].sanitize(src[key]);
828
+ const v = this._shape[key].sanitize(src[key]);
829
+ if (v !== void 0) out[key] = v;
794
830
  }
795
831
  if (this._openSchema) {
796
832
  for (const key of Object.keys(src)) {
@@ -931,8 +967,8 @@ var Lazy = class extends Base {
931
967
  this.resolved = null;
932
968
  }
933
969
  get schema() {
934
- var _a;
935
- return (_a = this.resolved) != null ? _a : this.resolved = this.fn();
970
+ var _a2;
971
+ return (_a2 = this.resolved) != null ? _a2 : this.resolved = this.fn();
936
972
  }
937
973
  sanitize(raw) {
938
974
  return this.schema.sanitize(raw);
@@ -983,7 +1019,7 @@ function schemaKeys(schema) {
983
1019
  );
984
1020
  }
985
1021
  function describeSchema(schema) {
986
- var _a;
1022
+ var _a2;
987
1023
  const s = schema;
988
1024
  switch (s._kind) {
989
1025
  case "union":
@@ -998,7 +1034,7 @@ function describeSchema(schema) {
998
1034
  if ("_shape" in s) return { kind: "shape", shape: s._shape, openValue: s._openSchema };
999
1035
  if ("item" in s) return { kind: "array", item: s.item };
1000
1036
  if ("inner" in s) return { kind: "optional", inner: s.inner };
1001
- if ("fn" in s) return { kind: "lazy", resolved: (_a = s.resolved) != null ? _a : s.resolved = s.fn() };
1037
+ if ("fn" in s) return { kind: "lazy", resolved: (_a2 = s.resolved) != null ? _a2 : s.resolved = s.fn() };
1002
1038
  return { kind: "leaf" };
1003
1039
  }
1004
1040
  var px = {
@@ -1052,24 +1088,327 @@ var px = {
1052
1088
  /** Defers schema creation — required for recursive types. Must supply a default value. */
1053
1089
  lazy: (fn, defaultVal) => new Lazy(fn, defaultVal)
1054
1090
  };
1091
+ var PX_PLAYER_SCHEMA_VERSION = "1.1";
1092
+ var WIRE_VERSION_KEY = "version";
1093
+ var ANIMATOR_KEY = "animator";
1094
+ var META_KEY = "meta";
1095
+ var WireVersionRelation = /* @__PURE__ */ ((WireVersionRelation2) => {
1096
+ WireVersionRelation2["unstamped"] = "unstamped";
1097
+ WireVersionRelation2["same"] = "same";
1098
+ WireVersionRelation2["older"] = "older";
1099
+ WireVersionRelation2["newer"] = "newer";
1100
+ WireVersionRelation2["otherGeneration"] = "otherGeneration";
1101
+ return WireVersionRelation2;
1102
+ })(WireVersionRelation || {});
1103
+ var VERSION_RE = /^(\d+)\.(\d+)(?:\.(\d+))?$/;
1104
+ function parseWireVersion(raw) {
1105
+ if (typeof raw !== "string") return void 0;
1106
+ const m = VERSION_RE.exec(raw.trim());
1107
+ if (!m) return void 0;
1108
+ return { a: Number(m[1]), b: Number(m[2]), c: m[3] === void 0 ? 0 : Number(m[3]) };
1109
+ }
1110
+ function formatWireVersion(v) {
1111
+ return v.a + "." + v.b + "." + v.c;
1112
+ }
1113
+ var _a;
1114
+ var PLAYER_WIRE_VERSION = (_a = parseWireVersion(PX_PLAYER_SCHEMA_VERSION)) != null ? _a : { a: 1, b: 1, c: 0 };
1115
+ function getAnimatorBlock(doc) {
1116
+ if (!doc || typeof doc !== "object") return void 0;
1117
+ const atRoot = readObjectProp(doc, ANIMATOR_KEY);
1118
+ if (atRoot) return atRoot;
1119
+ const meta = readObjectProp(doc, META_KEY);
1120
+ return meta ? readObjectProp(meta, ANIMATOR_KEY) : void 0;
1121
+ }
1122
+ function readObjectProp(obj, key) {
1123
+ const value = obj[key];
1124
+ return value && typeof value === "object" && !Array.isArray(value) ? value : void 0;
1125
+ }
1126
+ function readWireVersion(doc) {
1127
+ const animator = getAnimatorBlock(doc);
1128
+ return animator ? parseWireVersion(animator[WIRE_VERSION_KEY]) : void 0;
1129
+ }
1130
+ function compareWireVersion(file, mine, readerReadsEditorPart) {
1131
+ if (!file) return "unstamped";
1132
+ if (file.a !== mine.a) return "otherGeneration";
1133
+ if (file.b !== mine.b) return file.b > mine.b ? "newer" : "older";
1134
+ if (!readerReadsEditorPart || file.c === mine.c) return "same";
1135
+ return file.c > mine.c ? "newer" : "older";
1136
+ }
1137
+ function versionAdvice(relation, file, mine, isPlayer) {
1138
+ if (!file) return void 0;
1139
+ const target = isPlayer ? "player" : "editor";
1140
+ const gap = "written for schema " + formatWireVersion(file) + ", this " + target + " reads " + formatWireVersion(mine);
1141
+ switch (relation) {
1142
+ case "newer":
1143
+ return "This file is " + gap + ". Update the " + target + " to open it fully.";
1144
+ case "older":
1145
+ return "This file is " + gap + ". Saving it from this " + target + " rewrites it in the current format.";
1146
+ case "otherGeneration":
1147
+ return "This file is " + gap + " \u2014 a different format generation, which no conversion bridges. Open it in a " + target + " of that generation, or accept this document without the parts named above.";
1148
+ default:
1149
+ return void 0;
1150
+ }
1151
+ }
1152
+ var WireStepKind = /* @__PURE__ */ ((WireStepKind2) => {
1153
+ WireStepKind2["additive"] = "additive";
1154
+ WireStepKind2["converted"] = "converted";
1155
+ return WireStepKind2;
1156
+ })(WireStepKind || {});
1157
+ var BASELINE_PLAYER_VERSION = "1.1";
1158
+ var PLAYER_WIRE_STEPS = [];
1159
+ function applyWireSteps(doc, cfg) {
1160
+ const from = readWireVersion(doc);
1161
+ const relation = compareWireVersion(from, cfg.target, cfg.readerReadsEditorPart);
1162
+ if (!from || relation !== "older") {
1163
+ return {
1164
+ doc,
1165
+ from,
1166
+ relation,
1167
+ applied: [],
1168
+ advice: versionAdvice(relation, from, cfg.target, !cfg.readerReadsEditorPart)
1169
+ };
1170
+ }
1171
+ const due = [];
1172
+ for (const step of cfg.steps) {
1173
+ const stepTo = parseWireVersion(step.to);
1174
+ if (!stepTo) continue;
1175
+ if (compareWireVersion(from, stepTo, cfg.readerReadsEditorPart) !== "older") continue;
1176
+ if (!step.up) continue;
1177
+ due.push(step);
1178
+ }
1179
+ if (!due.length || !doc || typeof doc !== "object") return { doc, from, relation, applied: [] };
1180
+ const target = clonePlain(doc);
1181
+ const applied = [];
1182
+ for (const step of due) {
1183
+ try {
1184
+ step.up(target);
1185
+ applied.push(step);
1186
+ } catch (e) {
1187
+ break;
1188
+ }
1189
+ }
1190
+ if (!applied.length) return { doc, from, relation, applied: [] };
1191
+ stampVersion(target, cfg.target, cfg.readerReadsEditorPart);
1192
+ return { doc: target, from, relation, applied };
1193
+ }
1194
+ function convertPlayerDocument(doc) {
1195
+ return applyWireSteps(doc, {
1196
+ steps: PLAYER_WIRE_STEPS,
1197
+ target: PLAYER_WIRE_VERSION,
1198
+ readerReadsEditorPart: false
1199
+ });
1200
+ }
1201
+ function clonePlain(value) {
1202
+ const structured = globalThis.structuredClone;
1203
+ return structured ? structured(value) : JSON.parse(JSON.stringify(value));
1204
+ }
1205
+ function stampVersion(doc, target, readerReadsEditorPart) {
1206
+ const animator = getAnimatorBlock(doc);
1207
+ if (!animator) return;
1208
+ const previous = parseWireVersion(animator[WIRE_VERSION_KEY]);
1209
+ animator[WIRE_VERSION_KEY] = formatWireVersion({
1210
+ a: target.a,
1211
+ b: target.b,
1212
+ c: readerReadsEditorPart ? target.c : previous ? previous.c : 0
1213
+ });
1214
+ }
1215
+ function applyWireStepsDown(doc, cfg) {
1216
+ const from = readWireVersion(doc);
1217
+ if (!from) {
1218
+ return { ok: false, blocking: [], reason: "The document carries no version, so there is nothing to convert down from." };
1219
+ }
1220
+ const relation = compareWireVersion(from, cfg.target, cfg.readerReadsEditorPart);
1221
+ if (relation === "otherGeneration") {
1222
+ return {
1223
+ ok: false,
1224
+ blocking: [],
1225
+ reason: "Schema " + formatWireVersion(from) + " and " + formatWireVersion(cfg.target) + " are different generations; no conversion bridges them."
1226
+ };
1227
+ }
1228
+ if (relation !== "newer") return { ok: true, doc, applied: [] };
1229
+ const toUndo = [];
1230
+ for (const step of cfg.steps) {
1231
+ const stepTo = parseWireVersion(step.to);
1232
+ if (!stepTo) continue;
1233
+ if (compareWireVersion(stepTo, cfg.target, cfg.readerReadsEditorPart) !== "newer") continue;
1234
+ if (compareWireVersion(stepTo, from, cfg.readerReadsEditorPart) === "newer") continue;
1235
+ toUndo.push(step);
1236
+ }
1237
+ toUndo.reverse();
1238
+ const blocking = toUndo.filter((s) => s.kind === "converted" && !s.down);
1239
+ if (blocking.length) {
1240
+ return {
1241
+ ok: false,
1242
+ blocking,
1243
+ reason: "Cannot convert down to " + formatWireVersion(cfg.target) + ": " + blocking.map((s) => s.from + " \u2192 " + s.to + " (" + s.reason + ")").join("; ") + " cannot be undone."
1244
+ };
1245
+ }
1246
+ const target = clonePlain(doc);
1247
+ const applied = [];
1248
+ for (const step of toUndo) {
1249
+ if (!step.down) continue;
1250
+ try {
1251
+ step.down(target);
1252
+ applied.push(step);
1253
+ } catch (e) {
1254
+ return {
1255
+ ok: false,
1256
+ blocking: [step],
1257
+ reason: "Undoing " + step.from + " \u2192 " + step.to + " failed: " + String(e)
1258
+ };
1259
+ }
1260
+ }
1261
+ stampVersion(target, cfg.target, cfg.readerReadsEditorPart);
1262
+ return { ok: true, doc: target, applied };
1263
+ }
1264
+ function downgradePlayerDocument(doc, target) {
1265
+ return applyWireStepsDown(doc, { steps: PLAYER_WIRE_STEPS, target, readerReadsEditorPart: false });
1266
+ }
1267
+ var PxFillMode = {
1268
+ forwards: "forwards",
1269
+ backwards: "backwards",
1270
+ both: "both",
1271
+ none: "none"
1272
+ };
1273
+ var PxPlaybackDirection = {
1274
+ normal: "normal",
1275
+ reverse: "reverse",
1276
+ alternate: "alternate",
1277
+ alternateReverse: "alternate-reverse"
1278
+ };
1055
1279
  var PX_ANIM_SRC_ATTR_NAME = "data-px-animation-src";
1056
1280
  var PX_ANIM_ATTR_NAME = "_px_animator";
1057
- var PxAnimatorMode = {
1058
- auto: "auto",
1059
- waapi: "waapi",
1060
- frames: "frames"
1281
+ var PxStartOn = {
1282
+ load: "load",
1283
+ mouseOver: "mouseOver",
1284
+ click: "click",
1285
+ scrollIntoView: "scrollIntoView",
1286
+ programmatic: "programmatic"
1287
+ };
1288
+ var PxOutAction = {
1289
+ continue: "continue",
1290
+ pause: "pause",
1291
+ reset: "reset",
1292
+ reverse: "reverse"
1293
+ };
1294
+ var PxFinishAction = {
1295
+ hold: "hold",
1296
+ reset: "reset"
1297
+ };
1298
+ var PxScrollKind = {
1299
+ view: "view",
1300
+ scroll: "scroll"
1301
+ };
1302
+ var PxScrollAxis = {
1303
+ block: "block",
1304
+ inline: "inline",
1305
+ x: "x",
1306
+ y: "y"
1061
1307
  };
1062
- var PxAnimatorEngine = {
1063
- waapi: PxAnimatorMode.waapi,
1064
- frames: PxAnimatorMode.frames
1308
+ var PxScrollSource = {
1309
+ nearest: "nearest",
1310
+ root: "root"
1311
+ };
1312
+ var PxPinAlign = {
1313
+ top: "top",
1314
+ center: "center",
1315
+ bottom: "bottom"
1316
+ };
1317
+ var PxScrollPhase = {
1318
+ cover: "cover",
1319
+ contain: "contain",
1320
+ entry: "entry",
1321
+ exit: "exit",
1322
+ entryCrossing: "entry-crossing",
1323
+ exitCrossing: "exit-crossing"
1324
+ };
1325
+ var PxAlongPathMode = {
1326
+ sampled: "sampled",
1327
+ offsetPath: "offsetPath"
1328
+ };
1329
+ var PX_TIMELINE_SHARED_KEYS = ["duration", "iterations", "engine", "frameRate"];
1330
+ var PX_TIME_ONLY_TIMELINE_KEYS = ["trigger", "delay", "fillMode", "direction"];
1331
+ var PX_FLAT_RUNTIME_VIEW_KEYS = [
1332
+ ...PX_TIMELINE_SHARED_KEYS,
1333
+ ...PX_TIME_ONLY_TIMELINE_KEYS,
1334
+ "fill",
1335
+ "resetOnFinish",
1336
+ "timelineSource",
1337
+ "scroll"
1338
+ ];
1339
+ var PxTimelineEngine = {
1340
+ native: "native",
1341
+ js: "js"
1342
+ };
1343
+ var PxTimelineEngineExtra = __spreadProps2(__spreadValues2({}, PxTimelineEngine), {
1344
+ auto: "auto"
1345
+ });
1346
+ function resolveTimelineEngine(engine) {
1347
+ return engine === PxTimelineEngineExtra.js ? PxTimelineEngine.js : PxTimelineEngine.native;
1348
+ }
1349
+ function isNativeForced(engine) {
1350
+ return engine === PxTimelineEngineExtra.native;
1351
+ }
1352
+ function mayUseNativeScrollTimeline(engine) {
1353
+ return engine !== PxTimelineEngineExtra.js;
1354
+ }
1355
+ var PX_TRIGGER_DEFAULTS = {
1356
+ startOn: "load",
1357
+ outAction: "continue",
1358
+ scrollIntoViewThreshold: 0
1359
+ };
1360
+ var PxControlMode = {
1361
+ /** No control props — the document's trigger decides, and nothing is taken over. */
1362
+ static: "static",
1363
+ /** `progress` / `time` — the host scrubs; the component seeks and stays paused. */
1364
+ fixedTime: "fixedTime",
1365
+ /** `play` / `pause` — the host drives playback with booleans. */
1366
+ play: "play",
1367
+ /** `autoplay` — the document's own trigger starts it. */
1368
+ autoplay: "autoplay"
1369
+ };
1370
+ function resolveControlMode(props) {
1371
+ const hasFixedTime = props.progress !== void 0 || props.time !== void 0;
1372
+ const hasPlayPause = props.play !== void 0 || props.pause !== void 0;
1373
+ const hasAutoplay = !!props.autoplay;
1374
+ const warnings = [];
1375
+ const named = (a, b, winner) => a + " and " + b + " were both set \u2014 " + winner + " wins, " + (winner === a ? b : a) + " is ignored.";
1376
+ if (hasFixedTime) {
1377
+ if (hasPlayPause) warnings.push(named("progress/time", "play/pause", "progress/time"));
1378
+ if (hasAutoplay) warnings.push(named("progress/time", "autoplay", "progress/time"));
1379
+ return { mode: PxControlMode.fixedTime, warnings };
1380
+ }
1381
+ if (hasPlayPause) {
1382
+ if (hasAutoplay) warnings.push(named("play/pause", "autoplay", "play/pause"));
1383
+ return { mode: PxControlMode.play, warnings };
1384
+ }
1385
+ if (hasAutoplay) return { mode: PxControlMode.autoplay, warnings };
1386
+ return { mode: PxControlMode.static, warnings };
1387
+ }
1388
+ function controlModeTakesOverTrigger(mode) {
1389
+ return mode !== PxControlMode.autoplay;
1390
+ }
1391
+ function resolveTrigger(trigger) {
1392
+ var _a2, _b, _c;
1393
+ return {
1394
+ startOn: (_a2 = trigger == null ? void 0 : trigger.startOn) != null ? _a2 : PX_TRIGGER_DEFAULTS.startOn,
1395
+ outAction: (_b = trigger == null ? void 0 : trigger.outAction) != null ? _b : PX_TRIGGER_DEFAULTS.outAction,
1396
+ scrollIntoViewThreshold: (_c = trigger == null ? void 0 : trigger.scrollIntoViewThreshold) != null ? _c : PX_TRIGGER_DEFAULTS.scrollIntoViewThreshold
1397
+ };
1398
+ }
1399
+ var PxLoopRepeatAt = {
1400
+ /** Segment from the START; the repetition runs BEFORE the first keyframe
1401
+ * (intro loops that play until the main timeline begins). */
1402
+ start: "start",
1403
+ /** DEFAULT — segment from the END; the repetition runs AFTER the last keyframe
1404
+ * (idle/outro loops that continue once the main timeline has finished). */
1405
+ end: "end"
1065
1406
  };
1066
- var PxLoopExtend = {
1067
- /** Segment from the START; the animation is extended BEFORE the first keyframe
1068
- * (intro loops that run before the main timeline begins). */
1069
- before: "before",
1070
- /** DEFAULT — segment from the END; extended AFTER the last keyframe (idle/outro
1071
- * loops that continue once the main timeline has finished). */
1072
- after: "after"
1407
+ var PxLoopDirection = {
1408
+ /** DEFAULT — cycle: every repetition replays the segment the same way round. */
1409
+ normal: "normal",
1410
+ /** Ping-pong: repetitions alternate forward / backward. */
1411
+ alternate: "alternate"
1073
1412
  };
1074
1413
  var PxMaskType = {
1075
1414
  luminance: "luminance",
@@ -1079,8 +1418,9 @@ var PxUnits = {
1079
1418
  userSpaceOnUse: "userSpaceOnUse",
1080
1419
  objectBoundingBox: "objectBoundingBox"
1081
1420
  };
1082
- var PxCloneType = {
1083
- content: "content"
1421
+ var PxCloneWithout = {
1422
+ translate: "translate"
1423
+ // transform: 'transform', // future: drop rotate/scale too (content only)
1084
1424
  };
1085
1425
  var PxPathOverflow = {
1086
1426
  clip: "clip",
@@ -1102,8 +1442,10 @@ var PxStrokeTrimSubPaths = {
1102
1442
  separate: "separate",
1103
1443
  combined: "combined"
1104
1444
  };
1105
- var TEXT_ATTR = "text";
1106
1445
  var TEXT_CONTENT_ATTR = "textContent";
1446
+ var CLASS_ATTR = "class";
1447
+ var TRANSFORM_ATTR = "transform";
1448
+ var OFFSET_DISTANCE_ATTR = "offsetDistance";
1107
1449
  var INTERNAL_ATTRS = /* @__PURE__ */ new Set([
1108
1450
  "type",
1109
1451
  "children",
@@ -1111,14 +1453,20 @@ var INTERNAL_ATTRS = /* @__PURE__ */ new Set([
1111
1453
  "meta",
1112
1454
  "animate",
1113
1455
  "effects",
1114
- TEXT_ATTR,
1115
1456
  TEXT_CONTENT_ATTR
1116
1457
  ]);
1117
- var PX_TRANSFORM_PART_KEYS = ["translate", "rotate", "scale", "origin"];
1118
- var PxGradientUnits = {
1119
- userSpaceOnUse: "userSpaceOnUse",
1120
- objectBoundingBox: "objectBoundingBox"
1458
+ var TRANSFORM_PART = {
1459
+ translate: "translate",
1460
+ rotate: "rotate",
1461
+ scale: "scale",
1462
+ origin: "origin"
1121
1463
  };
1464
+ var PX_TRANSFORM_PART_KEYS = [
1465
+ TRANSFORM_PART.translate,
1466
+ TRANSFORM_PART.rotate,
1467
+ TRANSFORM_PART.scale,
1468
+ TRANSFORM_PART.origin
1469
+ ];
1122
1470
  var PxGradientSpreadMethod = {
1123
1471
  pad: "pad",
1124
1472
  reflect: "reflect",
@@ -1132,27 +1480,38 @@ function isPxElementFileFormat(fileJson) {
1132
1480
  if (!(fileJson && typeof fileJson === "object" && !Array.isArray(fileJson))) {
1133
1481
  return false;
1134
1482
  }
1135
- return fileJson["type"] === "svg";
1483
+ return fileJson.type === "svg";
1136
1484
  }
1137
1485
  function getAnimatorConfig(doc) {
1138
- var _a;
1139
- const cfg = (doc == null ? void 0 : doc.animator) || ((_a = doc == null ? void 0 : doc.meta) == null ? void 0 : _a.animator);
1140
- return cfg ? flattenAnimatorTimeline(cfg) : void 0;
1141
- }
1486
+ var _a2;
1487
+ const cfg = (doc == null ? void 0 : doc.animator) || ((_a2 = doc == null ? void 0 : doc.meta) == null ? void 0 : _a2.animator);
1488
+ if (!cfg) return void 0;
1489
+ const memoised = wireViewMemo.get(cfg);
1490
+ if (memoised) return memoised;
1491
+ const wire = cfg;
1492
+ const stray = PX_FLAT_RUNTIME_VIEW_KEYS.filter((k) => wire[k] !== void 0);
1493
+ const source = stray.length ? __spreadValues2({}, wire) : cfg;
1494
+ for (const k of stray) delete source[k];
1495
+ const view = flattenAnimatorTimeline(source);
1496
+ wireViewMemo.set(cfg, view);
1497
+ return view;
1498
+ }
1499
+ var wireViewMemo = /* @__PURE__ */ new WeakMap();
1142
1500
  var flattenMemo = /* @__PURE__ */ new WeakMap();
1143
1501
  function flattenAnimatorTimeline(cfg) {
1144
1502
  const timeline = cfg.timeline;
1145
1503
  if (timeline === void 0 || timeline === null || typeof timeline !== "object") return cfg;
1146
1504
  const memoised = flattenMemo.get(cfg);
1147
1505
  if (memoised) return memoised;
1148
- const _a = cfg, { timeline: _dropped } = _a, flat = __objRest2(_a, ["timeline"]);
1506
+ const _a2 = cfg, { timeline: _dropped } = _a2, flat = __objRest2(_a2, ["timeline"]);
1507
+ if (timeline.engine !== void 0) flat.engine = timeline.engine;
1508
+ if (timeline.frameRate !== void 0) flat.frameRate = timeline.frameRate;
1149
1509
  if (timeline.type === "scroll" || timeline.type === "view") {
1150
1510
  flat.timelineSource = "scroll";
1151
1511
  if (timeline.duration !== void 0) flat.duration = timeline.duration;
1152
1512
  if (timeline.iterations !== void 0) flat.iterations = timeline.iterations;
1153
1513
  const scroll = __spreadValues2({}, flat.scroll || {});
1154
1514
  scroll.kind = timeline.type;
1155
- if (timeline.engine !== void 0) scroll.driver = timeline.engine;
1156
1515
  if (timeline.axis !== void 0) scroll.axis = timeline.axis;
1157
1516
  if (timeline.source !== void 0) scroll.source = timeline.source;
1158
1517
  if (timeline.subject !== void 0) scroll.subject = timeline.subject;
@@ -1163,34 +1522,34 @@ function flattenAnimatorTimeline(cfg) {
1163
1522
  else if (pin && typeof pin === "object") {
1164
1523
  scroll.pin = true;
1165
1524
  if (pin.align !== void 0) scroll.pinAlign = pin.align;
1166
- if (pin.top !== void 0) scroll.pinTop = pin.top;
1525
+ if (pin.offset !== void 0) scroll.pinOffset = pin.offset;
1167
1526
  if (pin.distance !== void 0) scroll.pinDistance = pin.distance;
1168
1527
  }
1169
1528
  flat.scroll = scroll;
1170
1529
  } else {
1171
1530
  if (timeline.duration !== void 0) flat.duration = timeline.duration;
1172
1531
  if (timeline.trigger !== void 0) {
1173
- const _b = timeline.trigger, { onFinish } = _b, restTrigger = __objRest2(_b, ["onFinish"]);
1532
+ const _b = timeline.trigger, { finishAction } = _b, restTrigger = __objRest2(_b, ["finishAction"]);
1174
1533
  if (Object.keys(restTrigger).length) flat.trigger = restTrigger;
1175
- if (onFinish !== void 0) flat.resetOnFinish = onFinish === "reset";
1534
+ if (finishAction !== void 0) flat.resetOnFinish = finishAction === "reset";
1176
1535
  }
1177
1536
  if (timeline.delay !== void 0) flat.delay = timeline.delay;
1178
1537
  if (timeline.iterations !== void 0) flat.iterations = timeline.iterations;
1179
1538
  if (timeline.direction !== void 0) flat.direction = timeline.direction;
1180
- if (timeline.fill !== void 0) flat.fill = timeline.fill;
1539
+ if (timeline.fillMode !== void 0) flat.fill = timeline.fillMode;
1181
1540
  }
1182
1541
  flattenMemo.set(cfg, flat);
1183
1542
  return flat;
1184
1543
  }
1185
1544
  function getDefs(doc) {
1186
- var _a;
1545
+ var _a2;
1187
1546
  if (!doc) return void 0;
1188
- return (_a = getAnimatorConfig(doc)) == null ? void 0 : _a.definitions;
1547
+ return (_a2 = getAnimatorConfig(doc)) == null ? void 0 : _a2.definitions;
1189
1548
  }
1190
1549
  function getBindings(doc) {
1191
- var _a;
1550
+ var _a2;
1192
1551
  if (!doc) return void 0;
1193
- const animateById = (_a = getAnimatorConfig(doc)) == null ? void 0 : _a.animateById;
1552
+ const animateById = (_a2 = getAnimatorConfig(doc)) == null ? void 0 : _a2.animateById;
1194
1553
  if (!animateById) return void 0;
1195
1554
  return Object.entries(animateById).map(([id, anim]) => ({ id: id.startsWith("#") ? id.slice(1) : id, animate: anim }));
1196
1555
  }
@@ -1206,14 +1565,13 @@ var PxKeyframeValueSchema = implementsInterface()(px.union([
1206
1565
  // e.g. for colors
1207
1566
  px.number(),
1208
1567
  px.array(px.number()),
1209
- // ORDER LAW: the key-discriminated object shapes (`{path}`, `{paths}`) come BEFORE the
1568
+ // ORDER LAW: the key-discriminated object shape (`{pathData}`) comes BEFORE the
1210
1569
  // all-optional transform-parts record. In default (non-strict) mode that record accepts
1211
1570
  // ANY object (every key optional, unknown keys ignored), so listing it earlier made
1212
- // Union.sanitize route `{path}`/`{paths}` values into it and strip them to `{}` —
1571
+ // Union.sanitize route `{pathData}` values into it and strip them to `{}` —
1213
1572
  // silent morph-data loss (repro: the editor's keyframeValueSanitize spec). Validity is
1214
1573
  // order-independent (`some()`); only sanitize routing depends on this order.
1215
- px.object({ path: px.string() }),
1216
- px.lazy(() => px.object({ paths: px.array(PxBezierPathSchema) }), { paths: [] }),
1574
+ px.object({ pathData: px.string() }),
1217
1575
  // Gradient `stops` timeline — each kf value is the full stops-array snapshot.
1218
1576
  px.lazy(() => px.array(PxGradientStopSchema), []),
1219
1577
  px.lazy(() => PxTransformPartsSchema, {})
@@ -1228,16 +1586,32 @@ var PxKeyframeSchema = implementsInterface()(px.object({
1228
1586
  // (review §1.3): editor data lives under `meta`. The editor still carries it on
1229
1587
  // its internal COPY-PASTE payload, which never validates against this schema.)
1230
1588
  }));
1589
+ var anyKf = (kf) => kf;
1590
+ var kfTime = (kf) => {
1591
+ var _a2, _b;
1592
+ return (_b = (_a2 = anyKf(kf).time) != null ? _a2 : anyKf(kf).t) != null ? _b : 0;
1593
+ };
1594
+ var kfValue = (kf) => {
1595
+ var _a2;
1596
+ return (_a2 = anyKf(kf).value) != null ? _a2 : anyKf(kf).v;
1597
+ };
1598
+ var kfEasing = (kf) => {
1599
+ var _a2;
1600
+ return (_a2 = anyKf(kf).easing) != null ? _a2 : anyKf(kf).e;
1601
+ };
1602
+ var kfTangentIn = (kf) => anyKf(kf).tangentIn;
1603
+ var kfTangentOut = (kf) => anyKf(kf).tangentOut;
1231
1604
  var PxLoopSchema = implementsInterface()(px.object({
1232
1605
  segmentCount: px.number().optional(),
1233
- extend: px.enum([PxLoopExtend.before, PxLoopExtend.after]).optional(),
1234
- alternate: px.boolean().optional()
1606
+ repeatAt: px.enum([PxLoopRepeatAt.start, PxLoopRepeatAt.end]).optional(),
1607
+ direction: px.enum([PxLoopDirection.normal, PxLoopDirection.alternate]).optional()
1235
1608
  }));
1236
1609
  var PxPropertyAnimationSchema = implementsInterface()(px.object({
1237
1610
  value: PxKeyframeValueSchema.optional(),
1238
1611
  keyframes: px.array(PxKeyframeSchema).optional(),
1239
1612
  loop: px.union([PxLoopSchema, px.boolean()]).optional(),
1240
- autoOrient: px.boolean().optional()
1613
+ autoOrient: px.boolean().optional(),
1614
+ alongPathMode: px.enum([PxAlongPathMode.sampled, PxAlongPathMode.offsetPath]).optional()
1241
1615
  }));
1242
1616
  var PxTransformPartsSchema = implementsInterface()(px.object({
1243
1617
  translate: px.tuple([px.number(), px.number()]).optional(),
@@ -1261,18 +1635,17 @@ var PxElementAnimationSchema = implementsInterface()(px.union([
1261
1635
  PxAnimationDefinitionSchema
1262
1636
  ]));
1263
1637
  var PxTriggerSchema = implementsInterface()(px.object({
1264
- startOn: px.enum(["load", "mouseOver", "click", "scrollIntoView", "programmatic"]).optional(),
1265
- outAction: px.enum(["continue", "pause", "reset", "reverse"]).optional(),
1638
+ startOn: px.enum([PxStartOn.load, PxStartOn.mouseOver, PxStartOn.click, PxStartOn.scrollIntoView, PxStartOn.programmatic], PX_TRIGGER_DEFAULTS.startOn).optional(),
1639
+ outAction: px.enum([PxOutAction.continue, PxOutAction.pause, PxOutAction.reset, PxOutAction.reverse], PX_TRIGGER_DEFAULTS.outAction).optional(),
1266
1640
  // What happens after a NATURAL finish — `'hold'` (default: keep the end state per
1267
- // `fill`) or `'reset'` (snap back to the start state). The trigger-vocabulary home of
1268
- // the old top-level `resetOnFinish: boolean` (read-legacy) — review §2.3: both
1269
- // "what happens at the end" knobs now sit side by side and share one style of value.
1270
- onFinish: px.enum(["hold", "reset"]).optional(),
1641
+ // `fill`) or `'reset'` (snap back to the start state). Pairs with `outAction` ("what
1642
+ // happens when the trigger condition ends"); both end-of-life knobs now read alike.
1643
+ finishAction: px.enum([PxFinishAction.hold, PxFinishAction.reset]).optional(),
1271
1644
  scrollIntoViewThreshold: px.number().optional()
1272
1645
  }));
1273
1646
  var PxGlyphSchema = implementsInterface()(px.object({
1274
1647
  width: px.number(),
1275
- d: px.string()
1648
+ pathData: px.string()
1276
1649
  }));
1277
1650
  var PxGlyphFontSchema = implementsInterface()(px.object({
1278
1651
  fontFamily: px.string(),
@@ -1287,11 +1660,17 @@ var PxDefsSchema = implementsInterface()(px.object({
1287
1660
  // Review §2.6: the schema now matches the declared type — a style preset is a flat
1288
1661
  // record of string|number attribute values, nothing nested.
1289
1662
  styles: px.record(px.record(px.union([px.string(), px.number()]))).optional(),
1290
- glyphs: px.record(PxGlyphFontSchema).optional()
1663
+ fonts: px.record(PxGlyphFontSchema).optional()
1291
1664
  }));
1292
- var PX_SCROLL_PHASES = ["cover", "contain", "entry", "exit", "entry-crossing", "exit-crossing"];
1293
1665
  var PxScrollRangePointSchema = implementsInterface()(px.object({
1294
- phase: px.enum(PX_SCROLL_PHASES).optional(),
1666
+ phase: px.enum([
1667
+ PxScrollPhase.cover,
1668
+ PxScrollPhase.contain,
1669
+ PxScrollPhase.entry,
1670
+ PxScrollPhase.exit,
1671
+ PxScrollPhase.entryCrossing,
1672
+ PxScrollPhase.exitCrossing
1673
+ ]).optional(),
1295
1674
  fraction: px.number().optional()
1296
1675
  }));
1297
1676
  var PxScrollRangeSchema = px.object({
@@ -1299,34 +1678,38 @@ var PxScrollRangeSchema = px.object({
1299
1678
  end: PxScrollRangePointSchema.optional()
1300
1679
  });
1301
1680
  var PxScrollSchema = implementsInterface()(px.object({
1302
- driver: px.enum(["custom", "native"]).optional(),
1303
- kind: px.enum(["view", "scroll"]).optional(),
1304
- axis: px.enum(["block", "inline", "x", "y"]).optional(),
1305
- source: px.enum(["nearest", "root"]).optional(),
1681
+ kind: px.enum([PxScrollKind.view, PxScrollKind.scroll]).optional(),
1682
+ axis: px.enum([PxScrollAxis.block, PxScrollAxis.inline, PxScrollAxis.x, PxScrollAxis.y]).optional(),
1683
+ source: px.enum([PxScrollSource.nearest, PxScrollSource.root]).optional(),
1306
1684
  // Free-form: the two keywords `parent`/`scroller` plus any CSS selector.
1307
1685
  subject: px.string().optional(),
1308
1686
  smoothing: px.number().optional(),
1309
1687
  pin: px.boolean().optional(),
1310
- pinAlign: px.enum(["top", "center", "bottom"]).optional(),
1311
- pinTop: px.number().optional(),
1688
+ pinAlign: px.enum([PxPinAlign.top, PxPinAlign.center, PxPinAlign.bottom]).optional(),
1689
+ pinOffset: px.number().optional(),
1312
1690
  pinDistance: px.number().optional(),
1313
1691
  range: PxScrollRangeSchema.optional()
1314
1692
  }));
1315
- var PxTimelinePinSchema = px.object({
1316
- align: px.enum(["top", "center", "bottom"]).optional(),
1317
- top: px.number().optional(),
1693
+ var PxTimelinePinSchema = implementsInterface()(px.object({
1694
+ align: px.enum([PxPinAlign.top, PxPinAlign.center, PxPinAlign.bottom]).optional(),
1695
+ offset: px.number().optional(),
1318
1696
  distance: px.number().optional()
1319
- });
1320
- var PxClockTimelineSchema = px.object({
1321
- type: px.literal("clock"),
1697
+ }));
1698
+ var PxTimelineEngineSchema = px.enum([PxTimelineEngineExtra.auto, PxTimelineEngineExtra.native, PxTimelineEngineExtra.js]).optional();
1699
+ var PxTimeTimelineSchema = implementsInterface()(px.object({
1700
+ type: px.literal("time").optional(),
1701
+ engine: PxTimelineEngineSchema,
1702
+ frameRate: px.number().optional(),
1322
1703
  // §2.8: duration is a property of the TIMELINE — how long one pass takes.
1323
1704
  duration: px.number().optional(),
1324
1705
  trigger: PxTriggerSchema.optional(),
1325
1706
  delay: px.number().optional(),
1326
1707
  iterations: px.union([px.number(), px.literal("infinite")]).optional(),
1327
- fill: px.enum(["forwards", "backwards", "both", "none"]).optional(),
1328
- direction: px.enum(["normal", "reverse", "alternate", "alternate-reverse"]).optional()
1329
- });
1708
+ // `fillMode` on the wire (CSS `animation-fill-mode`; the runtime view calls it `fill`)
1709
+ // — never `fill`, which is paint everywhere else in the format.
1710
+ fillMode: px.enum([PxFillMode.forwards, PxFillMode.backwards, PxFillMode.both, PxFillMode.none]).optional(),
1711
+ direction: px.enum([PxPlaybackDirection.normal, PxPlaybackDirection.reverse, PxPlaybackDirection.alternate, PxPlaybackDirection.alternateReverse]).optional()
1712
+ }));
1330
1713
  var scrollishTimelineShape = {
1331
1714
  // §2.8: duration is a property of the TIMELINE — under scrubbing it is the keyframe
1332
1715
  // span the scroll range maps onto.
@@ -1334,9 +1717,10 @@ var scrollishTimelineShape = {
1334
1717
  // Finite repeat count IS meaningful when scrubbing — the scroll range maps onto
1335
1718
  // duration × iterations (rule D4; `'infinite'` cannot map to a range, so no literal here).
1336
1719
  iterations: px.number().optional(),
1337
- engine: px.enum(["custom", "native"]).optional(),
1338
- axis: px.enum(["block", "inline", "x", "y"]).optional(),
1339
- source: px.enum(["nearest", "root"]).optional(),
1720
+ engine: PxTimelineEngineSchema,
1721
+ frameRate: px.number().optional(),
1722
+ axis: px.enum([PxScrollAxis.block, PxScrollAxis.inline, PxScrollAxis.x, PxScrollAxis.y]).optional(),
1723
+ source: px.enum([PxScrollSource.nearest, PxScrollSource.root]).optional(),
1340
1724
  subject: px.string().optional(),
1341
1725
  // 'parent' | 'scroller' | any CSS selector
1342
1726
  smoothing: px.number().optional(),
@@ -1344,23 +1728,29 @@ var scrollishTimelineShape = {
1344
1728
  pin: px.union([px.boolean(), PxTimelinePinSchema]).optional(),
1345
1729
  range: PxScrollRangeSchema.optional()
1346
1730
  };
1347
- var PxScrollTimelineSchema = px.object(__spreadValues2({ type: px.literal("scroll") }, scrollishTimelineShape));
1348
- var PxViewTimelineSchema = px.object(__spreadValues2({ type: px.literal("view") }, scrollishTimelineShape));
1731
+ var PxScrollTimelineSchema = implementsInterface()(
1732
+ px.object(__spreadValues2({ type: px.literal("scroll") }, scrollishTimelineShape))
1733
+ );
1734
+ var PxViewTimelineSchema = implementsInterface()(
1735
+ px.object(__spreadValues2({ type: px.literal("view") }, scrollishTimelineShape))
1736
+ );
1349
1737
  var PxTimelineSchema = px.discriminatedUnion("type", [
1350
- PxClockTimelineSchema,
1738
+ PxTimeTimelineSchema,
1739
+ // first = the member an absent `type` selects
1351
1740
  PxScrollTimelineSchema,
1352
1741
  PxViewTimelineSchema
1353
1742
  ]);
1354
1743
  var PxAnimatorConfigSchema = implementsInterface()(px.object({
1355
- mode: px.enum([PxAnimatorMode.auto, PxAnimatorMode.waapi, PxAnimatorMode.frames]).optional(),
1356
- // (`duration` lives INSIDE `timeline` on the wire — §2.8; the flat field below
1357
- // exists only on the runtime view, like the rest of the playback dynamics.)
1358
- frameRate: px.number().optional(),
1744
+ // (`mode`, `duration` and `frameRate` live INSIDE `timeline` on the wire — §2.8; they exist
1745
+ // at this level only on the runtime view, like the rest of the playback dynamics.)
1359
1746
  // THE spelling of "what advances progress" — clock / scroll / view (review §2.1).
1360
1747
  timeline: PxTimelineSchema.optional(),
1361
1748
  definitions: PxDefsSchema.optional(),
1362
1749
  animateById: px.record(PxElementAnimationSchema).optional(),
1363
- debugInstName: px.string().optional()
1750
+ debugGlobalName: px.string().optional(),
1751
+ // Declared HERE because this is a closed object: an undeclared key would be stripped by
1752
+ // `sanitize` and flagged by strict validation on our own files.
1753
+ version: px.string().optional()
1364
1754
  }));
1365
1755
  var PxBindingSchema = implementsInterface()(px.object({
1366
1756
  id: px.string(),
@@ -1409,7 +1799,7 @@ var PxRepeaterEffectSchema = implementsInterface()(px.object({
1409
1799
  origin: PxAnimatableVec2Schema.optional()
1410
1800
  }));
1411
1801
  var PxMaskedByEffectSchema = implementsInterface()(px.object({
1412
- sourceId: px.string().optional(),
1802
+ source: px.string().optional(),
1413
1803
  maskType: px.enum([PxMaskType.luminance, PxMaskType.alpha]).optional(),
1414
1804
  maskUnits: px.enum([PxUnits.userSpaceOnUse, PxUnits.objectBoundingBox]).optional(),
1415
1805
  maskContentUnits: px.enum([PxUnits.userSpaceOnUse, PxUnits.objectBoundingBox]).optional(),
@@ -1419,7 +1809,7 @@ var PxMaskedByEffectSchema = implementsInterface()(px.object({
1419
1809
  height: px.number().optional()
1420
1810
  }));
1421
1811
  var PxClipPathEffectSchema = implementsInterface()(px.object({
1422
- d: PxAnimatableStringSchema.optional()
1812
+ pathData: PxAnimatableStringSchema.optional()
1423
1813
  }));
1424
1814
  var PxStrokeTrimEffectSchema = implementsInterface()(px.object({
1425
1815
  offset: PxAnimatableNumberSchema.optional(),
@@ -1432,9 +1822,10 @@ var PxRetimeEffectSchema = implementsInterface()(px.object({
1432
1822
  timeCrop: px.tuple([px.number(), px.number()]).optional()
1433
1823
  }));
1434
1824
  var PxCloneEffectSchema = implementsInterface()(px.object({
1435
- // Contextual kind — the `type` convention, see `PxNodeBase.type`.
1436
- type: px.enum([PxCloneType.content]).optional(),
1437
- sourceId: px.string().optional(),
1825
+ // Subtractive on purpose: the `<use>` can only point at one wrapper layer of the
1826
+ // source, so the choices form a ladder — 'translate' now, maybe 'transform' later.
1827
+ without: px.enum([PxCloneWithout.translate]).optional(),
1828
+ source: px.string().optional(),
1438
1829
  retime: PxRetimeEffectSchema.optional()
1439
1830
  }));
1440
1831
  var PxGradientStopSchema = implementsInterface()(px.object({
@@ -1455,13 +1846,13 @@ var PxFillGradientEffectSchema = implementsInterface()(px.object({
1455
1846
  radius: PxAnimatableNumberSchema.optional(),
1456
1847
  focal: PxAnimatableVec2Schema.optional(),
1457
1848
  stops: PxAnimatableGradientStopsSchema.optional(),
1458
- gradientUnits: px.enum([PxGradientUnits.userSpaceOnUse, PxGradientUnits.objectBoundingBox]).optional(),
1849
+ gradientUnits: px.enum([PxUnits.userSpaceOnUse, PxUnits.objectBoundingBox]).optional(),
1459
1850
  spreadMethod: px.enum([PxGradientSpreadMethod.pad, PxGradientSpreadMethod.reflect, PxGradientSpreadMethod.repeat]).optional(),
1460
1851
  gradientTransform: px.string().optional()
1461
1852
  }));
1462
1853
  var PxStrokeGradientEffectSchema = PxFillGradientEffectSchema;
1463
1854
  var PxTextPathEffectSchema = implementsInterface()(px.object({
1464
- path: px.string(),
1855
+ pathData: px.string(),
1465
1856
  pathOverflow: px.enum([PxPathOverflow.clip, PxPathOverflow.extend]).optional(),
1466
1857
  lengthAdjust: px.enum([PxLengthAdjust.spacing, PxLengthAdjust.spacingAndGlyphs]).optional(),
1467
1858
  method: px.enum([PxTextPathMethod.align, PxTextPathMethod.stretch]).optional(),
@@ -1501,20 +1892,100 @@ function validateNodeEffects(root, opts) {
1501
1892
  walk(root, "root");
1502
1893
  return warnings;
1503
1894
  }
1895
+ function validateGlyphFontRefs(root, fonts) {
1896
+ if (!fonts || !Object.keys(fonts).length) return [];
1897
+ const problems = [];
1898
+ const walk = (node, path, inherited, inGlyphText) => {
1899
+ var _a2, _b;
1900
+ if (!node) return;
1901
+ const own = typeof node.fontFamily === "string" ? node.fontFamily : void 0;
1902
+ const family = own != null ? own : inherited;
1903
+ const isGlyphText = inGlyphText || node.type === "text" && !!((_b = (_a2 = node.effects) == null ? void 0 : _a2.text) == null ? void 0 : _b.useGlyphs);
1904
+ if (isGlyphText && own && !Object.prototype.hasOwnProperty.call(fonts, own)) {
1905
+ const problem = path + ': glyph-mode text uses font-family "' + own + '", which has no entry in animator.definitions.fonts';
1906
+ if (!problems.includes(problem)) problems.push(problem);
1907
+ }
1908
+ if (Array.isArray(node.children)) {
1909
+ node.children.forEach((c, i) => walk(c, path + ".children[" + i + "]", family, isGlyphText));
1910
+ }
1911
+ };
1912
+ walk(root, "root", void 0, false);
1913
+ return problems;
1914
+ }
1915
+ function validateEasingRefs(root, easings) {
1916
+ const problems = [];
1917
+ const walk = (node, path) => {
1918
+ if (Array.isArray(node)) {
1919
+ node.forEach((item, i) => walk(item, path + "[" + i + "]"));
1920
+ return;
1921
+ }
1922
+ if (!node || typeof node !== "object") return;
1923
+ const easing = node.easing;
1924
+ if (typeof easing === "string" && !(easings && Object.prototype.hasOwnProperty.call(easings, easing))) {
1925
+ const problem = path + '.easing: "' + easing + '" names no entry in animator.definitions.easings \u2014 it will play linear';
1926
+ if (!problems.includes(problem)) problems.push(problem);
1927
+ }
1928
+ for (const [key, value] of Object.entries(node)) {
1929
+ if (key === "easing") continue;
1930
+ if (value && typeof value === "object") walk(value, path + "." + key);
1931
+ }
1932
+ };
1933
+ walk(root, "root");
1934
+ return problems;
1935
+ }
1936
+ function validateVersionStamp(doc) {
1937
+ var _a2;
1938
+ const version = (_a2 = getAnimatorConfig(doc)) == null ? void 0 : _a2.version;
1939
+ if (version === void 0) return [];
1940
+ if (parseWireVersion(version) !== void 0) return [];
1941
+ return ["root.animator.version: " + JSON.stringify(version) + ' is not a version stamp ("a.b" or "a.b.c") \u2014 it reads as unstamped'];
1942
+ }
1943
+ function validateDocument(doc, opts) {
1944
+ var _a2;
1945
+ const strict = (opts == null ? void 0 : opts.strict) !== false;
1946
+ const ctx = { errors: [], warnings: [], strict };
1947
+ const problems = PxAnimatedSvgDocumentSchema.isValid(doc, ctx, ["root"]) ? [] : [...ctx.errors];
1948
+ if (doc && typeof doc === "object") {
1949
+ for (const w of validateNodeEffects(doc, { strict })) {
1950
+ if (!problems.includes(w)) problems.push(w);
1951
+ }
1952
+ const defs = (_a2 = getAnimatorConfig(doc)) == null ? void 0 : _a2.definitions;
1953
+ for (const w of validateGlyphFontRefs(doc, defs == null ? void 0 : defs.fonts)) {
1954
+ if (!problems.includes(w)) problems.push(w);
1955
+ }
1956
+ for (const w of validateEasingRefs(doc, defs == null ? void 0 : defs.easings)) {
1957
+ if (!problems.includes(w)) problems.push(w);
1958
+ }
1959
+ for (const w of validateVersionStamp(doc)) {
1960
+ if (!problems.includes(w)) problems.push(w);
1961
+ }
1962
+ }
1963
+ return problems;
1964
+ }
1504
1965
  var PxNodeBase = px.openObject({
1505
1966
  // CONVENTION (SCHEMA-DESIGN R1 / issues N4): `type` is the ONE word for "what
1506
1967
  // kind of thing is this", discriminated by its CARRIER — here the node TAG
1507
- // (`rect`, `text`), and inside a sub-object that object's kind (`clone.type`,
1968
+ // (`rect`, `text`), and inside a sub-object that object's kind (`fillGradient.type`,
1508
1969
  // `fillGradient.type`, editor `preset.type`). Each sits in its own object, so
1509
1970
  // the carrier disambiguates completely; synonyms (`cloneKind`, `presetShape`)
1510
1971
  // would add words that all mean "type" and still need the carrier to read.
1511
1972
  // Guarding a `type` SLOT against a wrong VALUE is the job of strict enums
1512
1973
  // (issues V3), never of distinct key names.
1513
1974
  type: px.string(),
1975
+ // The escape hatch for elements that carry a REAL `type` attribute — `<feTurbulence
1976
+ // type="fractalNoise">`, `<feFuncR type="table">`, `<feColorMatrix type="saturate">`.
1977
+ // `type` is taken by the tag name, so the attribute travels here and the renderer puts
1978
+ // it back (`PxAnimatorDOM.renderNode`, `PxRnRender`). Declared here — not merely
1979
+ // documented — because a wire key that is not in a schema is invisible to the
1980
+ // minifier's reserve list and gets renamed (MINIFICATION-BOUNDARY-PLAN.md §1.1).
1981
+ domType: px.string().optional(),
1982
+ // Text content of a `<text>` / `<tspan>`. Declared, so a non-string value is a schema error
1983
+ // and the minifier reserves the key; `text` is NOT an alias for it and is not read anywhere.
1984
+ textContent: px.string().optional(),
1514
1985
  id: px.string().optional(),
1515
1986
  meta: px.any().optional(),
1516
1987
  // Player-effects bucket emitted by the Editor's lightweight design format.
1517
- // Consumed and removed by `applyPlayerEffects` before any other normalisation
1988
+ // Consumed and removed by `applyPlayerEffects` before any other normalization
1518
1989
  // (see `createAnimatorImpl`), so downstream code never sees it.
1519
1990
  effects: PxEffectsSchema.optional(),
1520
1991
  // `PxElementAnimation` (not just `PxAnimationDefinition`) — accepts
@@ -1546,8 +2017,8 @@ var PxBezierPathSchema = implementsInterface()(px.object({
1546
2017
  c: px.boolean().optional()
1547
2018
  }));
1548
2019
  function isPxElementFileFormatDeep(fileJson) {
1549
- const valid = PxAnimatedSvgDocumentSchema.isValid(fileJson);
1550
- return { valid, errors: valid ? [] : ["Document failed schema validation"] };
2020
+ const errors = validateDocument(fileJson, { strict: false });
2021
+ return { valid: errors.length === 0, errors };
1551
2022
  }
1552
2023
  var _idCounter = 0;
1553
2024
  function generateUniqueId() {
@@ -1567,7 +2038,7 @@ function deepClone(value) {
1567
2038
  return cloned;
1568
2039
  }
1569
2040
  function generateNewIds(doc) {
1570
- var _a, _b;
2041
+ var _a2, _b;
1571
2042
  const cloned = deepClone(doc);
1572
2043
  const idMap = /* @__PURE__ */ new Map();
1573
2044
  const hashRefAttrs = /* @__PURE__ */ new Set(["href", "xlink:href"]);
@@ -1585,7 +2056,8 @@ function generateNewIds(doc) {
1585
2056
  "flood-color",
1586
2057
  "lighting-color"
1587
2058
  ]);
1588
- const directIdRefAttrs = /* @__PURE__ */ new Set(["sourceId", "targetId", "boundElementId"]);
2059
+ const directIdRefAttrs = /* @__PURE__ */ new Set(["targetId", "boundElementId"]);
2060
+ const isEffectSourceRef = (key, parentKey) => key === "source" && (parentKey === "maskedBy" || parentKey === "clone");
1589
2061
  function collectIds(node) {
1590
2062
  if (!node || typeof node !== "object") return;
1591
2063
  if (node.id && typeof node.id === "string") {
@@ -1602,7 +2074,7 @@ function generateNewIds(doc) {
1602
2074
  }
1603
2075
  }
1604
2076
  }
1605
- function updateRefs(node) {
2077
+ function updateRefs(node, parentKey) {
1606
2078
  if (!node || typeof node !== "object") return;
1607
2079
  for (const [key, value] of Object.entries(node)) {
1608
2080
  if (key === "children") {
@@ -1622,7 +2094,7 @@ function generateNewIds(doc) {
1622
2094
  }
1623
2095
  } else if (urlRefAttrs.has(key)) {
1624
2096
  node[key] = replaceUrlRefs(value, idMap);
1625
- } else if (directIdRefAttrs.has(key)) {
2097
+ } else if (directIdRefAttrs.has(key) || isEffectSourceRef(key, parentKey)) {
1626
2098
  const hasHash = value.startsWith("#");
1627
2099
  const newId = idMap.get(hasHash ? value.slice(1) : value);
1628
2100
  if (newId) {
@@ -1638,13 +2110,13 @@ function generateNewIds(doc) {
1638
2110
  }
1639
2111
  }
1640
2112
  } else if (typeof value === "object" && value !== null) {
1641
- updateRefs(value);
2113
+ updateRefs(value, key);
1642
2114
  }
1643
2115
  }
1644
2116
  }
1645
2117
  collectIds(cloned);
1646
2118
  updateRefs(cloned);
1647
- const docAnimate = (_a = cloned.animator) == null ? void 0 : _a.animateById;
2119
+ const docAnimate = (_a2 = cloned.animator) == null ? void 0 : _a2.animateById;
1648
2120
  if (docAnimate && typeof docAnimate === "object") {
1649
2121
  const updatedAnimate = {};
1650
2122
  for (const [key, anim] of Object.entries(docAnimate)) {
@@ -1701,7 +2173,7 @@ function isDangerousAttrName(nameLower) {
1701
2173
  if (nameLower.startsWith("on")) return true;
1702
2174
  return false;
1703
2175
  }
1704
- function sanitiseAttributeValue(name, value) {
2176
+ function sanitizeAttributeValue(name, value) {
1705
2177
  const nameLower = name.toLowerCase();
1706
2178
  if (isDangerousAttrName(nameLower)) {
1707
2179
  console.warn("Attribute blocked (event handler / dangerous): ", nameLower);
@@ -1726,10 +2198,10 @@ function sanitiseAttributeValue(name, value) {
1726
2198
  return value;
1727
2199
  }
1728
2200
  function resolveStyle(style, defs) {
1729
- var _a;
2201
+ var _a2;
1730
2202
  if (!style) return void 0;
1731
2203
  if (typeof style === "string") {
1732
- return (_a = defs == null ? void 0 : defs.styles) == null ? void 0 : _a[style];
2204
+ return (_a2 = defs == null ? void 0 : defs.styles) == null ? void 0 : _a2[style];
1733
2205
  }
1734
2206
  return style;
1735
2207
  }
@@ -1740,18 +2212,18 @@ function getNormalizedProps(props) {
1740
2212
  if (INTERNAL_ATTRS.has(key)) continue;
1741
2213
  if (key === "style") continue;
1742
2214
  let value = props[rawKey];
1743
- if (COLOUR_ATTR_NAMES.has(key) && Array.isArray(value)) {
2215
+ if (COLOR_ATTR_NAMES.has(key) && Array.isArray(value)) {
1744
2216
  propsCopy[key] = toRGBA(value);
1745
2217
  } else if (key === "transform" && value !== null && typeof value === "object" && !Array.isArray(value) && !value.keyframes) {
1746
2218
  const parts = value.value && typeof value.value === "object" ? value.value : value;
1747
- propsCopy["transform"] = composeTransformParts(parts, { withUnits: false });
2219
+ propsCopy[TRANSFORM_ATTR] = composeTransformParts(parts, { withUnits: false });
1748
2220
  } else if (TRANSFORM_FN_NAMES.has(key)) {
1749
2221
  if (Array.isArray(value)) {
1750
2222
  if (key === "translate") value = value.map((v) => v + "px");
1751
2223
  value = value.join(",");
1752
2224
  }
1753
2225
  if (key === "rotate") value = value + "deg";
1754
- propsCopy["transform"] = key + "(" + value + ")";
2226
+ propsCopy[TRANSFORM_ATTR] = key + "(" + value + ")";
1755
2227
  } else if (Array.isArray(value)) {
1756
2228
  propsCopy[key] = value.join(",");
1757
2229
  } else if (value !== void 0 && value !== null) {
@@ -1761,8 +2233,7 @@ function getNormalizedProps(props) {
1761
2233
  return propsCopy;
1762
2234
  }
1763
2235
  function getKfTranslate(kf) {
1764
- var _a;
1765
- const v = (_a = kf.value) != null ? _a : kf.v;
2236
+ const v = kfValue(kf);
1766
2237
  if (!v) return void 0;
1767
2238
  if (Array.isArray(v) && v.length >= 2 && typeof v[0] === "number" && typeof v[1] === "number") {
1768
2239
  return [v[0], v[1]];
@@ -1772,31 +2243,27 @@ function getKfTranslate(kf) {
1772
2243
  return void 0;
1773
2244
  }
1774
2245
  function getKfTime(kf) {
1775
- var _a, _b;
1776
- return (_b = (_a = kf.time) != null ? _a : kf.t) != null ? _b : 0;
2246
+ return kfTime(kf);
1777
2247
  }
1778
2248
  function getKfEasing(kf) {
1779
- var _a;
1780
- return (_a = kf.easing) != null ? _a : kf.e;
2249
+ return kfEasing(kf);
1781
2250
  }
1782
2251
  function propAnimIsMotionPath(anim) {
1783
- var _a, _b;
1784
2252
  const kfs = anim.keyframes;
1785
2253
  if (!Array.isArray(kfs)) return false;
1786
2254
  if (anim.autoOrient) return true;
1787
2255
  for (const kf of kfs) {
1788
- if (((_a = kf.tangentIn) != null ? _a : kf.ti) || ((_b = kf.tangentOut) != null ? _b : kf.to)) return true;
2256
+ if (kfTangentIn(kf) || kfTangentOut(kf)) return true;
1789
2257
  }
1790
2258
  return false;
1791
2259
  }
1792
2260
  var _segmentCache = /* @__PURE__ */ new WeakMap();
1793
2261
  function getSegmentCache(prevKf, nextKf, prevPos, nextPos) {
1794
- var _a, _b;
1795
2262
  let byNext = _segmentCache.get(prevKf);
1796
2263
  const existing = byNext == null ? void 0 : byNext.get(nextKf);
1797
2264
  if (existing) return existing;
1798
- const to = (_a = prevKf.tangentOut) != null ? _a : prevKf.to;
1799
- const ti = (_b = nextKf.tangentIn) != null ? _b : nextKf.ti;
2265
+ const to = kfTangentOut(prevKf);
2266
+ const ti = kfTangentIn(nextKf);
1800
2267
  const P1 = [prevPos[0] + (to ? to[0] : 0), prevPos[1] + (to ? to[1] : 0)];
1801
2268
  const P2 = [nextPos[0] + (ti ? ti[0] : 0), nextPos[1] + (ti ? ti[1] : 0)];
1802
2269
  const lut = bezier2D_arcLengthLUT(prevPos, P1, P2, nextPos);
@@ -1845,13 +2312,13 @@ function tFromArcFraction(lut, arcFrac) {
1845
2312
  var DEFAULT_FLATNESS_TOL = 0.5;
1846
2313
  var DEFAULT_ROTATION_TOL = 5;
1847
2314
  var DEFAULT_MAX_SAMPLES = 32;
1848
- function materialiseMotionPathInPropAnim(anim, opts) {
1849
- var _a, _b, _c;
2315
+ function materializeMotionPathInPropAnim(anim, opts) {
2316
+ var _a2, _b, _c;
1850
2317
  if (!propAnimIsMotionPath(anim)) return anim;
1851
2318
  const kfs = anim.keyframes;
1852
2319
  if (!Array.isArray(kfs) || kfs.length < 2) return anim;
1853
2320
  const autoOrient = !!anim.autoOrient;
1854
- const flatnessTol = (_a = opts == null ? void 0 : opts.flatnessTolerance) != null ? _a : DEFAULT_FLATNESS_TOL;
2321
+ const flatnessTol = (_a2 = opts == null ? void 0 : opts.flatnessTolerance) != null ? _a2 : DEFAULT_FLATNESS_TOL;
1855
2322
  const rotationTol = (_b = opts == null ? void 0 : opts.rotationTolerance) != null ? _b : DEFAULT_ROTATION_TOL;
1856
2323
  const maxSamples = (_c = opts == null ? void 0 : opts.maxSamplesPerSegment) != null ? _c : DEFAULT_MAX_SAMPLES;
1857
2324
  const out = [];
@@ -1877,7 +2344,7 @@ function materialiseMotionPathInPropAnim(anim, opts) {
1877
2344
  if (autoOrient && i > 0) {
1878
2345
  insertSharpCornerStepKfIfNeeded(out, prevKf, nextKf, prevPos, nextPos, rotationTol);
1879
2346
  }
1880
- materialiseSegment(out, prevKf, nextKf, prevPos, nextPos, autoOrient, flatnessTol, rotationTol, maxSamples);
2347
+ materializeSegment(out, prevKf, nextKf, prevPos, nextPos, autoOrient, flatnessTol, rotationTol, maxSamples);
1881
2348
  }
1882
2349
  const lastInE = getKfEasing(kfs[kfs.length - 1]);
1883
2350
  if (lastInE) out[out.length - 1].e = lastInE;
@@ -1887,10 +2354,9 @@ function materialiseMotionPathInPropAnim(anim, opts) {
1887
2354
  return result;
1888
2355
  }
1889
2356
  function unwrapAutoOrientRotations(kfs) {
1890
- var _a;
1891
2357
  let prev;
1892
2358
  for (const kf of kfs) {
1893
- const v = (_a = kf.v) != null ? _a : kf.value;
2359
+ const v = kfValue(kf);
1894
2360
  if (!v || typeof v.rotate !== "number") continue;
1895
2361
  if (prev === void 0) {
1896
2362
  prev = v.rotate;
@@ -1907,8 +2373,7 @@ function makeOutKf(time, value) {
1907
2373
  return { t: time, v: value };
1908
2374
  }
1909
2375
  function getKfValueParts(kf) {
1910
- var _a;
1911
- const v = (_a = kf.value) != null ? _a : kf.v;
2376
+ const v = kfValue(kf);
1912
2377
  if (!v || typeof v !== "object" || Array.isArray(v)) return void 0;
1913
2378
  return v;
1914
2379
  }
@@ -1969,9 +2434,8 @@ function wrappedAngleDelta(a, b) {
1969
2434
  return d;
1970
2435
  }
1971
2436
  function insertSharpCornerStepKfIfNeeded(out, prevKf, nextKf, prevPos, nextPos, rotationTol) {
1972
- var _a;
1973
2437
  const lastKf = out[out.length - 1];
1974
- const lastV = (_a = lastKf.v) != null ? _a : lastKf.value;
2438
+ const lastV = kfValue(lastKf);
1975
2439
  const prevExit = lastV == null ? void 0 : lastV.rotate;
1976
2440
  if (typeof prevExit !== "number") return;
1977
2441
  const boundaryV = getKfValueParts(prevKf);
@@ -1994,7 +2458,7 @@ function insertSharpCornerStepKfIfNeeded(out, prevKf, nextKf, prevPos, nextPos,
1994
2458
  out.push(makeOutKf(stepTime, dupValue));
1995
2459
  }
1996
2460
  var CORNER_STEP_AFTER_BOUNDARY_MS = 0.05;
1997
- function materialiseSegment(out, prevKf, nextKf, prevPos, nextPos, autoOrient, flatnessTol, rotationTol, maxSamples) {
2461
+ function materializeSegment(out, prevKf, nextKf, prevPos, nextPos, autoOrient, flatnessTol, rotationTol, maxSamples) {
1998
2462
  const seg = getSegmentCache(prevKf, nextKf, prevPos, nextPos);
1999
2463
  const prevTime = getKfTime(prevKf);
2000
2464
  const nextTime = getKfTime(nextKf);
@@ -2117,16 +2581,16 @@ function perpDist(q, pA, pB) {
2117
2581
  const cross = (q[0] - pA[0]) * dy - (q[1] - pA[1]) * dx;
2118
2582
  return Math.abs(cross) / Math.sqrt(len2);
2119
2583
  }
2120
- function materialiseMotionPathsInTree(root, opts) {
2121
- const out = walkAndMaterialise(root, opts);
2584
+ function materializeMotionPathsInTree(root, opts) {
2585
+ const out = walkAndMaterialize(root, opts);
2122
2586
  return out != null ? out : root;
2123
2587
  }
2124
- function walkAndMaterialise(node, opts) {
2588
+ function walkAndMaterialize(node, opts) {
2125
2589
  let newChildren;
2126
2590
  if (node.children) {
2127
2591
  for (let i = 0; i < node.children.length; i++) {
2128
2592
  const ch = node.children[i];
2129
- const ret = walkAndMaterialise(ch, opts);
2593
+ const ret = walkAndMaterialize(ch, opts);
2130
2594
  if (ret !== null) {
2131
2595
  if (!newChildren) newChildren = node.children.slice();
2132
2596
  newChildren[i] = ret;
@@ -2139,9 +2603,9 @@ function walkAndMaterialise(node, opts) {
2139
2603
  const animDef = animBucket;
2140
2604
  const transformAnim = animDef.transform;
2141
2605
  if (transformAnim && typeof transformAnim === "object" && propAnimIsMotionPath(transformAnim)) {
2142
- const materialised = materialiseMotionPathInPropAnim(transformAnim, opts);
2143
- if (materialised !== transformAnim) {
2144
- newAnimate = __spreadProps2(__spreadValues2({}, animDef), { transform: materialised });
2606
+ const materialized = materializeMotionPathInPropAnim(transformAnim, opts);
2607
+ if (materialized !== transformAnim) {
2608
+ newAnimate = __spreadProps2(__spreadValues2({}, animDef), { transform: materialized });
2145
2609
  }
2146
2610
  }
2147
2611
  }
@@ -2242,8 +2706,8 @@ function isPathString(value) {
2242
2706
  return typeof value === "string" && extractPathData(value) !== void 0;
2243
2707
  }
2244
2708
  function normalizePathValue(value) {
2245
- if (value && typeof value === "object" && typeof value.path === "string") {
2246
- const d = extractPathData(value.path);
2709
+ if (value && typeof value === "object" && typeof value.pathData === "string") {
2710
+ const d = extractPathData(value.pathData);
2247
2711
  return d ? { paths: parseSvgPathToBezier(d) } : value;
2248
2712
  }
2249
2713
  if (value && typeof value === "object" && "paths" in value) {
@@ -2282,21 +2746,21 @@ function normalizePathValue(value) {
2282
2746
  return value;
2283
2747
  }
2284
2748
  function resolveEasing(easing, defs) {
2285
- var _a;
2749
+ var _a2;
2286
2750
  if (!easing) return void 0;
2287
2751
  if (Array.isArray(easing)) {
2288
2752
  return easing;
2289
2753
  }
2290
- if ((_a = defs == null ? void 0 : defs.easings) == null ? void 0 : _a[easing]) {
2754
+ if ((_a2 = defs == null ? void 0 : defs.easings) == null ? void 0 : _a2[easing]) {
2291
2755
  return defs.easings[easing];
2292
2756
  }
2293
2757
  console.warn("Unknown easing name: " + easing);
2294
2758
  return void 0;
2295
2759
  }
2296
2760
  function resolveAnimation(animRef, defs) {
2297
- var _a;
2761
+ var _a2;
2298
2762
  if (typeof animRef === "string") {
2299
- const resolved = (_a = defs == null ? void 0 : defs.animations) == null ? void 0 : _a[animRef];
2763
+ const resolved = (_a2 = defs == null ? void 0 : defs.animations) == null ? void 0 : _a2[animRef];
2300
2764
  if (!resolved) {
2301
2765
  console.warn("Unknown animation name: " + animRef);
2302
2766
  }
@@ -2321,13 +2785,13 @@ function resolveElementAnimation(animate, defs) {
2321
2785
  return results;
2322
2786
  }
2323
2787
  function interpolateValue(propName, a, b, t) {
2324
- var _a, _b;
2788
+ var _a2, _b;
2325
2789
  if (propName === "d") {
2326
- const aPaths = (_a = a == null ? void 0 : a.paths) != null ? _a : Array.isArray(a) ? a : [];
2790
+ const aPaths = (_a2 = a == null ? void 0 : a.paths) != null ? _a2 : Array.isArray(a) ? a : [];
2327
2791
  const bPaths = (_b = b == null ? void 0 : b.paths) != null ? _b : Array.isArray(b) ? b : [];
2328
2792
  return { paths: interpolateBeziers(aPaths, bPaths, t) };
2329
2793
  }
2330
- if (COLOUR_ATTR_NAMES.has(propName)) {
2794
+ if (COLOR_ATTR_NAMES.has(propName)) {
2331
2795
  return interpolateColor(a || [0, 0, 0, 1], b || [0, 0, 0, 1], t);
2332
2796
  }
2333
2797
  if (propName === "transform" && typeof a === "object" && a !== null && !Array.isArray(a) && typeof b === "object" && b !== null && !Array.isArray(b)) {
@@ -2359,11 +2823,11 @@ function interpolateTransformParts(a, b, t) {
2359
2823
  return out;
2360
2824
  }
2361
2825
  function expandLoopKeyframes(propName, keyframes, loop, duration) {
2362
- var _a, _b, _c, _d, _e;
2826
+ var _a2, _b, _c, _d, _e;
2363
2827
  const totalIntervals = keyframes.length - 1;
2364
- const segCount = clamp((_a = loop.segmentCount) != null ? _a : totalIntervals, 1, totalIntervals);
2828
+ const segCount = clamp((_a2 = loop.segmentCount) != null ? _a2 : totalIntervals, 1, totalIntervals);
2365
2829
  let segKfs;
2366
- if (loop.extend === PxLoopExtend.before) {
2830
+ if (loop.repeatAt === PxLoopRepeatAt.start) {
2367
2831
  segKfs = keyframes.slice(0, segCount + 1);
2368
2832
  } else {
2369
2833
  segKfs = keyframes.slice(totalIntervals - segCount);
@@ -2371,7 +2835,7 @@ function expandLoopKeyframes(propName, keyframes, loop, duration) {
2371
2835
  const firstT = (_b = keyframes[0].t) != null ? _b : 0;
2372
2836
  const lastT = (_c = keyframes[keyframes.length - 1].t) != null ? _c : 0;
2373
2837
  let fillStart, fillEnd;
2374
- if (loop.extend === PxLoopExtend.before) {
2838
+ if (loop.repeatAt === PxLoopRepeatAt.start) {
2375
2839
  fillStart = 0;
2376
2840
  fillEnd = firstT;
2377
2841
  } else {
@@ -2384,26 +2848,23 @@ function expandLoopKeyframes(propName, keyframes, loop, duration) {
2384
2848
  const segEndT = (_e = segKfs[segKfs.length - 1].t) != null ? _e : 0;
2385
2849
  const segDuration = segEndT - segStartT;
2386
2850
  if (segDuration <= 0) return keyframes;
2387
- const template = segKfs.map((kf) => {
2388
- var _a2, _b2;
2389
- return {
2390
- relT: (kf.t - segStartT) / segDuration,
2391
- v: kf.v,
2392
- e: kf.e,
2393
- tangentIn: (_a2 = kf.tangentIn) != null ? _a2 : kf.ti,
2394
- tangentOut: (_b2 = kf.tangentOut) != null ? _b2 : kf.to
2395
- };
2396
- });
2851
+ const template = segKfs.map((kf) => ({
2852
+ relT: (kf.t - segStartT) / segDuration,
2853
+ v: kf.v,
2854
+ e: kf.e,
2855
+ tangentIn: kfTangentIn(kf),
2856
+ tangentOut: kfTangentOut(kf)
2857
+ }));
2397
2858
  const fullReps = Math.floor(fillDuration / segDuration);
2398
2859
  const remainder = fillDuration - fullReps * segDuration;
2399
2860
  const partialFraction = remainder / segDuration;
2400
2861
  const looped = [];
2401
- const separateBoundary = loop.extend !== PxLoopExtend.before;
2862
+ const separateBoundary = loop.repeatAt !== PxLoopRepeatAt.start;
2402
2863
  const originalTerminalKf = keyframes[keyframes.length - 1];
2403
2864
  let terminalEasingOverride;
2404
2865
  let hasTerminalEasingOverride = false;
2405
2866
  function appendRep(repStart, isReversed, partial) {
2406
- var _a2;
2867
+ var _a3;
2407
2868
  let entries;
2408
2869
  if (isReversed) {
2409
2870
  entries = [];
@@ -2440,7 +2901,7 @@ function expandLoopKeyframes(propName, keyframes, loop, duration) {
2440
2901
  return;
2441
2902
  }
2442
2903
  const prevKf = looped.length > 0 ? looped[looped.length - 1] : originalTerminalKf;
2443
- const isBoundary = separateBoundary && i === 0 && prevKf !== void 0 && Math.abs(((_a2 = prevKf.t) != null ? _a2 : 0) - (repStart + entry.relT * segDuration)) < 1e-9;
2904
+ const isBoundary = separateBoundary && i === 0 && prevKf !== void 0 && Math.abs(((_a3 = prevKf.t) != null ? _a3 : 0) - (repStart + entry.relT * segDuration)) < 1e-9;
2444
2905
  if (isBoundary) {
2445
2906
  if (deepEqualValue(prevKf.v, entry.v)) {
2446
2907
  if (looped.length > 0) {
@@ -2506,30 +2967,30 @@ function expandLoopKeyframes(propName, keyframes, loop, duration) {
2506
2967
  looped.push(pushed);
2507
2968
  }
2508
2969
  }
2509
- if (loop.extend === PxLoopExtend.before) {
2970
+ if (loop.repeatAt === PxLoopRepeatAt.start) {
2510
2971
  if (partialFraction > 1e-9) {
2511
- const isReversed = !!loop.alternate && fullReps % 2 === 0;
2972
+ const isReversed = loop.direction === PxLoopDirection.alternate && fullReps % 2 === 0;
2512
2973
  appendRepTail(fillStart, isReversed, partialFraction);
2513
2974
  }
2514
2975
  for (let rep = 0; rep < fullReps; rep++) {
2515
2976
  const distFromBoundary = fullReps - 1 - rep;
2516
- const isReversed = !!loop.alternate && distFromBoundary % 2 === 0;
2977
+ const isReversed = loop.direction === PxLoopDirection.alternate && distFromBoundary % 2 === 0;
2517
2978
  const repStart = fillStart + remainder + rep * segDuration;
2518
2979
  appendRep(repStart, isReversed);
2519
2980
  }
2520
2981
  } else {
2521
2982
  for (let rep = 0; rep < fullReps; rep++) {
2522
- const isReversed = !!loop.alternate && rep % 2 === 0;
2983
+ const isReversed = loop.direction === PxLoopDirection.alternate && rep % 2 === 0;
2523
2984
  const repStart = fillStart + rep * segDuration;
2524
2985
  appendRep(repStart, isReversed);
2525
2986
  }
2526
2987
  if (partialFraction > 1e-9) {
2527
- const isReversed = !!loop.alternate && fullReps % 2 === 0;
2988
+ const isReversed = loop.direction === PxLoopDirection.alternate && fullReps % 2 === 0;
2528
2989
  const repStart = fillStart + fullReps * segDuration;
2529
2990
  appendRep(repStart, isReversed, partialFraction);
2530
2991
  }
2531
2992
  }
2532
- if (loop.extend === PxLoopExtend.before) {
2993
+ if (loop.repeatAt === PxLoopRepeatAt.start) {
2533
2994
  return [...looped, ...keyframes];
2534
2995
  } else {
2535
2996
  if (hasTerminalEasingOverride && keyframes.length > 0) {
@@ -2541,34 +3002,34 @@ function expandLoopKeyframes(propName, keyframes, loop, duration) {
2541
3002
  }
2542
3003
  }
2543
3004
  function normalizeKeyframes(propName, propAnim, duration, defs) {
2544
- var _a, _b, _c, _d, _e, _f, _g;
3005
+ var _a2;
2545
3006
  const keyframes = propAnim.keyframes || [];
2546
3007
  const normalized = [];
2547
3008
  for (const kf of keyframes) {
2548
- const timePct = (_b = (_a = kf.time) != null ? _a : kf.t) != null ? _b : 0;
2549
- let value = (_c = kf.value) != null ? _c : kf.v;
2550
- const easing = (_d = kf.easing) != null ? _d : kf.e;
3009
+ const timePct = kfTime(kf);
3010
+ let value = kfValue(kf);
3011
+ const easing = kfEasing(kf);
2551
3012
  if (propName === "d") {
2552
3013
  value = normalizePathValue(value);
2553
3014
  }
2554
3015
  const propNameKebab = isCamelCaseWord(propName) ? camelCaseToKebabWordIfNeeded(propName) : propName;
2555
- if (COLOUR_ATTR_NAMES.has(propNameKebab)) {
2556
- value = (_e = parseColor(value)) != null ? _e : value;
3016
+ if (COLOR_ATTR_NAMES.has(propNameKebab)) {
3017
+ value = (_a2 = parseColor(value)) != null ? _a2 : value;
2557
3018
  }
2558
3019
  const normKf = {
2559
3020
  t: timePct,
2560
3021
  v: value,
2561
3022
  e: resolveEasing(easing, defs)
2562
3023
  };
2563
- const tIn = (_f = kf.tangentIn) != null ? _f : kf.ti;
2564
- const tOut = (_g = kf.tangentOut) != null ? _g : kf.to;
3024
+ const tIn = kfTangentIn(kf);
3025
+ const tOut = kfTangentOut(kf);
2565
3026
  if (tIn) normKf.tangentIn = tIn;
2566
3027
  if (tOut) normKf.tangentOut = tOut;
2567
3028
  normalized.push(normKf);
2568
3029
  }
2569
3030
  normalized.sort((a, b) => {
2570
- var _a2, _b2;
2571
- return ((_a2 = a.t) != null ? _a2 : 0) - ((_b2 = b.t) != null ? _b2 : 0);
3031
+ var _a3, _b;
3032
+ return ((_a3 = a.t) != null ? _a3 : 0) - ((_b = b.t) != null ? _b : 0);
2572
3033
  });
2573
3034
  const loopRaw = propAnim.loop;
2574
3035
  const loop = loopRaw === true ? {} : loopRaw || void 0;
@@ -2586,24 +3047,26 @@ function mergeAnimationDefinitions(animations) {
2586
3047
  }
2587
3048
  return merged;
2588
3049
  }
2589
- function materialiseInternalLoopsInPropAnim(propName, propAnim, duration) {
3050
+ function materializeInternalLoopsInPropAnim(propName, propAnim, duration) {
2590
3051
  const loopRaw = propAnim.loop;
2591
3052
  if (loopRaw === void 0 || loopRaw === null || loopRaw === false) return propAnim;
2592
3053
  const loop = loopRaw === true ? {} : loopRaw;
2593
3054
  const rawKfs = propAnim.keyframes;
2594
3055
  if (!Array.isArray(rawKfs) || rawKfs.length < 2) return propAnim;
2595
3056
  const propNameKebab = isCamelCaseWord(propName) ? camelCaseToKebabWordIfNeeded(propName) : propName;
2596
- const isColour = COLOUR_ATTR_NAMES.has(propNameKebab);
3057
+ const isColor = COLOR_ATTR_NAMES.has(propNameKebab);
2597
3058
  const kfs = rawKfs.map((kf) => {
2598
- var _a, _b, _c, _d, _e, _f, _g, _h;
2599
- const t = (_a = kf.t) != null ? _a : kf.time;
2600
- let v = (_b = kf.v) != null ? _b : kf.value;
3059
+ var _a2;
3060
+ const t = kfTime(kf);
3061
+ let v = kfValue(kf);
2601
3062
  if (propName === "d") v = normalizePathValue(v);
2602
- if (isColour) v = (_c = parseColor(v)) != null ? _c : v;
2603
- const e = (_d = kf.e) != null ? _d : kf.easing;
3063
+ if (isColor) v = (_a2 = parseColor(v)) != null ? _a2 : v;
3064
+ const e = kfEasing(kf);
2604
3065
  const out2 = { t, v, e };
2605
- if ((_e = kf.tangentIn) != null ? _e : kf.ti) out2.tangentIn = (_f = kf.tangentIn) != null ? _f : kf.ti;
2606
- if ((_g = kf.tangentOut) != null ? _g : kf.to) out2.tangentOut = (_h = kf.tangentOut) != null ? _h : kf.to;
3066
+ const tIn = kfTangentIn(kf);
3067
+ const tOut = kfTangentOut(kf);
3068
+ if (tIn) out2.tangentIn = tIn;
3069
+ if (tOut) out2.tangentOut = tOut;
2607
3070
  return out2;
2608
3071
  });
2609
3072
  const expanded = expandLoopKeyframes(propName, kfs, loop, duration);
@@ -2611,15 +3074,15 @@ function materialiseInternalLoopsInPropAnim(propName, propAnim, duration) {
2611
3074
  if (propAnim.autoOrient !== void 0) out.autoOrient = propAnim.autoOrient;
2612
3075
  return out;
2613
3076
  }
2614
- function materialiseInternalLoopsInTree(root, duration) {
2615
- const ret = walkAndMaterialiseLoops(root, duration);
3077
+ function materializeInternalLoopsInTree(root, duration) {
3078
+ const ret = walkAndMaterializeLoops(root, duration);
2616
3079
  return ret != null ? ret : root;
2617
3080
  }
2618
- function walkAndMaterialiseLoops(node, duration) {
3081
+ function walkAndMaterializeLoops(node, duration) {
2619
3082
  let newChildren;
2620
3083
  if (node.children) {
2621
3084
  for (let i = 0; i < node.children.length; i++) {
2622
- const ret = walkAndMaterialiseLoops(node.children[i], duration);
3085
+ const ret = walkAndMaterializeLoops(node.children[i], duration);
2623
3086
  if (ret !== null) {
2624
3087
  if (!newChildren) newChildren = node.children.slice();
2625
3088
  newChildren[i] = ret;
@@ -2632,10 +3095,10 @@ function walkAndMaterialiseLoops(node, duration) {
2632
3095
  const animDef = animBucket;
2633
3096
  for (const propName of Object.keys(animDef)) {
2634
3097
  const propAnim = animDef[propName];
2635
- const materialised = materialiseInternalLoopsInPropAnim(propName, propAnim, duration);
2636
- if (materialised !== propAnim) {
3098
+ const materialized = materializeInternalLoopsInPropAnim(propName, propAnim, duration);
3099
+ if (materialized !== propAnim) {
2637
3100
  if (!newAnimate) newAnimate = __spreadValues2({}, animDef);
2638
- newAnimate[propName] = materialised;
3101
+ newAnimate[propName] = materialized;
2639
3102
  }
2640
3103
  }
2641
3104
  }
@@ -2654,7 +3117,7 @@ function mergeStaticTransformIntoAnimDef(animDef, staticTransform) {
2654
3117
  const staticParts = staticTransform && typeof staticTransform === "object" && !Array.isArray(staticTransform) ? staticTransform : parseTransformParts(staticTransform);
2655
3118
  if (!staticParts || !Object.keys(staticParts).length) return animDef;
2656
3119
  const mergeKfValue = (v) => v && typeof v === "object" && !Array.isArray(v) ? __spreadValues2(__spreadValues2({}, staticParts), v) : v;
2657
- const transformAnim = animDef["transform"];
3120
+ const transformAnim = animDef[TRANSFORM_ATTR];
2658
3121
  if (transformAnim && typeof transformAnim === "object") {
2659
3122
  const anim = transformAnim;
2660
3123
  if (Array.isArray(anim.keyframes)) {
@@ -2679,7 +3142,7 @@ function mergeStaticTransformIntoAnimDef(animDef, staticTransform) {
2679
3142
  delete rest[ch];
2680
3143
  return __spreadProps2(__spreadValues2({}, rest), { transform: lifted });
2681
3144
  }
2682
- function normalizeAnimationDefinition(animDef, duration, defs, engine = PxAnimatorEngine.waapi) {
3145
+ function normalizeAnimationDefinition(animDef, duration, defs, engine = PxTimelineEngine.native) {
2683
3146
  const normalized = {};
2684
3147
  for (const [propName, propAnim] of Object.entries(animDef)) {
2685
3148
  if (propName === "transform" && propAnim.alongPathMode === "offsetPath" && animDef["offsetDistance"] !== void 0) {
@@ -2690,12 +3153,12 @@ function normalizeAnimationDefinition(animDef, duration, defs, engine = PxAnimat
2690
3153
  const out = { keyframes: normalizedKfs };
2691
3154
  if (propAnim.autoOrient !== void 0) out.autoOrient = propAnim.autoOrient;
2692
3155
  if (propAnim.loop !== void 0) out.loop = propAnim.loop;
2693
- normalized[propName] = engine === PxAnimatorEngine.waapi && propName === "transform" ? materialiseMotionPathInPropAnim(out) : out;
3156
+ normalized[propName] = engine === PxTimelineEngine.native && propName === "transform" ? materializeMotionPathInPropAnim(out) : out;
2694
3157
  }
2695
3158
  }
2696
3159
  return normalized;
2697
3160
  }
2698
- function getNormalisedBindings(doc, engine = PxAnimatorEngine.waapi) {
3161
+ function getNormalizedBindings(doc, engine = PxTimelineEngine.native) {
2699
3162
  const animatorConfig = getAnimatorConfig(doc) || {};
2700
3163
  const defs = getDefs(doc);
2701
3164
  const duration = animatorConfig.duration || 1e3;
@@ -2741,12 +3204,12 @@ function getNormalisedBindings(doc, engine = PxAnimatorEngine.waapi) {
2741
3204
  return bindings;
2742
3205
  }
2743
3206
  function getKeyframesPair(keyframes, progress) {
2744
- var _a, _b;
3207
+ var _a2, _b;
2745
3208
  const last = keyframes.length - 1;
2746
3209
  let prevKf = keyframes[0];
2747
3210
  let nextKf = keyframes[last > 0 ? 1 : 0];
2748
3211
  for (let j = 0; j < last; j++) {
2749
- const aOff = (_a = keyframes[j].t) != null ? _a : 0;
3212
+ const aOff = (_a2 = keyframes[j].t) != null ? _a2 : 0;
2750
3213
  const bOff = (_b = keyframes[j + 1].t) != null ? _b : 0;
2751
3214
  if (aOff <= progress && progress <= bOff) {
2752
3215
  prevKf = keyframes[j];
@@ -2761,13 +3224,13 @@ function getKeyframesPair(keyframes, progress) {
2761
3224
  return { prevKf, nextKf };
2762
3225
  }
2763
3226
  function calcPropertyValue(propName, propAnim, progress) {
2764
- var _a, _b, _c, _d, _e, _f, _g;
3227
+ var _a2, _b, _c, _d;
2765
3228
  const keyframes = propAnim.keyframes || [];
2766
3229
  if (keyframes.length === 0) return null;
2767
3230
  const { prevKf, nextKf } = getKeyframesPair(keyframes, progress);
2768
- let localProgress = prevKf === nextKf ? 0 : remap(progress, (_a = prevKf.t) != null ? _a : 0, (_b = nextKf.t) != null ? _b : 0, 0, 1);
3231
+ let localProgress = prevKf === nextKf ? 0 : remap(progress, (_a2 = prevKf.t) != null ? _a2 : 0, (_b = nextKf.t) != null ? _b : 0, 0, 1);
2769
3232
  localProgress = clamp(localProgress, 0, 1);
2770
- const easing = (_c = prevKf.e) != null ? _c : prevKf.easing;
3233
+ const easing = kfEasing(prevKf);
2771
3234
  if (easing && Array.isArray(easing)) {
2772
3235
  try {
2773
3236
  localProgress = cubicBezier(easing)(localProgress);
@@ -2776,17 +3239,17 @@ function calcPropertyValue(propName, propAnim, progress) {
2776
3239
  }
2777
3240
  let cssAttrName = isCamelCaseWord(propName) ? camelCaseToKebabWordIfNeeded(propName) : propName;
2778
3241
  let cssValue = null;
2779
- const prevV = (_d = prevKf == null ? void 0 : prevKf.v) != null ? _d : prevKf == null ? void 0 : prevKf.value;
2780
- const nextV = (_e = nextKf == null ? void 0 : nextKf.v) != null ? _e : nextKf == null ? void 0 : nextKf.value;
3242
+ const prevV = prevKf == null ? void 0 : prevKf.v;
3243
+ const nextV = nextKf == null ? void 0 : nextKf.v;
2781
3244
  if (cssAttrName === "d") {
2782
- const prevPaths = (_f = prevV == null ? void 0 : prevV.paths) != null ? _f : Array.isArray(prevV) ? prevV : [];
2783
- const nextPaths = (_g = nextV == null ? void 0 : nextV.paths) != null ? _g : Array.isArray(nextV) ? nextV : [];
3245
+ const prevPaths = (_c = prevV == null ? void 0 : prevV.paths) != null ? _c : Array.isArray(prevV) ? prevV : [];
3246
+ const nextPaths = (_d = nextV == null ? void 0 : nextV.paths) != null ? _d : Array.isArray(nextV) ? nextV : [];
2784
3247
  cssValue = interpolateBeziers(
2785
3248
  prevPaths,
2786
3249
  nextPaths,
2787
3250
  localProgress
2788
3251
  ).map((bz) => bezierToSvgPath(bz)).join("");
2789
- } else if (COLOUR_ATTR_NAMES.has(cssAttrName)) {
3252
+ } else if (COLOR_ATTR_NAMES.has(cssAttrName)) {
2790
3253
  cssValue = toRGBA(interpolateColor(
2791
3254
  prevV || [0, 0, 0, 1],
2792
3255
  nextV || [0, 0, 0, 1],
@@ -2892,13 +3355,13 @@ function deepClonePxNode(value) {
2892
3355
  function regenerateIdsAndRewriteRefs(root, genId3) {
2893
3356
  const oldToNew = /* @__PURE__ */ new Map();
2894
3357
  const walkAssign = (n) => {
2895
- var _a;
3358
+ var _a2;
2896
3359
  if (typeof n.id === "string") {
2897
3360
  const newId = genId3();
2898
3361
  oldToNew.set(n.id, newId);
2899
3362
  n.id = newId;
2900
3363
  }
2901
- (_a = n.children) == null ? void 0 : _a.forEach(walkAssign);
3364
+ (_a2 = n.children) == null ? void 0 : _a2.forEach(walkAssign);
2902
3365
  };
2903
3366
  walkAssign(root);
2904
3367
  const rewriteUrl = (s) => s.replace(/url\(#([^)]+)\)/g, (m, oldId) => {
@@ -2906,7 +3369,7 @@ function regenerateIdsAndRewriteRefs(root, genId3) {
2906
3369
  return newId ? "url(#" + newId + ")" : m;
2907
3370
  });
2908
3371
  const walkRewrite = (n) => {
2909
- var _a;
3372
+ var _a2;
2910
3373
  if (typeof n.href === "string" && n.href.startsWith("#")) {
2911
3374
  const newId = oldToNew.get(n.href.slice(1));
2912
3375
  if (newId) n.href = "#" + newId;
@@ -2918,7 +3381,7 @@ function regenerateIdsAndRewriteRefs(root, genId3) {
2918
3381
  n[k] = rewriteUrl(v);
2919
3382
  }
2920
3383
  }
2921
- (_a = n.children) == null ? void 0 : _a.forEach(walkRewrite);
3384
+ (_a2 = n.children) == null ? void 0 : _a2.forEach(walkRewrite);
2922
3385
  };
2923
3386
  walkRewrite(root);
2924
3387
  return oldToNew;
@@ -2928,7 +3391,7 @@ function toFiniteNum(v) {
2928
3391
  return Number.isFinite(n) ? n : 0;
2929
3392
  }
2930
3393
  function applyUseOffsetToG(gNode) {
2931
- var _a;
3394
+ var _a2;
2932
3395
  const x = toFiniteNum(gNode.x);
2933
3396
  const y = toFiniteNum(gNode.y);
2934
3397
  delete gNode.x;
@@ -2937,15 +3400,15 @@ function applyUseOffsetToG(gNode) {
2937
3400
  const offset = "translate(" + x + "," + y + ")";
2938
3401
  const carriesTransform = gNode.transform !== void 0 || gNode.animate !== void 0;
2939
3402
  if (carriesTransform) {
2940
- const inner = { type: "g", transform: offset, children: (_a = gNode.children) != null ? _a : [] };
3403
+ const inner = { type: "g", transform: offset, children: (_a2 = gNode.children) != null ? _a2 : [] };
2941
3404
  gNode.children = [inner];
2942
3405
  } else {
2943
3406
  gNode.transform = offset;
2944
3407
  }
2945
3408
  return gNode;
2946
3409
  }
2947
- function materialiseAnimatedUseInstances(root) {
2948
- var _a;
3410
+ function materializeAnimatedUseInstances(root) {
3411
+ var _a2;
2949
3412
  const idMap = buildIdMap(root);
2950
3413
  const animatedIds = computeAnimatedSubtreeIds(root, idMap);
2951
3414
  if (animatedIds.size === 0) return root;
@@ -2953,10 +3416,10 @@ function materialiseAnimatedUseInstances(root) {
2953
3416
  const genId3 = () => "_lw_use_mat_" + ++idCounter;
2954
3417
  const rootViewport = readRootViewport(root);
2955
3418
  const defsCollector = [];
2956
- const walked = walkAndMaterialise2(root, idMap, animatedIds, genId3, defsCollector, rootViewport);
3419
+ const walked = walkAndMaterialize2(root, idMap, animatedIds, genId3, defsCollector, rootViewport);
2957
3420
  if (defsCollector.length === 0) return walked;
2958
3421
  const defsNode = { type: "defs", children: defsCollector };
2959
- const newChildren = [...(_a = walked.children) != null ? _a : [], defsNode];
3422
+ const newChildren = [...(_a2 = walked.children) != null ? _a2 : [], defsNode];
2960
3423
  return __spreadProps2(__spreadValues2({}, walked), { children: newChildren });
2961
3424
  }
2962
3425
  function readRootViewport(root) {
@@ -2978,9 +3441,9 @@ function numericAttr(v) {
2978
3441
  function buildIdMap(root) {
2979
3442
  const map = /* @__PURE__ */ new Map();
2980
3443
  const visit = (n) => {
2981
- var _a;
3444
+ var _a2;
2982
3445
  if (typeof n.id === "string") map.set(n.id, n);
2983
- (_a = n.children) == null ? void 0 : _a.forEach(visit);
3446
+ (_a2 = n.children) == null ? void 0 : _a2.forEach(visit);
2984
3447
  };
2985
3448
  visit(root);
2986
3449
  return map;
@@ -3026,16 +3489,16 @@ function stripHash(href) {
3026
3489
  if (typeof href !== "string") return void 0;
3027
3490
  return href.startsWith("#") ? href.slice(1) : href;
3028
3491
  }
3029
- function materialiseOneUse(useNode, target, idMap, animatedIds, genId3, defsCollector, rootViewport) {
3030
- var _a, _b, _c, _d;
3492
+ function materializeOneUse(useNode, target, idMap, animatedIds, genId3, defsCollector, rootViewport) {
3493
+ var _a2, _b, _c, _d;
3031
3494
  const clone2 = deepClonePxNode(target);
3032
3495
  regenerateIdsAndRewriteRefs(clone2, genId3);
3033
3496
  const symbolViewBox = clone2.type === "symbol" ? parseViewBox(clone2.viewBox) : void 0;
3034
- const useW = (_b = (_a = numericAttr(useNode.width)) != null ? _a : symbolViewBox == null ? void 0 : symbolViewBox[2]) != null ? _b : rootViewport[0];
3497
+ const useW = (_b = (_a2 = numericAttr(useNode.width)) != null ? _a2 : symbolViewBox == null ? void 0 : symbolViewBox[2]) != null ? _b : rootViewport[0];
3035
3498
  const useH = (_d = (_c = numericAttr(useNode.height)) != null ? _c : symbolViewBox == null ? void 0 : symbolViewBox[3]) != null ? _d : rootViewport[1];
3036
3499
  const rewrittenClone = clone2.type === "symbol" ? rewriteSymbolRootToGroup(clone2, genId3, defsCollector, useW, useH) : clone2;
3037
- const materialisedClone = walkAndMaterialise2(rewrittenClone, idMap, animatedIds, genId3, defsCollector, rootViewport);
3038
- const newNode = __spreadProps2(__spreadValues2({}, useNode), { type: "g", children: [materialisedClone] });
3500
+ const materializedClone = walkAndMaterialize2(rewrittenClone, idMap, animatedIds, genId3, defsCollector, rootViewport);
3501
+ const newNode = __spreadProps2(__spreadValues2({}, useNode), { type: "g", children: [materializedClone] });
3039
3502
  delete newNode.href;
3040
3503
  delete newNode.width;
3041
3504
  delete newNode.height;
@@ -3073,18 +3536,18 @@ function parseViewBox(v) {
3073
3536
  if (parts.length < 4 || parts.some((n) => !Number.isFinite(n))) return void 0;
3074
3537
  return [parts[0], parts[1], parts[2], parts[3]];
3075
3538
  }
3076
- function walkAndMaterialise2(node, idMap, animatedIds, genId3, defsCollector, rootViewport) {
3539
+ function walkAndMaterialize2(node, idMap, animatedIds, genId3, defsCollector, rootViewport) {
3077
3540
  if (node.type === "use" && typeof node.href === "string") {
3078
3541
  const targetId = stripHash(node.href);
3079
3542
  if (targetId && animatedIds.has(targetId)) {
3080
3543
  const target = idMap.get(targetId);
3081
- if (target) return materialiseOneUse(node, target, idMap, animatedIds, genId3, defsCollector, rootViewport);
3544
+ if (target) return materializeOneUse(node, target, idMap, animatedIds, genId3, defsCollector, rootViewport);
3082
3545
  }
3083
3546
  }
3084
3547
  if (!node.children) return node;
3085
3548
  let changed = false;
3086
3549
  const newChildren = node.children.map((ch) => {
3087
- const m = walkAndMaterialise2(ch, idMap, animatedIds, genId3, defsCollector, rootViewport);
3550
+ const m = walkAndMaterialize2(ch, idMap, animatedIds, genId3, defsCollector, rootViewport);
3088
3551
  if (m !== ch) changed = true;
3089
3552
  return m;
3090
3553
  });
@@ -3100,7 +3563,7 @@ function partsRecord(part, value, origin) {
3100
3563
  return rec;
3101
3564
  }
3102
3565
  function readAnimatable(raw) {
3103
- var _a, _b, _c;
3566
+ var _a2, _b;
3104
3567
  if (raw === void 0) return {
3105
3568
  kind: "absent"
3106
3569
  /* Absent */
@@ -3108,20 +3571,20 @@ function readAnimatable(raw) {
3108
3571
  if (Array.isArray(raw)) return { kind: "static", value: raw };
3109
3572
  if (typeof raw === "object") {
3110
3573
  const obj = raw;
3111
- const kfs = (_a = obj.keyframes) != null ? _a : obj.kfs;
3574
+ const kfs = obj.keyframes;
3112
3575
  if (kfs) {
3113
- const out = { kind: "animated", keyframes: kfs.map(normaliseKeyframe), autoOrient: obj.autoOrient, loop: obj.loop };
3114
- const base = (_b = obj.value) != null ? _b : obj.v;
3576
+ const out = { kind: "animated", keyframes: kfs.map(normalizeKeyframe), autoOrient: obj.autoOrient, loop: obj.loop };
3577
+ const base = (_a2 = obj.value) != null ? _a2 : obj.v;
3115
3578
  if (base !== void 0 && out.kind === "animated") out.base = base;
3116
3579
  return out;
3117
3580
  }
3118
- const staticValue = (_c = obj.value) != null ? _c : obj.v;
3581
+ const staticValue = (_b = obj.value) != null ? _b : obj.v;
3119
3582
  if (staticValue !== void 0) return { kind: "static", value: staticValue };
3120
3583
  }
3121
3584
  return { kind: "static", value: raw };
3122
3585
  }
3123
3586
  function writeAnimatableChannel(node, attrName, read, opts) {
3124
- var _a, _b, _c, _d;
3587
+ var _a2, _b, _c, _d;
3125
3588
  const toOut = (v) => (opts == null ? void 0 : opts.asString) && v !== void 0 && v !== null ? String(v) : v;
3126
3589
  if (read.kind === "absent") return;
3127
3590
  if (read.kind === "static") {
@@ -3135,10 +3598,10 @@ function writeAnimatableChannel(node, attrName, read, opts) {
3135
3598
  if (read.autoOrient !== void 0) block.autoOrient = read.autoOrient;
3136
3599
  animate[attrName] = block;
3137
3600
  node.animate = animate;
3138
- 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;
3601
+ 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;
3139
3602
  if (baseline !== void 0) node[attrName] = toOut(baseline);
3140
3603
  }
3141
- function normaliseKeyframe(kf) {
3604
+ function normalizeKeyframe(kf) {
3142
3605
  if (!kf || typeof kf !== "object") return kf;
3143
3606
  const k = kf;
3144
3607
  if (k.t === void 0 && k.v === void 0 && k.e === void 0 && k.to === void 0 && k.ti === void 0) {
@@ -3153,12 +3616,12 @@ function normaliseKeyframe(kf) {
3153
3616
  return out;
3154
3617
  }
3155
3618
  function readStaticOrigin(raw, ctx) {
3156
- var _a;
3619
+ var _a2;
3157
3620
  const o = readAnimatable(raw);
3158
3621
  if (o.kind === "absent") return void 0;
3159
3622
  if (o.kind === "static") return o.value;
3160
3623
  ctx.warnings.push("transformBy.origin: animated origin approximated by its first keyframe");
3161
- return (_a = o.keyframes[0]) == null ? void 0 : _a.value;
3624
+ return (_a2 = o.keyframes[0]) == null ? void 0 : _a2.value;
3162
3625
  }
3163
3626
  function keyframeWith(kf, value) {
3164
3627
  const out = { value };
@@ -3264,9 +3727,9 @@ function stripHash2(href) {
3264
3727
  return typeof href === "string" ? href.replace(/^#/, "") : void 0;
3265
3728
  }
3266
3729
  function indexById(node, map) {
3267
- var _a;
3730
+ var _a2;
3268
3731
  if (typeof node.id === "string") map.set(node.id, node);
3269
- (_a = node.children) == null ? void 0 : _a.forEach((child) => indexById(child, map));
3732
+ (_a2 = node.children) == null ? void 0 : _a2.forEach((child) => indexById(child, map));
3270
3733
  }
3271
3734
  function spliceDefs(root, defs) {
3272
3735
  if (!defs.length) return;
@@ -3278,9 +3741,9 @@ function regenerateIdsInClone(root, ctx) {
3278
3741
  return regenerateIdsAndRewriteRefs(root, () => genId(ctx, "retimed"));
3279
3742
  }
3280
3743
  function identifyContentRefTargets(node, ctx, allocator) {
3281
- var _a, _b, _c;
3282
- if (node.type === "use" && ((_b = (_a = node.effects) == null ? void 0 : _a.clone) == null ? void 0 : _b.type) === "content") {
3283
- const sourceId = stripHash2(node.effects.clone.sourceId);
3744
+ var _a2, _b, _c;
3745
+ if (node.type === "use" && ((_b = (_a2 = node.effects) == null ? void 0 : _a2.clone) == null ? void 0 : _b.without) === "translate") {
3746
+ const sourceId = stripHash2(node.effects.clone.source);
3284
3747
  if (typeof sourceId === "string" && sourceId && !ctx.contentRefInnerIds.has(sourceId)) {
3285
3748
  ctx.contentRefInnerIds.set(sourceId, allocator(sourceId));
3286
3749
  }
@@ -3305,10 +3768,10 @@ function splitForContentRef(node, transformBy, originalId, innerId, ctx) {
3305
3768
  return outerWrapper;
3306
3769
  }
3307
3770
  function liftBodyTranslate(node, transformBy) {
3308
- var _a, _b, _c;
3771
+ var _a2, _b, _c;
3309
3772
  const out = {};
3310
3773
  let didLiftAnimate = false;
3311
- const animTr = (_a = node.animate) == null ? void 0 : _a.transform;
3774
+ const animTr = (_a2 = node.animate) == null ? void 0 : _a2.transform;
3312
3775
  if (animTr && typeof animTr === "object" && Array.isArray(animTr.keyframes)) {
3313
3776
  const kfs = animTr.keyframes;
3314
3777
  const hasTranslate = kfs.some((kf) => kf.value && kf.value.translate);
@@ -3524,7 +3987,7 @@ function synthesiseGradientDef(fx, id, ctx) {
3524
3987
  return out;
3525
3988
  }
3526
3989
  function applyGeomVec(out, xAttr, yAttr, raw) {
3527
- var _a, _b, _c;
3990
+ var _a2, _b, _c;
3528
3991
  const read = readAnimatable(raw);
3529
3992
  if (read.kind === "absent") return;
3530
3993
  if (read.kind === "static") {
@@ -3543,7 +4006,7 @@ function applyGeomVec(out, xAttr, yAttr, raw) {
3543
4006
  if (read.loop !== void 0) block.loop = read.loop;
3544
4007
  return block;
3545
4008
  };
3546
- const animate = (_a = out.animate) != null ? _a : {};
4009
+ const animate = (_a2 = out.animate) != null ? _a2 : {};
3547
4010
  animate[xAttr] = axisChannel(0);
3548
4011
  animate[yAttr] = axisChannel(1);
3549
4012
  out.animate = animate;
@@ -3559,7 +4022,7 @@ function applyGeomNumber(out, attrName, raw) {
3559
4022
  writeAnimatableChannel(out, attrName, read, { asString: true });
3560
4023
  }
3561
4024
  function buildStopChildren(stops, ctx) {
3562
- var _a, _b, _c, _d;
4025
+ var _a2, _b;
3563
4026
  if (!stops) return [];
3564
4027
  const read = readAnimatable(stops);
3565
4028
  if (read.kind === "absent") return [];
@@ -3569,14 +4032,14 @@ function buildStopChildren(stops, ctx) {
3569
4032
  const loopFromSource = read.loop;
3570
4033
  let stopCount = 0;
3571
4034
  for (const kf of kfs) {
3572
- const v = (_a = kf.value) != null ? _a : kf.v;
4035
+ const v = kfValue(kf);
3573
4036
  if (Array.isArray(v) && v.length > stopCount) stopCount = v.length;
3574
4037
  }
3575
4038
  if (!stopCount) return [];
3576
- const firstKfValue = (_b = kfs[0].value) != null ? _b : kfs[0].v;
4039
+ const firstKfValue = kfValue(kfs[0]);
3577
4040
  const baselineStops = [];
3578
4041
  for (let i = 0; i < stopCount; i++) {
3579
- 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" };
4042
+ 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" };
3580
4043
  baselineStops.push({ offset: s.offset, color: s.color });
3581
4044
  }
3582
4045
  return baselineStops.map((bs, i) => animatedStopNode(bs, kfs, i, ctx, loopFromSource));
@@ -3589,16 +4052,16 @@ function staticStopNode(s) {
3589
4052
  };
3590
4053
  }
3591
4054
  function animatedStopNode(baseline, kfs, stopIdx, _ctx, loop) {
3592
- var _a, _b, _c, _d, _e;
4055
+ var _a2;
3593
4056
  const colorKfs = [];
3594
4057
  const offsetKfs = [];
3595
4058
  let offsetVaries = false;
3596
4059
  for (const kf of kfs) {
3597
- const t = (_b = (_a = kf.time) != null ? _a : kf.t) != null ? _b : 0;
3598
- const arr = (_c = kf.value) != null ? _c : kf.v;
3599
- const sliced = (_d = arr == null ? void 0 : arr[stopIdx]) != null ? _d : prevDefinedStop(kfs, kfs.indexOf(kf), stopIdx);
4060
+ const t = kfTime(kf);
4061
+ const arr = kfValue(kf);
4062
+ const sliced = (_a2 = arr == null ? void 0 : arr[stopIdx]) != null ? _a2 : prevDefinedStop(kfs, kfs.indexOf(kf), stopIdx);
3600
4063
  if (!sliced) continue;
3601
- const easing = (_e = kf.easing) != null ? _e : kf.e;
4064
+ const easing = kfEasing(kf);
3602
4065
  const colorOut = { time: t, value: sliced.color };
3603
4066
  if (easing !== void 0) colorOut.easing = easing;
3604
4067
  colorKfs.push(colorOut);
@@ -3625,13 +4088,12 @@ function animatedStopNode(baseline, kfs, stopIdx, _ctx, loop) {
3625
4088
  return stop;
3626
4089
  }
3627
4090
  function prevDefinedStop(kfs, fromIdx, stopIdx) {
3628
- var _a, _b;
3629
4091
  for (let i = fromIdx; i >= 0; i--) {
3630
- const arr = (_a = kfs[i].value) != null ? _a : kfs[i].v;
4092
+ const arr = kfValue(kfs[i]);
3631
4093
  if (arr == null ? void 0 : arr[stopIdx]) return arr[stopIdx];
3632
4094
  }
3633
4095
  for (let i = fromIdx + 1; i < kfs.length; i++) {
3634
- const arr = (_b = kfs[i].value) != null ? _b : kfs[i].v;
4096
+ const arr = kfValue(kfs[i]);
3635
4097
  if (arr == null ? void 0 : arr[stopIdx]) return arr[stopIdx];
3636
4098
  }
3637
4099
  return void 0;
@@ -3641,10 +4103,10 @@ function formatOffset(o) {
3641
4103
  return pct + "%";
3642
4104
  }
3643
4105
  function applyClipPathEffect(node, fx, ctx) {
3644
- if (!(fx == null ? void 0 : fx.d)) return node;
4106
+ if (!(fx == null ? void 0 : fx.pathData)) return node;
3645
4107
  const clipId = genId(ctx, "clip");
3646
4108
  const pathChild = { type: "path" };
3647
- const read = readAnimatable(fx.d);
4109
+ const read = readAnimatable(fx.pathData);
3648
4110
  if (read.kind !== "absent") {
3649
4111
  if (read.kind === "static") {
3650
4112
  pathChild.d = pathString(read.value);
@@ -3659,14 +4121,14 @@ function applyClipPathEffect(node, fx, ctx) {
3659
4121
  }
3660
4122
  function pathString(v) {
3661
4123
  if (typeof v === "string") return v;
3662
- if (v && typeof v === "object" && typeof v.path === "string") return v.path;
4124
+ if (v && typeof v === "object" && typeof v.pathData === "string") return v.pathData;
3663
4125
  return void 0;
3664
4126
  }
3665
4127
  function applyMaskedByEffect(node, fx, transformBy, ctx) {
3666
4128
  if (!fx) return node;
3667
- const sourceId = stripHash2(fx.sourceId);
4129
+ const sourceId = stripHash2(fx.source);
3668
4130
  if (!sourceId) {
3669
- ctx.errors.push("maskedBy.sourceId missing \u2014 cannot build mask");
4131
+ ctx.errors.push("maskedBy.source missing \u2014 cannot build mask");
3670
4132
  return node;
3671
4133
  }
3672
4134
  const maskId = genId(ctx, "mask");
@@ -3704,8 +4166,8 @@ function wrapInverseTransform(inner, fx, ctx) {
3704
4166
  }
3705
4167
  function wrapInversePart(inner, part, raw, origin, ctx) {
3706
4168
  if (raw === void 0) return inner;
3707
- const normalisedRaw = part === "scale" && Array.isArray(raw) ? [raw[0] / 100, raw[1] / 100] : raw;
3708
- const v = readAnimatable(normalisedRaw);
4169
+ const normalizedRaw = part === "scale" && Array.isArray(raw) ? [raw[0] / 100, raw[1] / 100] : raw;
4170
+ const v = readAnimatable(normalizedRaw);
3709
4171
  if (v.kind === "static") {
3710
4172
  return { type: "g", transform: { value: partsRecord(part, invertPartValue(part, v.value), origin) }, children: [inner] };
3711
4173
  }
@@ -3729,16 +4191,16 @@ function invertPartValue(part, value) {
3729
4191
  return [1 / value[0], 1 / value[1]];
3730
4192
  }
3731
4193
  function negatedSpatialTangents(kf) {
3732
- var _a, _b;
4194
+ var _a2, _b;
3733
4195
  const out = {};
3734
- const to = (_a = kf.tangentOut) != null ? _a : kf.to;
4196
+ const to = (_a2 = kf.tangentOut) != null ? _a2 : kf.to;
3735
4197
  const ti = (_b = kf.tangentIn) != null ? _b : kf.ti;
3736
4198
  if (Array.isArray(to)) out.tangentOut = [-to[0], -to[1]];
3737
4199
  if (Array.isArray(ti)) out.tangentIn = [-ti[0], -ti[1]];
3738
4200
  return out;
3739
4201
  }
3740
4202
  function wrapInverseAnimatedBodyTransform(inner, node, _ctx) {
3741
- var _a;
4203
+ var _a2;
3742
4204
  const animate = node.animate && typeof node.animate === "object" && !Array.isArray(node.animate) ? node.animate : void 0;
3743
4205
  const animTr = animate == null ? void 0 : animate.transform;
3744
4206
  const kfs = animTr && typeof animTr === "object" && Array.isArray(animTr.keyframes) ? animTr.keyframes : void 0;
@@ -3747,7 +4209,7 @@ function wrapInverseAnimatedBodyTransform(inner, node, _ctx) {
3747
4209
  const rotateKfs = [];
3748
4210
  const scaleKfs = [];
3749
4211
  for (const kf of kfs) {
3750
- const v = ((_a = kf.value) != null ? _a : kf.v) || {};
4212
+ const v = ((_a2 = kf.value) != null ? _a2 : kf.v) || {};
3751
4213
  const baseKf = keyframeWith(kf, void 0);
3752
4214
  if (Array.isArray(v.translate)) {
3753
4215
  translateKfs.push(__spreadProps2(__spreadValues2(__spreadValues2({}, baseKf), negatedSpatialTangents(kf)), { value: { translate: [-v.translate[0], -v.translate[1]] } }));
@@ -3811,7 +4273,7 @@ function readTransformationFromBody(node) {
3811
4273
  return void 0;
3812
4274
  }
3813
4275
  function parseTransformStringToParts(s) {
3814
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m;
4276
+ var _a2, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m;
3815
4277
  const re = /([a-zA-Z]+)\s*\(([^)]*)\)/g;
3816
4278
  let m;
3817
4279
  const ops = [];
@@ -3825,7 +4287,7 @@ function parseTransformStringToParts(s) {
3825
4287
  for (let j = ops.length - 2; j >= 0; j--) {
3826
4288
  const cand = ops[j];
3827
4289
  if (cand.name !== "translate") continue;
3828
- const ox = (_a = cand.args[0]) != null ? _a : 0;
4290
+ const ox = (_a2 = cand.args[0]) != null ? _a2 : 0;
3829
4291
  const oy = (_b = cand.args[1]) != null ? _b : 0;
3830
4292
  const lx = (_c = last.args[0]) != null ? _c : 0;
3831
4293
  const ly = (_d = last.args[1]) != null ? _d : 0;
@@ -3940,8 +4402,8 @@ function interpKfs(kfs, t) {
3940
4402
  function collectMaskAncestorChains(root, ctx) {
3941
4403
  const interestingNodes = /* @__PURE__ */ new Set();
3942
4404
  const collectInterestingNodes = (n) => {
3943
- var _a, _b;
3944
- const maskSourceId = stripHash2((_b = (_a = n.effects) == null ? void 0 : _a.maskedBy) == null ? void 0 : _b.sourceId);
4405
+ var _a2, _b;
4406
+ const maskSourceId = stripHash2((_b = (_a2 = n.effects) == null ? void 0 : _a2.maskedBy) == null ? void 0 : _b.source);
3945
4407
  if (typeof maskSourceId === "string") {
3946
4408
  interestingNodes.add(n);
3947
4409
  const sourceNode = ctx.idMap.get(maskSourceId);
@@ -3962,7 +4424,7 @@ function collectMaskAncestorChains(root, ctx) {
3962
4424
  walk(root, []);
3963
4425
  }
3964
4426
  function extractTranslateOnly(node, ctx) {
3965
- var _a, _b, _c;
4427
+ var _a2, _b, _c;
3966
4428
  const tr = node.transform;
3967
4429
  const animateBlock = node.animate && typeof node.animate === "object" && !Array.isArray(node.animate) ? node.animate.transform : void 0;
3968
4430
  if (tr === void 0 && !animateBlock) return void 0;
@@ -3970,7 +4432,7 @@ function extractTranslateOnly(node, ctx) {
3970
4432
  if (typeof tr === "string") {
3971
4433
  const parts = parseTranslateOnlyFromString(tr, ctx);
3972
4434
  if (parts) out.translate = parts;
3973
- } else if (tr && typeof tr === "object" && !tr.keyframes && !tr.kfs) {
4435
+ } else if (tr && typeof tr === "object" && !tr.keyframes) {
3974
4436
  const wrapped = tr.value;
3975
4437
  const value = wrapped && typeof wrapped === "object" ? wrapped : tr;
3976
4438
  if (value && typeof value === "object" && Array.isArray(value.translate)) {
@@ -3984,7 +4446,7 @@ function extractTranslateOnly(node, ctx) {
3984
4446
  const kfs = animateBlock.keyframes;
3985
4447
  const translateKfs = [];
3986
4448
  for (const kf of kfs) {
3987
- const v = (_a = kf.value) != null ? _a : kf.v;
4449
+ const v = (_a2 = kf.value) != null ? _a2 : kf.v;
3988
4450
  const t = (_c = (_b = kf.time) != null ? _b : kf.t) != null ? _c : 0;
3989
4451
  if (v && typeof v === "object" && Array.isArray(v.translate)) {
3990
4452
  translateKfs.push({ time: t, value: [v.translate[0] || 0, v.translate[1] || 0] });
@@ -4017,15 +4479,14 @@ function parseTranslateOnlyFromString(s, ctx) {
4017
4479
  if (droppedNonTranslate) ctx.warnings.push("maskedBy ancestor: non-translate transform in string ignored: " + s);
4018
4480
  return seen ? [x, y] : void 0;
4019
4481
  }
4020
- var CONTENT_SUBREF = "content";
4021
4482
  function applyRefHref(node, clone2, ctx) {
4022
4483
  if (!clone2) return;
4023
- const sourceId = stripHash2(clone2.sourceId);
4484
+ const sourceId = stripHash2(clone2.source);
4024
4485
  if (!sourceId) {
4025
- if (clone2.type === CONTENT_SUBREF) ctx.errors.push("clone: content ref missing sourceId");
4486
+ if (clone2.without === PxCloneWithout.translate) ctx.errors.push("clone: content ref missing `source`");
4026
4487
  return;
4027
4488
  }
4028
- const targetId = clone2.type === CONTENT_SUBREF ? ctx.contentRefInnerIds.get(sourceId) || sourceId : sourceId;
4489
+ const targetId = clone2.without === PxCloneWithout.translate ? ctx.contentRefInnerIds.get(sourceId) || sourceId : sourceId;
4029
4490
  node.href = "#" + targetId;
4030
4491
  }
4031
4492
  function applyRefAndTransformationEffect(node, clone2, transformBy, ctx) {
@@ -4033,9 +4494,9 @@ function applyRefAndTransformationEffect(node, clone2, transformBy, ctx) {
4033
4494
  return applyTransformByEffect(node, transformBy, ctx);
4034
4495
  }
4035
4496
  function applyRepeaterEffect(node, fx, ctx) {
4036
- var _a, _b;
4497
+ var _a2, _b;
4037
4498
  if (!fx) return node;
4038
- const copies = (_a = fx.copies) != null ? _a : 1;
4499
+ const copies = (_a2 = fx.copies) != null ? _a2 : 1;
4039
4500
  if (copies < 1) {
4040
4501
  ctx.errors.push("repeater.copies invalid: " + fx.copies);
4041
4502
  return node;
@@ -4101,10 +4562,10 @@ function synthesiseScale(raw, i) {
4101
4562
  const scalePower = (v) => [Math.pow(v[0], i), Math.pow(v[1], i)];
4102
4563
  return mapAnimatable(raw, scalePower, true);
4103
4564
  }
4104
- var RETIME_MATERIALISATION_MODE_INLINE_G = false;
4565
+ var RETIME_MATERIALIZATION_MODE_INLINE_G = false;
4105
4566
  function asRetime(r) {
4106
- var _a, _b;
4107
- return { start: (_a = r.start) != null ? _a : 0, stretch: (_b = r.stretch) != null ? _b : 1 };
4567
+ var _a2, _b;
4568
+ return { start: (_a2 = r.start) != null ? _a2 : 0, stretch: (_b = r.stretch) != null ? _b : 1 };
4108
4569
  }
4109
4570
  var CROP_EDGE_MS = 1;
4110
4571
  function applyTimeCrop(useNode, crop, ctx) {
@@ -4132,12 +4593,12 @@ function concatRetime(child, parent) {
4132
4593
  };
4133
4594
  }
4134
4595
  function readCloneRetime(n) {
4135
- var _a, _b;
4136
- return (_b = (_a = n.effects) == null ? void 0 : _a.clone) == null ? void 0 : _b.retime;
4596
+ var _a2, _b;
4597
+ return (_b = (_a2 = n.effects) == null ? void 0 : _a2.clone) == null ? void 0 : _b.retime;
4137
4598
  }
4138
4599
  function clearCloneRetime(n) {
4139
- var _a;
4140
- const clone2 = (_a = n.effects) == null ? void 0 : _a.clone;
4600
+ var _a2;
4601
+ const clone2 = (_a2 = n.effects) == null ? void 0 : _a2.clone;
4141
4602
  if (!clone2) return;
4142
4603
  delete clone2.retime;
4143
4604
  if (Object.keys(clone2).length === 0) delete n.effects.clone;
@@ -4148,9 +4609,9 @@ function applyAllRetimeEffects(root, ctx) {
4148
4609
  indexById(root, ctx.idMap);
4149
4610
  const sites = [];
4150
4611
  const collect = (n) => {
4151
- var _a;
4612
+ var _a2;
4152
4613
  if (readCloneRetime(n)) sites.push(n);
4153
- (_a = n.children) == null ? void 0 : _a.forEach(collect);
4614
+ (_a2 = n.children) == null ? void 0 : _a2.forEach(collect);
4154
4615
  };
4155
4616
  collect(root);
4156
4617
  const reachCount = /* @__PURE__ */ new Map();
@@ -4158,7 +4619,7 @@ function applyAllRetimeEffects(root, ctx) {
4158
4619
  let count = 0;
4159
4620
  const visited = /* @__PURE__ */ new Set();
4160
4621
  const walk = (n) => {
4161
- var _a;
4622
+ var _a2;
4162
4623
  if (!n) return;
4163
4624
  if (n !== site && readCloneRetime(n)) count++;
4164
4625
  if (n.type === "use" && n.href) {
@@ -4168,7 +4629,7 @@ function applyAllRetimeEffects(root, ctx) {
4168
4629
  walk(ctx.idMap.get(id));
4169
4630
  }
4170
4631
  }
4171
- (_a = n.children) == null ? void 0 : _a.forEach(walk);
4632
+ (_a2 = n.children) == null ? void 0 : _a2.forEach(walk);
4172
4633
  };
4173
4634
  const rootId = stripHash2(site.href);
4174
4635
  if (rootId) {
@@ -4178,19 +4639,19 @@ function applyAllRetimeEffects(root, ctx) {
4178
4639
  reachCount.set(site, count);
4179
4640
  }
4180
4641
  sites.sort((a, b) => {
4181
- var _a, _b;
4182
- return ((_a = reachCount.get(b)) != null ? _a : 0) - ((_b = reachCount.get(a)) != null ? _b : 0);
4642
+ var _a2, _b;
4643
+ return ((_a2 = reachCount.get(b)) != null ? _a2 : 0) - ((_b = reachCount.get(a)) != null ? _b : 0);
4183
4644
  });
4184
4645
  for (const useNode of sites) {
4185
4646
  const retime = readCloneRetime(useNode);
4186
4647
  if (!retime) continue;
4187
4648
  const crop = retime.timeCrop;
4188
4649
  clearCloneRetime(useNode);
4189
- materialiseRetime(useNode, asRetime(retime), ctx);
4650
+ materializeRetime(useNode, asRetime(retime), ctx);
4190
4651
  if (crop) applyTimeCrop(useNode, crop, ctx);
4191
4652
  }
4192
4653
  }
4193
- function materialiseRetime(useNode, retime, ctx) {
4654
+ function materializeRetime(useNode, retime, ctx) {
4194
4655
  const targetId = stripHash2(useNode.href);
4195
4656
  if (!targetId) {
4196
4657
  ctx.errors.push("retime: <use> has no href to follow");
@@ -4198,7 +4659,7 @@ function materialiseRetime(useNode, retime, ctx) {
4198
4659
  }
4199
4660
  const chainRootId = buildChainClone(targetId, retime, ctx, /* @__PURE__ */ new Set());
4200
4661
  if (!chainRootId) return;
4201
- if (RETIME_MATERIALISATION_MODE_INLINE_G) {
4662
+ if (RETIME_MATERIALIZATION_MODE_INLINE_G) {
4202
4663
  const cloneNode = ctx.idMap.get(chainRootId);
4203
4664
  useNode.type = "g";
4204
4665
  delete useNode.href;
@@ -4238,15 +4699,15 @@ function buildChainClone(targetId, accum, ctx, chain) {
4238
4699
  if (subId2) cloneNode.href = "#" + subId2;
4239
4700
  }
4240
4701
  } else {
4241
- materialiseNestedRetimeUses(cloneNode, accum, ctx, chain, targetId);
4702
+ materializeNestedRetimeUses(cloneNode, accum, ctx, chain, targetId);
4242
4703
  }
4243
4704
  ctx.defs.push(cloneNode);
4244
4705
  if (typeof cloneNode.id === "string") ctx.idMap.set(cloneNode.id, cloneNode);
4245
4706
  return typeof cloneNode.id === "string" ? cloneNode.id : void 0;
4246
4707
  }
4247
- function materialiseNestedRetimeUses(node, accum, ctx, chain, parentTargetId) {
4708
+ function materializeNestedRetimeUses(node, accum, ctx, chain, parentTargetId) {
4248
4709
  const visit = (n) => {
4249
- var _a;
4710
+ var _a2;
4250
4711
  const retime = readCloneRetime(n);
4251
4712
  if (n.type === "use" && retime && n.href) {
4252
4713
  const subId = stripHash2(n.href);
@@ -4259,14 +4720,14 @@ function materialiseNestedRetimeUses(node, accum, ctx, chain, parentTargetId) {
4259
4720
  }
4260
4721
  clearCloneRetime(n);
4261
4722
  }
4262
- (_a = n.children) == null ? void 0 : _a.forEach(visit);
4723
+ (_a2 = n.children) == null ? void 0 : _a2.forEach(visit);
4263
4724
  };
4264
4725
  visit(node);
4265
4726
  }
4266
4727
  function remapKeyframeTimes(node, start, stretch) {
4267
- var _a;
4728
+ var _a2;
4268
4729
  remapKeyframeTimesOnly(node, start, stretch);
4269
- (_a = node.children) == null ? void 0 : _a.forEach((c) => remapKeyframeTimes(c, start, stretch));
4730
+ (_a2 = node.children) == null ? void 0 : _a2.forEach((c) => remapKeyframeTimes(c, start, stretch));
4270
4731
  }
4271
4732
  function remapKeyframeTimesOnly(node, start, stretch) {
4272
4733
  const remap2 = (kfs) => {
@@ -4441,10 +4902,10 @@ function numRange(v) {
4441
4902
  function estimateTextAdvance(node) {
4442
4903
  let chars = 0, maxFont = 16;
4443
4904
  const walk = (el) => {
4444
- var _a, _b;
4445
- const fs = parseFloat(String((_a = el.fontSize) != null ? _a : "")) || 0;
4905
+ var _a2;
4906
+ const fs = parseFloat(String((_a2 = el.fontSize) != null ? _a2 : "")) || 0;
4446
4907
  if (fs) maxFont = Math.max(maxFont, fs);
4447
- const t = (_b = el.text) != null ? _b : el.textContent;
4908
+ const t = el.textContent;
4448
4909
  if (typeof t === "string") chars += t.length;
4449
4910
  if (el.children) for (const c of el.children) walk(c);
4450
4911
  };
@@ -4466,14 +4927,14 @@ function shiftAnimatable(v, by) {
4466
4927
  return out;
4467
4928
  }
4468
4929
  function extendedPathForBrowser(pathD, opts) {
4469
- var _a;
4930
+ var _a2;
4470
4931
  if (opts.pathOverflow === "clip") return { d: pathD, startShift: 0 };
4471
4932
  const sampler = createPathSampler(pathD);
4472
4933
  if (!sampler || sampler.closed || sampler.totalLength <= 0) return { d: pathD, startShift: 0 };
4473
4934
  const L = sampler.totalLength;
4474
4935
  const margin = EXTEND_MARGIN_FRAC * L;
4475
4936
  const so = numRange(opts.startOffset);
4476
- const runWidth = numRange(opts.textLength).max || ((_a = opts.advance) != null ? _a : 0);
4937
+ const runWidth = numRange(opts.textLength).max || ((_a2 = opts.advance) != null ? _a2 : 0);
4477
4938
  const startOverflow = Math.max(0, -so.min);
4478
4939
  const endOverflow = Math.max(0, so.max + runWidth - L);
4479
4940
  const startExt = startOverflow > 0 ? startOverflow + margin : 0;
@@ -4494,10 +4955,10 @@ function extendedPathForBrowser(pathD, opts) {
4494
4955
  return { d, startShift: startExt };
4495
4956
  }
4496
4957
  function applyTextPathEffect(node, fx, ctx) {
4497
- var _a;
4498
- if (!fx || typeof fx.path !== "string" || !fx.path) return node;
4958
+ var _a2;
4959
+ if (!fx || typeof fx.pathData !== "string" || !fx.pathData) return node;
4499
4960
  const pathId = genId(ctx, "tpath");
4500
- const { d, startShift } = extendedPathForBrowser(fx.path, {
4961
+ const { d, startShift } = extendedPathForBrowser(fx.pathData, {
4501
4962
  pathOverflow: fx.pathOverflow,
4502
4963
  startOffset: fx.startOffset,
4503
4964
  textLength: fx.textLength,
@@ -4507,7 +4968,7 @@ function applyTextPathEffect(node, fx, ctx) {
4507
4968
  const textPath = {
4508
4969
  type: "textPath",
4509
4970
  href: "#" + pathId,
4510
- children: (_a = node.children) != null ? _a : []
4971
+ children: (_a2 = node.children) != null ? _a2 : []
4511
4972
  };
4512
4973
  if (fx.lengthAdjust !== void 0) textPath.lengthAdjust = fx.lengthAdjust;
4513
4974
  if (fx.method !== void 0) textPath.method = fx.method;
@@ -4593,7 +5054,6 @@ var TEXT_ATTR_KEYS = [
4593
5054
  "stroke",
4594
5055
  "strokeWidth",
4595
5056
  "effects",
4596
- TEXT_ATTR,
4597
5057
  TEXT_CONTENT_ATTR,
4598
5058
  "xml:space"
4599
5059
  ];
@@ -4631,15 +5091,15 @@ function paintAnimateOf(node) {
4631
5091
  return out;
4632
5092
  }
4633
5093
  function resolveStyle2(node, parent) {
4634
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
5094
+ var _a2, _b, _c, _d, _e, _f, _g, _h, _i, _j;
4635
5095
  const isTextRoot = node.type === "text";
4636
5096
  const nodeStyle = node.style;
4637
5097
  const own = (key) => {
4638
- var _a2;
4639
- return isTextRoot ? void 0 : (_a2 = node[key]) != null ? _a2 : nodeStyle == null ? void 0 : nodeStyle[key];
5098
+ var _a3;
5099
+ return isTextRoot ? void 0 : (_a3 = node[key]) != null ? _a3 : nodeStyle == null ? void 0 : nodeStyle[key];
4640
5100
  };
4641
5101
  const res = {
4642
- fontFamily: (_a = str(node.fontFamily)) != null ? _a : parent.fontFamily,
5102
+ fontFamily: (_a2 = str(node.fontFamily)) != null ? _a2 : parent.fontFamily,
4643
5103
  fontSize: (_b = parseLen(node.fontSize)) != null ? _b : parent.fontSize,
4644
5104
  fill: (_c = node.fill) != null ? _c : parent.fill,
4645
5105
  stroke: (_d = node.stroke) != null ? _d : parent.stroke,
@@ -4656,10 +5116,10 @@ function resolveStyle2(node, parent) {
4656
5116
  return res;
4657
5117
  }
4658
5118
  function rootStyleOf(node) {
4659
- var _a, _b, _c;
5119
+ var _a2, _b, _c;
4660
5120
  return {
4661
5121
  fontFamily: str(node.fontFamily),
4662
- fontSize: (_a = parseLen(node.fontSize)) != null ? _a : DEFAULT_FONT_SIZE,
5122
+ fontSize: (_a2 = parseLen(node.fontSize)) != null ? _a2 : DEFAULT_FONT_SIZE,
4663
5123
  fill: node.fill,
4664
5124
  stroke: node.stroke,
4665
5125
  strokeWidth: node.strokeWidth,
@@ -4680,9 +5140,9 @@ function paintOf(s) {
4680
5140
  return p;
4681
5141
  }
4682
5142
  function glyphFontFor(s, glyphs, soleFont, warnings) {
4683
- var _a;
5143
+ var _a2;
4684
5144
  const gf = s.fontFamily ? glyphs[s.fontFamily] : soleFont;
4685
- if (!gf) warnings == null ? void 0 : warnings.push('textGlyphs: no glyphs for font "' + ((_a = s.fontFamily) != null ? _a : "") + '"');
5145
+ if (!gf) warnings == null ? void 0 : warnings.push('textGlyphs: no glyphs for font "' + ((_a2 = s.fontFamily) != null ? _a2 : "") + '"');
4686
5146
  return gf;
4687
5147
  }
4688
5148
  function soleFontOf(glyphs) {
@@ -4703,26 +5163,26 @@ function missingGlyphBoxEm(advanceEm, ascentEm) {
4703
5163
  const ix0 = x0 + t, ix1 = x1 - t, iyb = -t, iyt = y1 + t;
4704
5164
  return outer + "M" + ix0 + " " + iyb + "L" + ix0 + " " + iyt + "L" + ix1 + " " + iyt + "L" + ix1 + " " + iyb + "Z";
4705
5165
  }
4706
- function materialiseGlyphTextHorizontal(node, opts) {
4707
- var _a, _b, _c, _d;
5166
+ function materializeGlyphTextHorizontal(node, opts) {
5167
+ var _a2, _b, _c;
4708
5168
  const { glyphs, create = jsonElementFactory, warnings } = opts;
4709
5169
  const soleFont = soleFontOf(glyphs);
4710
- const pen = { x: (_a = parseLen(node.x)) != null ? _a : 0, y: (_b = parseLen(node.y)) != null ? _b : 0 };
5170
+ const pen = { x: (_a2 = parseLen(node.x)) != null ? _a2 : 0, y: (_b = parseLen(node.y)) != null ? _b : 0 };
4711
5171
  const placements = [];
4712
5172
  const lines = [{ start: pen.x, end: pen.x }];
4713
5173
  let line = 0;
4714
5174
  const renderChars = (content, s) => {
4715
- var _a2;
5175
+ var _a3;
4716
5176
  const gf = glyphFontFor(s, glyphs, soleFont, warnings);
4717
5177
  const upm = (gf == null ? void 0 : gf.unitsPerEm) || 1e3;
4718
5178
  const scale = s.fontSize / upm;
4719
- const ascentEm = (_a2 = gf == null ? void 0 : gf.ascent) != null ? _a2 : 0.9 * upm;
5179
+ const ascentEm = (_a3 = gf == null ? void 0 : gf.ascent) != null ? _a3 : 0.9 * upm;
4720
5180
  const paint = paintOf(s);
4721
5181
  for (let i = 0; i < content.length; i++) {
4722
5182
  const ch = content.charAt(i);
4723
5183
  const g = gf == null ? void 0 : gf.glyphs[ch];
4724
- if (g && g.d) {
4725
- placements.push({ glyphD: g.d, m: [scale, 0, 0, scale, pen.x, pen.y], paint, line, x: pen.x, y: pen.y, scale });
5184
+ if (g && g.pathData) {
5185
+ placements.push({ glyphD: g.pathData, m: [scale, 0, 0, scale, pen.x, pen.y], paint, line, x: pen.x, y: pen.y, scale });
4726
5186
  pen.x += g.width * scale;
4727
5187
  } else if (/\S/.test(ch)) {
4728
5188
  const advEm = g && g.width > 0 ? g.width : MISSING_GLYPH_ADVANCE_EM * upm;
@@ -4736,7 +5196,7 @@ function materialiseGlyphTextHorizontal(node, opts) {
4736
5196
  }
4737
5197
  };
4738
5198
  const walk = (el, parentStyle) => {
4739
- var _a2, _b2, _c2, _d2;
5199
+ var _a3, _b2, _c2;
4740
5200
  const s = resolveStyle2(el, parentStyle);
4741
5201
  const x = parseLen(el.x);
4742
5202
  const y = parseLen(el.y);
@@ -4746,16 +5206,16 @@ function materialiseGlyphTextHorizontal(node, opts) {
4746
5206
  lines.push({ start: pen.x, end: pen.x });
4747
5207
  }
4748
5208
  if (y !== void 0) pen.y = y;
4749
- pen.x += (_a2 = parseLen(el.dx)) != null ? _a2 : 0;
5209
+ pen.x += (_a3 = parseLen(el.dx)) != null ? _a3 : 0;
4750
5210
  pen.y += (_b2 = parseLen(el.dy)) != null ? _b2 : 0;
4751
- const content = (_c2 = str(el[TEXT_CONTENT_ATTR])) != null ? _c2 : str(el[TEXT_ATTR]);
4752
- if (content && !((_d2 = el.children) == null ? void 0 : _d2.length)) renderChars(content, s);
5211
+ const content = str(el[TEXT_CONTENT_ATTR]);
5212
+ if (content && !((_c2 = el.children) == null ? void 0 : _c2.length)) renderChars(content, s);
4753
5213
  if (el.children) for (const ch of el.children) walk(ch, s);
4754
5214
  };
4755
5215
  const rootStyle = rootStyleOf(node);
4756
5216
  if (node.children) for (const ch of node.children) walk(ch, rootStyle);
4757
- const rootContent = (_c = str(node[TEXT_CONTENT_ATTR])) != null ? _c : str(node[TEXT_ATTR]);
4758
- if (rootContent && !((_d = node.children) == null ? void 0 : _d.length)) renderChars(rootContent, rootStyle);
5217
+ const rootContent = str(node[TEXT_CONTENT_ATTR]);
5218
+ if (rootContent && !((_c = node.children) == null ? void 0 : _c.length)) renderChars(rootContent, rootStyle);
4759
5219
  const anchor = str(node.textAnchor);
4760
5220
  if (anchor === "middle" || anchor === "end") {
4761
5221
  for (const p of placements) {
@@ -4767,8 +5227,8 @@ function materialiseGlyphTextHorizontal(node, opts) {
4767
5227
  return toGroup(node, buildPaths(placements, create, warnings), create);
4768
5228
  }
4769
5229
  function layoutGlyphTextChars(node, opts) {
4770
- var _a, _b, _c, _d, _e, _f;
4771
- if ((_a = opts.alongPath) == null ? void 0 : _a.pathD) return layoutGlyphTextCharsAlongPath(node, opts.alongPath.pathD, opts);
5230
+ var _a2, _b, _c, _d, _e;
5231
+ if ((_a2 = opts.alongPath) == null ? void 0 : _a2.pathD) return layoutGlyphTextCharsAlongPath(node, opts.alongPath.pathD, opts);
4772
5232
  const { glyphs, warnings } = opts;
4773
5233
  const soleFont = soleFontOf(glyphs);
4774
5234
  const pen = { x: (_b = parseLen(node.x)) != null ? _b : 0, y: (_c = parseLen(node.y)) != null ? _c : 0 };
@@ -4776,11 +5236,11 @@ function layoutGlyphTextChars(node, opts) {
4776
5236
  const lines = [{ start: pen.x, end: pen.x }];
4777
5237
  let line = 0;
4778
5238
  const renderChars = (content, s) => {
4779
- var _a2;
5239
+ var _a3;
4780
5240
  const gf = glyphFontFor(s, glyphs, soleFont, warnings);
4781
5241
  const upm = (gf == null ? void 0 : gf.unitsPerEm) || 1e3;
4782
5242
  const scale = s.fontSize / upm;
4783
- const ascent = ((_a2 = gf == null ? void 0 : gf.ascent) != null ? _a2 : 0.9 * upm) * scale;
5243
+ const ascent = ((_a3 = gf == null ? void 0 : gf.ascent) != null ? _a3 : 0.9 * upm) * scale;
4784
5244
  for (let i = 0; i < content.length; i++) {
4785
5245
  const ch = content.charAt(i);
4786
5246
  const g = gf == null ? void 0 : gf.glyphs[ch];
@@ -4791,7 +5251,7 @@ function layoutGlyphTextChars(node, opts) {
4791
5251
  }
4792
5252
  };
4793
5253
  const walk = (el, parentStyle) => {
4794
- var _a2, _b2, _c2, _d2;
5254
+ var _a3, _b2, _c2;
4795
5255
  const s = resolveStyle2(el, parentStyle);
4796
5256
  const x = parseLen(el.x);
4797
5257
  const y = parseLen(el.y);
@@ -4801,10 +5261,10 @@ function layoutGlyphTextChars(node, opts) {
4801
5261
  lines.push({ start: pen.x, end: pen.x });
4802
5262
  }
4803
5263
  if (y !== void 0) pen.y = y;
4804
- pen.x += (_a2 = parseLen(el.dx)) != null ? _a2 : 0;
5264
+ pen.x += (_a3 = parseLen(el.dx)) != null ? _a3 : 0;
4805
5265
  pen.y += (_b2 = parseLen(el.dy)) != null ? _b2 : 0;
4806
- const content = (_c2 = str(el[TEXT_CONTENT_ATTR])) != null ? _c2 : str(el[TEXT_ATTR]);
4807
- if (content && !((_d2 = el.children) == null ? void 0 : _d2.length)) renderChars(content, s);
5266
+ const content = str(el[TEXT_CONTENT_ATTR]);
5267
+ if (content && !((_c2 = el.children) == null ? void 0 : _c2.length)) renderChars(content, s);
4808
5268
  if (el.children) for (const ch of el.children) walk(ch, s);
4809
5269
  };
4810
5270
  const rootStyle = rootStyleOf(node);
@@ -4818,8 +5278,8 @@ function layoutGlyphTextChars(node, opts) {
4818
5278
  boxes.push({ x: pen.x, y: pen.y, width: 0, ascent: ((_d = gf == null ? void 0 : gf.ascent) != null ? _d : 0.9 * upm) * (s.fontSize / upm), fontSize: s.fontSize, line });
4819
5279
  }
4820
5280
  }
4821
- const rootContent = (_e = str(node[TEXT_CONTENT_ATTR])) != null ? _e : str(node[TEXT_ATTR]);
4822
- if (rootContent && !((_f = node.children) == null ? void 0 : _f.length)) renderChars(rootContent, rootStyle);
5281
+ const rootContent = str(node[TEXT_CONTENT_ATTR]);
5282
+ if (rootContent && !((_e = node.children) == null ? void 0 : _e.length)) renderChars(rootContent, rootStyle);
4823
5283
  const anchor = str(node.textAnchor);
4824
5284
  if (anchor === "middle" || anchor === "end") {
4825
5285
  for (const b of boxes) {
@@ -4827,13 +5287,13 @@ function layoutGlyphTextChars(node, opts) {
4827
5287
  b.x += anchor === "middle" ? -w / 2 : -w;
4828
5288
  }
4829
5289
  }
4830
- return boxes.map((_g) => {
4831
- var _h = _g, { line: _l } = _h, b = __objRest2(_h, ["line"]);
5290
+ return boxes.map((_f) => {
5291
+ var _g = _f, { line: _l } = _g, b = __objRest2(_g, ["line"]);
4832
5292
  return b;
4833
5293
  });
4834
5294
  }
4835
5295
  function layoutGlyphTextCharsAlongPath(node, pathD, opts) {
4836
- var _a, _b;
5296
+ var _a2, _b;
4837
5297
  const { glyphs, warnings, alongPath } = opts;
4838
5298
  const sampler = createPathSampler(pathD);
4839
5299
  if (!sampler) {
@@ -4844,14 +5304,14 @@ function layoutGlyphTextCharsAlongPath(node, pathD, opts) {
4844
5304
  const chars = [];
4845
5305
  let adv = 0;
4846
5306
  const walk = (el, parentStyle) => {
4847
- var _a2, _b2, _c;
5307
+ var _a3, _b2;
4848
5308
  const s = resolveStyle2(el, parentStyle);
4849
- const content = (_a2 = str(el[TEXT_CONTENT_ATTR])) != null ? _a2 : str(el[TEXT_ATTR]);
4850
- if (content && !((_b2 = el.children) == null ? void 0 : _b2.length)) {
5309
+ const content = str(el[TEXT_CONTENT_ATTR]);
5310
+ if (content && !((_a3 = el.children) == null ? void 0 : _a3.length)) {
4851
5311
  const gf = glyphFontFor(s, glyphs, soleFont, warnings);
4852
5312
  const upm = (gf == null ? void 0 : gf.unitsPerEm) || 1e3;
4853
5313
  const scale = s.fontSize / upm;
4854
- const ascent = ((_c = gf == null ? void 0 : gf.ascent) != null ? _c : 0.9 * upm) * scale;
5314
+ const ascent = ((_b2 = gf == null ? void 0 : gf.ascent) != null ? _b2 : 0.9 * upm) * scale;
4855
5315
  for (let i = 0; i < content.length; i++) {
4856
5316
  const ch = content.charAt(i);
4857
5317
  const g = gf == null ? void 0 : gf.glyphs[ch];
@@ -4866,7 +5326,7 @@ function layoutGlyphTextCharsAlongPath(node, pathD, opts) {
4866
5326
  walk(node, rootStyleOf(node));
4867
5327
  const width = adv;
4868
5328
  const tlr = readAnimatable(alongPath == null ? void 0 : alongPath.textLength);
4869
- const tlv = tlr.kind === "animated" ? Number((_a = tlr.keyframes[0]) == null ? void 0 : _a.value) || 0 : tlr.kind === "static" ? Number(tlr.value) || 0 : 0;
5329
+ const tlv = tlr.kind === "animated" ? Number((_a2 = tlr.keyframes[0]) == null ? void 0 : _a2.value) || 0 : tlr.kind === "static" ? Number(tlr.value) || 0 : 0;
4870
5330
  const k = tlv > 0 && width > 0 ? tlv / width : 1;
4871
5331
  const so = readAnimatable(alongPath == null ? void 0 : alongPath.startOffset);
4872
5332
  const { along: alongOffset, perp } = alongPathNodeOffsets(node);
@@ -4898,21 +5358,21 @@ function collectAlongPathCells(node, glyphs, soleFont, warnings) {
4898
5358
  const cells = [];
4899
5359
  let adv = 0;
4900
5360
  const walk = (el, parentStyle) => {
4901
- var _a, _b, _c;
5361
+ var _a2, _b;
4902
5362
  const s = resolveStyle2(el, parentStyle);
4903
- const content = (_a = str(el[TEXT_CONTENT_ATTR])) != null ? _a : str(el[TEXT_ATTR]);
4904
- if (content && !((_b = el.children) == null ? void 0 : _b.length)) {
5363
+ const content = str(el[TEXT_CONTENT_ATTR]);
5364
+ if (content && !((_a2 = el.children) == null ? void 0 : _a2.length)) {
4905
5365
  const gf = glyphFontFor(s, glyphs, soleFont, warnings);
4906
5366
  if (gf) {
4907
5367
  const scale = s.fontSize / gf.unitsPerEm;
4908
- const ascentEm = (_c = gf.ascent) != null ? _c : 0.9 * gf.unitsPerEm;
5368
+ const ascentEm = (_b = gf.ascent) != null ? _b : 0.9 * gf.unitsPerEm;
4909
5369
  const paint = paintOf(s);
4910
5370
  for (let i = 0; i < content.length; i++) {
4911
5371
  const ch = content.charAt(i);
4912
5372
  const g = gf.glyphs[ch];
4913
- if (g && g.d) {
5373
+ if (g && g.pathData) {
4914
5374
  const glyphAdv = g.width * scale;
4915
- cells.push({ glyphD: g.d, widthEm: g.width, scale, paint, midBase: adv + glyphAdv / 2 });
5375
+ cells.push({ glyphD: g.pathData, widthEm: g.width, scale, paint, midBase: adv + glyphAdv / 2 });
4916
5376
  adv += glyphAdv;
4917
5377
  } else if (/\S/.test(ch)) {
4918
5378
  const wEm = g && g.width > 0 ? g.width : MISSING_GLYPH_ADVANCE_EM * gf.unitsPerEm;
@@ -4937,13 +5397,13 @@ function alongAffine(sampler, dist, scale, widthEm, perp = 0) {
4937
5397
  return [scale * cos, scale * sin, -scale * sin, scale * cos, x - scale * cos * hw - perp * sin, y - scale * sin * hw + perp * cos];
4938
5398
  }
4939
5399
  function alongPathNodeOffsets(node) {
4940
- var _a, _b, _c;
5400
+ var _a2, _b, _c;
4941
5401
  return {
4942
- along: ((_a = parseLen(node.x)) != null ? _a : 0) + ((_b = parseLen(node.dx)) != null ? _b : 0),
5402
+ along: ((_a2 = parseLen(node.x)) != null ? _a2 : 0) + ((_b = parseLen(node.dx)) != null ? _b : 0),
4943
5403
  perp: (_c = parseLen(node.dy)) != null ? _c : 0
4944
5404
  };
4945
5405
  }
4946
- function materialiseGlyphTextAlongPath(node, pathD, startOffset, opts, textLength, pathOverflow) {
5406
+ function materializeGlyphTextAlongPath(node, pathD, startOffset, opts, textLength, pathOverflow) {
4947
5407
  const { glyphs, create = jsonElementFactory, warnings } = opts;
4948
5408
  const sampler = pathD ? createPathSampler(pathD) : null;
4949
5409
  if (!sampler) {
@@ -4979,7 +5439,7 @@ function materialiseGlyphTextAlongPath(node, pathD, startOffset, opts, textLengt
4979
5439
  return toGroup(node, buildPaths(placements, create, warnings), create);
4980
5440
  }
4981
5441
  function numTrackOf(raw) {
4982
- var _a;
5442
+ var _a2;
4983
5443
  const r = readAnimatable(raw);
4984
5444
  if (r.kind === "animated" && r.keyframes.length >= 2) {
4985
5445
  const kfs = [...r.keyframes].sort((k1, k2) => (Number(k1.time) || 0) - (Number(k2.time) || 0));
@@ -5002,7 +5462,7 @@ function numTrackOf(raw) {
5002
5462
  }
5003
5463
  };
5004
5464
  }
5005
- const v = r.kind === "animated" ? Number((_a = r.keyframes[0]) == null ? void 0 : _a.value) || 0 : r.kind === "static" ? Number(r.value) || 0 : 0;
5465
+ const v = r.kind === "animated" ? Number((_a2 = r.keyframes[0]) == null ? void 0 : _a2.value) || 0 : r.kind === "static" ? Number(r.value) || 0 : 0;
5006
5466
  return { animated: false, times: [], at: () => v };
5007
5467
  }
5008
5468
  function mergeTrackTimes(a, b) {
@@ -5022,8 +5482,8 @@ function buildAnimatedAlongPath(cells, sampler, distOf, times, loop, create, isC
5022
5482
  const onPath = (dist) => dist >= 0 && dist <= sampler.totalLength;
5023
5483
  const out = [];
5024
5484
  for (const c of cells) {
5025
- const centred = [c.scale, 0, 0, c.scale, -c.scale * (c.widthEm / 2), 0];
5026
- const d = transformPathData(c.glyphD, centred);
5485
+ const centered = [c.scale, 0, 0, c.scale, -c.scale * (c.widthEm / 2), 0];
5486
+ const d = transformPathData(c.glyphD, centered);
5027
5487
  const sampleKf = (dist, time) => {
5028
5488
  const { x, y, angle } = sampler.sampleAtDistance(dist);
5029
5489
  const cos = Math.cos(angle), sin = Math.sin(angle);
@@ -5084,7 +5544,7 @@ function paintProps(paint) {
5084
5544
  return p;
5085
5545
  }
5086
5546
  function missingGlyphProps(isMissing) {
5087
- return isMissing ? { class: MISSING_GLYPH_CLASS_NAME } : {};
5547
+ return isMissing ? { [CLASS_ATTR]: MISSING_GLYPH_CLASS_NAME } : {};
5088
5548
  }
5089
5549
  function buildPaths(placements, create, warnings) {
5090
5550
  if (!placements.length) {
@@ -5121,24 +5581,24 @@ function toGroup(node, children, create) {
5121
5581
  }
5122
5582
  return create("g", gProps, children);
5123
5583
  }
5124
- function materialiseGlyphText(node, opts) {
5125
- if (opts.alongPath) return materialiseGlyphTextAlongPath(node, opts.alongPath.pathD, opts.alongPath.startOffset, opts, opts.alongPath.textLength, opts.alongPath.pathOverflow);
5126
- return materialiseGlyphTextHorizontal(node, opts);
5584
+ function materializeGlyphText(node, opts) {
5585
+ if (opts.alongPath) return materializeGlyphTextAlongPath(node, opts.alongPath.pathD, opts.alongPath.startOffset, opts, opts.alongPath.textLength, opts.alongPath.pathOverflow);
5586
+ return materializeGlyphTextHorizontal(node, opts);
5127
5587
  }
5128
5588
  function applyTextGlyphsEffect(node, fx, ctx) {
5129
5589
  if (!(fx == null ? void 0 : fx.useGlyphs)) return node;
5130
5590
  if (!ctx.glyphs) {
5131
- ctx.warnings.push("textGlyphs: no definitions.glyphs \u2014 left as native <text>");
5591
+ ctx.warnings.push("textGlyphs: no definitions.fonts \u2014 left as native <text>");
5132
5592
  return node;
5133
5593
  }
5134
- return materialiseGlyphTextHorizontal(node, { glyphs: ctx.glyphs, warnings: ctx.warnings });
5594
+ return materializeGlyphTextHorizontal(node, { glyphs: ctx.glyphs, warnings: ctx.warnings });
5135
5595
  }
5136
5596
  function applyTextGlyphsAlongPath(node, ctx, pathD, startOffset, textLength, pathOverflow) {
5137
5597
  if (!ctx.glyphs) {
5138
- ctx.warnings.push("textGlyphs: no definitions.glyphs");
5598
+ ctx.warnings.push("textGlyphs: no definitions.fonts");
5139
5599
  return null;
5140
5600
  }
5141
- return materialiseGlyphTextAlongPath(node, pathD, startOffset, { glyphs: ctx.glyphs, warnings: ctx.warnings }, textLength, pathOverflow);
5601
+ return materializeGlyphTextAlongPath(node, pathD, startOffset, { glyphs: ctx.glyphs, warnings: ctx.warnings }, textLength, pathOverflow);
5142
5602
  }
5143
5603
  function applyStrokeTrimEffect(node, strokeTrim, ctx) {
5144
5604
  if (!strokeTrim) return node;
@@ -5275,12 +5735,11 @@ function getOffsetIndexRange(minMaxOffset) {
5275
5735
  ];
5276
5736
  }
5277
5737
  function readScalarValues(r) {
5278
- var _a;
5279
5738
  if (r.kind === "absent") return [];
5280
5739
  if (r.kind === "static") return [r.value];
5281
5740
  const out = [];
5282
5741
  for (const kf of r.keyframes) {
5283
- const v = (_a = kf.value) != null ? _a : kf.v;
5742
+ const v = kfValue(kf);
5284
5743
  if (typeof v === "number") out.push(v);
5285
5744
  }
5286
5745
  return out;
@@ -5290,14 +5749,11 @@ function computeAnimAttr(read, map) {
5290
5749
  if (read.kind === "static") return { kind: "static", value: map(read.value) };
5291
5750
  return {
5292
5751
  kind: "animated",
5293
- keyframes: read.keyframes.map((kf) => {
5294
- var _a, _b, _c, _d;
5295
- return {
5296
- time: (_b = (_a = kf.time) != null ? _a : kf.t) != null ? _b : 0,
5297
- value: map((_c = kf.value) != null ? _c : kf.v),
5298
- easing: (_d = kf.easing) != null ? _d : kf.e
5299
- };
5300
- }),
5752
+ keyframes: read.keyframes.map((kf) => ({
5753
+ time: kfTime(kf),
5754
+ value: map(kfValue(kf)),
5755
+ easing: kfEasing(kf)
5756
+ })),
5301
5757
  loop: read.loop
5302
5758
  };
5303
5759
  }
@@ -5307,7 +5763,6 @@ function applyAttr(node, attrName, attr) {
5307
5763
  }
5308
5764
  var OPACITY_STEP_MS = 10;
5309
5765
  function computeOpacityFromRange(rangeRead) {
5310
- var _a, _b, _c, _d, _e, _f;
5311
5766
  const hide = (v) => v[0] === v[1];
5312
5767
  if (rangeRead.kind === "absent") return void 0;
5313
5768
  if (rangeRead.kind === "static") return hide(rangeRead.value) ? { kind: "static", value: 0 } : void 0;
@@ -5315,7 +5770,7 @@ function computeOpacityFromRange(rangeRead) {
5315
5770
  let anyHide = false;
5316
5771
  let allHide = true;
5317
5772
  for (const kf of kfs) {
5318
- if (hide((_a = kf.value) != null ? _a : kf.v)) anyHide = true;
5773
+ if (hide(kfValue(kf))) anyHide = true;
5319
5774
  else allHide = false;
5320
5775
  }
5321
5776
  if (!anyHide) return void 0;
@@ -5325,10 +5780,10 @@ function computeOpacityFromRange(rangeRead) {
5325
5780
  const kf = kfs[i];
5326
5781
  const prevKf = i > 0 ? kfs[i - 1] : void 0;
5327
5782
  const nextKf = i < kfs.length - 1 ? kfs[i + 1] : void 0;
5328
- const t = (_c = (_b = kf.time) != null ? _b : kf.t) != null ? _c : 0;
5329
- const thisHide = hide((_d = kf.value) != null ? _d : kf.v);
5330
- const prevHide = prevKf ? thisHide && hide((_e = prevKf.value) != null ? _e : prevKf.v) : thisHide;
5331
- const nextHide = nextKf ? thisHide && hide((_f = nextKf.value) != null ? _f : nextKf.v) : thisHide;
5783
+ const t = kfTime(kf);
5784
+ const thisHide = hide(kfValue(kf));
5785
+ const prevHide = prevKf ? thisHide && hide(kfValue(prevKf)) : thisHide;
5786
+ const nextHide = nextKf ? thisHide && hide(kfValue(nextKf)) : thisHide;
5332
5787
  if (prevHide && !nextHide) {
5333
5788
  out.push({ time: t, value: 0 });
5334
5789
  out.push({ time: t + OPACITY_STEP_MS, value: 1 });
@@ -5343,14 +5798,11 @@ function computeOpacityFromRange(rangeRead) {
5343
5798
  function readRangeWithCrossings(raw) {
5344
5799
  const r = readAnimatable(raw);
5345
5800
  if (r.kind !== "animated") return r;
5346
- const kfs = r.keyframes.map((kf) => {
5347
- var _a, _b, _c, _d;
5348
- return {
5349
- time: (_b = (_a = kf.time) != null ? _a : kf.t) != null ? _b : 0,
5350
- value: (_c = kf.value) != null ? _c : kf.v,
5351
- easing: (_d = kf.easing) != null ? _d : kf.e
5352
- };
5353
- });
5801
+ const kfs = r.keyframes.map((kf) => ({
5802
+ time: kfTime(kf),
5803
+ value: kfValue(kf),
5804
+ easing: kfEasing(kf)
5805
+ }));
5354
5806
  const hasReverse = kfs.some((kf) => kf.value[0] > kf.value[1]);
5355
5807
  if (!hasReverse) {
5356
5808
  return {
@@ -5447,20 +5899,20 @@ function pxBezierPathLength(path) {
5447
5899
  return total;
5448
5900
  }
5449
5901
  function segmentLength(path, from, to) {
5450
- var _a, _b, _c, _d;
5902
+ var _a2, _b, _c, _d;
5451
5903
  const v = path.v;
5452
5904
  const p0 = v[from];
5453
5905
  const p3 = v[to];
5454
- const p1 = (_b = (_a = path.o) == null ? void 0 : _a[from]) != null ? _b : p0;
5906
+ const p1 = (_b = (_a2 = path.o) == null ? void 0 : _a2[from]) != null ? _b : p0;
5455
5907
  const p2 = (_d = (_c = path.i) == null ? void 0 : _c[to]) != null ? _d : p3;
5456
5908
  const lut = bezier2D_arcLengthLUT(p0, p1, p2, p3);
5457
5909
  return lut.ds[lut.ds.length - 1];
5458
5910
  }
5459
5911
  var ARC_KAPPA = 0.5522847498307936;
5460
5912
  function shapeToPathD(node) {
5461
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
5913
+ var _a2, _b, _c, _d, _e, _f, _g, _h, _i, _j;
5462
5914
  if (node.type === "rect") {
5463
- const x = Number((_a = node.x) != null ? _a : 0), y = Number((_b = node.y) != null ? _b : 0);
5915
+ const x = Number((_a2 = node.x) != null ? _a2 : 0), y = Number((_b = node.y) != null ? _b : 0);
5464
5916
  const w = Number((_c = node.width) != null ? _c : 0), h = Number((_d = node.height) != null ? _d : 0);
5465
5917
  return "M" + (x + w) + "," + y + "L" + (x + w) + "," + (y + h) + "L" + x + "," + (y + h) + "L" + x + "," + y + "L" + (x + w) + "," + y + "z";
5466
5918
  }
@@ -5476,7 +5928,7 @@ function shapeToPathD(node) {
5476
5928
  return void 0;
5477
5929
  }
5478
5930
  function applyPlayerEffects(root) {
5479
- var _a, _b;
5931
+ var _a2, _b;
5480
5932
  const ctx = {
5481
5933
  defs: [],
5482
5934
  warnings: [],
@@ -5487,8 +5939,8 @@ function applyPlayerEffects(root) {
5487
5939
  maskAncestorChains: /* @__PURE__ */ new Map(),
5488
5940
  // Resolved engine: `frames` ONLY when explicitly set; auto/waapi/unset →
5489
5941
  // waapi (we're not 100% sure it's frames, and CSS/WAAPI need the inline form).
5490
- engine: ((_a = getAnimatorConfig(root)) == null ? void 0 : _a.mode) === PxAnimatorMode.frames ? PxAnimatorEngine.frames : PxAnimatorEngine.waapi,
5491
- glyphs: (_b = getDefs(root)) == null ? void 0 : _b.glyphs
5942
+ engine: resolveTimelineEngine((_a2 = getAnimatorConfig(root)) == null ? void 0 : _a2.engine),
5943
+ glyphs: (_b = getDefs(root)) == null ? void 0 : _b.fonts
5492
5944
  };
5493
5945
  const working = clone(root);
5494
5946
  indexById(working, ctx.idMap);
@@ -5511,7 +5963,7 @@ function applyPlayerEffects_exceptRetime(node, ctx) {
5511
5963
  let consumedByGlyphs = false;
5512
5964
  if (text == null ? void 0 : text.useGlyphs) {
5513
5965
  if (textPath) {
5514
- const pathD = typeof textPath.path === "string" ? textPath.path : void 0;
5966
+ const pathD = typeof textPath.pathData === "string" ? textPath.pathData : void 0;
5515
5967
  const glyphed = applyTextGlyphsAlongPath(n, ctx, pathD, textPath.startOffset, textPath.textLength, textPath.pathOverflow);
5516
5968
  if (glyphed) {
5517
5969
  n = glyphed;
@@ -5543,26 +5995,6 @@ function applyPlayerEffects_retime(node, ctx) {
5543
5995
  applyAllRetimeEffects(node, ctx);
5544
5996
  return node;
5545
5997
  }
5546
- var kfTime = (kf) => {
5547
- var _a, _b;
5548
- return (_b = (_a = kf.t) != null ? _a : kf.time) != null ? _b : 0;
5549
- };
5550
- var kfValue = (kf) => {
5551
- var _a;
5552
- return (_a = kf.v) != null ? _a : kf.value;
5553
- };
5554
- var kfEasing = (kf) => {
5555
- var _a;
5556
- return (_a = kf.e) != null ? _a : kf.easing;
5557
- };
5558
- var kfTangentIn = (kf) => {
5559
- var _a;
5560
- return (_a = kf.tangentIn) != null ? _a : kf.ti;
5561
- };
5562
- var kfTangentOut = (kf) => {
5563
- var _a;
5564
- return (_a = kf.tangentOut) != null ? _a : kf.to;
5565
- };
5566
5998
  function cubicAt(p0, c1, c2, p1, t) {
5567
5999
  const u = 1 - t;
5568
6000
  const a = u * u * u, b = 3 * u * u * t, c = 3 * u * t * t, d = t * t * t;
@@ -5586,7 +6018,7 @@ var fmt2 = (n) => {
5586
6018
  return Object.is(r, -0) ? "0" : String(r);
5587
6019
  };
5588
6020
  function buildOffsetPath(propAnim) {
5589
- var _a, _b, _c;
6021
+ var _a2, _b, _c;
5590
6022
  if (propAnim.alongPathMode !== "offsetPath") return void 0;
5591
6023
  const kfs = propAnim.keyframes;
5592
6024
  if (!kfs || kfs.length < 2) return void 0;
@@ -5599,7 +6031,7 @@ function buildOffsetPath(propAnim) {
5599
6031
  if (!tr || tr.length < 2) return void 0;
5600
6032
  const parts = Object.keys(v);
5601
6033
  if (parts.some((p) => p !== "translate" && p !== "origin")) return void 0;
5602
- const o = (_a = v == null ? void 0 : v.origin) != null ? _a : [0, 0];
6034
+ const o = (_a2 = v == null ? void 0 : v.origin) != null ? _a2 : [0, 0];
5603
6035
  if (o[0] !== anchor[0] || o[1] !== anchor[1]) return void 0;
5604
6036
  points.push([tr[0] + anchor[0], tr[1] + anchor[1]]);
5605
6037
  }
@@ -5628,9 +6060,9 @@ function buildOffsetPath(propAnim) {
5628
6060
  }
5629
6061
  return { pathStr: d, distanceKfs, autoOrient: !!propAnim.autoOrient, anchor };
5630
6062
  }
5631
- function materialiseOffsetPathsInTree(root) {
6063
+ function materializeOffsetPathsInTree(root) {
5632
6064
  const walk = (node) => {
5633
- var _a;
6065
+ var _a2;
5634
6066
  let out = node;
5635
6067
  const anim = node.animate;
5636
6068
  const transform = anim == null ? void 0 : anim["transform"];
@@ -5638,16 +6070,16 @@ function materialiseOffsetPathsInTree(root) {
5638
6070
  const built = buildOffsetPath(transform);
5639
6071
  if (built) {
5640
6072
  const newAnimate = __spreadValues2({}, anim);
5641
- delete newAnimate["transform"];
6073
+ delete newAnimate[TRANSFORM_ATTR];
5642
6074
  const distance = { keyframes: built.distanceKfs };
5643
6075
  if (transform.loop !== void 0) distance.loop = transform.loop;
5644
- newAnimate["offsetDistance"] = distance;
6076
+ newAnimate[OFFSET_DISTANCE_ATTR] = distance;
5645
6077
  const staticTr = node.transform;
5646
6078
  let newTransform = staticTr;
5647
6079
  if (staticTr && typeof staticTr === "object") {
5648
6080
  const t = __spreadValues2({}, staticTr);
5649
- delete t["translate"];
5650
- delete t["origin"];
6081
+ delete t[TRANSFORM_PART.translate];
6082
+ delete t[TRANSFORM_PART.origin];
5651
6083
  newTransform = Object.keys(t).length ? t : void 0;
5652
6084
  }
5653
6085
  out = __spreadProps2(__spreadValues2({}, node), {
@@ -5663,7 +6095,7 @@ function materialiseOffsetPathsInTree(root) {
5663
6095
  else delete out.transform;
5664
6096
  }
5665
6097
  }
5666
- if ((_a = out.children) == null ? void 0 : _a.length) {
6098
+ if ((_a2 = out.children) == null ? void 0 : _a2.length) {
5667
6099
  const children = out.children.map(walk);
5668
6100
  if (children.some((c, i) => c !== out.children[i])) out = __spreadProps2(__spreadValues2({}, out), { children });
5669
6101
  }
@@ -5671,15 +6103,15 @@ function materialiseOffsetPathsInTree(root) {
5671
6103
  };
5672
6104
  return walk(root);
5673
6105
  }
5674
- function materialiseAllInTree(doc, engine, opts) {
5675
- var _a, _b;
6106
+ function materializeAllInTree(doc, engine, opts) {
6107
+ var _a2, _b;
5676
6108
  let root = applyPlayerEffects(doc).root;
5677
- root = materialiseOffsetPathsInTree(root);
5678
- const duration = (_b = (_a = getAnimatorConfig(root)) == null ? void 0 : _a.duration) != null ? _b : DEFAULT_DURATION_MS;
5679
- root = materialiseInternalLoopsInTree(root, duration);
5680
- if (engine === PxAnimatorEngine.waapi) {
5681
- root = materialiseMotionPathsInTree(root, opts == null ? void 0 : opts.motionPath);
5682
- root = materialiseAnimatedUseInstances(root);
6109
+ root = materializeOffsetPathsInTree(root);
6110
+ const duration = (_b = (_a2 = getAnimatorConfig(root)) == null ? void 0 : _a2.duration) != null ? _b : DEFAULT_DURATION_MS;
6111
+ root = materializeInternalLoopsInTree(root, duration);
6112
+ if (engine === PxTimelineEngine.native) {
6113
+ root = materializeMotionPathsInTree(root, opts == null ? void 0 : opts.motionPath);
6114
+ root = materializeAnimatedUseInstances(root);
5683
6115
  root = pruneUnreferencedDefs(root);
5684
6116
  }
5685
6117
  return root;
@@ -5687,9 +6119,9 @@ function materialiseAllInTree(doc, engine, opts) {
5687
6119
  function pruneUnreferencedDefs(root) {
5688
6120
  const stripHash3 = (h) => h.startsWith("#") ? h.slice(1) : h;
5689
6121
  const walk = (n, fn) => {
5690
- var _a;
6122
+ var _a2;
5691
6123
  fn(n);
5692
- (_a = n.children) == null ? void 0 : _a.forEach((c) => walk(c, fn));
6124
+ (_a2 = n.children) == null ? void 0 : _a2.forEach((c) => walk(c, fn));
5693
6125
  };
5694
6126
  let changed = true;
5695
6127
  while (changed) {
@@ -5713,6 +6145,38 @@ function pruneUnreferencedDefs(root) {
5713
6145
  }
5714
6146
  return root;
5715
6147
  }
6148
+ var PX_RATE_REJECTED = "setPlaybackRate: rate must be finite and non-zero";
6149
+ function isValidPlaybackRate(rate) {
6150
+ return Number.isFinite(rate) && rate !== 0;
6151
+ }
6152
+ function seekCeilingMs(durationMs, iterations) {
6153
+ if (!(durationMs > 0)) return 0;
6154
+ if (iterations === Infinity) return Infinity;
6155
+ return durationMs * (iterations > 0 ? iterations : 1);
6156
+ }
6157
+ function progressSpanMs(durationMs, iterations) {
6158
+ if (!(durationMs > 0)) return 0;
6159
+ if (iterations === Infinity) return durationMs;
6160
+ return durationMs * (iterations > 0 ? iterations : 1);
6161
+ }
6162
+ function clampSeekMs(timeMs, ceilingMs) {
6163
+ if (Number.isNaN(timeMs) || timeMs < 0) return 0;
6164
+ if (Number.isFinite(ceilingMs)) return timeMs > ceilingMs ? ceilingMs : timeMs;
6165
+ return Number.isFinite(timeMs) ? timeMs : 0;
6166
+ }
6167
+ function timeToProgress(timeMs, durationMs, iterations) {
6168
+ const span = progressSpanMs(durationMs, iterations);
6169
+ if (!(span > 0) || !Number.isFinite(timeMs)) return 0;
6170
+ if (timeMs <= 0) return 0;
6171
+ if (iterations === Infinity) return timeMs % span / span;
6172
+ return timeMs >= span ? 1 : timeMs / span;
6173
+ }
6174
+ function progressToTimeMs(progress, durationMs, iterations) {
6175
+ const span = progressSpanMs(durationMs, iterations);
6176
+ if (!(span > 0) || !Number.isFinite(progress)) return 0;
6177
+ if (progress <= 0) return 0;
6178
+ return progress >= 1 ? span : progress * span;
6179
+ }
5716
6180
  function requestFrame(cb) {
5717
6181
  const g = globalThis;
5718
6182
  if (typeof g.requestAnimationFrame === "function") return g.requestAnimationFrame(cb);
@@ -5727,9 +6191,9 @@ function cancelFrame(handle) {
5727
6191
  g.clearTimeout(handle);
5728
6192
  }
5729
6193
  function createBasicFrameLoopAnimator(doc, adapter, callbacks) {
5730
- var _a;
6194
+ var _a2;
5731
6195
  const config = getAnimatorConfig(doc) || {};
5732
- const bindings = getNormalisedBindings(doc, PxAnimatorEngine.frames);
6196
+ const bindings = getNormalizedBindings(doc, PxTimelineEngine.js);
5733
6197
  const _iterations = config.iterations;
5734
6198
  let iterations = 1;
5735
6199
  if (typeof _iterations === "number") iterations = _iterations || 1;
@@ -5738,7 +6202,7 @@ function createBasicFrameLoopAnimator(doc, adapter, callbacks) {
5738
6202
  const duration = +(config.duration || DEFAULT_DURATION_MS);
5739
6203
  const totalDuration = duration && iterations ? duration * (iterations === Infinity ? Infinity : iterations) : duration ? (iterations != null ? iterations : 1) * duration : 0;
5740
6204
  const direction = config.direction || "normal";
5741
- const fill = (_a = config.fill) != null ? _a : "forwards";
6205
+ const fill = (_a2 = config.fill) != null ? _a2 : "forwards";
5742
6206
  const fillsForwards = fill === "forwards" || fill === "both";
5743
6207
  const fillsBackwards = fill === "backwards" || fill === "both";
5744
6208
  let timerId = null;
@@ -5800,7 +6264,7 @@ function createBasicFrameLoopAnimator(doc, adapter, callbacks) {
5800
6264
  }
5801
6265
  }
5802
6266
  const tick = () => {
5803
- var _a2, _b;
6267
+ var _a3, _b;
5804
6268
  if (!adapter.isConnected()) {
5805
6269
  pauseAnim();
5806
6270
  return;
@@ -5816,7 +6280,7 @@ function createBasicFrameLoopAnimator(doc, adapter, callbacks) {
5816
6280
  renderFrame(0);
5817
6281
  if (!finishCalled) {
5818
6282
  finishCalled = true;
5819
- (_a2 = callbacks == null ? void 0 : callbacks.onFinish) == null ? void 0 : _a2.call(callbacks);
6283
+ (_a3 = callbacks == null ? void 0 : callbacks.onFinish) == null ? void 0 : _a3.call(callbacks);
5820
6284
  }
5821
6285
  return;
5822
6286
  }
@@ -5908,17 +6372,17 @@ function createBasicFrameLoopAnimator(doc, adapter, callbacks) {
5908
6372
  }
5909
6373
  };
5910
6374
  const cancelAnim = () => {
5911
- var _a2;
6375
+ var _a3;
5912
6376
  pauseAnim();
5913
6377
  timeBeforeLastStartMs = 0;
5914
6378
  lastStartedTs = 0;
5915
6379
  playing = false;
5916
6380
  finishCalled = false;
5917
6381
  renderFrame(timeBeforeLastStartMs);
5918
- (_a2 = callbacks == null ? void 0 : callbacks.onCancel) == null ? void 0 : _a2.call(callbacks);
6382
+ (_a3 = callbacks == null ? void 0 : callbacks.onCancel) == null ? void 0 : _a3.call(callbacks);
5919
6383
  };
5920
6384
  const finishAnim = (callOnFinish = true) => {
5921
- var _a2;
6385
+ var _a3;
5922
6386
  if (Number.isFinite(totalDuration)) {
5923
6387
  timeBeforeLastStartMs = totalDuration;
5924
6388
  } else {
@@ -5933,7 +6397,7 @@ function createBasicFrameLoopAnimator(doc, adapter, callbacks) {
5933
6397
  renderFrame(fillsForwards ? timeBeforeLastStartMs : 0);
5934
6398
  if (callOnFinish && !finishCalled) {
5935
6399
  finishCalled = true;
5936
- (_a2 = callbacks == null ? void 0 : callbacks.onFinish) == null ? void 0 : _a2.call(callbacks);
6400
+ (_a3 = callbacks == null ? void 0 : callbacks.onFinish) == null ? void 0 : _a3.call(callbacks);
5937
6401
  }
5938
6402
  };
5939
6403
  const api = {
@@ -5943,14 +6407,14 @@ function createBasicFrameLoopAnimator(doc, adapter, callbacks) {
5943
6407
  return _isPlaying();
5944
6408
  },
5945
6409
  "play": () => {
5946
- var _a2;
6410
+ var _a3;
5947
6411
  startAnim();
5948
- (_a2 = callbacks == null ? void 0 : callbacks.onPlay) == null ? void 0 : _a2.call(callbacks);
6412
+ (_a3 = callbacks == null ? void 0 : callbacks.onPlay) == null ? void 0 : _a3.call(callbacks);
5949
6413
  },
5950
6414
  "pause": () => {
5951
- var _a2;
6415
+ var _a3;
5952
6416
  pauseAnim();
5953
- (_a2 = callbacks == null ? void 0 : callbacks.onPause) == null ? void 0 : _a2.call(callbacks);
6417
+ (_a3 = callbacks == null ? void 0 : callbacks.onPause) == null ? void 0 : _a3.call(callbacks);
5954
6418
  },
5955
6419
  "cancel": () => {
5956
6420
  cancelAnim();
@@ -5959,8 +6423,8 @@ function createBasicFrameLoopAnimator(doc, adapter, callbacks) {
5959
6423
  finishAnim(true);
5960
6424
  },
5961
6425
  "setPlaybackRate": (rate) => {
5962
- if (!isFinite(rate) || rate === 0) {
5963
- console.warn("setPlaybackRate: rate must be finite and non-zero");
6426
+ if (!isValidPlaybackRate(rate)) {
6427
+ console.warn(PX_RATE_REJECTED);
5964
6428
  return;
5965
6429
  }
5966
6430
  let current = getRawAnimTime();
@@ -5974,21 +6438,67 @@ function createBasicFrameLoopAnimator(doc, adapter, callbacks) {
5974
6438
  return getAnimCurrentTime();
5975
6439
  },
5976
6440
  "setCurrentTime": (newTime) => {
5977
- if (newTime < 0) newTime = 0;
5978
- if (Number.isFinite(totalDuration) && newTime > totalDuration) newTime = totalDuration;
6441
+ newTime = clampSeekMs(newTime, totalDuration);
5979
6442
  timeBeforeLastStartMs = newTime;
5980
6443
  if (playing) lastStartedTs = Date.now();
5981
6444
  if (!Number.isFinite(totalDuration) || newTime < totalDuration) finishCalled = false;
5982
6445
  renderFrame(getAnimCurrentTime());
5983
6446
  },
6447
+ "getCurrentProgress": () => timeToProgress(getAnimCurrentTime(), duration, iterations),
6448
+ "setCurrentProgress": (progress) => {
6449
+ api.setCurrentTime(progressToTimeMs(progress, duration, iterations));
6450
+ },
5984
6451
  "destroy": () => {
5985
- var _a2;
6452
+ var _a3;
5986
6453
  api.cancel();
5987
- (_a2 = callbacks == null ? void 0 : callbacks.onRemove) == null ? void 0 : _a2.call(callbacks);
6454
+ (_a3 = callbacks == null ? void 0 : callbacks.onRemove) == null ? void 0 : _a3.call(callbacks);
5988
6455
  }
5989
6456
  };
5990
6457
  return api;
5991
6458
  }
6459
+ var PxDiagnosticKind = {
6460
+ /** The document is wrong — regenerate or repair the file. */
6461
+ document: "document",
6462
+ /** The page or app cannot provide what the document asks for — fix the mount. */
6463
+ host: "host",
6464
+ /** The platform cannot do it and the player degraded — usually nothing to fix. */
6465
+ platform: "platform",
6466
+ /** The call is wrong or self-contradictory — fix the options or props you passed. */
6467
+ usage: "usage",
6468
+ /** The player failed where it did not expect to — report it to us. */
6469
+ internal: "internal"
6470
+ };
6471
+ function asError(error) {
6472
+ return typeof error === "string" ? new Error(error) : error;
6473
+ }
6474
+ function isSilenced(silent, kind) {
6475
+ if (!silent) return false;
6476
+ return silent === true || silent.includes(kind);
6477
+ }
6478
+ function createDiagnostics(config, prefix) {
6479
+ const tag = prefix ? prefix + " " : "";
6480
+ return {
6481
+ warn: (kind, message, detail) => {
6482
+ if (config == null ? void 0 : config.onWarn) {
6483
+ config.onWarn({ kind, message, detail });
6484
+ return;
6485
+ }
6486
+ if (isSilenced(config == null ? void 0 : config.silent, kind)) return;
6487
+ const line = tag + kind + ": " + message;
6488
+ if (detail === void 0) console.warn(line);
6489
+ else console.warn(line, detail);
6490
+ },
6491
+ error: (kind, error) => {
6492
+ const err = asError(error);
6493
+ if (config == null ? void 0 : config.onError) {
6494
+ config.onError({ kind, message: err.message, error: err });
6495
+ return;
6496
+ }
6497
+ if (isSilenced(config == null ? void 0 : config.silent, kind)) return;
6498
+ console.error(tag + kind + ": " + err.message);
6499
+ }
6500
+ };
6501
+ }
5992
6502
  var IDENTITY = [1, 0, 0, 1, 0, 0];
5993
6503
  function mul(m, n) {
5994
6504
  return [
@@ -6038,9 +6548,9 @@ function lerp(a, b, f) {
6038
6548
  return a + (b - a) * f;
6039
6549
  }
6040
6550
  function interpParts(kfs, t) {
6041
- var _a, _b, _c, _d, _e, _f, _g;
6551
+ var _a2, _b, _c, _d, _e, _f, _g;
6042
6552
  if (!kfs.length) return {};
6043
- if (t <= ((_a = kfs[0].time) != null ? _a : 0)) return kfs[0].value || {};
6553
+ if (t <= ((_a2 = kfs[0].time) != null ? _a2 : 0)) return kfs[0].value || {};
6044
6554
  if (t >= ((_b = kfs[kfs.length - 1].time) != null ? _b : 0)) return kfs[kfs.length - 1].value || {};
6045
6555
  let i = 0;
6046
6556
  while (i < kfs.length - 1 && ((_c = kfs[i + 1].time) != null ? _c : 0) < t) i++;
@@ -6071,10 +6581,10 @@ function nodeMatrix(node, t) {
6071
6581
  return IDENTITY;
6072
6582
  }
6073
6583
  function evalScalar(animated, staticVal, fallback, t) {
6074
- var _a, _b, _c, _d, _e, _f;
6584
+ var _a2, _b, _c, _d, _e, _f;
6075
6585
  if (animated && animated.keyframes && animated.keyframes.length) {
6076
6586
  const kfs = animated.keyframes;
6077
- if (t <= ((_a = kfs[0].time) != null ? _a : 0)) return kfs[0].value;
6587
+ if (t <= ((_a2 = kfs[0].time) != null ? _a2 : 0)) return kfs[0].value;
6078
6588
  if (t >= ((_b = kfs[kfs.length - 1].time) != null ? _b : 0)) return kfs[kfs.length - 1].value;
6079
6589
  let i = 0;
6080
6590
  while (i < kfs.length - 1 && ((_c = kfs[i + 1].time) != null ? _c : 0) < t) i++;
@@ -6087,9 +6597,9 @@ function evalScalar(animated, staticVal, fallback, t) {
6087
6597
  var CONTAINER_TYPES = /* @__PURE__ */ new Set(["svg", "g", "symbol"]);
6088
6598
  var SKIP_TYPES = /* @__PURE__ */ new Set(["defs", "mask", "clipPath", "title"]);
6089
6599
  function buildIdMap2(node, map) {
6090
- var _a;
6600
+ var _a2;
6091
6601
  if (typeof node.id === "string") map.set(node.id, node);
6092
- (_a = node.children) == null ? void 0 : _a.forEach((c) => buildIdMap2(c, map));
6602
+ (_a2 = node.children) == null ? void 0 : _a2.forEach((c) => buildIdMap2(c, map));
6093
6603
  }
6094
6604
  function num(v) {
6095
6605
  return v === void 0 || v === null ? 0 : Number(v);
@@ -6098,7 +6608,7 @@ function round(n) {
6098
6608
  return Math.round(n * 100) / 100 + 0;
6099
6609
  }
6100
6610
  function geomKey(node) {
6101
- var _a;
6611
+ var _a2;
6102
6612
  switch (node.type) {
6103
6613
  case "rect":
6104
6614
  return num(node.width) + "," + num(node.height) + "," + num(node.x) + "," + num(node.y);
@@ -6107,14 +6617,14 @@ function geomKey(node) {
6107
6617
  case "circle":
6108
6618
  return num(node.r) + "," + num(node.cx) + "," + num(node.cy);
6109
6619
  case "path":
6110
- return String((_a = node.d) != null ? _a : "");
6620
+ return String((_a2 = node.d) != null ? _a2 : "");
6111
6621
  default:
6112
6622
  return "";
6113
6623
  }
6114
6624
  }
6115
6625
  function describePrimitive(node, m, t) {
6116
- var _a, _b, _c, _d, _e;
6117
- const fill = (_a = node.fill) != null ? _a : "";
6626
+ var _a2, _b, _c, _d, _e;
6627
+ const fill = (_a2 = node.fill) != null ? _a2 : "";
6118
6628
  const stroke = (_b = node.stroke) != null ? _b : "";
6119
6629
  const sw = (_d = (_c = node["stroke-width"]) != null ? _c : node.strokeWidth) != null ? _d : "";
6120
6630
  const opacity = round(evalScalar((_e = node.animate) == null ? void 0 : _e.opacity, node.opacity, 1, t));
@@ -6123,7 +6633,7 @@ function describePrimitive(node, m, t) {
6123
6633
  return node.type + "|" + geomKey(node) + "|[" + mat + "]|f:" + fill + "|s:" + stroke + "|sw:" + (num(sw) || "") + "|o:" + opacity + "|m:" + masked;
6124
6634
  }
6125
6635
  function flatten(node, parent, t, idMap, out) {
6126
- var _a;
6636
+ var _a2;
6127
6637
  const type = node.type || "";
6128
6638
  if (SKIP_TYPES.has(type)) return;
6129
6639
  const m = mul(parent, nodeMatrix(node, t));
@@ -6136,33 +6646,33 @@ function flatten(node, parent, t, idMap, out) {
6136
6646
  return;
6137
6647
  }
6138
6648
  if (CONTAINER_TYPES.has(type)) {
6139
- (_a = node.children) == null ? void 0 : _a.forEach((c) => flatten(c, m, t, idMap, out));
6649
+ (_a2 = node.children) == null ? void 0 : _a2.forEach((c) => flatten(c, m, t, idMap, out));
6140
6650
  return;
6141
6651
  }
6142
6652
  out.push(describePrimitive(node, m, t));
6143
6653
  }
6144
6654
  function collectSampleTimes(node, into) {
6145
- var _a;
6655
+ var _a2;
6146
6656
  into.add(0);
6147
6657
  const scanAnim = (anim) => {
6148
- var _a2;
6658
+ var _a3;
6149
6659
  if (!anim || typeof anim !== "object") return;
6150
6660
  for (const key of Object.keys(anim)) {
6151
- const kfs = (_a2 = anim[key]) == null ? void 0 : _a2.keyframes;
6661
+ const kfs = (_a3 = anim[key]) == null ? void 0 : _a3.keyframes;
6152
6662
  if (Array.isArray(kfs)) kfs.forEach((kf) => {
6153
- var _a3;
6154
- return into.add((_a3 = kf.time) != null ? _a3 : 0);
6663
+ var _a4;
6664
+ return into.add((_a4 = kf.time) != null ? _a4 : 0);
6155
6665
  });
6156
6666
  }
6157
6667
  };
6158
6668
  scanAnim(node.animate);
6159
6669
  if (node.transform && typeof node.transform === "object" && node.transform.keyframes) {
6160
6670
  node.transform.keyframes.forEach((kf) => {
6161
- var _a2;
6162
- return into.add((_a2 = kf.time) != null ? _a2 : 0);
6671
+ var _a3;
6672
+ return into.add((_a3 = kf.time) != null ? _a3 : 0);
6163
6673
  });
6164
6674
  }
6165
- (_a = node.children) == null ? void 0 : _a.forEach((c) => collectSampleTimes(c, into));
6675
+ (_a2 = node.children) == null ? void 0 : _a2.forEach((c) => collectSampleTimes(c, into));
6166
6676
  }
6167
6677
  function visualModelAt(root, t) {
6168
6678
  const idMap = /* @__PURE__ */ new Map();
@@ -6196,14 +6706,205 @@ function subtractMultiset(a, b) {
6196
6706
  }
6197
6707
  return extra;
6198
6708
  }
6709
+ var FLAT_ONLY_KEYS = [
6710
+ "timelineSource",
6711
+ "scroll",
6712
+ "trigger",
6713
+ "delay",
6714
+ "iterations",
6715
+ "direction",
6716
+ "fill",
6717
+ "resetOnFinish",
6718
+ "duration",
6719
+ "mode",
6720
+ "frameRate"
6721
+ ];
6722
+ var CONTENT_KEYS = ["definitions", "animateById"];
6723
+ var isPlainObject = (v) => !!v && typeof v === "object" && !Array.isArray(v);
6724
+ var timelineTypeOf = (t) => isPlainObject(t) && typeof t.type === "string" ? t.type : "time";
6725
+ var isScrollish = (type) => type === "scroll" || type === "view";
6726
+ function mergePlain(base, patch) {
6727
+ const out = isPlainObject(base) ? __spreadValues2({}, base) : {};
6728
+ for (const key of Object.keys(patch)) {
6729
+ const value = patch[key];
6730
+ if (value === null) {
6731
+ delete out[key];
6732
+ continue;
6733
+ }
6734
+ if (isPlainObject(value)) {
6735
+ out[key] = mergePlain(out[key], value);
6736
+ continue;
6737
+ }
6738
+ out[key] = value;
6739
+ }
6740
+ return out;
6741
+ }
6742
+ function mergeTimeline(base, patch, warn) {
6743
+ const baseType = timelineTypeOf(base);
6744
+ const patchNamesType = isPlainObject(patch) && typeof patch.type === "string";
6745
+ const patchType = patchNamesType ? String(patch.type) : baseType;
6746
+ let merged;
6747
+ if (patchType !== baseType) {
6748
+ const carried = {};
6749
+ if (isPlainObject(base)) {
6750
+ for (const k of PX_TIMELINE_SHARED_KEYS) {
6751
+ if (base[k] !== void 0) carried[k] = base[k];
6752
+ }
6753
+ }
6754
+ merged = mergePlain(carried, patch);
6755
+ } else {
6756
+ merged = mergePlain(base, patch);
6757
+ }
6758
+ if (isScrollish(patchType)) {
6759
+ for (const k of PX_TIME_ONLY_TIMELINE_KEYS) {
6760
+ if (merged[k] === void 0) continue;
6761
+ warn("animator.timeline." + k + ": no slot on a '" + patchType + "' timeline \u2014 dropped");
6762
+ delete merged[k];
6763
+ }
6764
+ if (merged.iterations === "infinite") {
6765
+ warn("animator.timeline.iterations: 'infinite' cannot map onto a scroll range \u2014 dropped");
6766
+ delete merged.iterations;
6767
+ }
6768
+ }
6769
+ return merged;
6770
+ }
6771
+ function foldTimelineOverride(timeline, shortcuts) {
6772
+ let base;
6773
+ if (typeof timeline === "string") {
6774
+ try {
6775
+ base = JSON.parse(timeline);
6776
+ } catch (e) {
6777
+ console.warn("timeline override: not valid JSON \u2014 ignored", e);
6778
+ base = void 0;
6779
+ }
6780
+ } else {
6781
+ base = timeline != null ? timeline : void 0;
6782
+ }
6783
+ const { duration, delay, iterations, startOn } = shortcuts;
6784
+ if (duration === void 0 && delay === void 0 && iterations === void 0 && startOn === void 0) {
6785
+ return base === void 0 ? void 0 : { timeline: base };
6786
+ }
6787
+ const out = isPlainObject(base) ? __spreadValues2({}, base) : {};
6788
+ if (duration !== void 0) out.duration = duration;
6789
+ if (delay !== void 0) out.delay = delay;
6790
+ if (iterations !== void 0) out.iterations = iterations;
6791
+ if (startOn !== void 0) {
6792
+ out.trigger = __spreadProps2(__spreadValues2({}, out.trigger), { startOn });
6793
+ }
6794
+ return { timeline: out };
6795
+ }
6796
+ function mergeAnimatorConfig(base, patch) {
6797
+ const warnings = [];
6798
+ const warn = (m) => warnings.push(m);
6799
+ if (patch === null) return { config: void 0, warnings };
6800
+ if (!isPlainObject(patch) || Object.keys(patch).length === 0) {
6801
+ return { config: base, warnings };
6802
+ }
6803
+ const flatInBase = isPlainObject(base) ? FLAT_ONLY_KEYS.filter((k) => base[k] !== void 0) : [];
6804
+ if (flatInBase.length) {
6805
+ warn("animator: the base carries the flat runtime spelling (" + flatInBase.join(", ") + "); the patch merges the wire spelling only");
6806
+ }
6807
+ const out = isPlainObject(base) ? __spreadValues2({}, base) : {};
6808
+ for (const key of Object.keys(patch)) {
6809
+ const value = patch[key];
6810
+ if (value === null) {
6811
+ delete out[key];
6812
+ continue;
6813
+ }
6814
+ if (key === "timeline") {
6815
+ out.timeline = isPlainObject(value) ? mergeTimeline(out.timeline, value, warn) : value;
6816
+ continue;
6817
+ }
6818
+ if (isPlainObject(value)) {
6819
+ out[key] = mergePlain(out[key], value);
6820
+ continue;
6821
+ }
6822
+ out[key] = value;
6823
+ }
6824
+ return { config: out, warnings };
6825
+ }
6826
+ function applyAnimatorConfig(doc, patch, opts) {
6827
+ var _a2, _b;
6828
+ const reset = !!(opts == null ? void 0 : opts.resetDefaults);
6829
+ if (!doc || (patch === void 0 || !reset && (patch === null || !isPlainObject(patch) || !Object.keys(patch).length))) {
6830
+ return { doc, warnings: [] };
6831
+ }
6832
+ const anyDoc = doc;
6833
+ const atRoot = isPlainObject(anyDoc.animator);
6834
+ const atMeta = !atRoot && isPlainObject((_a2 = anyDoc.meta) == null ? void 0 : _a2.animator);
6835
+ const current = atRoot ? anyDoc.animator : atMeta ? anyDoc.meta.animator : void 0;
6836
+ const warnings = [];
6837
+ if (atRoot && isPlainObject((_b = anyDoc.meta) == null ? void 0 : _b.animator)) {
6838
+ warnings.push("animator: doc.meta.animator is shadowed by doc.animator and was not patched");
6839
+ }
6840
+ let base = current;
6841
+ if (reset) {
6842
+ const kept = {};
6843
+ for (const k of CONTENT_KEYS) {
6844
+ if (isPlainObject(current) && current[k] !== void 0) kept[k] = current[k];
6845
+ }
6846
+ base = kept;
6847
+ }
6848
+ const merged = mergeAnimatorConfig(base, patch != null ? patch : {});
6849
+ warnings.push(...merged.warnings);
6850
+ if (merged.config === current) return { doc, warnings };
6851
+ if (atMeta) {
6852
+ return {
6853
+ doc: __spreadProps2(__spreadValues2({}, anyDoc), { meta: __spreadProps2(__spreadValues2({}, anyDoc.meta), { animator: merged.config }) }),
6854
+ warnings
6855
+ };
6856
+ }
6857
+ return { doc: __spreadProps2(__spreadValues2({}, anyDoc), { animator: merged.config }), warnings };
6858
+ }
6859
+ var MAX_REPORTED = 6;
6860
+ function diagnoseDocument(doc) {
6861
+ try {
6862
+ return { problems: validateDocument(doc) };
6863
+ } catch (e) {
6864
+ return { problems: [] };
6865
+ }
6866
+ }
6867
+ function reportDocumentDiagnostics(doc, where) {
6868
+ const { problems } = diagnoseDocument(doc);
6869
+ if (!problems.length) return;
6870
+ const shown = problems.slice(0, MAX_REPORTED);
6871
+ const more = problems.length - shown.length;
6872
+ console.warn(
6873
+ 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."
6874
+ );
6875
+ }
6876
+
6877
+ // src/shared/PxAnimatorCallbacks.ts
6878
+ function toEngineCallbacks(inline) {
6879
+ const { onPlay, onPause, onCancel, onFinish, onRemove, onStop, onWarn, onError, silent } = inline != null ? inline : {};
6880
+ const withStop = (own) => own || onStop ? () => {
6881
+ own == null ? void 0 : own();
6882
+ onStop == null ? void 0 : onStop();
6883
+ } : void 0;
6884
+ return {
6885
+ onPlay,
6886
+ onPause: withStop(onPause),
6887
+ onCancel: withStop(onCancel),
6888
+ onFinish: withStop(onFinish),
6889
+ onRemove: withStop(onRemove),
6890
+ onWarn,
6891
+ onError,
6892
+ silent
6893
+ };
6894
+ }
6199
6895
 
6200
- // src/PxAnimatorTriggers.ts
6201
- function setupAnimationTriggers(api, config) {
6202
- const { startOn, outAction = "continue", scrollIntoViewThreshold = 0 } = config;
6896
+ // src/triggers/PxAnimatorTriggers.ts
6897
+ function setupAnimationTriggers(api, config, diag) {
6898
+ const report = diag != null ? diag : createDiagnostics(void 0, "[PxAnimator]");
6899
+ const cleanups = [];
6900
+ const dispose = () => {
6901
+ for (const undo of cleanups.splice(0)) undo();
6902
+ };
6903
+ const { startOn, outAction, scrollIntoViewThreshold } = resolveTrigger(config);
6203
6904
  const root = api.getRootElement();
6204
6905
  if (!root) {
6205
- console.warn("setupAnimationTriggers: No root element found for animation.");
6206
- return api;
6906
+ report.warn(PxDiagnosticKind.host, "setupAnimationTriggers: No root element found for animation.");
6907
+ return dispose;
6207
6908
  }
6208
6909
  let reversed = false;
6209
6910
  const start = () => {
@@ -6238,6 +6939,7 @@ function setupAnimationTriggers(api, config) {
6238
6939
  startHandler();
6239
6940
  } else {
6240
6941
  window.addEventListener("load", startHandler, { once: true });
6942
+ cleanups.push(() => window.removeEventListener("load", startHandler));
6241
6943
  }
6242
6944
  break;
6243
6945
  }
@@ -6252,6 +6954,10 @@ function setupAnimationTriggers(api, config) {
6252
6954
  };
6253
6955
  root.addEventListener("mouseenter", mouseOverHandler);
6254
6956
  root.addEventListener("mouseleave", mouseOutHandler);
6957
+ cleanups.push(() => {
6958
+ root.removeEventListener("mouseenter", mouseOverHandler);
6959
+ root.removeEventListener("mouseleave", mouseOutHandler);
6960
+ });
6255
6961
  break;
6256
6962
  }
6257
6963
  case "click": {
@@ -6263,16 +6969,17 @@ function setupAnimationTriggers(api, config) {
6263
6969
  }
6264
6970
  };
6265
6971
  root.addEventListener("click", clickHandler);
6972
+ cleanups.push(() => root.removeEventListener("click", clickHandler));
6266
6973
  break;
6267
6974
  }
6268
6975
  case "scrollIntoView": {
6269
6976
  const effectiveRatio = (entry) => {
6270
- var _a, _b;
6977
+ var _a2, _b;
6271
6978
  const target = entry.boundingClientRect;
6272
6979
  const visible = entry.intersectionRect;
6273
6980
  if (!(target == null ? void 0 : target.height) || !visible) return entry.intersectionRatio;
6274
6981
  const live = typeof window !== "undefined" && window.innerHeight ? window.innerHeight : Infinity;
6275
- const declared = (_b = (_a = entry.rootBounds) == null ? void 0 : _a.height) != null ? _b : Infinity;
6982
+ const declared = (_b = (_a2 = entry.rootBounds) == null ? void 0 : _a2.height) != null ? _b : Infinity;
6276
6983
  const viewport = Math.min(live, declared);
6277
6984
  const denom = Math.min(target.height, Number.isFinite(viewport) ? viewport : target.height);
6278
6985
  return denom > 0 ? visible.height / denom : entry.intersectionRatio;
@@ -6294,48 +7001,55 @@ function setupAnimationTriggers(api, config) {
6294
7001
  { threshold: thresholdSteps }
6295
7002
  );
6296
7003
  observer.observe(root);
7004
+ cleanups.push(() => observer.disconnect());
6297
7005
  break;
6298
7006
  }
6299
7007
  case "programmatic":
6300
7008
  break;
6301
7009
  }
6302
- return api;
7010
+ return dispose;
6303
7011
  }
6304
7012
 
6305
- // src/PxAnimatorFrameLoop.ts
7013
+ // src/engines/PxAnimatorFrameLoop.ts
6306
7014
  function getSelector(id) {
6307
7015
  return "#" + id;
6308
7016
  }
6309
7017
  function createFrameLoopAnimator(doc, adapter, callbacks, rootElement) {
7018
+ var _a2;
6310
7019
  const config = getAnimatorConfig(doc) || {};
7020
+ const diag = createDiagnostics(callbacks, "[PxAnimator]");
6311
7021
  if (!rootElement) {
6312
7022
  if (doc.id) {
6313
7023
  const rootSelector = getSelector(doc.id);
6314
7024
  rootElement = document.querySelector(rootSelector);
6315
- if (!rootElement) console.warn("createFrameLoopAnimator: No root element found for selector: ", rootSelector);
7025
+ if (!rootElement) diag.warn(PxDiagnosticKind.host, "createFrameLoopAnimator: No root element found for selector: " + rootSelector);
6316
7026
  } else {
6317
- console.warn("createFrameLoopAnimator: No root element provided");
7027
+ diag.warn(PxDiagnosticKind.host, "createFrameLoopAnimator: No root element provided");
6318
7028
  }
6319
7029
  }
6320
7030
  const basicApi = createBasicFrameLoopAnimator(
6321
7031
  doc,
6322
- adapter || createDomAdapter(rootElement),
7032
+ adapter || createDomAdapter(rootElement, diag),
6323
7033
  callbacks
6324
7034
  );
6325
7035
  const api = __spreadProps(__spreadValues({}, basicApi), {
6326
7036
  "getRootElement": () => rootElement || null
6327
7037
  });
6328
- if (config.trigger) {
6329
- if (isScrollTimeline(config)) {
6330
- console.warn("scroll timeline: `animator.trigger` is ignored (triggers do not apply to scroll-driven playback)");
6331
- } else {
6332
- setupAnimationTriggers(api, config.trigger);
6333
- }
7038
+ if (isScrollTimeline(config)) {
7039
+ if (config.trigger) diag.warn(PxDiagnosticKind.usage, "scroll timeline: `animator.trigger` is ignored (triggers do not apply to scroll-driven playback)");
7040
+ } else {
7041
+ const detachTriggers = setupAnimationTriggers(api, (_a2 = config.trigger) != null ? _a2 : {}, diag);
7042
+ const destroyEngine = api.destroy.bind(api);
7043
+ api.destroy = () => {
7044
+ detachTriggers();
7045
+ destroyEngine();
7046
+ };
6334
7047
  }
6335
7048
  return api;
6336
7049
  }
6337
- function createDomAdapter(rootElement) {
7050
+ function createDomAdapter(rootElement, diag) {
6338
7051
  const warnedSelectors = /* @__PURE__ */ new Set();
7052
+ const report = diag != null ? diag : createDiagnostics(void 0, "[PxAnimator]");
6339
7053
  const adapter = {
6340
7054
  isConnected: () => {
6341
7055
  if (!rootElement) return true;
@@ -6347,7 +7061,7 @@ function createDomAdapter(rootElement) {
6347
7061
  const elements = (rootElement == null ? void 0 : rootElement.querySelectorAll(selector)) || document.querySelectorAll(selector);
6348
7062
  if (elements.length === 0 && !warnedSelectors.has(selector)) {
6349
7063
  warnedSelectors.add(selector);
6350
- console.warn('setAttribute: No elements found for selector "' + selector + '"');
7064
+ report.warn(PxDiagnosticKind.host, 'setAttribute: No elements found for selector "' + selector + '"');
6351
7065
  }
6352
7066
  for (let i = 0; i < elements.length; i++) {
6353
7067
  const element = elements[i];
@@ -6362,18 +7076,17 @@ function createDomAdapter(rootElement) {
6362
7076
  return adapter;
6363
7077
  }
6364
7078
 
6365
- // src/PxAnimatorWebApi.ts
7079
+ // src/engines/PxAnimatorWebApi.ts
6366
7080
  function createCssKf(kf, t, propName, unsupportedSet) {
6367
- var _a, _b;
6368
- let value = (_a = kf.v) != null ? _a : kf.value;
6369
- const e = (_b = kf.e) != null ? _b : kf.easing;
7081
+ let value = kfValue(kf);
7082
+ const e = kfEasing(kf);
6370
7083
  const cssKf = {
6371
7084
  offset: t,
6372
7085
  easing: e && Array.isArray(e) ? "cubic-bezier(" + e.join(",") + ")" : void 0
6373
7086
  };
6374
7087
  let cssValue;
6375
7088
  let cssKey = propName;
6376
- if (COLOUR_ATTR_NAMES.has(propName) && Array.isArray(value)) {
7089
+ if (COLOR_ATTR_NAMES.has(propName) && Array.isArray(value)) {
6377
7090
  cssValue = toRGBA(value);
6378
7091
  } else if (propName === "transform" && value !== null && typeof value === "object" && !Array.isArray(value)) {
6379
7092
  cssValue = composeTransformParts(value, { withUnits: true });
@@ -6400,11 +7113,11 @@ function createCssKf(kf, t, propName, unsupportedSet) {
6400
7113
  return cssKf;
6401
7114
  }
6402
7115
  function clipKeyframesToDuration(propName, keyframes, duration) {
6403
- var _a, _b, _c, _d, _e;
7116
+ var _a2, _b, _c, _d, _e;
6404
7117
  const result = [];
6405
7118
  for (let i = 0; i < keyframes.length; i++) {
6406
7119
  const kf = keyframes[i];
6407
- const t = (_a = kf.t) != null ? _a : 0;
7120
+ const t = (_a2 = kf.t) != null ? _a2 : 0;
6408
7121
  if (t < 0) {
6409
7122
  const next = keyframes[i + 1];
6410
7123
  if (next && ((_b = next.t) != null ? _b : 0) >= 0) {
@@ -6433,7 +7146,7 @@ function clipKeyframesToDuration(propName, keyframes, duration) {
6433
7146
  return result;
6434
7147
  }
6435
7148
  function convertToWebApiKeyframes(animDef, unsupportedSet, config) {
6436
- var _a;
7149
+ var _a2;
6437
7150
  const result = /* @__PURE__ */ new Map();
6438
7151
  for (const [propName, propAnim] of Object.entries(animDef)) {
6439
7152
  const duration = config.duration || 1;
@@ -6441,7 +7154,7 @@ function convertToWebApiKeyframes(animDef, unsupportedSet, config) {
6441
7154
  const cssKeyframes = [];
6442
7155
  for (let i = 0; i < clippedKeyframes.length; i++) {
6443
7156
  const kf = clippedKeyframes[i];
6444
- const t = clamp(((_a = kf.t) != null ? _a : 0) / duration, 0, 1);
7157
+ const t = clamp(((_a2 = kf.t) != null ? _a2 : 0) / duration, 0, 1);
6445
7158
  const cssKf = createCssKf(kf, t, propName, unsupportedSet);
6446
7159
  if (i === 0 && (cssKf.offset || 0) > 0) {
6447
7160
  cssKeyframes.push(__spreadProps(__spreadValues({}, cssKf), { offset: 0 }));
@@ -6460,18 +7173,19 @@ function convertToWebApiKeyframes(animDef, unsupportedSet, config) {
6460
7173
  return result;
6461
7174
  }
6462
7175
  function createWebApiAnimator(doc, callbacks, rootElement, forceEvenIfHasUnsupportedAttrs, scrollTimeline) {
6463
- var _a;
7176
+ var _a2, _b;
6464
7177
  const config = getAnimatorConfig(doc) || {};
7178
+ const diag = createDiagnostics(callbacks, "[PxAnimator]");
6465
7179
  if (!rootElement) {
6466
7180
  if (doc.id) {
6467
7181
  const rootSelector = getSelector(doc.id);
6468
7182
  rootElement = document.querySelector(rootSelector);
6469
- if (!rootElement) console.warn("createFrameLoopAnimator: No root element found for selector: ", rootSelector);
7183
+ if (!rootElement) diag.warn(PxDiagnosticKind.host, "createWebApiAnimator: No root element found for selector: " + rootSelector);
6470
7184
  } else {
6471
- console.warn("createFrameLoopAnimator: No root element provided");
7185
+ diag.warn(PxDiagnosticKind.host, "createWebApiAnimator: No root element provided");
6472
7186
  }
6473
7187
  }
6474
- const bindings = getNormalisedBindings(doc, PxAnimatorEngine.waapi);
7188
+ const bindings = getNormalizedBindings(doc, PxTimelineEngine.native);
6475
7189
  const animations = [];
6476
7190
  const _iterations = config.iterations;
6477
7191
  let iterations;
@@ -6481,18 +7195,18 @@ function createWebApiAnimator(doc, callbacks, rootElement, forceEvenIfHasUnsuppo
6481
7195
  let finishNotified = false;
6482
7196
  let removeCalled = false;
6483
7197
  if (!(bindings == null ? void 0 : bindings.length)) {
6484
- console.warn("createWebApiAnimator: No animation bindings defined");
7198
+ diag.warn(PxDiagnosticKind.document, "createWebApiAnimator: No animation bindings defined");
6485
7199
  }
6486
7200
  for (const binding of bindings || []) {
6487
7201
  const animDef = binding.animate;
6488
7202
  if (!animDef || typeof animDef !== "object" || Array.isArray(animDef)) {
6489
- console.warn("createWebApiAnimator: Empty or unresolved binding", binding);
7203
+ diag.warn(PxDiagnosticKind.document, "createWebApiAnimator: Empty or unresolved binding", binding);
6490
7204
  continue;
6491
7205
  }
6492
7206
  const selector = getSelector(binding.id);
6493
7207
  const elements = (rootElement == null ? void 0 : rootElement.querySelectorAll(selector)) || document.querySelectorAll(selector);
6494
7208
  if (elements.length === 0) {
6495
- console.warn('createWebApiAnimator: No elements found for selector "' + selector + '"');
7209
+ diag.warn(PxDiagnosticKind.host, 'createWebApiAnimator: No elements found for selector "' + selector + '"');
6496
7210
  }
6497
7211
  const keyframesMap = convertToWebApiKeyframes(animDef, unsupportedSet, config);
6498
7212
  const positiveDelay = config.delay && config.delay > 0 ? config.delay : void 0;
@@ -6508,7 +7222,7 @@ function createWebApiAnimator(doc, callbacks, rootElement, forceEvenIfHasUnsuppo
6508
7222
  // animation ends — consistent with Lottie and other animation runtimes.
6509
7223
  // Without this, seeking to the last frame reverts elements to their
6510
7224
  // pre-animation state (the Web Animations API "after" phase with fill:'none').
6511
- fill: (_a = config.fill) != null ? _a : "forwards",
7225
+ fill: (_a2 = config.fill) != null ? _a2 : "forwards",
6512
7226
  direction: config.direction,
6513
7227
  iterations
6514
7228
  };
@@ -6525,61 +7239,61 @@ function createWebApiAnimator(doc, callbacks, rootElement, forceEvenIfHasUnsuppo
6525
7239
  if (scrollTimeline.rangeEnd) a.rangeEnd = scrollTimeline.rangeEnd;
6526
7240
  }
6527
7241
  if (callbacks == null ? void 0 : callbacks.onFinish) anim.onfinish = () => {
6528
- var _a2;
7242
+ var _a3;
6529
7243
  if (finishNotified) return;
6530
7244
  finishNotified = true;
6531
- (_a2 = callbacks.onFinish) == null ? void 0 : _a2.call(callbacks);
7245
+ (_a3 = callbacks.onFinish) == null ? void 0 : _a3.call(callbacks);
6532
7246
  };
6533
7247
  if (callbacks == null ? void 0 : callbacks.onRemove) anim.onremove = () => {
6534
- var _a2;
7248
+ var _a3;
6535
7249
  if (removeCalled) return;
6536
7250
  removeCalled = true;
6537
- (_a2 = callbacks.onRemove) == null ? void 0 : _a2.call(callbacks);
7251
+ (_a3 = callbacks.onRemove) == null ? void 0 : _a3.call(callbacks);
6538
7252
  };
6539
7253
  if (seekPosition !== void 0) {
6540
7254
  anim.currentTime = seekPosition;
6541
7255
  }
6542
7256
  animations.push(anim);
6543
7257
  } catch (e) {
6544
- console.warn(e);
7258
+ diag.warn(PxDiagnosticKind.internal, "createWebApiAnimator: could not build the animation", e);
6545
7259
  }
6546
7260
  }
6547
7261
  }
6548
7262
  }
6549
7263
  }
6550
7264
  if (!forceEvenIfHasUnsupportedAttrs && unsupportedSet.size) {
6551
- console.warn("Unsupported CSS attrs: " + [...unsupportedSet].join(", "));
7265
+ diag.warn(PxDiagnosticKind.platform, "Unsupported CSS attrs: " + [...unsupportedSet].join(", "));
6552
7266
  return null;
6553
7267
  }
6554
7268
  const api = {
6555
7269
  "isReady": () => true,
6556
7270
  "getRootElement": () => rootElement || null,
6557
7271
  "isPlaying": () => {
6558
- var _a2;
6559
- return ((_a2 = animations[0]) == null ? void 0 : _a2.playState) === "running";
7272
+ var _a3;
7273
+ return ((_a3 = animations[0]) == null ? void 0 : _a3.playState) === "running";
6560
7274
  },
6561
7275
  "play": () => {
6562
- var _a2;
7276
+ var _a3;
6563
7277
  finishNotified = false;
6564
7278
  animations.forEach((a) => a.play());
6565
- (_a2 = callbacks == null ? void 0 : callbacks.onPlay) == null ? void 0 : _a2.call(callbacks);
7279
+ (_a3 = callbacks == null ? void 0 : callbacks.onPlay) == null ? void 0 : _a3.call(callbacks);
6566
7280
  },
6567
7281
  "pause": () => {
6568
- var _a2;
7282
+ var _a3;
6569
7283
  animations.forEach((a) => a.pause());
6570
- (_a2 = callbacks == null ? void 0 : callbacks.onPause) == null ? void 0 : _a2.call(callbacks);
7284
+ (_a3 = callbacks == null ? void 0 : callbacks.onPause) == null ? void 0 : _a3.call(callbacks);
6571
7285
  },
6572
7286
  "cancel": () => {
6573
- var _a2;
7287
+ var _a3;
6574
7288
  finishNotified = false;
6575
7289
  animations.forEach((a) => a.cancel());
6576
- (_a2 = callbacks == null ? void 0 : callbacks.onCancel) == null ? void 0 : _a2.call(callbacks);
7290
+ (_a3 = callbacks == null ? void 0 : callbacks.onCancel) == null ? void 0 : _a3.call(callbacks);
6577
7291
  },
6578
7292
  "finish": () => {
6579
- var _a2;
7293
+ var _a3;
6580
7294
  for (const a of animations) {
6581
7295
  try {
6582
- if (((_a2 = a.effect) == null ? void 0 : _a2.getTiming().iterations) === Infinity) {
7296
+ if (((_a3 = a.effect) == null ? void 0 : _a3.getTiming().iterations) === Infinity) {
6583
7297
  a.effect.updateTiming({ iterations: 1 });
6584
7298
  a.finish();
6585
7299
  a.effect.updateTiming({ iterations: Infinity });
@@ -6592,36 +7306,55 @@ function createWebApiAnimator(doc, callbacks, rootElement, forceEvenIfHasUnsuppo
6592
7306
  }
6593
7307
  },
6594
7308
  "setPlaybackRate": (rate) => {
7309
+ if (!isValidPlaybackRate(rate)) {
7310
+ diag.warn(PxDiagnosticKind.usage, PX_RATE_REJECTED);
7311
+ return api;
7312
+ }
6595
7313
  animations.forEach((a) => a.playbackRate = rate);
6596
7314
  return api;
6597
7315
  },
6598
7316
  "getCurrentTime": () => {
6599
- var _a2, _b;
6600
- const res = (_b = (_a2 = animations[0]) == null ? void 0 : _a2.currentTime) != null ? _b : null;
7317
+ var _a3, _b2;
7318
+ const res = (_b2 = (_a3 = animations[0]) == null ? void 0 : _a3.currentTime) != null ? _b2 : null;
6601
7319
  return res !== null ? +res : null;
6602
7320
  },
6603
7321
  "setCurrentTime": (time) => {
7322
+ var _a3;
7323
+ const ceiling = seekCeilingMs((_a3 = config.duration) != null ? _a3 : 0, iterations != null ? iterations : 1);
7324
+ const seek = ceiling > 0 ? clampSeekMs(time, ceiling) : Math.max(0, time);
6604
7325
  finishNotified = false;
6605
7326
  animations.forEach((a) => {
6606
- a.currentTime = time;
7327
+ a.currentTime = seek;
6607
7328
  });
6608
7329
  },
7330
+ "getCurrentProgress": () => {
7331
+ var _a3;
7332
+ const t = api.getCurrentTime();
7333
+ return t === null ? null : timeToProgress(t, (_a3 = config.duration) != null ? _a3 : 0, iterations != null ? iterations : 1);
7334
+ },
7335
+ "setCurrentProgress": (progress) => {
7336
+ var _a3;
7337
+ api.setCurrentTime(progressToTimeMs(progress, (_a3 = config.duration) != null ? _a3 : 0, iterations != null ? iterations : 1));
7338
+ },
6609
7339
  "destroy": () => {
6610
- var _a2;
7340
+ var _a3;
6611
7341
  api.cancel();
6612
7342
  animations.splice(0, animations.length);
6613
7343
  if (!removeCalled) {
6614
7344
  removeCalled = true;
6615
- (_a2 = callbacks == null ? void 0 : callbacks.onRemove) == null ? void 0 : _a2.call(callbacks);
7345
+ (_a3 = callbacks == null ? void 0 : callbacks.onRemove) == null ? void 0 : _a3.call(callbacks);
6616
7346
  }
6617
7347
  }
6618
7348
  };
6619
- if (config.trigger) {
6620
- if (config.timelineSource === "scroll") {
6621
- console.warn("scroll timeline: `animator.trigger` is ignored (triggers do not apply to scroll-driven playback)");
6622
- } else {
6623
- setupAnimationTriggers(api, config.trigger);
6624
- }
7349
+ if (config.timelineSource === "scroll") {
7350
+ if (config.trigger) diag.warn(PxDiagnosticKind.usage, "scroll timeline: `animator.trigger` is ignored (triggers do not apply to scroll-driven playback)");
7351
+ } else {
7352
+ const detachTriggers = setupAnimationTriggers(api, (_b = config.trigger) != null ? _b : {}, diag);
7353
+ const destroyEngine = api.destroy.bind(api);
7354
+ api.destroy = () => {
7355
+ detachTriggers();
7356
+ destroyEngine();
7357
+ };
6625
7358
  }
6626
7359
  if (scrollTimeline) {
6627
7360
  animations.forEach((a) => a.play());
@@ -6629,21 +7362,22 @@ function createWebApiAnimator(doc, callbacks, rootElement, forceEvenIfHasUnsuppo
6629
7362
  return api;
6630
7363
  }
6631
7364
 
6632
- // src/PxScrollDriver.ts
7365
+ // src/scroll/PxScrollDriver.ts
6633
7366
  function nativeRangeOffset(point, defaultFraction, view) {
6634
- var _a, _b, _c;
7367
+ var _a2, _b, _c;
6635
7368
  const fraction = typeof (point == null ? void 0 : point.fraction) === "number" ? point.fraction : defaultFraction;
6636
- const pct = (_b = (_a = globalThis.CSS) == null ? void 0 : _a.percent) == null ? void 0 : _b.call(_a, fraction * 100);
7369
+ const pct = (_b = (_a2 = globalThis.CSS) == null ? void 0 : _a2.percent) == null ? void 0 : _b.call(_a2, fraction * 100);
6637
7370
  if (pct === void 0) return void 0;
6638
7371
  return view ? { rangeName: (_c = point == null ? void 0 : point.phase) != null ? _c : "cover", offset: pct } : { offset: pct };
6639
7372
  }
6640
- function createNativeScrollTimeline(subject, config) {
6641
- var _a, _b, _c, _d;
7373
+ function createNativeScrollTimeline(subject, config, diag) {
7374
+ var _a2, _b, _c, _d;
7375
+ const report = diag != null ? diag : createDiagnostics(void 0, "[PxAnimator]");
6642
7376
  if (!config || !isScrollTimeline(config)) return null;
6643
7377
  const scroll = config.scroll || {};
6644
- const kind = (_a = scroll.kind) != null ? _a : "view";
7378
+ const kind = (_a2 = scroll.kind) != null ? _a2 : "view";
6645
7379
  if (scroll.smoothing) {
6646
- console.warn('scroll timeline: `smoothing` needs the built-in driver \u2014 ignoring `driver: "native"`');
7380
+ report.warn(PxDiagnosticKind.platform, "scroll timeline: `smoothing` needs the built-in driver \u2014 using the built-in driver instead of the browser timeline");
6647
7381
  return null;
6648
7382
  }
6649
7383
  const g = globalThis;
@@ -6654,13 +7388,13 @@ function createNativeScrollTimeline(subject, config) {
6654
7388
  let timeline;
6655
7389
  try {
6656
7390
  if (view) {
6657
- timeline = new Ctor({ subject: resolveScrollSubject(subject, scroll.subject), axis });
7391
+ timeline = new Ctor({ subject: resolveScrollSubject(subject, scroll.subject, report), axis });
6658
7392
  } else {
6659
7393
  const source = scroll.source === "root" ? documentScroller() : findNearestScroller(subject, "y") || findNearestScroller(subject, "x") || documentScroller();
6660
7394
  timeline = new Ctor({ source, axis });
6661
7395
  }
6662
7396
  } catch (e) {
6663
- console.warn("scroll timeline: native timeline construction failed \u2014 falling back to the custom driver", e);
7397
+ report.warn(PxDiagnosticKind.platform, "scroll timeline: native timeline construction failed \u2014 falling back to the player measuring progress itself", e);
6664
7398
  return null;
6665
7399
  }
6666
7400
  return {
@@ -6687,8 +7421,9 @@ function documentScroller() {
6687
7421
  }
6688
7422
  var SUBJECT_PARENT = "parent";
6689
7423
  var SUBJECT_SCROLLER = "scroller";
6690
- function resolveScrollSubject(svgRoot, subject) {
6691
- var _a, _b;
7424
+ function resolveScrollSubject(svgRoot, subject, diag) {
7425
+ var _a2, _b;
7426
+ const report = diag != null ? diag : createDiagnostics(void 0, "[PxAnimator]");
6692
7427
  const spec = subject == null ? void 0 : subject.trim();
6693
7428
  if (!spec) return svgRoot;
6694
7429
  if (spec === SUBJECT_PARENT) {
@@ -6697,7 +7432,7 @@ function resolveScrollSubject(svgRoot, subject) {
6697
7432
  const position = getComputedStyle(p).position;
6698
7433
  if (position === "sticky" || position === "fixed") outermostPinned = p;
6699
7434
  }
6700
- return (_b = (_a = outermostPinned == null ? void 0 : outermostPinned.parentElement) != null ? _a : svgRoot.parentElement) != null ? _b : svgRoot;
7435
+ return (_b = (_a2 = outermostPinned == null ? void 0 : outermostPinned.parentElement) != null ? _a2 : svgRoot.parentElement) != null ? _b : svgRoot;
6701
7436
  }
6702
7437
  if (spec === SUBJECT_SCROLLER) {
6703
7438
  return findNearestScroller(svgRoot, "y") || findNearestScroller(svgRoot, "x") || documentScroller();
@@ -6706,21 +7441,22 @@ function resolveScrollSubject(svgRoot, subject) {
6706
7441
  try {
6707
7442
  found = document.querySelector(spec);
6708
7443
  } catch (e) {
6709
- console.warn('scroll timeline: subject "' + spec + '" is not a valid selector \u2014 measuring the SVG itself');
7444
+ report.warn(PxDiagnosticKind.document, 'scroll timeline: subject "' + spec + '" is not a valid selector \u2014 measuring the SVG itself');
6710
7445
  return svgRoot;
6711
7446
  }
6712
7447
  if (!found) {
6713
- console.warn('scroll timeline: subject "' + spec + '" matched no element \u2014 measuring the SVG itself');
7448
+ report.warn(PxDiagnosticKind.host, 'scroll timeline: subject "' + spec + '" matched no element \u2014 measuring the SVG itself');
6714
7449
  return svgRoot;
6715
7450
  }
6716
7451
  return found;
6717
7452
  }
6718
- function createScrollDriver(subject, config, onProgress) {
6719
- var _a, _b;
7453
+ function createScrollDriver(subject, config, onProgress, diag) {
7454
+ var _a2, _b;
6720
7455
  if (!config || !isScrollTimeline(config)) return null;
7456
+ const report = diag != null ? diag : createDiagnostics(void 0, "[PxAnimator]");
6721
7457
  const scroll = config.scroll || {};
6722
- const kind = (_a = scroll.kind) != null ? _a : "view";
6723
- const measured = resolveScrollSubject(subject, scroll.subject);
7458
+ const kind = (_a2 = scroll.kind) != null ? _a2 : "view";
7459
+ const measured = resolveScrollSubject(subject, scroll.subject, report);
6724
7460
  const nearest = findNearestScroller(subject, "y") || findNearestScroller(subject, "x");
6725
7461
  const scroller = kind === "scroll" && scroll.source === "root" ? documentScroller() : nearest || documentScroller();
6726
7462
  const isRootScroller = scroller === documentScroller();
@@ -6838,8 +7574,8 @@ function applyScrollPin(svgRoot, scroll) {
6838
7574
  style.position = "sticky";
6839
7575
  const alignFactor = scroll.pinAlign === "center" ? 0.5 : scroll.pinAlign === "bottom" ? 1 : 0;
6840
7576
  const applyTop = () => {
6841
- var _a;
6842
- const extra = (_a = scroll.pinTop) != null ? _a : 0;
7577
+ var _a2;
7578
+ const extra = (_a2 = scroll.pinOffset) != null ? _a2 : 0;
6843
7579
  if (!alignFactor) {
6844
7580
  style.top = extra + "px";
6845
7581
  return;
@@ -6879,42 +7615,43 @@ function applyScrollPin(svgRoot, scroll) {
6879
7615
  };
6880
7616
  }
6881
7617
 
6882
- // src/PxAnimatorBind.ts
7618
+ // src/engines/PxAnimatorBind.ts
6883
7619
  function finaliseAnimator(animatorConfig, callbacks, make) {
6884
7620
  let apiRef;
6885
7621
  let effectiveCallbacks = callbacks;
6886
7622
  if (animatorConfig.resetOnFinish) {
6887
7623
  effectiveCallbacks = __spreadProps(__spreadValues({}, callbacks), {
6888
7624
  onFinish: () => {
6889
- var _a;
6890
- (_a = callbacks == null ? void 0 : callbacks.onFinish) == null ? void 0 : _a.call(callbacks);
7625
+ var _a2;
7626
+ (_a2 = callbacks == null ? void 0 : callbacks.onFinish) == null ? void 0 : _a2.call(callbacks);
6891
7627
  apiRef == null ? void 0 : apiRef.cancel();
6892
7628
  }
6893
7629
  });
6894
7630
  }
6895
7631
  const res = make(effectiveCallbacks);
6896
7632
  apiRef = res;
6897
- if (animatorConfig.debugInstName) {
6898
- window[animatorConfig.debugInstName] = res;
7633
+ if (animatorConfig.debugGlobalName) {
7634
+ window[animatorConfig.debugGlobalName] = res;
6899
7635
  }
6900
7636
  return res;
6901
7637
  }
6902
7638
  function bindWithEngineChoice(doc, adapter, callbacks, rootElement) {
6903
7639
  const animatorConfig = getAnimatorConfig(doc) || {};
7640
+ const diag = createDiagnostics(callbacks, "[PxAnimator]");
6904
7641
  if (isScrollTimeline(animatorConfig)) {
6905
7642
  return finaliseAnimator(animatorConfig, callbacks, (cb) => {
6906
- var _a, _b;
7643
+ var _a2;
6907
7644
  let unpin = () => {
6908
7645
  };
6909
- if (animatorConfig.mode !== PxAnimatorMode.frames && ((_a = animatorConfig.scroll) == null ? void 0 : _a.driver) === "native" && rootElement) {
7646
+ if (mayUseNativeScrollTimeline(animatorConfig.engine) && rootElement) {
6910
7647
  unpin = applyScrollPin(rootElement, animatorConfig.scroll);
6911
- const native = createNativeScrollTimeline(rootElement, animatorConfig);
7648
+ const native = createNativeScrollTimeline(rootElement, animatorConfig, diag);
6912
7649
  if (native) {
6913
7650
  const api2 = createWebApiAnimator(
6914
7651
  doc,
6915
7652
  cb,
6916
7653
  rootElement,
6917
- animatorConfig.mode === PxAnimatorMode.waapi,
7654
+ isNativeForced(animatorConfig.engine),
6918
7655
  native
6919
7656
  );
6920
7657
  if (api2) {
@@ -6930,15 +7667,16 @@ function bindWithEngineChoice(doc, adapter, callbacks, rootElement) {
6930
7667
  unpin = () => {
6931
7668
  };
6932
7669
  }
6933
- const api = (animatorConfig.mode !== PxAnimatorMode.frames ? createWebApiAnimator(doc, cb, rootElement, animatorConfig.mode === PxAnimatorMode.waapi) : null) || createFrameLoopAnimator(doc, adapter, cb, rootElement);
6934
- const subject = ((_b = api.getRootElement) == null ? void 0 : _b.call(api)) || rootElement;
7670
+ const api = (animatorConfig.engine !== PxTimelineEngineExtra.js ? createWebApiAnimator(doc, cb, rootElement, isNativeForced(animatorConfig.engine)) : null) || createFrameLoopAnimator(doc, adapter, cb, rootElement);
7671
+ const subject = ((_a2 = api.getRootElement) == null ? void 0 : _a2.call(api)) || rootElement;
6935
7672
  if (subject) {
6936
7673
  unpin = applyScrollPin(subject, animatorConfig.scroll);
6937
7674
  const totalMs = scrollTotalDurationMs(animatorConfig);
6938
7675
  const driver = createScrollDriver(
6939
7676
  subject,
6940
7677
  animatorConfig,
6941
- (progress) => api.setCurrentTime(progress * totalMs)
7678
+ (progress) => api.setCurrentTime(progress * totalMs),
7679
+ diag
6942
7680
  );
6943
7681
  if (driver) {
6944
7682
  const destroy = api.destroy.bind(api);
@@ -6949,58 +7687,58 @@ function bindWithEngineChoice(doc, adapter, callbacks, rootElement) {
6949
7687
  };
6950
7688
  }
6951
7689
  } else {
6952
- console.warn("scroll timeline: no root element to observe \u2014 animation will stay at frame 0");
7690
+ diag.warn(PxDiagnosticKind.host, "scroll timeline: no root element to observe \u2014 animation will stay at frame 0");
6953
7691
  }
6954
7692
  return api;
6955
7693
  });
6956
7694
  }
6957
7695
  return finaliseAnimator(animatorConfig, callbacks, (cb) => {
6958
- if (animatorConfig.mode === PxAnimatorMode.frames) {
7696
+ if (animatorConfig.engine === PxTimelineEngineExtra.js) {
6959
7697
  return createFrameLoopAnimator(doc, adapter, cb, rootElement);
6960
7698
  }
6961
7699
  return createWebApiAnimator(
6962
7700
  doc,
6963
7701
  cb,
6964
7702
  rootElement,
6965
- animatorConfig.mode === PxAnimatorMode.waapi
6966
- // forcing waapi
7703
+ isNativeForced(animatorConfig.engine)
6967
7704
  ) || createFrameLoopAnimator(doc, adapter, cb, rootElement);
6968
7705
  });
6969
7706
  }
6970
7707
 
6971
- // src/PxAnimatorDOM.ts
7708
+ // src/dom/PxAnimatorDOM.ts
6972
7709
  var SVG_NS = "http://www.w3.org/2000/svg";
6973
- function createElement(tagName, normalisedProps, style, children, textContent) {
7710
+ function createElement(tagName, normalizedProps, style, children, textContent, diag) {
6974
7711
  if (DISALLOWED_SVG_TAGS_LOWER.has(tagName.toLowerCase())) {
6975
- console.warn("SVG tag blocked (dangerous): ", tagName);
7712
+ (diag != null ? diag : createDiagnostics(void 0, "[PxAnimator]")).warn(PxDiagnosticKind.document, "SVG tag blocked (dangerous): " + tagName);
6976
7713
  return null;
6977
7714
  }
6978
7715
  const element = document.createElementNS(SVG_NS, tagName);
6979
- for (const propName in normalisedProps) {
6980
- const sanitised = sanitiseAttributeValue(propName, normalisedProps[propName]);
6981
- if (sanitised === void 0) continue;
7716
+ for (const propName in normalizedProps) {
7717
+ const sanitized = sanitizeAttributeValue(propName, normalizedProps[propName]);
7718
+ if (sanitized === void 0) continue;
6982
7719
  if (CSS_ONLY_STYLE_PROPS.has(propName)) {
6983
- element.style[propName] = String(sanitised);
7720
+ element.style[propName] = String(sanitized);
6984
7721
  continue;
6985
7722
  }
6986
- element.setAttribute(camelCaseToKebabWordIfNeeded(propName), sanitised);
7723
+ element.setAttribute(camelCaseToKebabWordIfNeeded(propName), sanitized);
6987
7724
  }
6988
7725
  if (style) {
6989
7726
  for (const styleProp in style) {
6990
7727
  element.style[styleProp] = String(style[styleProp]);
6991
7728
  }
6992
7729
  }
6993
- if (children) {
7730
+ if (children == null ? void 0 : children.length) {
6994
7731
  for (const child of children) {
6995
7732
  element.appendChild(child);
6996
7733
  }
7734
+ } else if (textContent) {
7735
+ element.textContent = textContent;
6997
7736
  }
6998
- if (textContent) element.textContent = textContent;
6999
7737
  return element;
7000
7738
  }
7001
- function renderNode(node, defs) {
7739
+ function renderNode(node, defs, diag) {
7002
7740
  if (!node) return null;
7003
- const _a = node, { type, children, style } = _a, props = __objRest(_a, ["type", "children", "style"]);
7741
+ const _a2 = node, { type, children, style } = _a2, props = __objRest(_a2, ["type", "children", "style"]);
7004
7742
  const domType = props.domType;
7005
7743
  if (domType !== void 0) delete props.domType;
7006
7744
  const nodeDefs = getDefs(node) || defs;
@@ -7008,7 +7746,7 @@ function renderNode(node, defs) {
7008
7746
  let childElements;
7009
7747
  if (children) {
7010
7748
  for (const ch of children) {
7011
- const child = renderNode(ch, nodeDefs);
7749
+ const child = renderNode(ch, nodeDefs, diag);
7012
7750
  if (child) {
7013
7751
  if (!childElements) childElements = [];
7014
7752
  childElements.push(child);
@@ -7020,31 +7758,39 @@ function renderNode(node, defs) {
7020
7758
  getNormalizedProps(props),
7021
7759
  resolvedStyle,
7022
7760
  childElements,
7023
- props[TEXT_CONTENT_ATTR] || props[TEXT_ATTR]
7761
+ props[TEXT_CONTENT_ATTR],
7762
+ diag
7024
7763
  );
7025
7764
  if (element && domType !== void 0) element.setAttribute("type", domType);
7026
7765
  return element;
7027
7766
  }
7028
7767
 
7029
- // src/PxAnimatorKeys.ts
7030
- var PX_ANIMATOR_DATA_KEY = "data";
7768
+ // src/shared/PxAnimatorKeys.ts
7769
+ var PX_ANIMATOR_DOC_KEY = "doc";
7031
7770
 
7032
- // src/PxAnimator.ts
7771
+ // src/animator/PxAnimator.ts
7033
7772
  function createAnimatorFromConfig(doc, adapter, callbacks, rootElement) {
7034
7773
  return bindWithEngineChoice(doc, adapter, callbacks, rootElement);
7035
7774
  }
7036
- function createAnimatorImpl(doc, adapter, callbacks, containerElement) {
7775
+ function createAnimatorImpl(doc, adapter, callbacks, containerElement, patch, resetTimeline) {
7776
+ const diag = createDiagnostics(callbacks, "[PxAnimator]");
7037
7777
  const effectsWarnings = validateNodeEffects(doc);
7038
- for (const w of effectsWarnings) console.warn("[PxAnimator] effects shape warning:", w);
7778
+ for (const w of effectsWarnings) diag.warn(PxDiagnosticKind.document, "effects shape: " + w);
7779
+ reportDocumentDiagnostics(doc, "[PxAnimator] createAnimator");
7780
+ if (patch !== void 0 || resetTimeline) {
7781
+ const patched = applyAnimatorConfig(doc, patch != null ? patch : {}, { resetDefaults: !!resetTimeline });
7782
+ for (const w of patched.warnings) diag.warn(PxDiagnosticKind.usage, "timeline override: " + w);
7783
+ doc = patched.doc;
7784
+ }
7039
7785
  const animatorConfig = getAnimatorConfig(doc) || {};
7040
- const engine = animatorConfig.mode === PxAnimatorMode.frames ? PxAnimatorEngine.frames : PxAnimatorEngine.waapi;
7041
- doc = materialiseAllInTree(doc, engine);
7786
+ const engine = resolveTimelineEngine(animatorConfig.engine);
7787
+ doc = materializeAllInTree(doc, engine);
7042
7788
  let rootElement = null;
7043
7789
  if (containerElement) {
7044
7790
  doc = generateNewIds(doc);
7045
7791
  const containerEl = typeof containerElement === "string" ? document.querySelector(containerElement) : containerElement;
7046
7792
  if (containerEl) {
7047
- rootElement = renderNode(doc);
7793
+ rootElement = renderNode(doc, void 0, diag);
7048
7794
  if (rootElement) {
7049
7795
  containerEl.replaceChildren(rootElement);
7050
7796
  }
@@ -7061,16 +7807,22 @@ function createAnimatorImpl(doc, adapter, callbacks, containerElement) {
7061
7807
  }
7062
7808
  return api;
7063
7809
  }
7810
+ function resolveTimelineOption(options) {
7811
+ const { timeline, duration, delay, iterations, startOn } = options;
7812
+ return foldTimelineOverride(timeline, { duration, delay, iterations, startOn });
7813
+ }
7064
7814
  function createAnimator(options) {
7065
- const { src, data, adapter, callbacks, container } = options;
7066
- if (data !== void 0 && src !== void 0) {
7067
- throw new Error("createAnimator: provide either `src` or `data`, not both");
7815
+ const { src, doc, adapter, container, resetTimeline } = options;
7816
+ const patch = resolveTimelineOption(options);
7817
+ const callbacks = toEngineCallbacks(options);
7818
+ if (doc !== void 0 && src !== void 0) {
7819
+ throw new Error("createAnimator: provide either `src` or `doc`, not both");
7068
7820
  }
7069
- if (data === void 0 && src === void 0) {
7070
- throw new Error("createAnimator: either `src` or `data` is required");
7821
+ if (doc === void 0 && src === void 0) {
7822
+ throw new Error("createAnimator: either `src` or `doc` is required");
7071
7823
  }
7072
- if (data !== void 0) {
7073
- return createAnimatorImpl(data, adapter, callbacks, container);
7824
+ if (doc !== void 0) {
7825
+ return createAnimatorImpl(doc, adapter, callbacks, container, patch, resetTimeline);
7074
7826
  }
7075
7827
  let animator = null;
7076
7828
  let pending = [];
@@ -7082,19 +7834,27 @@ function createAnimator(options) {
7082
7834
  pending.push(call);
7083
7835
  }
7084
7836
  };
7837
+ const loadDiag = createDiagnostics(callbacks, "[PxAnimator]");
7085
7838
  fetch(src).then((res) => res.json()).then((json) => {
7086
7839
  if (destroyed) return;
7087
7840
  if (isPxElementFileFormat(json)) {
7088
- animator = createAnimatorImpl(json, adapter, callbacks, container);
7841
+ animator = createAnimatorImpl(json, adapter, callbacks, container, patch, resetTimeline);
7089
7842
  const queued = pending;
7090
7843
  pending = null;
7091
7844
  queued == null ? void 0 : queued.forEach((call) => call(animator));
7092
7845
  } else {
7093
- console.error('createAnimator: invalid animation document format at "' + src + '"');
7846
+ loadDiag.error(
7847
+ PxDiagnosticKind.document,
7848
+ 'createAnimator: invalid animation document format at "' + src + '"'
7849
+ );
7094
7850
  }
7095
7851
  }).catch((err) => {
7852
+ var _a2;
7096
7853
  pending = null;
7097
- console.error('createAnimator: failed to load "' + src + '"', err);
7854
+ loadDiag.error(
7855
+ PxDiagnosticKind.host,
7856
+ 'createAnimator: failed to load "' + src + '" \u2014 ' + ((_a2 = err == null ? void 0 : err.message) != null ? _a2 : String(err))
7857
+ );
7098
7858
  });
7099
7859
  return {
7100
7860
  "isReady": () => !!animator,
@@ -7119,6 +7879,10 @@ function createAnimator(options) {
7119
7879
  "setCurrentTime": (time) => {
7120
7880
  enqueue((api) => api.setCurrentTime(time));
7121
7881
  },
7882
+ "getCurrentProgress": () => animator ? animator.getCurrentProgress() : null,
7883
+ "setCurrentProgress": (progress) => {
7884
+ enqueue((api) => api.setCurrentProgress(progress));
7885
+ },
7122
7886
  "destroy": () => {
7123
7887
  destroyed = true;
7124
7888
  pending = null;
@@ -7126,82 +7890,118 @@ function createAnimator(options) {
7126
7890
  }
7127
7891
  };
7128
7892
  }
7129
- function loadTagAnimators() {
7893
+ function loadTagAnimators(options) {
7130
7894
  const elements = document.querySelectorAll("[" + PX_ANIM_SRC_ATTR_NAME + "]");
7131
7895
  for (let i = 0; i < elements.length; i++) {
7132
7896
  const element = elements[i];
7133
7897
  if (!element[PX_ANIM_ATTR_NAME]) {
7134
7898
  const src = element.getAttribute(PX_ANIM_SRC_ATTR_NAME);
7135
7899
  if (src) {
7136
- element[PX_ANIM_ATTR_NAME] = createAnimator({ src, container: element });
7900
+ element[PX_ANIM_ATTR_NAME] = createAnimator(__spreadProps(__spreadValues({}, options), { src, container: element }));
7137
7901
  }
7138
7902
  }
7139
7903
  }
7140
7904
  }
7141
- if (typeof window !== "undefined") {
7142
- window["loadTagAnimators"] = loadTagAnimators;
7143
- window["createAnimator"] = createAnimator;
7144
- window["setupAnimationTriggers"] = setupAnimationTriggers;
7145
- }
7146
7905
  export {
7147
- COLOUR_ATTR_NAMES,
7906
+ BASELINE_PLAYER_VERSION,
7907
+ COLOR_ATTR_NAMES,
7908
+ DEFAULT_DURATION_MS,
7148
7909
  MISSING_GLYPH_CLASS_NAME,
7149
- PX_ANIMATOR_DATA_KEY,
7910
+ PLAYER_WIRE_STEPS,
7911
+ PLAYER_WIRE_VERSION,
7912
+ PX_ANIMATOR_DOC_KEY,
7150
7913
  PX_ANIM_ATTR_NAME,
7151
7914
  PX_ANIM_SRC_ATTR_NAME,
7915
+ PX_PLAYER_SCHEMA_VERSION,
7152
7916
  PX_TRANSFORM_PART_KEYS,
7917
+ PX_TRIGGER_DEFAULTS,
7918
+ PxAlongPathMode,
7153
7919
  PxAnimatedSvgDocumentSchema,
7154
7920
  PxAnimationDefinitionSchema,
7155
7921
  PxAnimatorConfigSchema,
7156
- PxAnimatorEngine,
7157
- PxAnimatorMode,
7158
7922
  PxAttrValueSchema,
7159
7923
  PxBezierPathSchema,
7160
7924
  PxBindingSchema,
7925
+ PxClipPathEffectSchema,
7161
7926
  PxCloneEffectSchema,
7927
+ PxCloneWithout,
7928
+ PxControlMode,
7162
7929
  PxDefsSchema,
7930
+ PxDiagnosticKind,
7163
7931
  PxEasingOrRefSchema,
7164
7932
  PxEffectsSchema,
7165
7933
  PxElementAnimationSchema,
7166
7934
  PxFillGradientEffectSchema,
7935
+ PxFinishAction,
7167
7936
  PxGradientSpreadMethod,
7168
7937
  PxGradientStopSchema,
7169
7938
  PxGradientType,
7170
- PxGradientUnits,
7171
7939
  PxKeyframeSchema,
7172
7940
  PxKeyframeValueSchema,
7941
+ PxLengthAdjust,
7942
+ PxLoopDirection,
7943
+ PxLoopRepeatAt,
7173
7944
  PxLoopSchema,
7945
+ PxMaskType,
7174
7946
  PxMaskedByEffectSchema,
7175
7947
  PxNodeBase,
7176
7948
  PxNodeSchema,
7949
+ PxPathOverflow,
7950
+ PxPinAlign,
7177
7951
  PxPropertyAnimationSchema,
7178
7952
  PxRepeaterEffectSchema,
7179
7953
  PxRetimeEffectSchema,
7954
+ PxScrollAxis,
7955
+ PxScrollKind,
7956
+ PxScrollPhase,
7957
+ PxScrollRangePointSchema,
7958
+ PxScrollRangeSchema,
7959
+ PxScrollSchema,
7960
+ PxScrollSource,
7180
7961
  PxStrokeGradientEffectSchema,
7181
7962
  PxStrokeTrimEffectSchema,
7963
+ PxStrokeTrimSubPaths,
7182
7964
  PxSvgNodeExtra,
7183
7965
  PxTextEffectSchema,
7184
7966
  PxTextPathEffectSchema,
7967
+ PxTextPathMethod,
7968
+ PxTextPathSpacing,
7969
+ PxTimelineEngine,
7970
+ PxTimelineEngineExtra,
7971
+ PxTimelinePinSchema,
7972
+ PxTimelineSchema,
7185
7973
  PxTransformByEffectSchema,
7186
7974
  PxTransformPartsSchema,
7187
7975
  PxTransformValueSchema,
7188
7976
  PxTriggerSchema,
7977
+ PxUnits,
7189
7978
  STYLE_ATTR_NAMES,
7190
7979
  TRANSFORM_FN_NAMES,
7980
+ WIRE_VERSION_KEY,
7981
+ WireStepKind,
7982
+ WireVersionRelation,
7983
+ applyAnimatorConfig,
7191
7984
  applyPlayerEffects,
7192
7985
  calcAnimationValues,
7193
7986
  camelCaseToKebabWordIfNeeded,
7194
7987
  collectSampleTimes,
7988
+ compareWireVersion,
7989
+ controlModeTakesOverTrigger,
7990
+ convertPlayerDocument,
7195
7991
  createAnimator,
7196
- createAnimatorImpl,
7197
7992
  createBasicFrameLoopAnimator,
7993
+ createDiagnostics,
7198
7994
  createFrameLoopAnimator,
7199
7995
  createPathSampler,
7200
7996
  createWebApiAnimator,
7201
7997
  describeSchema,
7998
+ diagnoseDocument,
7202
7999
  diffInEffect,
8000
+ downgradePlayerDocument,
7203
8001
  evaluateMotionPathSegment,
7204
8002
  extendedPathForBrowser,
8003
+ foldTimelineOverride,
8004
+ formatWireVersion,
7205
8005
  generateNewIds,
7206
8006
  getAnimatorConfig,
7207
8007
  getBindings,
@@ -7213,24 +8013,33 @@ export {
7213
8013
  jsonElementFactory,
7214
8014
  layoutGlyphTextChars,
7215
8015
  loadTagAnimators,
7216
- materialiseAllInTree,
7217
- materialiseAnimatedUseInstances,
7218
- materialiseGlyphText,
7219
- materialiseGlyphTextAlongPath,
7220
- materialiseGlyphTextHorizontal,
7221
- materialiseInternalLoopsInPropAnim,
7222
- materialiseInternalLoopsInTree,
7223
- materialiseMotionPathInPropAnim,
7224
- materialiseMotionPathsInTree,
7225
- getNormalisedBindings as normalizeDocument,
8016
+ materializeAllInTree,
8017
+ materializeAnimatedUseInstances,
8018
+ materializeGlyphText,
8019
+ materializeGlyphTextAlongPath,
8020
+ materializeGlyphTextHorizontal,
8021
+ materializeInternalLoopsInPropAnim,
8022
+ materializeInternalLoopsInTree,
8023
+ materializeMotionPathInPropAnim,
8024
+ materializeMotionPathsInTree,
8025
+ mergeAnimatorConfig,
8026
+ getNormalizedBindings as normalizeDocument,
8027
+ parseWireVersion,
8028
+ progressToTimeMs,
7226
8029
  propAnimIsMotionPath,
7227
8030
  px,
8031
+ readWireVersion,
7228
8032
  renderNode,
8033
+ resolveControlMode,
8034
+ resolveTrigger,
7229
8035
  schemaKeys,
7230
8036
  setupAnimationTriggers,
7231
8037
  shiftAnimatable,
8038
+ timeToProgress,
7232
8039
  toRGBA,
8040
+ validateDocument,
7233
8041
  validateNodeEffects,
8042
+ versionAdvice,
7234
8043
  visualModelAt
7235
8044
  };
7236
8045
  //# sourceMappingURL=index.js.map