@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.
@@ -51,21 +51,21 @@ var PixodeskAnimator = (() => {
51
51
  // src/index.player.ts
52
52
  var index_player_exports = {};
53
53
  __export(index_player_exports, {
54
- PX_ANIMATOR_DATA_KEY: () => PX_ANIMATOR_DATA_KEY,
54
+ PX_ANIMATOR_DOC_KEY: () => PX_ANIMATOR_DOC_KEY,
55
55
  PX_ANIM_ATTR_NAME: () => PX_ANIM_ATTR_NAME,
56
56
  PX_ANIM_SRC_ATTR_NAME: () => PX_ANIM_SRC_ATTR_NAME,
57
- PxAnimatorEngine: () => PxAnimatorEngine,
58
- PxAnimatorMode: () => PxAnimatorMode,
57
+ PxTimelineEngine: () => PxTimelineEngine,
58
+ PxTimelineEngineExtra: () => PxTimelineEngineExtra,
59
59
  createAnimator: () => createAnimator,
60
- createAnimatorImpl: () => createAnimatorImpl,
61
60
  generateNewIds: () => generateNewIds,
62
61
  loadTagAnimators: () => loadTagAnimators,
63
- setupAnimationTriggers: () => setupAnimationTriggers
62
+ setupAnimationTriggers: () => setupAnimationTriggers,
63
+ validateDocument: () => validateDocument
64
64
  });
65
65
 
66
- // ../svg-animator-core/src/PxAnimatorUtil.ts
66
+ // ../svg-animator-core/src/util/PxAnimatorUtil.ts
67
67
  function bezierToSvgPath(path, forceCurves = false) {
68
- var _a, _b, _c, _d;
68
+ var _a2, _b, _c, _d;
69
69
  const v = path.v;
70
70
  const i = path.i;
71
71
  const o = path.o;
@@ -76,7 +76,7 @@ var PixodeskAnimator = (() => {
76
76
  d.push("M" + v[0][0] + "," + v[0][1]);
77
77
  for (let idx = 1; idx < len; idx++) {
78
78
  const prevV = v[idx - 1];
79
- const prevO = (_a = o == null ? void 0 : o[idx - 1]) != null ? _a : prevV;
79
+ const prevO = (_a2 = o == null ? void 0 : o[idx - 1]) != null ? _a2 : prevV;
80
80
  const currI = (_b = i == null ? void 0 : i[idx]) != null ? _b : v[idx];
81
81
  const currV = v[idx];
82
82
  const isLine = !forceCurves && (prevO[0] === prevV[0] && prevO[1] === prevV[1]) && (currI[0] === currV[0] && currI[1] === currV[1]);
@@ -127,7 +127,7 @@ var PixodeskAnimator = (() => {
127
127
  return res;
128
128
  }
129
129
  function interpolateBezier(path1, path2, progress) {
130
- var _a, _b, _c, _d, _e, _f, _g, _h, _i;
130
+ var _a2, _b, _c, _d, _e, _f, _g, _h, _i;
131
131
  if (!path1 || !path2) return path1 || path2 || { v: [] };
132
132
  const t = Math.min(Math.max(progress, 0), 1);
133
133
  const len = Math.min(path1.v.length, path2.v.length);
@@ -138,7 +138,7 @@ var PixodeskAnimator = (() => {
138
138
  const v1 = path1.v[idx];
139
139
  const v2 = path2.v[idx];
140
140
  v.push(interpolateVec(v1, v2, t));
141
- const i1 = (_b = (_a = path1.i) == null ? void 0 : _a[idx]) != null ? _b : v1;
141
+ const i1 = (_b = (_a2 = path1.i) == null ? void 0 : _a2[idx]) != null ? _b : v1;
142
142
  const i2 = (_d = (_c = path2.i) == null ? void 0 : _c[idx]) != null ? _d : v2;
143
143
  i.push(interpolateVec(i1, i2, t));
144
144
  const o1 = (_f = (_e = path1.o) == null ? void 0 : _e[idx]) != null ? _f : v1;
@@ -257,8 +257,8 @@ var PixodeskAnimator = (() => {
257
257
  return color.length === 4 ? "rgba(" + r + "," + g + "," + b + "," + color[3] + ")" : "rgb(" + r + "," + g + "," + b + ")";
258
258
  }
259
259
  function parseRgba(s) {
260
- var _a;
261
- const inner = (_a = s.match(/rgba?\((.*)\)/)) == null ? void 0 : _a[1];
260
+ var _a2;
261
+ const inner = (_a2 = s.match(/rgba?\((.*)\)/)) == null ? void 0 : _a2[1];
262
262
  if (!inner) throw new Error("Invalid rgb/rgba format");
263
263
  const parts = inner.split(",").map((v) => +v.trim());
264
264
  return [parts[0] / 255, parts[1] / 255, parts[2] / 255, ...parts[3] !== void 0 ? [parts[3]] : []];
@@ -293,13 +293,13 @@ var PixodeskAnimator = (() => {
293
293
  }
294
294
  return void 0;
295
295
  }
296
- var COLOUR_ATTR_NAMES = /* @__PURE__ */ new Set(["color", "fill", "flood-color", "lighting-color", "stop-color", "stroke"]);
296
+ var COLOR_ATTR_NAMES = /* @__PURE__ */ new Set(["color", "fill", "flood-color", "lighting-color", "stop-color", "stroke"]);
297
297
  var TRANSFORM_FN_NAMES = /* @__PURE__ */ new Set(["translate", "rotate", "scale", "skew"]);
298
298
  var PCT_BASED_ATTR_NAMES = /* @__PURE__ */ new Set(["offset-distance", "offsetDistance"]);
299
299
  function composeTransformParts(parts, opts) {
300
- var _a;
300
+ var _a2;
301
301
  if (!parts) return "";
302
- const withUnits = (_a = opts == null ? void 0 : opts.withUnits) != null ? _a : true;
302
+ const withUnits = (_a2 = opts == null ? void 0 : opts.withUnits) != null ? _a2 : true;
303
303
  const segs = [];
304
304
  const t = parts.translate;
305
305
  const o = parts.origin;
@@ -317,7 +317,7 @@ var PixodeskAnimator = (() => {
317
317
  return segs.join("");
318
318
  }
319
319
  function parseTransformParts(str2) {
320
- var _a, _b;
320
+ var _a2, _b;
321
321
  if (!str2 || typeof str2 !== "string") return void 0;
322
322
  const out = {};
323
323
  const re = /([a-zA-Z]+)\s*\(([^)]*)\)/g;
@@ -333,7 +333,7 @@ var PixodeskAnimator = (() => {
333
333
  if (nums.some((n) => Number.isNaN(n))) return void 0;
334
334
  if (fn === "translate") {
335
335
  if (nums.length < 1 || nums.length > 2) return void 0;
336
- out.translate = [nums[0], (_a = nums[1]) != null ? _a : 0];
336
+ out.translate = [nums[0], (_a2 = nums[1]) != null ? _a2 : 0];
337
337
  } else if (fn === "rotate") {
338
338
  if (nums.length !== 1) return void 0;
339
339
  out.rotate = nums[0];
@@ -511,7 +511,7 @@ var PixodeskAnimator = (() => {
511
511
  return cubicBezier(flipped);
512
512
  }
513
513
 
514
- // ../svg-animator-core/src/PxScrollMath.ts
514
+ // ../svg-animator-core/src/playback/PxScrollMath.ts
515
515
  function isScrollTimeline(config) {
516
516
  return (config == null ? void 0 : config.timelineSource) === "scroll";
517
517
  }
@@ -539,8 +539,8 @@ var PixodeskAnimator = (() => {
539
539
  }
540
540
  var DEFAULT_PHASE = "cover";
541
541
  function resolveRangePointU(point, defaultFraction, subjectSize, scrollportSize) {
542
- var _a;
543
- const [u0, u1] = scrollPhaseInterval((_a = point == null ? void 0 : point.phase) != null ? _a : DEFAULT_PHASE, subjectSize, scrollportSize);
542
+ var _a2;
543
+ const [u0, u1] = scrollPhaseInterval((_a2 = point == null ? void 0 : point.phase) != null ? _a2 : DEFAULT_PHASE, subjectSize, scrollportSize);
544
544
  const fraction = typeof (point == null ? void 0 : point.fraction) === "number" ? point.fraction : defaultFraction;
545
545
  return u0 + fraction * (u1 - u0);
546
546
  }
@@ -552,9 +552,9 @@ var PixodeskAnimator = (() => {
552
552
  return clamp((u - uStart) / (uEnd - uStart), 0, 1);
553
553
  }
554
554
  function scrollOffsetProgress(offset, maxOffset, range) {
555
- var _a, _b;
555
+ var _a2, _b;
556
556
  const raw = maxOffset > 0 ? clamp(offset / maxOffset, 0, 1) : 1;
557
- const start = typeof ((_a = range == null ? void 0 : range.start) == null ? void 0 : _a.fraction) === "number" ? range.start.fraction : 0;
557
+ const start = typeof ((_a2 = range == null ? void 0 : range.start) == null ? void 0 : _a2.fraction) === "number" ? range.start.fraction : 0;
558
558
  const end = typeof ((_b = range == null ? void 0 : range.end) == null ? void 0 : _b.fraction) === "number" ? range.end.fraction : 1;
559
559
  if (end <= start) return raw >= end ? 1 : 0;
560
560
  return clamp((raw - start) / (end - start), 0, 1);
@@ -567,7 +567,8 @@ var PixodeskAnimator = (() => {
567
567
  return vertical ? "x" : "y";
568
568
  }
569
569
 
570
- // ../svg-animator-core/src/PxSchema.ts
570
+ // ../svg-animator-core/src/schema/PxSchema.ts
571
+ var PX_UNKNOWN_KEY_ERROR = "unexpected extra key";
571
572
  function pathStr(path) {
572
573
  if (!path.length) return ".";
573
574
  let result = "";
@@ -675,6 +676,7 @@ var PixodeskAnimator = (() => {
675
676
  return false;
676
677
  }
677
678
  };
679
+ var UNION_MEMBER_ERROR_LIMIT = 4;
678
680
  var Union = class extends Base {
679
681
  constructor(schemas, defaultVal) {
680
682
  super();
@@ -690,10 +692,38 @@ var PixodeskAnimator = (() => {
690
692
  return this._default;
691
693
  }
692
694
  isValid(raw, ctx, path) {
693
- var _a;
695
+ var _a2;
694
696
  const probe = ctx && { errors: [], warnings: [], strict: ctx.strict };
695
697
  if (this.schemas.some((s) => s.isValid(raw, probe, path ? [...path] : void 0))) return true;
696
- 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));
698
+ if (!ctx) return false;
699
+ const base = pathStr(path != null ? path : []);
700
+ ctx.errors.push(base + ": no union member matched for value " + ((_a2 = JSON.stringify(raw)) != null ? _a2 : "").slice(0, 240));
701
+ let best;
702
+ let bestDepth = -1;
703
+ const leafExpectations = [];
704
+ for (const member of this.schemas) {
705
+ const sink = { errors: [], warnings: [], strict: ctx.strict };
706
+ member.isValid(raw, sink, path ? [...path] : void 0);
707
+ if (!sink.errors.length) continue;
708
+ const depth = Math.max(...sink.errors.map((e) => e.slice(0, e.indexOf(":")).length));
709
+ if (depth > bestDepth || depth === bestDepth && best && sink.errors.length < best.length) {
710
+ bestDepth = depth;
711
+ best = sink.errors;
712
+ }
713
+ if (depth <= base.length) {
714
+ for (const e of sink.errors) {
715
+ const m = /: expected (.+?), got /.exec(e);
716
+ if (m && !leafExpectations.includes(m[1])) leafExpectations.push(m[1]);
717
+ }
718
+ }
719
+ }
720
+ if (best && bestDepth > base.length) {
721
+ for (const e of best.slice(0, UNION_MEMBER_ERROR_LIMIT)) {
722
+ if (!ctx.errors.includes(e)) ctx.errors.push(e);
723
+ }
724
+ } else if (leafExpectations.length) {
725
+ ctx.errors.push(base + ": expected " + leafExpectations.join(" | "));
726
+ }
697
727
  return false;
698
728
  }
699
729
  _canSanitize(raw) {
@@ -702,6 +732,7 @@ var PixodeskAnimator = (() => {
702
732
  };
703
733
  var DiscriminatedUnion = class extends Base {
704
734
  constructor(_key, _schemas, defaultVal) {
735
+ var _a2;
705
736
  super();
706
737
  this._key = _key;
707
738
  this._schemas = _schemas;
@@ -711,18 +742,21 @@ var PixodeskAnimator = (() => {
711
742
  this._map = /* @__PURE__ */ new Map();
712
743
  for (const s of _schemas) {
713
744
  const keySchema = s._shape[_key];
714
- if (keySchema) this._map.set(keySchema._default, s);
745
+ if (!keySchema) continue;
746
+ const literal = (_a2 = keySchema.inner) != null ? _a2 : keySchema;
747
+ this._map.set(literal._default, s);
748
+ if (keySchema.inner) this._absentMember = s;
715
749
  }
716
750
  }
717
751
  _findSchema(raw) {
718
752
  if (raw === null || typeof raw !== "object" || Array.isArray(raw)) return void 0;
719
753
  const val = raw[this._key];
720
- if (val === void 0 || val === null) return void 0;
754
+ if (val === void 0 || val === null) return this._absentMember;
721
755
  return this._map.get(val);
722
756
  }
723
757
  sanitize(raw) {
724
- var _a;
725
- return ((_a = this._findSchema(raw)) != null ? _a : this._schemas[0]).sanitize(raw);
758
+ var _a2;
759
+ return ((_a2 = this._findSchema(raw)) != null ? _a2 : this._schemas[0]).sanitize(raw);
726
760
  }
727
761
  isValid(raw, ctx, path) {
728
762
  const schema = this._findSchema(raw);
@@ -751,7 +785,8 @@ var PixodeskAnimator = (() => {
751
785
  const src = raw && typeof raw === "object" && !Array.isArray(raw) ? raw : {};
752
786
  const out = {};
753
787
  for (const key of Object.keys(this._shape)) {
754
- out[key] = this._shape[key].sanitize(src[key]);
788
+ const v = this._shape[key].sanitize(src[key]);
789
+ if (v !== void 0) out[key] = v;
755
790
  }
756
791
  return out;
757
792
  }
@@ -773,7 +808,7 @@ var PixodeskAnimator = (() => {
773
808
  if (key in this._shape) continue;
774
809
  if (obj[key] === void 0) continue;
775
810
  p.push(key);
776
- ctx.errors.push(pathStr(p) + ": unexpected extra key");
811
+ ctx.errors.push(pathStr(p) + ": " + PX_UNKNOWN_KEY_ERROR);
777
812
  p.pop();
778
813
  ok = false;
779
814
  }
@@ -797,7 +832,8 @@ var PixodeskAnimator = (() => {
797
832
  const src = raw && typeof raw === "object" && !Array.isArray(raw) ? raw : {};
798
833
  const out = __spreadValues({}, src);
799
834
  for (const key of Object.keys(this._shape)) {
800
- out[key] = this._shape[key].sanitize(src[key]);
835
+ const v = this._shape[key].sanitize(src[key]);
836
+ if (v !== void 0) out[key] = v;
801
837
  }
802
838
  if (this._openSchema) {
803
839
  for (const key of Object.keys(src)) {
@@ -939,8 +975,8 @@ var PixodeskAnimator = (() => {
939
975
  this.resolved = null;
940
976
  }
941
977
  get schema() {
942
- var _a;
943
- return (_a = this.resolved) != null ? _a : this.resolved = this.fn();
978
+ var _a2;
979
+ return (_a2 = this.resolved) != null ? _a2 : this.resolved = this.fn();
944
980
  }
945
981
  sanitize(raw) {
946
982
  return this.schema.sanitize(raw);
@@ -1038,25 +1074,135 @@ var PixodeskAnimator = (() => {
1038
1074
  lazy: (fn, defaultVal) => new Lazy(fn, defaultVal)
1039
1075
  };
1040
1076
 
1041
- // ../svg-animator-core/src/PxAnimatorConstants.ts
1077
+ // ../svg-animator-core/src/version/PxSchemaVersion.ts
1078
+ var PX_PLAYER_SCHEMA_VERSION = "1.1";
1079
+
1080
+ // ../svg-animator-core/src/version/PxWireVersion.ts
1081
+ var VERSION_RE = /^(\d+)\.(\d+)(?:\.(\d+))?$/;
1082
+ function parseWireVersion(raw) {
1083
+ if (typeof raw !== "string") return void 0;
1084
+ const m = VERSION_RE.exec(raw.trim());
1085
+ if (!m) return void 0;
1086
+ return { a: Number(m[1]), b: Number(m[2]), c: m[3] === void 0 ? 0 : Number(m[3]) };
1087
+ }
1088
+ var _a;
1089
+ var PLAYER_WIRE_VERSION = (_a = parseWireVersion(PX_PLAYER_SCHEMA_VERSION)) != null ? _a : { a: 1, b: 1, c: 0 };
1090
+
1091
+ // ../svg-animator-core/src/format/PxAnimatorConstants.ts
1092
+ var PxFillMode = {
1093
+ forwards: "forwards",
1094
+ backwards: "backwards",
1095
+ both: "both",
1096
+ none: "none"
1097
+ };
1098
+ var PxPlaybackDirection = {
1099
+ normal: "normal",
1100
+ reverse: "reverse",
1101
+ alternate: "alternate",
1102
+ alternateReverse: "alternate-reverse"
1103
+ };
1042
1104
  var PX_ANIM_SRC_ATTR_NAME = "data-px-animation-src";
1043
1105
  var PX_ANIM_ATTR_NAME = "_px_animator";
1044
- var PxAnimatorMode = {
1045
- auto: "auto",
1046
- waapi: "waapi",
1047
- frames: "frames"
1106
+ var PxStartOn = {
1107
+ load: "load",
1108
+ mouseOver: "mouseOver",
1109
+ click: "click",
1110
+ scrollIntoView: "scrollIntoView",
1111
+ programmatic: "programmatic"
1048
1112
  };
1049
- var PxAnimatorEngine = {
1050
- waapi: PxAnimatorMode.waapi,
1051
- frames: PxAnimatorMode.frames
1113
+ var PxOutAction = {
1114
+ continue: "continue",
1115
+ pause: "pause",
1116
+ reset: "reset",
1117
+ reverse: "reverse"
1052
1118
  };
1053
- var PxLoopExtend = {
1054
- /** Segment from the START; the animation is extended BEFORE the first keyframe
1055
- * (intro loops that run before the main timeline begins). */
1056
- before: "before",
1057
- /** DEFAULT — segment from the END; extended AFTER the last keyframe (idle/outro
1058
- * loops that continue once the main timeline has finished). */
1059
- after: "after"
1119
+ var PxFinishAction = {
1120
+ hold: "hold",
1121
+ reset: "reset"
1122
+ };
1123
+ var PxScrollKind = {
1124
+ view: "view",
1125
+ scroll: "scroll"
1126
+ };
1127
+ var PxScrollAxis = {
1128
+ block: "block",
1129
+ inline: "inline",
1130
+ x: "x",
1131
+ y: "y"
1132
+ };
1133
+ var PxScrollSource = {
1134
+ nearest: "nearest",
1135
+ root: "root"
1136
+ };
1137
+ var PxPinAlign = {
1138
+ top: "top",
1139
+ center: "center",
1140
+ bottom: "bottom"
1141
+ };
1142
+ var PxScrollPhase = {
1143
+ cover: "cover",
1144
+ contain: "contain",
1145
+ entry: "entry",
1146
+ exit: "exit",
1147
+ entryCrossing: "entry-crossing",
1148
+ exitCrossing: "exit-crossing"
1149
+ };
1150
+ var PxAlongPathMode = {
1151
+ sampled: "sampled",
1152
+ offsetPath: "offsetPath"
1153
+ };
1154
+ var PX_TIMELINE_SHARED_KEYS = ["duration", "iterations", "engine", "frameRate"];
1155
+ var PX_TIME_ONLY_TIMELINE_KEYS = ["trigger", "delay", "fillMode", "direction"];
1156
+ var PX_FLAT_RUNTIME_VIEW_KEYS = [
1157
+ ...PX_TIMELINE_SHARED_KEYS,
1158
+ ...PX_TIME_ONLY_TIMELINE_KEYS,
1159
+ "fill",
1160
+ "resetOnFinish",
1161
+ "timelineSource",
1162
+ "scroll"
1163
+ ];
1164
+ var PxTimelineEngine = {
1165
+ native: "native",
1166
+ js: "js"
1167
+ };
1168
+ var PxTimelineEngineExtra = __spreadProps(__spreadValues({}, PxTimelineEngine), {
1169
+ auto: "auto"
1170
+ });
1171
+ function resolveTimelineEngine(engine) {
1172
+ return engine === PxTimelineEngineExtra.js ? PxTimelineEngine.js : PxTimelineEngine.native;
1173
+ }
1174
+ function isNativeForced(engine) {
1175
+ return engine === PxTimelineEngineExtra.native;
1176
+ }
1177
+ function mayUseNativeScrollTimeline(engine) {
1178
+ return engine !== PxTimelineEngineExtra.js;
1179
+ }
1180
+ var PX_TRIGGER_DEFAULTS = {
1181
+ startOn: "load",
1182
+ outAction: "continue",
1183
+ scrollIntoViewThreshold: 0
1184
+ };
1185
+ function resolveTrigger(trigger) {
1186
+ var _a2, _b, _c;
1187
+ return {
1188
+ startOn: (_a2 = trigger == null ? void 0 : trigger.startOn) != null ? _a2 : PX_TRIGGER_DEFAULTS.startOn,
1189
+ outAction: (_b = trigger == null ? void 0 : trigger.outAction) != null ? _b : PX_TRIGGER_DEFAULTS.outAction,
1190
+ scrollIntoViewThreshold: (_c = trigger == null ? void 0 : trigger.scrollIntoViewThreshold) != null ? _c : PX_TRIGGER_DEFAULTS.scrollIntoViewThreshold
1191
+ };
1192
+ }
1193
+ var PxLoopRepeatAt = {
1194
+ /** Segment from the START; the repetition runs BEFORE the first keyframe
1195
+ * (intro loops that play until the main timeline begins). */
1196
+ start: "start",
1197
+ /** DEFAULT — segment from the END; the repetition runs AFTER the last keyframe
1198
+ * (idle/outro loops that continue once the main timeline has finished). */
1199
+ end: "end"
1200
+ };
1201
+ var PxLoopDirection = {
1202
+ /** DEFAULT — cycle: every repetition replays the segment the same way round. */
1203
+ normal: "normal",
1204
+ /** Ping-pong: repetitions alternate forward / backward. */
1205
+ alternate: "alternate"
1060
1206
  };
1061
1207
  var PxMaskType = {
1062
1208
  luminance: "luminance",
@@ -1066,8 +1212,9 @@ var PixodeskAnimator = (() => {
1066
1212
  userSpaceOnUse: "userSpaceOnUse",
1067
1213
  objectBoundingBox: "objectBoundingBox"
1068
1214
  };
1069
- var PxCloneType = {
1070
- content: "content"
1215
+ var PxCloneWithout = {
1216
+ translate: "translate"
1217
+ // transform: 'transform', // future: drop rotate/scale too (content only)
1071
1218
  };
1072
1219
  var PxPathOverflow = {
1073
1220
  clip: "clip",
@@ -1089,8 +1236,10 @@ var PixodeskAnimator = (() => {
1089
1236
  separate: "separate",
1090
1237
  combined: "combined"
1091
1238
  };
1092
- var TEXT_ATTR = "text";
1093
1239
  var TEXT_CONTENT_ATTR = "textContent";
1240
+ var CLASS_ATTR = "class";
1241
+ var TRANSFORM_ATTR = "transform";
1242
+ var OFFSET_DISTANCE_ATTR = "offsetDistance";
1094
1243
  var INTERNAL_ATTRS = /* @__PURE__ */ new Set([
1095
1244
  "type",
1096
1245
  "children",
@@ -1098,13 +1247,20 @@ var PixodeskAnimator = (() => {
1098
1247
  "meta",
1099
1248
  "animate",
1100
1249
  "effects",
1101
- TEXT_ATTR,
1102
1250
  TEXT_CONTENT_ATTR
1103
1251
  ]);
1104
- var PxGradientUnits = {
1105
- userSpaceOnUse: "userSpaceOnUse",
1106
- objectBoundingBox: "objectBoundingBox"
1252
+ var TRANSFORM_PART = {
1253
+ translate: "translate",
1254
+ rotate: "rotate",
1255
+ scale: "scale",
1256
+ origin: "origin"
1107
1257
  };
1258
+ var PX_TRANSFORM_PART_KEYS = [
1259
+ TRANSFORM_PART.translate,
1260
+ TRANSFORM_PART.rotate,
1261
+ TRANSFORM_PART.scale,
1262
+ TRANSFORM_PART.origin
1263
+ ];
1108
1264
  var PxGradientSpreadMethod = {
1109
1265
  pad: "pad",
1110
1266
  reflect: "reflect",
@@ -1118,27 +1274,38 @@ var PixodeskAnimator = (() => {
1118
1274
  if (!(fileJson && typeof fileJson === "object" && !Array.isArray(fileJson))) {
1119
1275
  return false;
1120
1276
  }
1121
- return fileJson["type"] === "svg";
1277
+ return fileJson.type === "svg";
1122
1278
  }
1123
1279
  function getAnimatorConfig(doc) {
1124
- var _a;
1125
- const cfg = (doc == null ? void 0 : doc.animator) || ((_a = doc == null ? void 0 : doc.meta) == null ? void 0 : _a.animator);
1126
- return cfg ? flattenAnimatorTimeline(cfg) : void 0;
1127
- }
1280
+ var _a2;
1281
+ const cfg = (doc == null ? void 0 : doc.animator) || ((_a2 = doc == null ? void 0 : doc.meta) == null ? void 0 : _a2.animator);
1282
+ if (!cfg) return void 0;
1283
+ const memoised = wireViewMemo.get(cfg);
1284
+ if (memoised) return memoised;
1285
+ const wire = cfg;
1286
+ const stray = PX_FLAT_RUNTIME_VIEW_KEYS.filter((k) => wire[k] !== void 0);
1287
+ const source = stray.length ? __spreadValues({}, wire) : cfg;
1288
+ for (const k of stray) delete source[k];
1289
+ const view = flattenAnimatorTimeline(source);
1290
+ wireViewMemo.set(cfg, view);
1291
+ return view;
1292
+ }
1293
+ var wireViewMemo = /* @__PURE__ */ new WeakMap();
1128
1294
  var flattenMemo = /* @__PURE__ */ new WeakMap();
1129
1295
  function flattenAnimatorTimeline(cfg) {
1130
1296
  const timeline = cfg.timeline;
1131
1297
  if (timeline === void 0 || timeline === null || typeof timeline !== "object") return cfg;
1132
1298
  const memoised = flattenMemo.get(cfg);
1133
1299
  if (memoised) return memoised;
1134
- const _a = cfg, { timeline: _dropped } = _a, flat = __objRest(_a, ["timeline"]);
1300
+ const _a2 = cfg, { timeline: _dropped } = _a2, flat = __objRest(_a2, ["timeline"]);
1301
+ if (timeline.engine !== void 0) flat.engine = timeline.engine;
1302
+ if (timeline.frameRate !== void 0) flat.frameRate = timeline.frameRate;
1135
1303
  if (timeline.type === "scroll" || timeline.type === "view") {
1136
1304
  flat.timelineSource = "scroll";
1137
1305
  if (timeline.duration !== void 0) flat.duration = timeline.duration;
1138
1306
  if (timeline.iterations !== void 0) flat.iterations = timeline.iterations;
1139
1307
  const scroll = __spreadValues({}, flat.scroll || {});
1140
1308
  scroll.kind = timeline.type;
1141
- if (timeline.engine !== void 0) scroll.driver = timeline.engine;
1142
1309
  if (timeline.axis !== void 0) scroll.axis = timeline.axis;
1143
1310
  if (timeline.source !== void 0) scroll.source = timeline.source;
1144
1311
  if (timeline.subject !== void 0) scroll.subject = timeline.subject;
@@ -1149,39 +1316,39 @@ var PixodeskAnimator = (() => {
1149
1316
  else if (pin && typeof pin === "object") {
1150
1317
  scroll.pin = true;
1151
1318
  if (pin.align !== void 0) scroll.pinAlign = pin.align;
1152
- if (pin.top !== void 0) scroll.pinTop = pin.top;
1319
+ if (pin.offset !== void 0) scroll.pinOffset = pin.offset;
1153
1320
  if (pin.distance !== void 0) scroll.pinDistance = pin.distance;
1154
1321
  }
1155
1322
  flat.scroll = scroll;
1156
1323
  } else {
1157
1324
  if (timeline.duration !== void 0) flat.duration = timeline.duration;
1158
1325
  if (timeline.trigger !== void 0) {
1159
- const _b = timeline.trigger, { onFinish } = _b, restTrigger = __objRest(_b, ["onFinish"]);
1326
+ const _b = timeline.trigger, { finishAction } = _b, restTrigger = __objRest(_b, ["finishAction"]);
1160
1327
  if (Object.keys(restTrigger).length) flat.trigger = restTrigger;
1161
- if (onFinish !== void 0) flat.resetOnFinish = onFinish === "reset";
1328
+ if (finishAction !== void 0) flat.resetOnFinish = finishAction === "reset";
1162
1329
  }
1163
1330
  if (timeline.delay !== void 0) flat.delay = timeline.delay;
1164
1331
  if (timeline.iterations !== void 0) flat.iterations = timeline.iterations;
1165
1332
  if (timeline.direction !== void 0) flat.direction = timeline.direction;
1166
- if (timeline.fill !== void 0) flat.fill = timeline.fill;
1333
+ if (timeline.fillMode !== void 0) flat.fill = timeline.fillMode;
1167
1334
  }
1168
1335
  flattenMemo.set(cfg, flat);
1169
1336
  return flat;
1170
1337
  }
1171
1338
  function getDefs(doc) {
1172
- var _a;
1339
+ var _a2;
1173
1340
  if (!doc) return void 0;
1174
- return (_a = getAnimatorConfig(doc)) == null ? void 0 : _a.definitions;
1341
+ return (_a2 = getAnimatorConfig(doc)) == null ? void 0 : _a2.definitions;
1175
1342
  }
1176
1343
  function getBindings(doc) {
1177
- var _a;
1344
+ var _a2;
1178
1345
  if (!doc) return void 0;
1179
- const animateById = (_a = getAnimatorConfig(doc)) == null ? void 0 : _a.animateById;
1346
+ const animateById = (_a2 = getAnimatorConfig(doc)) == null ? void 0 : _a2.animateById;
1180
1347
  if (!animateById) return void 0;
1181
1348
  return Object.entries(animateById).map(([id, anim]) => ({ id: id.startsWith("#") ? id.slice(1) : id, animate: anim }));
1182
1349
  }
1183
1350
 
1184
- // ../svg-animator-core/src/PxAnimatorTypes.ts
1351
+ // ../svg-animator-core/src/format/PxAnimatorTypes.ts
1185
1352
  var PxEasingOrRefSchema = px.union([
1186
1353
  px.string(),
1187
1354
  px.tuple([px.number(), px.number(), px.number(), px.number()])
@@ -1191,14 +1358,13 @@ var PixodeskAnimator = (() => {
1191
1358
  // e.g. for colors
1192
1359
  px.number(),
1193
1360
  px.array(px.number()),
1194
- // ORDER LAW: the key-discriminated object shapes (`{path}`, `{paths}`) come BEFORE the
1361
+ // ORDER LAW: the key-discriminated object shape (`{pathData}`) comes BEFORE the
1195
1362
  // all-optional transform-parts record. In default (non-strict) mode that record accepts
1196
1363
  // ANY object (every key optional, unknown keys ignored), so listing it earlier made
1197
- // Union.sanitize route `{path}`/`{paths}` values into it and strip them to `{}` —
1364
+ // Union.sanitize route `{pathData}` values into it and strip them to `{}` —
1198
1365
  // silent morph-data loss (repro: the editor's keyframeValueSanitize spec). Validity is
1199
1366
  // order-independent (`some()`); only sanitize routing depends on this order.
1200
- px.object({ path: px.string() }),
1201
- px.lazy(() => px.object({ paths: px.array(PxBezierPathSchema) }), { paths: [] }),
1367
+ px.object({ pathData: px.string() }),
1202
1368
  // Gradient `stops` timeline — each kf value is the full stops-array snapshot.
1203
1369
  px.lazy(() => px.array(PxGradientStopSchema), []),
1204
1370
  px.lazy(() => PxTransformPartsSchema, {})
@@ -1213,16 +1379,32 @@ var PixodeskAnimator = (() => {
1213
1379
  // (review §1.3): editor data lives under `meta`. The editor still carries it on
1214
1380
  // its internal COPY-PASTE payload, which never validates against this schema.)
1215
1381
  }));
1382
+ var anyKf = (kf) => kf;
1383
+ var kfTime = (kf) => {
1384
+ var _a2, _b;
1385
+ return (_b = (_a2 = anyKf(kf).time) != null ? _a2 : anyKf(kf).t) != null ? _b : 0;
1386
+ };
1387
+ var kfValue = (kf) => {
1388
+ var _a2;
1389
+ return (_a2 = anyKf(kf).value) != null ? _a2 : anyKf(kf).v;
1390
+ };
1391
+ var kfEasing = (kf) => {
1392
+ var _a2;
1393
+ return (_a2 = anyKf(kf).easing) != null ? _a2 : anyKf(kf).e;
1394
+ };
1395
+ var kfTangentIn = (kf) => anyKf(kf).tangentIn;
1396
+ var kfTangentOut = (kf) => anyKf(kf).tangentOut;
1216
1397
  var PxLoopSchema = implementsInterface()(px.object({
1217
1398
  segmentCount: px.number().optional(),
1218
- extend: px.enum([PxLoopExtend.before, PxLoopExtend.after]).optional(),
1219
- alternate: px.boolean().optional()
1399
+ repeatAt: px.enum([PxLoopRepeatAt.start, PxLoopRepeatAt.end]).optional(),
1400
+ direction: px.enum([PxLoopDirection.normal, PxLoopDirection.alternate]).optional()
1220
1401
  }));
1221
1402
  var PxPropertyAnimationSchema = implementsInterface()(px.object({
1222
1403
  value: PxKeyframeValueSchema.optional(),
1223
1404
  keyframes: px.array(PxKeyframeSchema).optional(),
1224
1405
  loop: px.union([PxLoopSchema, px.boolean()]).optional(),
1225
- autoOrient: px.boolean().optional()
1406
+ autoOrient: px.boolean().optional(),
1407
+ alongPathMode: px.enum([PxAlongPathMode.sampled, PxAlongPathMode.offsetPath]).optional()
1226
1408
  }));
1227
1409
  var PxTransformPartsSchema = implementsInterface()(px.object({
1228
1410
  translate: px.tuple([px.number(), px.number()]).optional(),
@@ -1246,18 +1428,17 @@ var PixodeskAnimator = (() => {
1246
1428
  PxAnimationDefinitionSchema
1247
1429
  ]));
1248
1430
  var PxTriggerSchema = implementsInterface()(px.object({
1249
- startOn: px.enum(["load", "mouseOver", "click", "scrollIntoView", "programmatic"]).optional(),
1250
- outAction: px.enum(["continue", "pause", "reset", "reverse"]).optional(),
1431
+ startOn: px.enum([PxStartOn.load, PxStartOn.mouseOver, PxStartOn.click, PxStartOn.scrollIntoView, PxStartOn.programmatic], PX_TRIGGER_DEFAULTS.startOn).optional(),
1432
+ outAction: px.enum([PxOutAction.continue, PxOutAction.pause, PxOutAction.reset, PxOutAction.reverse], PX_TRIGGER_DEFAULTS.outAction).optional(),
1251
1433
  // What happens after a NATURAL finish — `'hold'` (default: keep the end state per
1252
- // `fill`) or `'reset'` (snap back to the start state). The trigger-vocabulary home of
1253
- // the old top-level `resetOnFinish: boolean` (read-legacy) — review §2.3: both
1254
- // "what happens at the end" knobs now sit side by side and share one style of value.
1255
- onFinish: px.enum(["hold", "reset"]).optional(),
1434
+ // `fill`) or `'reset'` (snap back to the start state). Pairs with `outAction` ("what
1435
+ // happens when the trigger condition ends"); both end-of-life knobs now read alike.
1436
+ finishAction: px.enum([PxFinishAction.hold, PxFinishAction.reset]).optional(),
1256
1437
  scrollIntoViewThreshold: px.number().optional()
1257
1438
  }));
1258
1439
  var PxGlyphSchema = implementsInterface()(px.object({
1259
1440
  width: px.number(),
1260
- d: px.string()
1441
+ pathData: px.string()
1261
1442
  }));
1262
1443
  var PxGlyphFontSchema = implementsInterface()(px.object({
1263
1444
  fontFamily: px.string(),
@@ -1272,11 +1453,17 @@ var PixodeskAnimator = (() => {
1272
1453
  // Review §2.6: the schema now matches the declared type — a style preset is a flat
1273
1454
  // record of string|number attribute values, nothing nested.
1274
1455
  styles: px.record(px.record(px.union([px.string(), px.number()]))).optional(),
1275
- glyphs: px.record(PxGlyphFontSchema).optional()
1456
+ fonts: px.record(PxGlyphFontSchema).optional()
1276
1457
  }));
1277
- var PX_SCROLL_PHASES = ["cover", "contain", "entry", "exit", "entry-crossing", "exit-crossing"];
1278
1458
  var PxScrollRangePointSchema = implementsInterface()(px.object({
1279
- phase: px.enum(PX_SCROLL_PHASES).optional(),
1459
+ phase: px.enum([
1460
+ PxScrollPhase.cover,
1461
+ PxScrollPhase.contain,
1462
+ PxScrollPhase.entry,
1463
+ PxScrollPhase.exit,
1464
+ PxScrollPhase.entryCrossing,
1465
+ PxScrollPhase.exitCrossing
1466
+ ]).optional(),
1280
1467
  fraction: px.number().optional()
1281
1468
  }));
1282
1469
  var PxScrollRangeSchema = px.object({
@@ -1284,34 +1471,38 @@ var PixodeskAnimator = (() => {
1284
1471
  end: PxScrollRangePointSchema.optional()
1285
1472
  });
1286
1473
  var PxScrollSchema = implementsInterface()(px.object({
1287
- driver: px.enum(["custom", "native"]).optional(),
1288
- kind: px.enum(["view", "scroll"]).optional(),
1289
- axis: px.enum(["block", "inline", "x", "y"]).optional(),
1290
- source: px.enum(["nearest", "root"]).optional(),
1474
+ kind: px.enum([PxScrollKind.view, PxScrollKind.scroll]).optional(),
1475
+ axis: px.enum([PxScrollAxis.block, PxScrollAxis.inline, PxScrollAxis.x, PxScrollAxis.y]).optional(),
1476
+ source: px.enum([PxScrollSource.nearest, PxScrollSource.root]).optional(),
1291
1477
  // Free-form: the two keywords `parent`/`scroller` plus any CSS selector.
1292
1478
  subject: px.string().optional(),
1293
1479
  smoothing: px.number().optional(),
1294
1480
  pin: px.boolean().optional(),
1295
- pinAlign: px.enum(["top", "center", "bottom"]).optional(),
1296
- pinTop: px.number().optional(),
1481
+ pinAlign: px.enum([PxPinAlign.top, PxPinAlign.center, PxPinAlign.bottom]).optional(),
1482
+ pinOffset: px.number().optional(),
1297
1483
  pinDistance: px.number().optional(),
1298
1484
  range: PxScrollRangeSchema.optional()
1299
1485
  }));
1300
- var PxTimelinePinSchema = px.object({
1301
- align: px.enum(["top", "center", "bottom"]).optional(),
1302
- top: px.number().optional(),
1486
+ var PxTimelinePinSchema = implementsInterface()(px.object({
1487
+ align: px.enum([PxPinAlign.top, PxPinAlign.center, PxPinAlign.bottom]).optional(),
1488
+ offset: px.number().optional(),
1303
1489
  distance: px.number().optional()
1304
- });
1305
- var PxClockTimelineSchema = px.object({
1306
- type: px.literal("clock"),
1490
+ }));
1491
+ var PxTimelineEngineSchema = px.enum([PxTimelineEngineExtra.auto, PxTimelineEngineExtra.native, PxTimelineEngineExtra.js]).optional();
1492
+ var PxTimeTimelineSchema = implementsInterface()(px.object({
1493
+ type: px.literal("time").optional(),
1494
+ engine: PxTimelineEngineSchema,
1495
+ frameRate: px.number().optional(),
1307
1496
  // §2.8: duration is a property of the TIMELINE — how long one pass takes.
1308
1497
  duration: px.number().optional(),
1309
1498
  trigger: PxTriggerSchema.optional(),
1310
1499
  delay: px.number().optional(),
1311
1500
  iterations: px.union([px.number(), px.literal("infinite")]).optional(),
1312
- fill: px.enum(["forwards", "backwards", "both", "none"]).optional(),
1313
- direction: px.enum(["normal", "reverse", "alternate", "alternate-reverse"]).optional()
1314
- });
1501
+ // `fillMode` on the wire (CSS `animation-fill-mode`; the runtime view calls it `fill`)
1502
+ // — never `fill`, which is paint everywhere else in the format.
1503
+ fillMode: px.enum([PxFillMode.forwards, PxFillMode.backwards, PxFillMode.both, PxFillMode.none]).optional(),
1504
+ direction: px.enum([PxPlaybackDirection.normal, PxPlaybackDirection.reverse, PxPlaybackDirection.alternate, PxPlaybackDirection.alternateReverse]).optional()
1505
+ }));
1315
1506
  var scrollishTimelineShape = {
1316
1507
  // §2.8: duration is a property of the TIMELINE — under scrubbing it is the keyframe
1317
1508
  // span the scroll range maps onto.
@@ -1319,9 +1510,10 @@ var PixodeskAnimator = (() => {
1319
1510
  // Finite repeat count IS meaningful when scrubbing — the scroll range maps onto
1320
1511
  // duration × iterations (rule D4; `'infinite'` cannot map to a range, so no literal here).
1321
1512
  iterations: px.number().optional(),
1322
- engine: px.enum(["custom", "native"]).optional(),
1323
- axis: px.enum(["block", "inline", "x", "y"]).optional(),
1324
- source: px.enum(["nearest", "root"]).optional(),
1513
+ engine: PxTimelineEngineSchema,
1514
+ frameRate: px.number().optional(),
1515
+ axis: px.enum([PxScrollAxis.block, PxScrollAxis.inline, PxScrollAxis.x, PxScrollAxis.y]).optional(),
1516
+ source: px.enum([PxScrollSource.nearest, PxScrollSource.root]).optional(),
1325
1517
  subject: px.string().optional(),
1326
1518
  // 'parent' | 'scroller' | any CSS selector
1327
1519
  smoothing: px.number().optional(),
@@ -1329,23 +1521,29 @@ var PixodeskAnimator = (() => {
1329
1521
  pin: px.union([px.boolean(), PxTimelinePinSchema]).optional(),
1330
1522
  range: PxScrollRangeSchema.optional()
1331
1523
  };
1332
- var PxScrollTimelineSchema = px.object(__spreadValues({ type: px.literal("scroll") }, scrollishTimelineShape));
1333
- var PxViewTimelineSchema = px.object(__spreadValues({ type: px.literal("view") }, scrollishTimelineShape));
1524
+ var PxScrollTimelineSchema = implementsInterface()(
1525
+ px.object(__spreadValues({ type: px.literal("scroll") }, scrollishTimelineShape))
1526
+ );
1527
+ var PxViewTimelineSchema = implementsInterface()(
1528
+ px.object(__spreadValues({ type: px.literal("view") }, scrollishTimelineShape))
1529
+ );
1334
1530
  var PxTimelineSchema = px.discriminatedUnion("type", [
1335
- PxClockTimelineSchema,
1531
+ PxTimeTimelineSchema,
1532
+ // first = the member an absent `type` selects
1336
1533
  PxScrollTimelineSchema,
1337
1534
  PxViewTimelineSchema
1338
1535
  ]);
1339
1536
  var PxAnimatorConfigSchema = implementsInterface()(px.object({
1340
- mode: px.enum([PxAnimatorMode.auto, PxAnimatorMode.waapi, PxAnimatorMode.frames]).optional(),
1341
- // (`duration` lives INSIDE `timeline` on the wire — §2.8; the flat field below
1342
- // exists only on the runtime view, like the rest of the playback dynamics.)
1343
- frameRate: px.number().optional(),
1537
+ // (`mode`, `duration` and `frameRate` live INSIDE `timeline` on the wire — §2.8; they exist
1538
+ // at this level only on the runtime view, like the rest of the playback dynamics.)
1344
1539
  // THE spelling of "what advances progress" — clock / scroll / view (review §2.1).
1345
1540
  timeline: PxTimelineSchema.optional(),
1346
1541
  definitions: PxDefsSchema.optional(),
1347
1542
  animateById: px.record(PxElementAnimationSchema).optional(),
1348
- debugInstName: px.string().optional()
1543
+ debugGlobalName: px.string().optional(),
1544
+ // Declared HERE because this is a closed object: an undeclared key would be stripped by
1545
+ // `sanitize` and flagged by strict validation on our own files.
1546
+ version: px.string().optional()
1349
1547
  }));
1350
1548
  var PxBindingSchema = implementsInterface()(px.object({
1351
1549
  id: px.string(),
@@ -1394,7 +1592,7 @@ var PixodeskAnimator = (() => {
1394
1592
  origin: PxAnimatableVec2Schema.optional()
1395
1593
  }));
1396
1594
  var PxMaskedByEffectSchema = implementsInterface()(px.object({
1397
- sourceId: px.string().optional(),
1595
+ source: px.string().optional(),
1398
1596
  maskType: px.enum([PxMaskType.luminance, PxMaskType.alpha]).optional(),
1399
1597
  maskUnits: px.enum([PxUnits.userSpaceOnUse, PxUnits.objectBoundingBox]).optional(),
1400
1598
  maskContentUnits: px.enum([PxUnits.userSpaceOnUse, PxUnits.objectBoundingBox]).optional(),
@@ -1404,7 +1602,7 @@ var PixodeskAnimator = (() => {
1404
1602
  height: px.number().optional()
1405
1603
  }));
1406
1604
  var PxClipPathEffectSchema = implementsInterface()(px.object({
1407
- d: PxAnimatableStringSchema.optional()
1605
+ pathData: PxAnimatableStringSchema.optional()
1408
1606
  }));
1409
1607
  var PxStrokeTrimEffectSchema = implementsInterface()(px.object({
1410
1608
  offset: PxAnimatableNumberSchema.optional(),
@@ -1417,9 +1615,10 @@ var PixodeskAnimator = (() => {
1417
1615
  timeCrop: px.tuple([px.number(), px.number()]).optional()
1418
1616
  }));
1419
1617
  var PxCloneEffectSchema = implementsInterface()(px.object({
1420
- // Contextual kind — the `type` convention, see `PxNodeBase.type`.
1421
- type: px.enum([PxCloneType.content]).optional(),
1422
- sourceId: px.string().optional(),
1618
+ // Subtractive on purpose: the `<use>` can only point at one wrapper layer of the
1619
+ // source, so the choices form a ladder — 'translate' now, maybe 'transform' later.
1620
+ without: px.enum([PxCloneWithout.translate]).optional(),
1621
+ source: px.string().optional(),
1423
1622
  retime: PxRetimeEffectSchema.optional()
1424
1623
  }));
1425
1624
  var PxGradientStopSchema = implementsInterface()(px.object({
@@ -1440,13 +1639,13 @@ var PixodeskAnimator = (() => {
1440
1639
  radius: PxAnimatableNumberSchema.optional(),
1441
1640
  focal: PxAnimatableVec2Schema.optional(),
1442
1641
  stops: PxAnimatableGradientStopsSchema.optional(),
1443
- gradientUnits: px.enum([PxGradientUnits.userSpaceOnUse, PxGradientUnits.objectBoundingBox]).optional(),
1642
+ gradientUnits: px.enum([PxUnits.userSpaceOnUse, PxUnits.objectBoundingBox]).optional(),
1444
1643
  spreadMethod: px.enum([PxGradientSpreadMethod.pad, PxGradientSpreadMethod.reflect, PxGradientSpreadMethod.repeat]).optional(),
1445
1644
  gradientTransform: px.string().optional()
1446
1645
  }));
1447
1646
  var PxStrokeGradientEffectSchema = PxFillGradientEffectSchema;
1448
1647
  var PxTextPathEffectSchema = implementsInterface()(px.object({
1449
- path: px.string(),
1648
+ pathData: px.string(),
1450
1649
  pathOverflow: px.enum([PxPathOverflow.clip, PxPathOverflow.extend]).optional(),
1451
1650
  lengthAdjust: px.enum([PxLengthAdjust.spacing, PxLengthAdjust.spacingAndGlyphs]).optional(),
1452
1651
  method: px.enum([PxTextPathMethod.align, PxTextPathMethod.stretch]).optional(),
@@ -1486,20 +1685,100 @@ var PixodeskAnimator = (() => {
1486
1685
  walk(root, "root");
1487
1686
  return warnings;
1488
1687
  }
1688
+ function validateGlyphFontRefs(root, fonts) {
1689
+ if (!fonts || !Object.keys(fonts).length) return [];
1690
+ const problems = [];
1691
+ const walk = (node, path, inherited, inGlyphText) => {
1692
+ var _a2, _b;
1693
+ if (!node) return;
1694
+ const own = typeof node.fontFamily === "string" ? node.fontFamily : void 0;
1695
+ const family = own != null ? own : inherited;
1696
+ const isGlyphText = inGlyphText || node.type === "text" && !!((_b = (_a2 = node.effects) == null ? void 0 : _a2.text) == null ? void 0 : _b.useGlyphs);
1697
+ if (isGlyphText && own && !Object.prototype.hasOwnProperty.call(fonts, own)) {
1698
+ const problem = path + ': glyph-mode text uses font-family "' + own + '", which has no entry in animator.definitions.fonts';
1699
+ if (!problems.includes(problem)) problems.push(problem);
1700
+ }
1701
+ if (Array.isArray(node.children)) {
1702
+ node.children.forEach((c, i) => walk(c, path + ".children[" + i + "]", family, isGlyphText));
1703
+ }
1704
+ };
1705
+ walk(root, "root", void 0, false);
1706
+ return problems;
1707
+ }
1708
+ function validateEasingRefs(root, easings) {
1709
+ const problems = [];
1710
+ const walk = (node, path) => {
1711
+ if (Array.isArray(node)) {
1712
+ node.forEach((item, i) => walk(item, path + "[" + i + "]"));
1713
+ return;
1714
+ }
1715
+ if (!node || typeof node !== "object") return;
1716
+ const easing = node.easing;
1717
+ if (typeof easing === "string" && !(easings && Object.prototype.hasOwnProperty.call(easings, easing))) {
1718
+ const problem = path + '.easing: "' + easing + '" names no entry in animator.definitions.easings \u2014 it will play linear';
1719
+ if (!problems.includes(problem)) problems.push(problem);
1720
+ }
1721
+ for (const [key, value] of Object.entries(node)) {
1722
+ if (key === "easing") continue;
1723
+ if (value && typeof value === "object") walk(value, path + "." + key);
1724
+ }
1725
+ };
1726
+ walk(root, "root");
1727
+ return problems;
1728
+ }
1729
+ function validateVersionStamp(doc) {
1730
+ var _a2;
1731
+ const version = (_a2 = getAnimatorConfig(doc)) == null ? void 0 : _a2.version;
1732
+ if (version === void 0) return [];
1733
+ if (parseWireVersion(version) !== void 0) return [];
1734
+ return ["root.animator.version: " + JSON.stringify(version) + ' is not a version stamp ("a.b" or "a.b.c") \u2014 it reads as unstamped'];
1735
+ }
1736
+ function validateDocument(doc, opts) {
1737
+ var _a2;
1738
+ const strict = (opts == null ? void 0 : opts.strict) !== false;
1739
+ const ctx = { errors: [], warnings: [], strict };
1740
+ const problems = PxAnimatedSvgDocumentSchema.isValid(doc, ctx, ["root"]) ? [] : [...ctx.errors];
1741
+ if (doc && typeof doc === "object") {
1742
+ for (const w of validateNodeEffects(doc, { strict })) {
1743
+ if (!problems.includes(w)) problems.push(w);
1744
+ }
1745
+ const defs = (_a2 = getAnimatorConfig(doc)) == null ? void 0 : _a2.definitions;
1746
+ for (const w of validateGlyphFontRefs(doc, defs == null ? void 0 : defs.fonts)) {
1747
+ if (!problems.includes(w)) problems.push(w);
1748
+ }
1749
+ for (const w of validateEasingRefs(doc, defs == null ? void 0 : defs.easings)) {
1750
+ if (!problems.includes(w)) problems.push(w);
1751
+ }
1752
+ for (const w of validateVersionStamp(doc)) {
1753
+ if (!problems.includes(w)) problems.push(w);
1754
+ }
1755
+ }
1756
+ return problems;
1757
+ }
1489
1758
  var PxNodeBase = px.openObject({
1490
1759
  // CONVENTION (SCHEMA-DESIGN R1 / issues N4): `type` is the ONE word for "what
1491
1760
  // kind of thing is this", discriminated by its CARRIER — here the node TAG
1492
- // (`rect`, `text`), and inside a sub-object that object's kind (`clone.type`,
1761
+ // (`rect`, `text`), and inside a sub-object that object's kind (`fillGradient.type`,
1493
1762
  // `fillGradient.type`, editor `preset.type`). Each sits in its own object, so
1494
1763
  // the carrier disambiguates completely; synonyms (`cloneKind`, `presetShape`)
1495
1764
  // would add words that all mean "type" and still need the carrier to read.
1496
1765
  // Guarding a `type` SLOT against a wrong VALUE is the job of strict enums
1497
1766
  // (issues V3), never of distinct key names.
1498
1767
  type: px.string(),
1768
+ // The escape hatch for elements that carry a REAL `type` attribute — `<feTurbulence
1769
+ // type="fractalNoise">`, `<feFuncR type="table">`, `<feColorMatrix type="saturate">`.
1770
+ // `type` is taken by the tag name, so the attribute travels here and the renderer puts
1771
+ // it back (`PxAnimatorDOM.renderNode`, `PxRnRender`). Declared here — not merely
1772
+ // documented — because a wire key that is not in a schema is invisible to the
1773
+ // minifier's reserve list and gets renamed (MINIFICATION-BOUNDARY-PLAN.md §1.1).
1774
+ domType: px.string().optional(),
1775
+ // Text content of a `<text>` / `<tspan>`. Declared, so a non-string value is a schema error
1776
+ // and the minifier reserves the key; `text` is NOT an alias for it and is not read anywhere.
1777
+ textContent: px.string().optional(),
1499
1778
  id: px.string().optional(),
1500
1779
  meta: px.any().optional(),
1501
1780
  // Player-effects bucket emitted by the Editor's lightweight design format.
1502
- // Consumed and removed by `applyPlayerEffects` before any other normalisation
1781
+ // Consumed and removed by `applyPlayerEffects` before any other normalization
1503
1782
  // (see `createAnimatorImpl`), so downstream code never sees it.
1504
1783
  effects: PxEffectsSchema.optional(),
1505
1784
  // `PxElementAnimation` (not just `PxAnimationDefinition`) — accepts
@@ -1531,7 +1810,7 @@ var PixodeskAnimator = (() => {
1531
1810
  c: px.boolean().optional()
1532
1811
  }));
1533
1812
 
1534
- // ../svg-animator-core/src/PxIdUtil.ts
1813
+ // ../svg-animator-core/src/util/PxIdUtil.ts
1535
1814
  var _idCounter = 0;
1536
1815
  function generateUniqueId() {
1537
1816
  const timestamp = Date.now().toString(36);
@@ -1550,7 +1829,7 @@ var PixodeskAnimator = (() => {
1550
1829
  return cloned;
1551
1830
  }
1552
1831
  function generateNewIds(doc) {
1553
- var _a, _b;
1832
+ var _a2, _b;
1554
1833
  const cloned = deepClone(doc);
1555
1834
  const idMap = /* @__PURE__ */ new Map();
1556
1835
  const hashRefAttrs = /* @__PURE__ */ new Set(["href", "xlink:href"]);
@@ -1568,7 +1847,8 @@ var PixodeskAnimator = (() => {
1568
1847
  "flood-color",
1569
1848
  "lighting-color"
1570
1849
  ]);
1571
- const directIdRefAttrs = /* @__PURE__ */ new Set(["sourceId", "targetId", "boundElementId"]);
1850
+ const directIdRefAttrs = /* @__PURE__ */ new Set(["targetId", "boundElementId"]);
1851
+ const isEffectSourceRef = (key, parentKey) => key === "source" && (parentKey === "maskedBy" || parentKey === "clone");
1572
1852
  function collectIds(node) {
1573
1853
  if (!node || typeof node !== "object") return;
1574
1854
  if (node.id && typeof node.id === "string") {
@@ -1585,7 +1865,7 @@ var PixodeskAnimator = (() => {
1585
1865
  }
1586
1866
  }
1587
1867
  }
1588
- function updateRefs(node) {
1868
+ function updateRefs(node, parentKey) {
1589
1869
  if (!node || typeof node !== "object") return;
1590
1870
  for (const [key, value] of Object.entries(node)) {
1591
1871
  if (key === "children") {
@@ -1605,7 +1885,7 @@ var PixodeskAnimator = (() => {
1605
1885
  }
1606
1886
  } else if (urlRefAttrs.has(key)) {
1607
1887
  node[key] = replaceUrlRefs(value, idMap);
1608
- } else if (directIdRefAttrs.has(key)) {
1888
+ } else if (directIdRefAttrs.has(key) || isEffectSourceRef(key, parentKey)) {
1609
1889
  const hasHash = value.startsWith("#");
1610
1890
  const newId = idMap.get(hasHash ? value.slice(1) : value);
1611
1891
  if (newId) {
@@ -1621,13 +1901,13 @@ var PixodeskAnimator = (() => {
1621
1901
  }
1622
1902
  }
1623
1903
  } else if (typeof value === "object" && value !== null) {
1624
- updateRefs(value);
1904
+ updateRefs(value, key);
1625
1905
  }
1626
1906
  }
1627
1907
  }
1628
1908
  collectIds(cloned);
1629
1909
  updateRefs(cloned);
1630
- const docAnimate = (_a = cloned.animator) == null ? void 0 : _a.animateById;
1910
+ const docAnimate = (_a2 = cloned.animator) == null ? void 0 : _a2.animateById;
1631
1911
  if (docAnimate && typeof docAnimate === "object") {
1632
1912
  const updatedAnimate = {};
1633
1913
  for (const [key, anim] of Object.entries(docAnimate)) {
@@ -1647,7 +1927,7 @@ var PixodeskAnimator = (() => {
1647
1927
  });
1648
1928
  }
1649
1929
 
1650
- // ../svg-animator-core/src/PxNodeProps.ts
1930
+ // ../svg-animator-core/src/util/PxNodeProps.ts
1651
1931
  var DISALLOWED_SVG_TAGS_LOWER = /* @__PURE__ */ new Set([
1652
1932
  "script",
1653
1933
  "foreignobject"
@@ -1686,7 +1966,7 @@ var PixodeskAnimator = (() => {
1686
1966
  if (nameLower.startsWith("on")) return true;
1687
1967
  return false;
1688
1968
  }
1689
- function sanitiseAttributeValue(name, value) {
1969
+ function sanitizeAttributeValue(name, value) {
1690
1970
  const nameLower = name.toLowerCase();
1691
1971
  if (isDangerousAttrName(nameLower)) {
1692
1972
  console.warn("Attribute blocked (event handler / dangerous): ", nameLower);
@@ -1711,10 +1991,10 @@ var PixodeskAnimator = (() => {
1711
1991
  return value;
1712
1992
  }
1713
1993
  function resolveStyle(style, defs) {
1714
- var _a;
1994
+ var _a2;
1715
1995
  if (!style) return void 0;
1716
1996
  if (typeof style === "string") {
1717
- return (_a = defs == null ? void 0 : defs.styles) == null ? void 0 : _a[style];
1997
+ return (_a2 = defs == null ? void 0 : defs.styles) == null ? void 0 : _a2[style];
1718
1998
  }
1719
1999
  return style;
1720
2000
  }
@@ -1725,18 +2005,18 @@ var PixodeskAnimator = (() => {
1725
2005
  if (INTERNAL_ATTRS.has(key)) continue;
1726
2006
  if (key === "style") continue;
1727
2007
  let value = props[rawKey];
1728
- if (COLOUR_ATTR_NAMES.has(key) && Array.isArray(value)) {
2008
+ if (COLOR_ATTR_NAMES.has(key) && Array.isArray(value)) {
1729
2009
  propsCopy[key] = toRGBA(value);
1730
2010
  } else if (key === "transform" && value !== null && typeof value === "object" && !Array.isArray(value) && !value.keyframes) {
1731
2011
  const parts = value.value && typeof value.value === "object" ? value.value : value;
1732
- propsCopy["transform"] = composeTransformParts(parts, { withUnits: false });
2012
+ propsCopy[TRANSFORM_ATTR] = composeTransformParts(parts, { withUnits: false });
1733
2013
  } else if (TRANSFORM_FN_NAMES.has(key)) {
1734
2014
  if (Array.isArray(value)) {
1735
2015
  if (key === "translate") value = value.map((v) => v + "px");
1736
2016
  value = value.join(",");
1737
2017
  }
1738
2018
  if (key === "rotate") value = value + "deg";
1739
- propsCopy["transform"] = key + "(" + value + ")";
2019
+ propsCopy[TRANSFORM_ATTR] = key + "(" + value + ")";
1740
2020
  } else if (Array.isArray(value)) {
1741
2021
  propsCopy[key] = value.join(",");
1742
2022
  } else if (value !== void 0 && value !== null) {
@@ -1746,10 +2026,9 @@ var PixodeskAnimator = (() => {
1746
2026
  return propsCopy;
1747
2027
  }
1748
2028
 
1749
- // ../svg-animator-core/src/PxMotionPath.ts
2029
+ // ../svg-animator-core/src/materialize/PxMotionPath.ts
1750
2030
  function getKfTranslate(kf) {
1751
- var _a;
1752
- const v = (_a = kf.value) != null ? _a : kf.v;
2031
+ const v = kfValue(kf);
1753
2032
  if (!v) return void 0;
1754
2033
  if (Array.isArray(v) && v.length >= 2 && typeof v[0] === "number" && typeof v[1] === "number") {
1755
2034
  return [v[0], v[1]];
@@ -1759,31 +2038,27 @@ var PixodeskAnimator = (() => {
1759
2038
  return void 0;
1760
2039
  }
1761
2040
  function getKfTime(kf) {
1762
- var _a, _b;
1763
- return (_b = (_a = kf.time) != null ? _a : kf.t) != null ? _b : 0;
2041
+ return kfTime(kf);
1764
2042
  }
1765
2043
  function getKfEasing(kf) {
1766
- var _a;
1767
- return (_a = kf.easing) != null ? _a : kf.e;
2044
+ return kfEasing(kf);
1768
2045
  }
1769
2046
  function propAnimIsMotionPath(anim) {
1770
- var _a, _b;
1771
2047
  const kfs = anim.keyframes;
1772
2048
  if (!Array.isArray(kfs)) return false;
1773
2049
  if (anim.autoOrient) return true;
1774
2050
  for (const kf of kfs) {
1775
- if (((_a = kf.tangentIn) != null ? _a : kf.ti) || ((_b = kf.tangentOut) != null ? _b : kf.to)) return true;
2051
+ if (kfTangentIn(kf) || kfTangentOut(kf)) return true;
1776
2052
  }
1777
2053
  return false;
1778
2054
  }
1779
2055
  var _segmentCache = /* @__PURE__ */ new WeakMap();
1780
2056
  function getSegmentCache(prevKf, nextKf, prevPos, nextPos) {
1781
- var _a, _b;
1782
2057
  let byNext = _segmentCache.get(prevKf);
1783
2058
  const existing = byNext == null ? void 0 : byNext.get(nextKf);
1784
2059
  if (existing) return existing;
1785
- const to = (_a = prevKf.tangentOut) != null ? _a : prevKf.to;
1786
- const ti = (_b = nextKf.tangentIn) != null ? _b : nextKf.ti;
2060
+ const to = kfTangentOut(prevKf);
2061
+ const ti = kfTangentIn(nextKf);
1787
2062
  const P1 = [prevPos[0] + (to ? to[0] : 0), prevPos[1] + (to ? to[1] : 0)];
1788
2063
  const P2 = [nextPos[0] + (ti ? ti[0] : 0), nextPos[1] + (ti ? ti[1] : 0)];
1789
2064
  const lut = bezier2D_arcLengthLUT(prevPos, P1, P2, nextPos);
@@ -1832,13 +2107,13 @@ var PixodeskAnimator = (() => {
1832
2107
  var DEFAULT_FLATNESS_TOL = 0.5;
1833
2108
  var DEFAULT_ROTATION_TOL = 5;
1834
2109
  var DEFAULT_MAX_SAMPLES = 32;
1835
- function materialiseMotionPathInPropAnim(anim, opts) {
1836
- var _a, _b, _c;
2110
+ function materializeMotionPathInPropAnim(anim, opts) {
2111
+ var _a2, _b, _c;
1837
2112
  if (!propAnimIsMotionPath(anim)) return anim;
1838
2113
  const kfs = anim.keyframes;
1839
2114
  if (!Array.isArray(kfs) || kfs.length < 2) return anim;
1840
2115
  const autoOrient = !!anim.autoOrient;
1841
- const flatnessTol = (_a = opts == null ? void 0 : opts.flatnessTolerance) != null ? _a : DEFAULT_FLATNESS_TOL;
2116
+ const flatnessTol = (_a2 = opts == null ? void 0 : opts.flatnessTolerance) != null ? _a2 : DEFAULT_FLATNESS_TOL;
1842
2117
  const rotationTol = (_b = opts == null ? void 0 : opts.rotationTolerance) != null ? _b : DEFAULT_ROTATION_TOL;
1843
2118
  const maxSamples = (_c = opts == null ? void 0 : opts.maxSamplesPerSegment) != null ? _c : DEFAULT_MAX_SAMPLES;
1844
2119
  const out = [];
@@ -1864,7 +2139,7 @@ var PixodeskAnimator = (() => {
1864
2139
  if (autoOrient && i > 0) {
1865
2140
  insertSharpCornerStepKfIfNeeded(out, prevKf, nextKf, prevPos, nextPos, rotationTol);
1866
2141
  }
1867
- materialiseSegment(out, prevKf, nextKf, prevPos, nextPos, autoOrient, flatnessTol, rotationTol, maxSamples);
2142
+ materializeSegment(out, prevKf, nextKf, prevPos, nextPos, autoOrient, flatnessTol, rotationTol, maxSamples);
1868
2143
  }
1869
2144
  const lastInE = getKfEasing(kfs[kfs.length - 1]);
1870
2145
  if (lastInE) out[out.length - 1].e = lastInE;
@@ -1874,10 +2149,9 @@ var PixodeskAnimator = (() => {
1874
2149
  return result;
1875
2150
  }
1876
2151
  function unwrapAutoOrientRotations(kfs) {
1877
- var _a;
1878
2152
  let prev;
1879
2153
  for (const kf of kfs) {
1880
- const v = (_a = kf.v) != null ? _a : kf.value;
2154
+ const v = kfValue(kf);
1881
2155
  if (!v || typeof v.rotate !== "number") continue;
1882
2156
  if (prev === void 0) {
1883
2157
  prev = v.rotate;
@@ -1894,8 +2168,7 @@ var PixodeskAnimator = (() => {
1894
2168
  return { t: time, v: value };
1895
2169
  }
1896
2170
  function getKfValueParts(kf) {
1897
- var _a;
1898
- const v = (_a = kf.value) != null ? _a : kf.v;
2171
+ const v = kfValue(kf);
1899
2172
  if (!v || typeof v !== "object" || Array.isArray(v)) return void 0;
1900
2173
  return v;
1901
2174
  }
@@ -1956,9 +2229,8 @@ var PixodeskAnimator = (() => {
1956
2229
  return d;
1957
2230
  }
1958
2231
  function insertSharpCornerStepKfIfNeeded(out, prevKf, nextKf, prevPos, nextPos, rotationTol) {
1959
- var _a;
1960
2232
  const lastKf = out[out.length - 1];
1961
- const lastV = (_a = lastKf.v) != null ? _a : lastKf.value;
2233
+ const lastV = kfValue(lastKf);
1962
2234
  const prevExit = lastV == null ? void 0 : lastV.rotate;
1963
2235
  if (typeof prevExit !== "number") return;
1964
2236
  const boundaryV = getKfValueParts(prevKf);
@@ -1981,7 +2253,7 @@ var PixodeskAnimator = (() => {
1981
2253
  out.push(makeOutKf(stepTime, dupValue));
1982
2254
  }
1983
2255
  var CORNER_STEP_AFTER_BOUNDARY_MS = 0.05;
1984
- function materialiseSegment(out, prevKf, nextKf, prevPos, nextPos, autoOrient, flatnessTol, rotationTol, maxSamples) {
2256
+ function materializeSegment(out, prevKf, nextKf, prevPos, nextPos, autoOrient, flatnessTol, rotationTol, maxSamples) {
1985
2257
  const seg = getSegmentCache(prevKf, nextKf, prevPos, nextPos);
1986
2258
  const prevTime = getKfTime(prevKf);
1987
2259
  const nextTime = getKfTime(nextKf);
@@ -2104,16 +2376,16 @@ var PixodeskAnimator = (() => {
2104
2376
  const cross = (q[0] - pA[0]) * dy - (q[1] - pA[1]) * dx;
2105
2377
  return Math.abs(cross) / Math.sqrt(len2);
2106
2378
  }
2107
- function materialiseMotionPathsInTree(root, opts) {
2108
- const out = walkAndMaterialise(root, opts);
2379
+ function materializeMotionPathsInTree(root, opts) {
2380
+ const out = walkAndMaterialize(root, opts);
2109
2381
  return out != null ? out : root;
2110
2382
  }
2111
- function walkAndMaterialise(node, opts) {
2383
+ function walkAndMaterialize(node, opts) {
2112
2384
  let newChildren;
2113
2385
  if (node.children) {
2114
2386
  for (let i = 0; i < node.children.length; i++) {
2115
2387
  const ch = node.children[i];
2116
- const ret = walkAndMaterialise(ch, opts);
2388
+ const ret = walkAndMaterialize(ch, opts);
2117
2389
  if (ret !== null) {
2118
2390
  if (!newChildren) newChildren = node.children.slice();
2119
2391
  newChildren[i] = ret;
@@ -2126,9 +2398,9 @@ var PixodeskAnimator = (() => {
2126
2398
  const animDef = animBucket;
2127
2399
  const transformAnim = animDef.transform;
2128
2400
  if (transformAnim && typeof transformAnim === "object" && propAnimIsMotionPath(transformAnim)) {
2129
- const materialised = materialiseMotionPathInPropAnim(transformAnim, opts);
2130
- if (materialised !== transformAnim) {
2131
- newAnimate = __spreadProps(__spreadValues({}, animDef), { transform: materialised });
2401
+ const materialized = materializeMotionPathInPropAnim(transformAnim, opts);
2402
+ if (materialized !== transformAnim) {
2403
+ newAnimate = __spreadProps(__spreadValues({}, animDef), { transform: materialized });
2132
2404
  }
2133
2405
  }
2134
2406
  }
@@ -2139,7 +2411,7 @@ var PixodeskAnimator = (() => {
2139
2411
  return cloned;
2140
2412
  }
2141
2413
 
2142
- // ../svg-animator-core/src/PxDefinitions.ts
2414
+ // ../svg-animator-core/src/animation/PxDefinitions.ts
2143
2415
  var LOOP_JUMP_SHIFT_MS = 1;
2144
2416
  function deepEqualValue(a, b) {
2145
2417
  if (a === b) return true;
@@ -2231,8 +2503,8 @@ var PixodeskAnimator = (() => {
2231
2503
  return typeof value === "string" && extractPathData(value) !== void 0;
2232
2504
  }
2233
2505
  function normalizePathValue(value) {
2234
- if (value && typeof value === "object" && typeof value.path === "string") {
2235
- const d = extractPathData(value.path);
2506
+ if (value && typeof value === "object" && typeof value.pathData === "string") {
2507
+ const d = extractPathData(value.pathData);
2236
2508
  return d ? { paths: parseSvgPathToBezier(d) } : value;
2237
2509
  }
2238
2510
  if (value && typeof value === "object" && "paths" in value) {
@@ -2271,21 +2543,21 @@ var PixodeskAnimator = (() => {
2271
2543
  return value;
2272
2544
  }
2273
2545
  function resolveEasing(easing, defs) {
2274
- var _a;
2546
+ var _a2;
2275
2547
  if (!easing) return void 0;
2276
2548
  if (Array.isArray(easing)) {
2277
2549
  return easing;
2278
2550
  }
2279
- if ((_a = defs == null ? void 0 : defs.easings) == null ? void 0 : _a[easing]) {
2551
+ if ((_a2 = defs == null ? void 0 : defs.easings) == null ? void 0 : _a2[easing]) {
2280
2552
  return defs.easings[easing];
2281
2553
  }
2282
2554
  console.warn("Unknown easing name: " + easing);
2283
2555
  return void 0;
2284
2556
  }
2285
2557
  function resolveAnimation(animRef, defs) {
2286
- var _a;
2558
+ var _a2;
2287
2559
  if (typeof animRef === "string") {
2288
- const resolved = (_a = defs == null ? void 0 : defs.animations) == null ? void 0 : _a[animRef];
2560
+ const resolved = (_a2 = defs == null ? void 0 : defs.animations) == null ? void 0 : _a2[animRef];
2289
2561
  if (!resolved) {
2290
2562
  console.warn("Unknown animation name: " + animRef);
2291
2563
  }
@@ -2310,13 +2582,13 @@ var PixodeskAnimator = (() => {
2310
2582
  return results;
2311
2583
  }
2312
2584
  function interpolateValue(propName, a, b, t) {
2313
- var _a, _b;
2585
+ var _a2, _b;
2314
2586
  if (propName === "d") {
2315
- const aPaths = (_a = a == null ? void 0 : a.paths) != null ? _a : Array.isArray(a) ? a : [];
2587
+ const aPaths = (_a2 = a == null ? void 0 : a.paths) != null ? _a2 : Array.isArray(a) ? a : [];
2316
2588
  const bPaths = (_b = b == null ? void 0 : b.paths) != null ? _b : Array.isArray(b) ? b : [];
2317
2589
  return { paths: interpolateBeziers(aPaths, bPaths, t) };
2318
2590
  }
2319
- if (COLOUR_ATTR_NAMES.has(propName)) {
2591
+ if (COLOR_ATTR_NAMES.has(propName)) {
2320
2592
  return interpolateColor(a || [0, 0, 0, 1], b || [0, 0, 0, 1], t);
2321
2593
  }
2322
2594
  if (propName === "transform" && typeof a === "object" && a !== null && !Array.isArray(a) && typeof b === "object" && b !== null && !Array.isArray(b)) {
@@ -2348,11 +2620,11 @@ var PixodeskAnimator = (() => {
2348
2620
  return out;
2349
2621
  }
2350
2622
  function expandLoopKeyframes(propName, keyframes, loop, duration) {
2351
- var _a, _b, _c, _d, _e;
2623
+ var _a2, _b, _c, _d, _e;
2352
2624
  const totalIntervals = keyframes.length - 1;
2353
- const segCount = clamp((_a = loop.segmentCount) != null ? _a : totalIntervals, 1, totalIntervals);
2625
+ const segCount = clamp((_a2 = loop.segmentCount) != null ? _a2 : totalIntervals, 1, totalIntervals);
2354
2626
  let segKfs;
2355
- if (loop.extend === PxLoopExtend.before) {
2627
+ if (loop.repeatAt === PxLoopRepeatAt.start) {
2356
2628
  segKfs = keyframes.slice(0, segCount + 1);
2357
2629
  } else {
2358
2630
  segKfs = keyframes.slice(totalIntervals - segCount);
@@ -2360,7 +2632,7 @@ var PixodeskAnimator = (() => {
2360
2632
  const firstT = (_b = keyframes[0].t) != null ? _b : 0;
2361
2633
  const lastT = (_c = keyframes[keyframes.length - 1].t) != null ? _c : 0;
2362
2634
  let fillStart, fillEnd;
2363
- if (loop.extend === PxLoopExtend.before) {
2635
+ if (loop.repeatAt === PxLoopRepeatAt.start) {
2364
2636
  fillStart = 0;
2365
2637
  fillEnd = firstT;
2366
2638
  } else {
@@ -2373,26 +2645,23 @@ var PixodeskAnimator = (() => {
2373
2645
  const segEndT = (_e = segKfs[segKfs.length - 1].t) != null ? _e : 0;
2374
2646
  const segDuration = segEndT - segStartT;
2375
2647
  if (segDuration <= 0) return keyframes;
2376
- const template = segKfs.map((kf) => {
2377
- var _a2, _b2;
2378
- return {
2379
- relT: (kf.t - segStartT) / segDuration,
2380
- v: kf.v,
2381
- e: kf.e,
2382
- tangentIn: (_a2 = kf.tangentIn) != null ? _a2 : kf.ti,
2383
- tangentOut: (_b2 = kf.tangentOut) != null ? _b2 : kf.to
2384
- };
2385
- });
2648
+ const template = segKfs.map((kf) => ({
2649
+ relT: (kf.t - segStartT) / segDuration,
2650
+ v: kf.v,
2651
+ e: kf.e,
2652
+ tangentIn: kfTangentIn(kf),
2653
+ tangentOut: kfTangentOut(kf)
2654
+ }));
2386
2655
  const fullReps = Math.floor(fillDuration / segDuration);
2387
2656
  const remainder = fillDuration - fullReps * segDuration;
2388
2657
  const partialFraction = remainder / segDuration;
2389
2658
  const looped = [];
2390
- const separateBoundary = loop.extend !== PxLoopExtend.before;
2659
+ const separateBoundary = loop.repeatAt !== PxLoopRepeatAt.start;
2391
2660
  const originalTerminalKf = keyframes[keyframes.length - 1];
2392
2661
  let terminalEasingOverride;
2393
2662
  let hasTerminalEasingOverride = false;
2394
2663
  function appendRep(repStart, isReversed, partial) {
2395
- var _a2;
2664
+ var _a3;
2396
2665
  let entries;
2397
2666
  if (isReversed) {
2398
2667
  entries = [];
@@ -2429,7 +2698,7 @@ var PixodeskAnimator = (() => {
2429
2698
  return;
2430
2699
  }
2431
2700
  const prevKf = looped.length > 0 ? looped[looped.length - 1] : originalTerminalKf;
2432
- const isBoundary = separateBoundary && i === 0 && prevKf !== void 0 && Math.abs(((_a2 = prevKf.t) != null ? _a2 : 0) - (repStart + entry.relT * segDuration)) < 1e-9;
2701
+ const isBoundary = separateBoundary && i === 0 && prevKf !== void 0 && Math.abs(((_a3 = prevKf.t) != null ? _a3 : 0) - (repStart + entry.relT * segDuration)) < 1e-9;
2433
2702
  if (isBoundary) {
2434
2703
  if (deepEqualValue(prevKf.v, entry.v)) {
2435
2704
  if (looped.length > 0) {
@@ -2495,30 +2764,30 @@ var PixodeskAnimator = (() => {
2495
2764
  looped.push(pushed);
2496
2765
  }
2497
2766
  }
2498
- if (loop.extend === PxLoopExtend.before) {
2767
+ if (loop.repeatAt === PxLoopRepeatAt.start) {
2499
2768
  if (partialFraction > 1e-9) {
2500
- const isReversed = !!loop.alternate && fullReps % 2 === 0;
2769
+ const isReversed = loop.direction === PxLoopDirection.alternate && fullReps % 2 === 0;
2501
2770
  appendRepTail(fillStart, isReversed, partialFraction);
2502
2771
  }
2503
2772
  for (let rep = 0; rep < fullReps; rep++) {
2504
2773
  const distFromBoundary = fullReps - 1 - rep;
2505
- const isReversed = !!loop.alternate && distFromBoundary % 2 === 0;
2774
+ const isReversed = loop.direction === PxLoopDirection.alternate && distFromBoundary % 2 === 0;
2506
2775
  const repStart = fillStart + remainder + rep * segDuration;
2507
2776
  appendRep(repStart, isReversed);
2508
2777
  }
2509
2778
  } else {
2510
2779
  for (let rep = 0; rep < fullReps; rep++) {
2511
- const isReversed = !!loop.alternate && rep % 2 === 0;
2780
+ const isReversed = loop.direction === PxLoopDirection.alternate && rep % 2 === 0;
2512
2781
  const repStart = fillStart + rep * segDuration;
2513
2782
  appendRep(repStart, isReversed);
2514
2783
  }
2515
2784
  if (partialFraction > 1e-9) {
2516
- const isReversed = !!loop.alternate && fullReps % 2 === 0;
2785
+ const isReversed = loop.direction === PxLoopDirection.alternate && fullReps % 2 === 0;
2517
2786
  const repStart = fillStart + fullReps * segDuration;
2518
2787
  appendRep(repStart, isReversed, partialFraction);
2519
2788
  }
2520
2789
  }
2521
- if (loop.extend === PxLoopExtend.before) {
2790
+ if (loop.repeatAt === PxLoopRepeatAt.start) {
2522
2791
  return [...looped, ...keyframes];
2523
2792
  } else {
2524
2793
  if (hasTerminalEasingOverride && keyframes.length > 0) {
@@ -2530,34 +2799,34 @@ var PixodeskAnimator = (() => {
2530
2799
  }
2531
2800
  }
2532
2801
  function normalizeKeyframes(propName, propAnim, duration, defs) {
2533
- var _a, _b, _c, _d, _e, _f, _g;
2802
+ var _a2;
2534
2803
  const keyframes = propAnim.keyframes || [];
2535
2804
  const normalized = [];
2536
2805
  for (const kf of keyframes) {
2537
- const timePct = (_b = (_a = kf.time) != null ? _a : kf.t) != null ? _b : 0;
2538
- let value = (_c = kf.value) != null ? _c : kf.v;
2539
- const easing = (_d = kf.easing) != null ? _d : kf.e;
2806
+ const timePct = kfTime(kf);
2807
+ let value = kfValue(kf);
2808
+ const easing = kfEasing(kf);
2540
2809
  if (propName === "d") {
2541
2810
  value = normalizePathValue(value);
2542
2811
  }
2543
2812
  const propNameKebab = isCamelCaseWord(propName) ? camelCaseToKebabWordIfNeeded(propName) : propName;
2544
- if (COLOUR_ATTR_NAMES.has(propNameKebab)) {
2545
- value = (_e = parseColor(value)) != null ? _e : value;
2813
+ if (COLOR_ATTR_NAMES.has(propNameKebab)) {
2814
+ value = (_a2 = parseColor(value)) != null ? _a2 : value;
2546
2815
  }
2547
2816
  const normKf = {
2548
2817
  t: timePct,
2549
2818
  v: value,
2550
2819
  e: resolveEasing(easing, defs)
2551
2820
  };
2552
- const tIn = (_f = kf.tangentIn) != null ? _f : kf.ti;
2553
- const tOut = (_g = kf.tangentOut) != null ? _g : kf.to;
2821
+ const tIn = kfTangentIn(kf);
2822
+ const tOut = kfTangentOut(kf);
2554
2823
  if (tIn) normKf.tangentIn = tIn;
2555
2824
  if (tOut) normKf.tangentOut = tOut;
2556
2825
  normalized.push(normKf);
2557
2826
  }
2558
2827
  normalized.sort((a, b) => {
2559
- var _a2, _b2;
2560
- return ((_a2 = a.t) != null ? _a2 : 0) - ((_b2 = b.t) != null ? _b2 : 0);
2828
+ var _a3, _b;
2829
+ return ((_a3 = a.t) != null ? _a3 : 0) - ((_b = b.t) != null ? _b : 0);
2561
2830
  });
2562
2831
  const loopRaw = propAnim.loop;
2563
2832
  const loop = loopRaw === true ? {} : loopRaw || void 0;
@@ -2575,24 +2844,26 @@ var PixodeskAnimator = (() => {
2575
2844
  }
2576
2845
  return merged;
2577
2846
  }
2578
- function materialiseInternalLoopsInPropAnim(propName, propAnim, duration) {
2847
+ function materializeInternalLoopsInPropAnim(propName, propAnim, duration) {
2579
2848
  const loopRaw = propAnim.loop;
2580
2849
  if (loopRaw === void 0 || loopRaw === null || loopRaw === false) return propAnim;
2581
2850
  const loop = loopRaw === true ? {} : loopRaw;
2582
2851
  const rawKfs = propAnim.keyframes;
2583
2852
  if (!Array.isArray(rawKfs) || rawKfs.length < 2) return propAnim;
2584
2853
  const propNameKebab = isCamelCaseWord(propName) ? camelCaseToKebabWordIfNeeded(propName) : propName;
2585
- const isColour = COLOUR_ATTR_NAMES.has(propNameKebab);
2854
+ const isColor = COLOR_ATTR_NAMES.has(propNameKebab);
2586
2855
  const kfs = rawKfs.map((kf) => {
2587
- var _a, _b, _c, _d, _e, _f, _g, _h;
2588
- const t = (_a = kf.t) != null ? _a : kf.time;
2589
- let v = (_b = kf.v) != null ? _b : kf.value;
2856
+ var _a2;
2857
+ const t = kfTime(kf);
2858
+ let v = kfValue(kf);
2590
2859
  if (propName === "d") v = normalizePathValue(v);
2591
- if (isColour) v = (_c = parseColor(v)) != null ? _c : v;
2592
- const e = (_d = kf.e) != null ? _d : kf.easing;
2860
+ if (isColor) v = (_a2 = parseColor(v)) != null ? _a2 : v;
2861
+ const e = kfEasing(kf);
2593
2862
  const out2 = { t, v, e };
2594
- if ((_e = kf.tangentIn) != null ? _e : kf.ti) out2.tangentIn = (_f = kf.tangentIn) != null ? _f : kf.ti;
2595
- if ((_g = kf.tangentOut) != null ? _g : kf.to) out2.tangentOut = (_h = kf.tangentOut) != null ? _h : kf.to;
2863
+ const tIn = kfTangentIn(kf);
2864
+ const tOut = kfTangentOut(kf);
2865
+ if (tIn) out2.tangentIn = tIn;
2866
+ if (tOut) out2.tangentOut = tOut;
2596
2867
  return out2;
2597
2868
  });
2598
2869
  const expanded = expandLoopKeyframes(propName, kfs, loop, duration);
@@ -2600,15 +2871,15 @@ var PixodeskAnimator = (() => {
2600
2871
  if (propAnim.autoOrient !== void 0) out.autoOrient = propAnim.autoOrient;
2601
2872
  return out;
2602
2873
  }
2603
- function materialiseInternalLoopsInTree(root, duration) {
2604
- const ret = walkAndMaterialiseLoops(root, duration);
2874
+ function materializeInternalLoopsInTree(root, duration) {
2875
+ const ret = walkAndMaterializeLoops(root, duration);
2605
2876
  return ret != null ? ret : root;
2606
2877
  }
2607
- function walkAndMaterialiseLoops(node, duration) {
2878
+ function walkAndMaterializeLoops(node, duration) {
2608
2879
  let newChildren;
2609
2880
  if (node.children) {
2610
2881
  for (let i = 0; i < node.children.length; i++) {
2611
- const ret = walkAndMaterialiseLoops(node.children[i], duration);
2882
+ const ret = walkAndMaterializeLoops(node.children[i], duration);
2612
2883
  if (ret !== null) {
2613
2884
  if (!newChildren) newChildren = node.children.slice();
2614
2885
  newChildren[i] = ret;
@@ -2621,10 +2892,10 @@ var PixodeskAnimator = (() => {
2621
2892
  const animDef = animBucket;
2622
2893
  for (const propName of Object.keys(animDef)) {
2623
2894
  const propAnim = animDef[propName];
2624
- const materialised = materialiseInternalLoopsInPropAnim(propName, propAnim, duration);
2625
- if (materialised !== propAnim) {
2895
+ const materialized = materializeInternalLoopsInPropAnim(propName, propAnim, duration);
2896
+ if (materialized !== propAnim) {
2626
2897
  if (!newAnimate) newAnimate = __spreadValues({}, animDef);
2627
- newAnimate[propName] = materialised;
2898
+ newAnimate[propName] = materialized;
2628
2899
  }
2629
2900
  }
2630
2901
  }
@@ -2643,7 +2914,7 @@ var PixodeskAnimator = (() => {
2643
2914
  const staticParts = staticTransform && typeof staticTransform === "object" && !Array.isArray(staticTransform) ? staticTransform : parseTransformParts(staticTransform);
2644
2915
  if (!staticParts || !Object.keys(staticParts).length) return animDef;
2645
2916
  const mergeKfValue = (v) => v && typeof v === "object" && !Array.isArray(v) ? __spreadValues(__spreadValues({}, staticParts), v) : v;
2646
- const transformAnim = animDef["transform"];
2917
+ const transformAnim = animDef[TRANSFORM_ATTR];
2647
2918
  if (transformAnim && typeof transformAnim === "object") {
2648
2919
  const anim = transformAnim;
2649
2920
  if (Array.isArray(anim.keyframes)) {
@@ -2668,7 +2939,7 @@ var PixodeskAnimator = (() => {
2668
2939
  delete rest[ch];
2669
2940
  return __spreadProps(__spreadValues({}, rest), { transform: lifted });
2670
2941
  }
2671
- function normalizeAnimationDefinition(animDef, duration, defs, engine = PxAnimatorEngine.waapi) {
2942
+ function normalizeAnimationDefinition(animDef, duration, defs, engine = PxTimelineEngine.native) {
2672
2943
  const normalized = {};
2673
2944
  for (const [propName, propAnim] of Object.entries(animDef)) {
2674
2945
  if (propName === "transform" && propAnim.alongPathMode === "offsetPath" && animDef["offsetDistance"] !== void 0) {
@@ -2679,12 +2950,12 @@ var PixodeskAnimator = (() => {
2679
2950
  const out = { keyframes: normalizedKfs };
2680
2951
  if (propAnim.autoOrient !== void 0) out.autoOrient = propAnim.autoOrient;
2681
2952
  if (propAnim.loop !== void 0) out.loop = propAnim.loop;
2682
- normalized[propName] = engine === PxAnimatorEngine.waapi && propName === "transform" ? materialiseMotionPathInPropAnim(out) : out;
2953
+ normalized[propName] = engine === PxTimelineEngine.native && propName === "transform" ? materializeMotionPathInPropAnim(out) : out;
2683
2954
  }
2684
2955
  }
2685
2956
  return normalized;
2686
2957
  }
2687
- function getNormalisedBindings(doc, engine = PxAnimatorEngine.waapi) {
2958
+ function getNormalizedBindings(doc, engine = PxTimelineEngine.native) {
2688
2959
  const animatorConfig = getAnimatorConfig(doc) || {};
2689
2960
  const defs = getDefs(doc);
2690
2961
  const duration = animatorConfig.duration || 1e3;
@@ -2730,12 +3001,12 @@ var PixodeskAnimator = (() => {
2730
3001
  return bindings;
2731
3002
  }
2732
3003
  function getKeyframesPair(keyframes, progress) {
2733
- var _a, _b;
3004
+ var _a2, _b;
2734
3005
  const last = keyframes.length - 1;
2735
3006
  let prevKf = keyframes[0];
2736
3007
  let nextKf = keyframes[last > 0 ? 1 : 0];
2737
3008
  for (let j = 0; j < last; j++) {
2738
- const aOff = (_a = keyframes[j].t) != null ? _a : 0;
3009
+ const aOff = (_a2 = keyframes[j].t) != null ? _a2 : 0;
2739
3010
  const bOff = (_b = keyframes[j + 1].t) != null ? _b : 0;
2740
3011
  if (aOff <= progress && progress <= bOff) {
2741
3012
  prevKf = keyframes[j];
@@ -2750,13 +3021,13 @@ var PixodeskAnimator = (() => {
2750
3021
  return { prevKf, nextKf };
2751
3022
  }
2752
3023
  function calcPropertyValue(propName, propAnim, progress) {
2753
- var _a, _b, _c, _d, _e, _f, _g;
3024
+ var _a2, _b, _c, _d;
2754
3025
  const keyframes = propAnim.keyframes || [];
2755
3026
  if (keyframes.length === 0) return null;
2756
3027
  const { prevKf, nextKf } = getKeyframesPair(keyframes, progress);
2757
- let localProgress = prevKf === nextKf ? 0 : remap(progress, (_a = prevKf.t) != null ? _a : 0, (_b = nextKf.t) != null ? _b : 0, 0, 1);
3028
+ let localProgress = prevKf === nextKf ? 0 : remap(progress, (_a2 = prevKf.t) != null ? _a2 : 0, (_b = nextKf.t) != null ? _b : 0, 0, 1);
2758
3029
  localProgress = clamp(localProgress, 0, 1);
2759
- const easing = (_c = prevKf.e) != null ? _c : prevKf.easing;
3030
+ const easing = kfEasing(prevKf);
2760
3031
  if (easing && Array.isArray(easing)) {
2761
3032
  try {
2762
3033
  localProgress = cubicBezier(easing)(localProgress);
@@ -2765,17 +3036,17 @@ var PixodeskAnimator = (() => {
2765
3036
  }
2766
3037
  let cssAttrName = isCamelCaseWord(propName) ? camelCaseToKebabWordIfNeeded(propName) : propName;
2767
3038
  let cssValue = null;
2768
- const prevV = (_d = prevKf == null ? void 0 : prevKf.v) != null ? _d : prevKf == null ? void 0 : prevKf.value;
2769
- const nextV = (_e = nextKf == null ? void 0 : nextKf.v) != null ? _e : nextKf == null ? void 0 : nextKf.value;
3039
+ const prevV = prevKf == null ? void 0 : prevKf.v;
3040
+ const nextV = nextKf == null ? void 0 : nextKf.v;
2770
3041
  if (cssAttrName === "d") {
2771
- const prevPaths = (_f = prevV == null ? void 0 : prevV.paths) != null ? _f : Array.isArray(prevV) ? prevV : [];
2772
- const nextPaths = (_g = nextV == null ? void 0 : nextV.paths) != null ? _g : Array.isArray(nextV) ? nextV : [];
3042
+ const prevPaths = (_c = prevV == null ? void 0 : prevV.paths) != null ? _c : Array.isArray(prevV) ? prevV : [];
3043
+ const nextPaths = (_d = nextV == null ? void 0 : nextV.paths) != null ? _d : Array.isArray(nextV) ? nextV : [];
2773
3044
  cssValue = interpolateBeziers(
2774
3045
  prevPaths,
2775
3046
  nextPaths,
2776
3047
  localProgress
2777
3048
  ).map((bz) => bezierToSvgPath(bz)).join("");
2778
- } else if (COLOUR_ATTR_NAMES.has(cssAttrName)) {
3049
+ } else if (COLOR_ATTR_NAMES.has(cssAttrName)) {
2779
3050
  cssValue = toRGBA(interpolateColor(
2780
3051
  prevV || [0, 0, 0, 1],
2781
3052
  nextV || [0, 0, 0, 1],
@@ -2872,7 +3143,7 @@ var PixodeskAnimator = (() => {
2872
3143
  return result;
2873
3144
  }
2874
3145
 
2875
- // ../svg-animator-core/src/PxNodeCloneUtil.ts
3146
+ // ../svg-animator-core/src/util/PxNodeCloneUtil.ts
2876
3147
  function deepClonePxNode(value) {
2877
3148
  if (value === null || typeof value !== "object") return value;
2878
3149
  if (Array.isArray(value)) return value.map(deepClonePxNode);
@@ -2883,13 +3154,13 @@ var PixodeskAnimator = (() => {
2883
3154
  function regenerateIdsAndRewriteRefs(root, genId3) {
2884
3155
  const oldToNew = /* @__PURE__ */ new Map();
2885
3156
  const walkAssign = (n) => {
2886
- var _a;
3157
+ var _a2;
2887
3158
  if (typeof n.id === "string") {
2888
3159
  const newId = genId3();
2889
3160
  oldToNew.set(n.id, newId);
2890
3161
  n.id = newId;
2891
3162
  }
2892
- (_a = n.children) == null ? void 0 : _a.forEach(walkAssign);
3163
+ (_a2 = n.children) == null ? void 0 : _a2.forEach(walkAssign);
2893
3164
  };
2894
3165
  walkAssign(root);
2895
3166
  const rewriteUrl = (s) => s.replace(/url\(#([^)]+)\)/g, (m, oldId) => {
@@ -2897,7 +3168,7 @@ var PixodeskAnimator = (() => {
2897
3168
  return newId ? "url(#" + newId + ")" : m;
2898
3169
  });
2899
3170
  const walkRewrite = (n) => {
2900
- var _a;
3171
+ var _a2;
2901
3172
  if (typeof n.href === "string" && n.href.startsWith("#")) {
2902
3173
  const newId = oldToNew.get(n.href.slice(1));
2903
3174
  if (newId) n.href = "#" + newId;
@@ -2909,7 +3180,7 @@ var PixodeskAnimator = (() => {
2909
3180
  n[k] = rewriteUrl(v);
2910
3181
  }
2911
3182
  }
2912
- (_a = n.children) == null ? void 0 : _a.forEach(walkRewrite);
3183
+ (_a2 = n.children) == null ? void 0 : _a2.forEach(walkRewrite);
2913
3184
  };
2914
3185
  walkRewrite(root);
2915
3186
  return oldToNew;
@@ -2919,7 +3190,7 @@ var PixodeskAnimator = (() => {
2919
3190
  return Number.isFinite(n) ? n : 0;
2920
3191
  }
2921
3192
  function applyUseOffsetToG(gNode) {
2922
- var _a;
3193
+ var _a2;
2923
3194
  const x = toFiniteNum(gNode.x);
2924
3195
  const y = toFiniteNum(gNode.y);
2925
3196
  delete gNode.x;
@@ -2928,7 +3199,7 @@ var PixodeskAnimator = (() => {
2928
3199
  const offset = "translate(" + x + "," + y + ")";
2929
3200
  const carriesTransform = gNode.transform !== void 0 || gNode.animate !== void 0;
2930
3201
  if (carriesTransform) {
2931
- const inner = { type: "g", transform: offset, children: (_a = gNode.children) != null ? _a : [] };
3202
+ const inner = { type: "g", transform: offset, children: (_a2 = gNode.children) != null ? _a2 : [] };
2932
3203
  gNode.children = [inner];
2933
3204
  } else {
2934
3205
  gNode.transform = offset;
@@ -2936,9 +3207,9 @@ var PixodeskAnimator = (() => {
2936
3207
  return gNode;
2937
3208
  }
2938
3209
 
2939
- // ../svg-animator-core/src/PxAnimatorUseMaterialiser.ts
2940
- function materialiseAnimatedUseInstances(root) {
2941
- var _a;
3210
+ // ../svg-animator-core/src/materialize/PxAnimatorUseMaterializer.ts
3211
+ function materializeAnimatedUseInstances(root) {
3212
+ var _a2;
2942
3213
  const idMap = buildIdMap(root);
2943
3214
  const animatedIds = computeAnimatedSubtreeIds(root, idMap);
2944
3215
  if (animatedIds.size === 0) return root;
@@ -2946,10 +3217,10 @@ var PixodeskAnimator = (() => {
2946
3217
  const genId3 = () => "_lw_use_mat_" + ++idCounter;
2947
3218
  const rootViewport = readRootViewport(root);
2948
3219
  const defsCollector = [];
2949
- const walked = walkAndMaterialise2(root, idMap, animatedIds, genId3, defsCollector, rootViewport);
3220
+ const walked = walkAndMaterialize2(root, idMap, animatedIds, genId3, defsCollector, rootViewport);
2950
3221
  if (defsCollector.length === 0) return walked;
2951
3222
  const defsNode = { type: "defs", children: defsCollector };
2952
- const newChildren = [...(_a = walked.children) != null ? _a : [], defsNode];
3223
+ const newChildren = [...(_a2 = walked.children) != null ? _a2 : [], defsNode];
2953
3224
  return __spreadProps(__spreadValues({}, walked), { children: newChildren });
2954
3225
  }
2955
3226
  function readRootViewport(root) {
@@ -2971,9 +3242,9 @@ var PixodeskAnimator = (() => {
2971
3242
  function buildIdMap(root) {
2972
3243
  const map = /* @__PURE__ */ new Map();
2973
3244
  const visit = (n) => {
2974
- var _a;
3245
+ var _a2;
2975
3246
  if (typeof n.id === "string") map.set(n.id, n);
2976
- (_a = n.children) == null ? void 0 : _a.forEach(visit);
3247
+ (_a2 = n.children) == null ? void 0 : _a2.forEach(visit);
2977
3248
  };
2978
3249
  visit(root);
2979
3250
  return map;
@@ -3019,16 +3290,16 @@ var PixodeskAnimator = (() => {
3019
3290
  if (typeof href !== "string") return void 0;
3020
3291
  return href.startsWith("#") ? href.slice(1) : href;
3021
3292
  }
3022
- function materialiseOneUse(useNode, target, idMap, animatedIds, genId3, defsCollector, rootViewport) {
3023
- var _a, _b, _c, _d;
3293
+ function materializeOneUse(useNode, target, idMap, animatedIds, genId3, defsCollector, rootViewport) {
3294
+ var _a2, _b, _c, _d;
3024
3295
  const clone2 = deepClonePxNode(target);
3025
3296
  regenerateIdsAndRewriteRefs(clone2, genId3);
3026
3297
  const symbolViewBox = clone2.type === "symbol" ? parseViewBox(clone2.viewBox) : void 0;
3027
- const useW = (_b = (_a = numericAttr(useNode.width)) != null ? _a : symbolViewBox == null ? void 0 : symbolViewBox[2]) != null ? _b : rootViewport[0];
3298
+ const useW = (_b = (_a2 = numericAttr(useNode.width)) != null ? _a2 : symbolViewBox == null ? void 0 : symbolViewBox[2]) != null ? _b : rootViewport[0];
3028
3299
  const useH = (_d = (_c = numericAttr(useNode.height)) != null ? _c : symbolViewBox == null ? void 0 : symbolViewBox[3]) != null ? _d : rootViewport[1];
3029
3300
  const rewrittenClone = clone2.type === "symbol" ? rewriteSymbolRootToGroup(clone2, genId3, defsCollector, useW, useH) : clone2;
3030
- const materialisedClone = walkAndMaterialise2(rewrittenClone, idMap, animatedIds, genId3, defsCollector, rootViewport);
3031
- const newNode = __spreadProps(__spreadValues({}, useNode), { type: "g", children: [materialisedClone] });
3301
+ const materializedClone = walkAndMaterialize2(rewrittenClone, idMap, animatedIds, genId3, defsCollector, rootViewport);
3302
+ const newNode = __spreadProps(__spreadValues({}, useNode), { type: "g", children: [materializedClone] });
3032
3303
  delete newNode.href;
3033
3304
  delete newNode.width;
3034
3305
  delete newNode.height;
@@ -3066,25 +3337,25 @@ var PixodeskAnimator = (() => {
3066
3337
  if (parts.length < 4 || parts.some((n) => !Number.isFinite(n))) return void 0;
3067
3338
  return [parts[0], parts[1], parts[2], parts[3]];
3068
3339
  }
3069
- function walkAndMaterialise2(node, idMap, animatedIds, genId3, defsCollector, rootViewport) {
3340
+ function walkAndMaterialize2(node, idMap, animatedIds, genId3, defsCollector, rootViewport) {
3070
3341
  if (node.type === "use" && typeof node.href === "string") {
3071
3342
  const targetId = stripHash(node.href);
3072
3343
  if (targetId && animatedIds.has(targetId)) {
3073
3344
  const target = idMap.get(targetId);
3074
- if (target) return materialiseOneUse(node, target, idMap, animatedIds, genId3, defsCollector, rootViewport);
3345
+ if (target) return materializeOneUse(node, target, idMap, animatedIds, genId3, defsCollector, rootViewport);
3075
3346
  }
3076
3347
  }
3077
3348
  if (!node.children) return node;
3078
3349
  let changed = false;
3079
3350
  const newChildren = node.children.map((ch) => {
3080
- const m = walkAndMaterialise2(ch, idMap, animatedIds, genId3, defsCollector, rootViewport);
3351
+ const m = walkAndMaterialize2(ch, idMap, animatedIds, genId3, defsCollector, rootViewport);
3081
3352
  if (m !== ch) changed = true;
3082
3353
  return m;
3083
3354
  });
3084
3355
  return changed ? __spreadProps(__spreadValues({}, node), { children: newChildren }) : node;
3085
3356
  }
3086
3357
 
3087
- // ../svg-animator-core/src/effects/transformParts.ts
3358
+ // ../svg-animator-core/src/effects/shared/transformParts.ts
3088
3359
  function partsRecord(part, value, origin) {
3089
3360
  const rec = {};
3090
3361
  if (part === "translate" /* Translate */) rec.translate = value;
@@ -3095,25 +3366,25 @@ var PixodeskAnimator = (() => {
3095
3366
  return rec;
3096
3367
  }
3097
3368
  function readAnimatable(raw) {
3098
- var _a, _b, _c;
3369
+ var _a2, _b;
3099
3370
  if (raw === void 0) return { kind: "absent" /* Absent */ };
3100
3371
  if (Array.isArray(raw)) return { kind: "static" /* Static */, value: raw };
3101
3372
  if (typeof raw === "object") {
3102
3373
  const obj = raw;
3103
- const kfs = (_a = obj.keyframes) != null ? _a : obj.kfs;
3374
+ const kfs = obj.keyframes;
3104
3375
  if (kfs) {
3105
- const out = { kind: "animated" /* Animated */, keyframes: kfs.map(normaliseKeyframe), autoOrient: obj.autoOrient, loop: obj.loop };
3106
- const base = (_b = obj.value) != null ? _b : obj.v;
3376
+ const out = { kind: "animated" /* Animated */, keyframes: kfs.map(normalizeKeyframe), autoOrient: obj.autoOrient, loop: obj.loop };
3377
+ const base = (_a2 = obj.value) != null ? _a2 : obj.v;
3107
3378
  if (base !== void 0 && out.kind === "animated" /* Animated */) out.base = base;
3108
3379
  return out;
3109
3380
  }
3110
- const staticValue = (_c = obj.value) != null ? _c : obj.v;
3381
+ const staticValue = (_b = obj.value) != null ? _b : obj.v;
3111
3382
  if (staticValue !== void 0) return { kind: "static" /* Static */, value: staticValue };
3112
3383
  }
3113
3384
  return { kind: "static" /* Static */, value: raw };
3114
3385
  }
3115
3386
  function writeAnimatableChannel(node, attrName, read, opts) {
3116
- var _a, _b, _c, _d;
3387
+ var _a2, _b, _c, _d;
3117
3388
  const toOut = (v) => (opts == null ? void 0 : opts.asString) && v !== void 0 && v !== null ? String(v) : v;
3118
3389
  if (read.kind === "absent" /* Absent */) return;
3119
3390
  if (read.kind === "static" /* Static */) {
@@ -3127,10 +3398,10 @@ var PixodeskAnimator = (() => {
3127
3398
  if (read.autoOrient !== void 0) block.autoOrient = read.autoOrient;
3128
3399
  animate[attrName] = block;
3129
3400
  node.animate = animate;
3130
- 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;
3401
+ 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;
3131
3402
  if (baseline !== void 0) node[attrName] = toOut(baseline);
3132
3403
  }
3133
- function normaliseKeyframe(kf) {
3404
+ function normalizeKeyframe(kf) {
3134
3405
  if (!kf || typeof kf !== "object") return kf;
3135
3406
  const k = kf;
3136
3407
  if (k.t === void 0 && k.v === void 0 && k.e === void 0 && k.to === void 0 && k.ti === void 0) {
@@ -3145,12 +3416,12 @@ var PixodeskAnimator = (() => {
3145
3416
  return out;
3146
3417
  }
3147
3418
  function readStaticOrigin(raw, ctx) {
3148
- var _a;
3419
+ var _a2;
3149
3420
  const o = readAnimatable(raw);
3150
3421
  if (o.kind === "absent" /* Absent */) return void 0;
3151
3422
  if (o.kind === "static" /* Static */) return o.value;
3152
3423
  ctx.warnings.push("transformBy.origin: animated origin approximated by its first keyframe");
3153
- return (_a = o.keyframes[0]) == null ? void 0 : _a.value;
3424
+ return (_a2 = o.keyframes[0]) == null ? void 0 : _a2.value;
3154
3425
  }
3155
3426
  function keyframeWith(kf, value) {
3156
3427
  const out = { value };
@@ -3161,7 +3432,7 @@ var PixodeskAnimator = (() => {
3161
3432
  return out;
3162
3433
  }
3163
3434
 
3164
- // ../svg-animator-core/src/effects/transformationEffect.ts
3435
+ // ../svg-animator-core/src/effects/transform/transformationEffect.ts
3165
3436
  function applyTransformByEffect(node, fx, ctx) {
3166
3437
  if (!fx) return node;
3167
3438
  delete node.transform;
@@ -3252,7 +3523,7 @@ var PixodeskAnimator = (() => {
3252
3523
  return inner;
3253
3524
  }
3254
3525
 
3255
- // ../svg-animator-core/src/effects/util.ts
3526
+ // ../svg-animator-core/src/effects/shared/util.ts
3256
3527
  function genId(ctx, prefix) {
3257
3528
  return "_lw_" + prefix + "_" + ctx.nextId++;
3258
3529
  }
@@ -3260,9 +3531,9 @@ var PixodeskAnimator = (() => {
3260
3531
  return typeof href === "string" ? href.replace(/^#/, "") : void 0;
3261
3532
  }
3262
3533
  function indexById(node, map) {
3263
- var _a;
3534
+ var _a2;
3264
3535
  if (typeof node.id === "string") map.set(node.id, node);
3265
- (_a = node.children) == null ? void 0 : _a.forEach((child) => indexById(child, map));
3536
+ (_a2 = node.children) == null ? void 0 : _a2.forEach((child) => indexById(child, map));
3266
3537
  }
3267
3538
  function spliceDefs(root, defs) {
3268
3539
  if (!defs.length) return;
@@ -3274,11 +3545,11 @@ var PixodeskAnimator = (() => {
3274
3545
  return regenerateIdsAndRewriteRefs(root, () => genId(ctx, "retimed"));
3275
3546
  }
3276
3547
 
3277
- // ../svg-animator-core/src/effects/contentRefSplit.ts
3548
+ // ../svg-animator-core/src/effects/reference/contentRefSplit.ts
3278
3549
  function identifyContentRefTargets(node, ctx, allocator) {
3279
- var _a, _b, _c;
3280
- if (node.type === "use" && ((_b = (_a = node.effects) == null ? void 0 : _a.clone) == null ? void 0 : _b.type) === "content") {
3281
- const sourceId = stripHash2(node.effects.clone.sourceId);
3550
+ var _a2, _b, _c;
3551
+ if (node.type === "use" && ((_b = (_a2 = node.effects) == null ? void 0 : _a2.clone) == null ? void 0 : _b.without) === "translate") {
3552
+ const sourceId = stripHash2(node.effects.clone.source);
3282
3553
  if (typeof sourceId === "string" && sourceId && !ctx.contentRefInnerIds.has(sourceId)) {
3283
3554
  ctx.contentRefInnerIds.set(sourceId, allocator(sourceId));
3284
3555
  }
@@ -3303,10 +3574,10 @@ var PixodeskAnimator = (() => {
3303
3574
  return outerWrapper;
3304
3575
  }
3305
3576
  function liftBodyTranslate(node, transformBy) {
3306
- var _a, _b, _c;
3577
+ var _a2, _b, _c;
3307
3578
  const out = {};
3308
3579
  let didLiftAnimate = false;
3309
- const animTr = (_a = node.animate) == null ? void 0 : _a.transform;
3580
+ const animTr = (_a2 = node.animate) == null ? void 0 : _a2.transform;
3310
3581
  if (animTr && typeof animTr === "object" && Array.isArray(animTr.keyframes)) {
3311
3582
  const kfs = animTr.keyframes;
3312
3583
  const hasTranslate = kfs.some((kf) => kf.value && kf.value.translate);
@@ -3489,7 +3760,7 @@ var PixodeskAnimator = (() => {
3489
3760
  return false;
3490
3761
  }
3491
3762
 
3492
- // ../svg-animator-core/src/effects/gradientEffect.ts
3763
+ // ../svg-animator-core/src/effects/paint/gradientEffect.ts
3493
3764
  function applyFillGradientEffect(node, fx, ctx) {
3494
3765
  return applyGradient(node, fx, ctx, "fill");
3495
3766
  }
@@ -3524,7 +3795,7 @@ var PixodeskAnimator = (() => {
3524
3795
  return out;
3525
3796
  }
3526
3797
  function applyGeomVec(out, xAttr, yAttr, raw) {
3527
- var _a, _b, _c;
3798
+ var _a2, _b, _c;
3528
3799
  const read = readAnimatable(raw);
3529
3800
  if (read.kind === "absent" /* Absent */) return;
3530
3801
  if (read.kind === "static" /* Static */) {
@@ -3543,7 +3814,7 @@ var PixodeskAnimator = (() => {
3543
3814
  if (read.loop !== void 0) block.loop = read.loop;
3544
3815
  return block;
3545
3816
  };
3546
- const animate = (_a = out.animate) != null ? _a : {};
3817
+ const animate = (_a2 = out.animate) != null ? _a2 : {};
3547
3818
  animate[xAttr] = axisChannel(0);
3548
3819
  animate[yAttr] = axisChannel(1);
3549
3820
  out.animate = animate;
@@ -3559,7 +3830,7 @@ var PixodeskAnimator = (() => {
3559
3830
  writeAnimatableChannel(out, attrName, read, { asString: true });
3560
3831
  }
3561
3832
  function buildStopChildren(stops, ctx) {
3562
- var _a, _b, _c, _d;
3833
+ var _a2, _b;
3563
3834
  if (!stops) return [];
3564
3835
  const read = readAnimatable(stops);
3565
3836
  if (read.kind === "absent" /* Absent */) return [];
@@ -3569,14 +3840,14 @@ var PixodeskAnimator = (() => {
3569
3840
  const loopFromSource = read.loop;
3570
3841
  let stopCount = 0;
3571
3842
  for (const kf of kfs) {
3572
- const v = (_a = kf.value) != null ? _a : kf.v;
3843
+ const v = kfValue(kf);
3573
3844
  if (Array.isArray(v) && v.length > stopCount) stopCount = v.length;
3574
3845
  }
3575
3846
  if (!stopCount) return [];
3576
- const firstKfValue = (_b = kfs[0].value) != null ? _b : kfs[0].v;
3847
+ const firstKfValue = kfValue(kfs[0]);
3577
3848
  const baselineStops = [];
3578
3849
  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" };
3850
+ 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
3851
  baselineStops.push({ offset: s.offset, color: s.color });
3581
3852
  }
3582
3853
  return baselineStops.map((bs, i) => animatedStopNode(bs, kfs, i, ctx, loopFromSource));
@@ -3589,16 +3860,16 @@ var PixodeskAnimator = (() => {
3589
3860
  };
3590
3861
  }
3591
3862
  function animatedStopNode(baseline, kfs, stopIdx, _ctx, loop) {
3592
- var _a, _b, _c, _d, _e;
3863
+ var _a2;
3593
3864
  const colorKfs = [];
3594
3865
  const offsetKfs = [];
3595
3866
  let offsetVaries = false;
3596
3867
  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);
3868
+ const t = kfTime(kf);
3869
+ const arr = kfValue(kf);
3870
+ const sliced = (_a2 = arr == null ? void 0 : arr[stopIdx]) != null ? _a2 : prevDefinedStop(kfs, kfs.indexOf(kf), stopIdx);
3600
3871
  if (!sliced) continue;
3601
- const easing = (_e = kf.easing) != null ? _e : kf.e;
3872
+ const easing = kfEasing(kf);
3602
3873
  const colorOut = { time: t, value: sliced.color };
3603
3874
  if (easing !== void 0) colorOut.easing = easing;
3604
3875
  colorKfs.push(colorOut);
@@ -3625,13 +3896,12 @@ var PixodeskAnimator = (() => {
3625
3896
  return stop;
3626
3897
  }
3627
3898
  function prevDefinedStop(kfs, fromIdx, stopIdx) {
3628
- var _a, _b;
3629
3899
  for (let i = fromIdx; i >= 0; i--) {
3630
- const arr = (_a = kfs[i].value) != null ? _a : kfs[i].v;
3900
+ const arr = kfValue(kfs[i]);
3631
3901
  if (arr == null ? void 0 : arr[stopIdx]) return arr[stopIdx];
3632
3902
  }
3633
3903
  for (let i = fromIdx + 1; i < kfs.length; i++) {
3634
- const arr = (_b = kfs[i].value) != null ? _b : kfs[i].v;
3904
+ const arr = kfValue(kfs[i]);
3635
3905
  if (arr == null ? void 0 : arr[stopIdx]) return arr[stopIdx];
3636
3906
  }
3637
3907
  return void 0;
@@ -3641,12 +3911,12 @@ var PixodeskAnimator = (() => {
3641
3911
  return pct + "%";
3642
3912
  }
3643
3913
 
3644
- // ../svg-animator-core/src/effects/clipPathEffect.ts
3914
+ // ../svg-animator-core/src/effects/clipping/clipPathEffect.ts
3645
3915
  function applyClipPathEffect(node, fx, ctx) {
3646
- if (!(fx == null ? void 0 : fx.d)) return node;
3916
+ if (!(fx == null ? void 0 : fx.pathData)) return node;
3647
3917
  const clipId = genId(ctx, "clip");
3648
3918
  const pathChild = { type: "path" };
3649
- const read = readAnimatable(fx.d);
3919
+ const read = readAnimatable(fx.pathData);
3650
3920
  if (read.kind !== "absent" /* Absent */) {
3651
3921
  if (read.kind === "static" /* Static */) {
3652
3922
  pathChild.d = pathString(read.value);
@@ -3661,16 +3931,16 @@ var PixodeskAnimator = (() => {
3661
3931
  }
3662
3932
  function pathString(v) {
3663
3933
  if (typeof v === "string") return v;
3664
- if (v && typeof v === "object" && typeof v.path === "string") return v.path;
3934
+ if (v && typeof v === "object" && typeof v.pathData === "string") return v.pathData;
3665
3935
  return void 0;
3666
3936
  }
3667
3937
 
3668
- // ../svg-animator-core/src/effects/maskedByEffect.ts
3938
+ // ../svg-animator-core/src/effects/clipping/maskedByEffect.ts
3669
3939
  function applyMaskedByEffect(node, fx, transformBy, ctx) {
3670
3940
  if (!fx) return node;
3671
- const sourceId = stripHash2(fx.sourceId);
3941
+ const sourceId = stripHash2(fx.source);
3672
3942
  if (!sourceId) {
3673
- ctx.errors.push("maskedBy.sourceId missing \u2014 cannot build mask");
3943
+ ctx.errors.push("maskedBy.source missing \u2014 cannot build mask");
3674
3944
  return node;
3675
3945
  }
3676
3946
  const maskId = genId(ctx, "mask");
@@ -3708,8 +3978,8 @@ var PixodeskAnimator = (() => {
3708
3978
  }
3709
3979
  function wrapInversePart(inner, part, raw, origin, ctx) {
3710
3980
  if (raw === void 0) return inner;
3711
- const normalisedRaw = part === "scale" /* Scale */ && Array.isArray(raw) ? [raw[0] / 100, raw[1] / 100] : raw;
3712
- const v = readAnimatable(normalisedRaw);
3981
+ const normalizedRaw = part === "scale" /* Scale */ && Array.isArray(raw) ? [raw[0] / 100, raw[1] / 100] : raw;
3982
+ const v = readAnimatable(normalizedRaw);
3713
3983
  if (v.kind === "static" /* Static */) {
3714
3984
  return { type: "g", transform: { value: partsRecord(part, invertPartValue(part, v.value), origin) }, children: [inner] };
3715
3985
  }
@@ -3733,16 +4003,16 @@ var PixodeskAnimator = (() => {
3733
4003
  return [1 / value[0], 1 / value[1]];
3734
4004
  }
3735
4005
  function negatedSpatialTangents(kf) {
3736
- var _a, _b;
4006
+ var _a2, _b;
3737
4007
  const out = {};
3738
- const to = (_a = kf.tangentOut) != null ? _a : kf.to;
4008
+ const to = (_a2 = kf.tangentOut) != null ? _a2 : kf.to;
3739
4009
  const ti = (_b = kf.tangentIn) != null ? _b : kf.ti;
3740
4010
  if (Array.isArray(to)) out.tangentOut = [-to[0], -to[1]];
3741
4011
  if (Array.isArray(ti)) out.tangentIn = [-ti[0], -ti[1]];
3742
4012
  return out;
3743
4013
  }
3744
4014
  function wrapInverseAnimatedBodyTransform(inner, node, _ctx) {
3745
- var _a;
4015
+ var _a2;
3746
4016
  const animate = node.animate && typeof node.animate === "object" && !Array.isArray(node.animate) ? node.animate : void 0;
3747
4017
  const animTr = animate == null ? void 0 : animate.transform;
3748
4018
  const kfs = animTr && typeof animTr === "object" && Array.isArray(animTr.keyframes) ? animTr.keyframes : void 0;
@@ -3751,7 +4021,7 @@ var PixodeskAnimator = (() => {
3751
4021
  const rotateKfs = [];
3752
4022
  const scaleKfs = [];
3753
4023
  for (const kf of kfs) {
3754
- const v = ((_a = kf.value) != null ? _a : kf.v) || {};
4024
+ const v = ((_a2 = kf.value) != null ? _a2 : kf.v) || {};
3755
4025
  const baseKf = keyframeWith(kf, void 0);
3756
4026
  if (Array.isArray(v.translate)) {
3757
4027
  translateKfs.push(__spreadProps(__spreadValues(__spreadValues({}, baseKf), negatedSpatialTangents(kf)), { value: { translate: [-v.translate[0], -v.translate[1]] } }));
@@ -3815,7 +4085,7 @@ var PixodeskAnimator = (() => {
3815
4085
  return void 0;
3816
4086
  }
3817
4087
  function parseTransformStringToParts(s) {
3818
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m;
4088
+ var _a2, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m;
3819
4089
  const re = /([a-zA-Z]+)\s*\(([^)]*)\)/g;
3820
4090
  let m;
3821
4091
  const ops = [];
@@ -3829,7 +4099,7 @@ var PixodeskAnimator = (() => {
3829
4099
  for (let j = ops.length - 2; j >= 0; j--) {
3830
4100
  const cand = ops[j];
3831
4101
  if (cand.name !== "translate") continue;
3832
- const ox = (_a = cand.args[0]) != null ? _a : 0;
4102
+ const ox = (_a2 = cand.args[0]) != null ? _a2 : 0;
3833
4103
  const oy = (_b = cand.args[1]) != null ? _b : 0;
3834
4104
  const lx = (_c = last.args[0]) != null ? _c : 0;
3835
4105
  const ly = (_d = last.args[1]) != null ? _d : 0;
@@ -3944,8 +4214,8 @@ var PixodeskAnimator = (() => {
3944
4214
  function collectMaskAncestorChains(root, ctx) {
3945
4215
  const interestingNodes = /* @__PURE__ */ new Set();
3946
4216
  const collectInterestingNodes = (n) => {
3947
- var _a, _b;
3948
- const maskSourceId = stripHash2((_b = (_a = n.effects) == null ? void 0 : _a.maskedBy) == null ? void 0 : _b.sourceId);
4217
+ var _a2, _b;
4218
+ const maskSourceId = stripHash2((_b = (_a2 = n.effects) == null ? void 0 : _a2.maskedBy) == null ? void 0 : _b.source);
3949
4219
  if (typeof maskSourceId === "string") {
3950
4220
  interestingNodes.add(n);
3951
4221
  const sourceNode = ctx.idMap.get(maskSourceId);
@@ -3966,7 +4236,7 @@ var PixodeskAnimator = (() => {
3966
4236
  walk(root, []);
3967
4237
  }
3968
4238
  function extractTranslateOnly(node, ctx) {
3969
- var _a, _b, _c;
4239
+ var _a2, _b, _c;
3970
4240
  const tr = node.transform;
3971
4241
  const animateBlock = node.animate && typeof node.animate === "object" && !Array.isArray(node.animate) ? node.animate.transform : void 0;
3972
4242
  if (tr === void 0 && !animateBlock) return void 0;
@@ -3974,7 +4244,7 @@ var PixodeskAnimator = (() => {
3974
4244
  if (typeof tr === "string") {
3975
4245
  const parts = parseTranslateOnlyFromString(tr, ctx);
3976
4246
  if (parts) out.translate = parts;
3977
- } else if (tr && typeof tr === "object" && !tr.keyframes && !tr.kfs) {
4247
+ } else if (tr && typeof tr === "object" && !tr.keyframes) {
3978
4248
  const wrapped = tr.value;
3979
4249
  const value = wrapped && typeof wrapped === "object" ? wrapped : tr;
3980
4250
  if (value && typeof value === "object" && Array.isArray(value.translate)) {
@@ -3988,7 +4258,7 @@ var PixodeskAnimator = (() => {
3988
4258
  const kfs = animateBlock.keyframes;
3989
4259
  const translateKfs = [];
3990
4260
  for (const kf of kfs) {
3991
- const v = (_a = kf.value) != null ? _a : kf.v;
4261
+ const v = (_a2 = kf.value) != null ? _a2 : kf.v;
3992
4262
  const t = (_c = (_b = kf.time) != null ? _b : kf.t) != null ? _c : 0;
3993
4263
  if (v && typeof v === "object" && Array.isArray(v.translate)) {
3994
4264
  translateKfs.push({ time: t, value: [v.translate[0] || 0, v.translate[1] || 0] });
@@ -4022,16 +4292,15 @@ var PixodeskAnimator = (() => {
4022
4292
  return seen ? [x, y] : void 0;
4023
4293
  }
4024
4294
 
4025
- // ../svg-animator-core/src/effects/refEffect.ts
4026
- var CONTENT_SUBREF = "content";
4295
+ // ../svg-animator-core/src/effects/reference/refEffect.ts
4027
4296
  function applyRefHref(node, clone2, ctx) {
4028
4297
  if (!clone2) return;
4029
- const sourceId = stripHash2(clone2.sourceId);
4298
+ const sourceId = stripHash2(clone2.source);
4030
4299
  if (!sourceId) {
4031
- if (clone2.type === CONTENT_SUBREF) ctx.errors.push("clone: content ref missing sourceId");
4300
+ if (clone2.without === PxCloneWithout.translate) ctx.errors.push("clone: content ref missing `source`");
4032
4301
  return;
4033
4302
  }
4034
- const targetId = clone2.type === CONTENT_SUBREF ? ctx.contentRefInnerIds.get(sourceId) || sourceId : sourceId;
4303
+ const targetId = clone2.without === PxCloneWithout.translate ? ctx.contentRefInnerIds.get(sourceId) || sourceId : sourceId;
4035
4304
  node.href = "#" + targetId;
4036
4305
  }
4037
4306
  function applyRefAndTransformationEffect(node, clone2, transformBy, ctx) {
@@ -4039,11 +4308,11 @@ var PixodeskAnimator = (() => {
4039
4308
  return applyTransformByEffect(node, transformBy, ctx);
4040
4309
  }
4041
4310
 
4042
- // ../svg-animator-core/src/effects/repeaterEffect.ts
4311
+ // ../svg-animator-core/src/effects/transform/repeaterEffect.ts
4043
4312
  function applyRepeaterEffect(node, fx, ctx) {
4044
- var _a, _b;
4313
+ var _a2, _b;
4045
4314
  if (!fx) return node;
4046
- const copies = (_a = fx.copies) != null ? _a : 1;
4315
+ const copies = (_a2 = fx.copies) != null ? _a2 : 1;
4047
4316
  if (copies < 1) {
4048
4317
  ctx.errors.push("repeater.copies invalid: " + fx.copies);
4049
4318
  return node;
@@ -4110,11 +4379,11 @@ var PixodeskAnimator = (() => {
4110
4379
  return mapAnimatable(raw, scalePower, true);
4111
4380
  }
4112
4381
 
4113
- // ../svg-animator-core/src/effects/retimeEffect.ts
4114
- var RETIME_MATERIALISATION_MODE_INLINE_G = false;
4382
+ // ../svg-animator-core/src/effects/reference/retimeEffect.ts
4383
+ var RETIME_MATERIALIZATION_MODE_INLINE_G = false;
4115
4384
  function asRetime(r) {
4116
- var _a, _b;
4117
- return { start: (_a = r.start) != null ? _a : 0, stretch: (_b = r.stretch) != null ? _b : 1 };
4385
+ var _a2, _b;
4386
+ return { start: (_a2 = r.start) != null ? _a2 : 0, stretch: (_b = r.stretch) != null ? _b : 1 };
4118
4387
  }
4119
4388
  var CROP_EDGE_MS = 1;
4120
4389
  function applyTimeCrop(useNode, crop, ctx) {
@@ -4142,12 +4411,12 @@ var PixodeskAnimator = (() => {
4142
4411
  };
4143
4412
  }
4144
4413
  function readCloneRetime(n) {
4145
- var _a, _b;
4146
- return (_b = (_a = n.effects) == null ? void 0 : _a.clone) == null ? void 0 : _b.retime;
4414
+ var _a2, _b;
4415
+ return (_b = (_a2 = n.effects) == null ? void 0 : _a2.clone) == null ? void 0 : _b.retime;
4147
4416
  }
4148
4417
  function clearCloneRetime(n) {
4149
- var _a;
4150
- const clone2 = (_a = n.effects) == null ? void 0 : _a.clone;
4418
+ var _a2;
4419
+ const clone2 = (_a2 = n.effects) == null ? void 0 : _a2.clone;
4151
4420
  if (!clone2) return;
4152
4421
  delete clone2.retime;
4153
4422
  if (Object.keys(clone2).length === 0) delete n.effects.clone;
@@ -4158,9 +4427,9 @@ var PixodeskAnimator = (() => {
4158
4427
  indexById(root, ctx.idMap);
4159
4428
  const sites = [];
4160
4429
  const collect = (n) => {
4161
- var _a;
4430
+ var _a2;
4162
4431
  if (readCloneRetime(n)) sites.push(n);
4163
- (_a = n.children) == null ? void 0 : _a.forEach(collect);
4432
+ (_a2 = n.children) == null ? void 0 : _a2.forEach(collect);
4164
4433
  };
4165
4434
  collect(root);
4166
4435
  const reachCount = /* @__PURE__ */ new Map();
@@ -4168,7 +4437,7 @@ var PixodeskAnimator = (() => {
4168
4437
  let count = 0;
4169
4438
  const visited = /* @__PURE__ */ new Set();
4170
4439
  const walk = (n) => {
4171
- var _a;
4440
+ var _a2;
4172
4441
  if (!n) return;
4173
4442
  if (n !== site && readCloneRetime(n)) count++;
4174
4443
  if (n.type === "use" && n.href) {
@@ -4178,7 +4447,7 @@ var PixodeskAnimator = (() => {
4178
4447
  walk(ctx.idMap.get(id));
4179
4448
  }
4180
4449
  }
4181
- (_a = n.children) == null ? void 0 : _a.forEach(walk);
4450
+ (_a2 = n.children) == null ? void 0 : _a2.forEach(walk);
4182
4451
  };
4183
4452
  const rootId = stripHash2(site.href);
4184
4453
  if (rootId) {
@@ -4188,19 +4457,19 @@ var PixodeskAnimator = (() => {
4188
4457
  reachCount.set(site, count);
4189
4458
  }
4190
4459
  sites.sort((a, b) => {
4191
- var _a, _b;
4192
- return ((_a = reachCount.get(b)) != null ? _a : 0) - ((_b = reachCount.get(a)) != null ? _b : 0);
4460
+ var _a2, _b;
4461
+ return ((_a2 = reachCount.get(b)) != null ? _a2 : 0) - ((_b = reachCount.get(a)) != null ? _b : 0);
4193
4462
  });
4194
4463
  for (const useNode of sites) {
4195
4464
  const retime = readCloneRetime(useNode);
4196
4465
  if (!retime) continue;
4197
4466
  const crop = retime.timeCrop;
4198
4467
  clearCloneRetime(useNode);
4199
- materialiseRetime(useNode, asRetime(retime), ctx);
4468
+ materializeRetime(useNode, asRetime(retime), ctx);
4200
4469
  if (crop) applyTimeCrop(useNode, crop, ctx);
4201
4470
  }
4202
4471
  }
4203
- function materialiseRetime(useNode, retime, ctx) {
4472
+ function materializeRetime(useNode, retime, ctx) {
4204
4473
  const targetId = stripHash2(useNode.href);
4205
4474
  if (!targetId) {
4206
4475
  ctx.errors.push("retime: <use> has no href to follow");
@@ -4208,7 +4477,7 @@ var PixodeskAnimator = (() => {
4208
4477
  }
4209
4478
  const chainRootId = buildChainClone(targetId, retime, ctx, /* @__PURE__ */ new Set());
4210
4479
  if (!chainRootId) return;
4211
- if (RETIME_MATERIALISATION_MODE_INLINE_G) {
4480
+ if (RETIME_MATERIALIZATION_MODE_INLINE_G) {
4212
4481
  const cloneNode = ctx.idMap.get(chainRootId);
4213
4482
  useNode.type = "g";
4214
4483
  delete useNode.href;
@@ -4248,15 +4517,15 @@ var PixodeskAnimator = (() => {
4248
4517
  if (subId2) cloneNode.href = "#" + subId2;
4249
4518
  }
4250
4519
  } else {
4251
- materialiseNestedRetimeUses(cloneNode, accum, ctx, chain, targetId);
4520
+ materializeNestedRetimeUses(cloneNode, accum, ctx, chain, targetId);
4252
4521
  }
4253
4522
  ctx.defs.push(cloneNode);
4254
4523
  if (typeof cloneNode.id === "string") ctx.idMap.set(cloneNode.id, cloneNode);
4255
4524
  return typeof cloneNode.id === "string" ? cloneNode.id : void 0;
4256
4525
  }
4257
- function materialiseNestedRetimeUses(node, accum, ctx, chain, parentTargetId) {
4526
+ function materializeNestedRetimeUses(node, accum, ctx, chain, parentTargetId) {
4258
4527
  const visit = (n) => {
4259
- var _a;
4528
+ var _a2;
4260
4529
  const retime = readCloneRetime(n);
4261
4530
  if (n.type === "use" && retime && n.href) {
4262
4531
  const subId = stripHash2(n.href);
@@ -4269,14 +4538,14 @@ var PixodeskAnimator = (() => {
4269
4538
  }
4270
4539
  clearCloneRetime(n);
4271
4540
  }
4272
- (_a = n.children) == null ? void 0 : _a.forEach(visit);
4541
+ (_a2 = n.children) == null ? void 0 : _a2.forEach(visit);
4273
4542
  };
4274
4543
  visit(node);
4275
4544
  }
4276
4545
  function remapKeyframeTimes(node, start, stretch) {
4277
- var _a;
4546
+ var _a2;
4278
4547
  remapKeyframeTimesOnly(node, start, stretch);
4279
- (_a = node.children) == null ? void 0 : _a.forEach((c) => remapKeyframeTimes(c, start, stretch));
4548
+ (_a2 = node.children) == null ? void 0 : _a2.forEach((c) => remapKeyframeTimes(c, start, stretch));
4280
4549
  }
4281
4550
  function remapKeyframeTimesOnly(node, start, stretch) {
4282
4551
  const remap2 = (kfs) => {
@@ -4293,7 +4562,7 @@ var PixodeskAnimator = (() => {
4293
4562
  }
4294
4563
  }
4295
4564
 
4296
- // ../svg-animator-core/src/effects/pathSampler.ts
4565
+ // ../svg-animator-core/src/effects/text/pathSampler.ts
4297
4566
  var LUT_STEPS = 48;
4298
4567
  var CMD_RE = /[MmLlHhVvCcSsQqTtAaZz]/;
4299
4568
  function tokenize(d) {
@@ -4441,7 +4710,7 @@ var PixodeskAnimator = (() => {
4441
4710
  };
4442
4711
  }
4443
4712
 
4444
- // ../svg-animator-core/src/effects/textPathEffect.ts
4713
+ // ../svg-animator-core/src/effects/text/textPathEffect.ts
4445
4714
  var EXTEND_MARGIN_FRAC = 0.15;
4446
4715
  function numRange(v) {
4447
4716
  const read = readAnimatable(v);
@@ -4455,10 +4724,10 @@ var PixodeskAnimator = (() => {
4455
4724
  function estimateTextAdvance(node) {
4456
4725
  let chars = 0, maxFont = 16;
4457
4726
  const walk = (el) => {
4458
- var _a, _b;
4459
- const fs = parseFloat(String((_a = el.fontSize) != null ? _a : "")) || 0;
4727
+ var _a2;
4728
+ const fs = parseFloat(String((_a2 = el.fontSize) != null ? _a2 : "")) || 0;
4460
4729
  if (fs) maxFont = Math.max(maxFont, fs);
4461
- const t = (_b = el.text) != null ? _b : el.textContent;
4730
+ const t = el.textContent;
4462
4731
  if (typeof t === "string") chars += t.length;
4463
4732
  if (el.children) for (const c of el.children) walk(c);
4464
4733
  };
@@ -4480,14 +4749,14 @@ var PixodeskAnimator = (() => {
4480
4749
  return out;
4481
4750
  }
4482
4751
  function extendedPathForBrowser(pathD, opts) {
4483
- var _a;
4752
+ var _a2;
4484
4753
  if (opts.pathOverflow === "clip") return { d: pathD, startShift: 0 };
4485
4754
  const sampler = createPathSampler(pathD);
4486
4755
  if (!sampler || sampler.closed || sampler.totalLength <= 0) return { d: pathD, startShift: 0 };
4487
4756
  const L = sampler.totalLength;
4488
4757
  const margin = EXTEND_MARGIN_FRAC * L;
4489
4758
  const so = numRange(opts.startOffset);
4490
- const runWidth = numRange(opts.textLength).max || ((_a = opts.advance) != null ? _a : 0);
4759
+ const runWidth = numRange(opts.textLength).max || ((_a2 = opts.advance) != null ? _a2 : 0);
4491
4760
  const startOverflow = Math.max(0, -so.min);
4492
4761
  const endOverflow = Math.max(0, so.max + runWidth - L);
4493
4762
  const startExt = startOverflow > 0 ? startOverflow + margin : 0;
@@ -4508,10 +4777,10 @@ var PixodeskAnimator = (() => {
4508
4777
  return { d, startShift: startExt };
4509
4778
  }
4510
4779
  function applyTextPathEffect(node, fx, ctx) {
4511
- var _a;
4512
- if (!fx || typeof fx.path !== "string" || !fx.path) return node;
4780
+ var _a2;
4781
+ if (!fx || typeof fx.pathData !== "string" || !fx.pathData) return node;
4513
4782
  const pathId = genId(ctx, "tpath");
4514
- const { d, startShift } = extendedPathForBrowser(fx.path, {
4783
+ const { d, startShift } = extendedPathForBrowser(fx.pathData, {
4515
4784
  pathOverflow: fx.pathOverflow,
4516
4785
  startOffset: fx.startOffset,
4517
4786
  textLength: fx.textLength,
@@ -4521,7 +4790,7 @@ var PixodeskAnimator = (() => {
4521
4790
  const textPath = {
4522
4791
  type: "textPath",
4523
4792
  href: "#" + pathId,
4524
- children: (_a = node.children) != null ? _a : []
4793
+ children: (_a2 = node.children) != null ? _a2 : []
4525
4794
  };
4526
4795
  if (fx.lengthAdjust !== void 0) textPath.lengthAdjust = fx.lengthAdjust;
4527
4796
  if (fx.method !== void 0) textPath.method = fx.method;
@@ -4536,7 +4805,7 @@ var PixodeskAnimator = (() => {
4536
4805
  writeAnimatableChannel(node, attrName, readAnimatable(raw), { asString: true });
4537
4806
  }
4538
4807
 
4539
- // ../svg-animator-core/src/effects/elementFactory.ts
4808
+ // ../svg-animator-core/src/effects/text/elementFactory.ts
4540
4809
  var jsonElementFactory = (type, props, children) => {
4541
4810
  const node = { type };
4542
4811
  for (const k in props) if (props[k] !== void 0) node[k] = props[k];
@@ -4545,7 +4814,7 @@ var PixodeskAnimator = (() => {
4545
4814
  return node;
4546
4815
  };
4547
4816
 
4548
- // ../svg-animator-core/src/effects/glyphPathBake.ts
4817
+ // ../svg-animator-core/src/effects/text/glyphPathBake.ts
4549
4818
  function fmt(v, decimals) {
4550
4819
  return Math.round(v) === v ? "" + Math.round(v) : v.toFixed(decimals);
4551
4820
  }
@@ -4591,7 +4860,7 @@ var PixodeskAnimator = (() => {
4591
4860
  return out;
4592
4861
  }
4593
4862
 
4594
- // ../svg-animator-core/src/effects/textGlyphsEffect.ts
4863
+ // ../svg-animator-core/src/effects/text/textGlyphsEffect.ts
4595
4864
  var DEFAULT_FONT_SIZE = 16;
4596
4865
  var TEXT_ATTR_KEYS = [
4597
4866
  "fontFamily",
@@ -4613,7 +4882,6 @@ var PixodeskAnimator = (() => {
4613
4882
  "stroke",
4614
4883
  "strokeWidth",
4615
4884
  "effects",
4616
- TEXT_ATTR,
4617
4885
  TEXT_CONTENT_ATTR,
4618
4886
  "xml:space"
4619
4887
  ];
@@ -4651,15 +4919,15 @@ var PixodeskAnimator = (() => {
4651
4919
  return out;
4652
4920
  }
4653
4921
  function resolveStyle2(node, parent) {
4654
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
4922
+ var _a2, _b, _c, _d, _e, _f, _g, _h, _i, _j;
4655
4923
  const isTextRoot = node.type === "text";
4656
4924
  const nodeStyle = node.style;
4657
4925
  const own = (key) => {
4658
- var _a2;
4659
- return isTextRoot ? void 0 : (_a2 = node[key]) != null ? _a2 : nodeStyle == null ? void 0 : nodeStyle[key];
4926
+ var _a3;
4927
+ return isTextRoot ? void 0 : (_a3 = node[key]) != null ? _a3 : nodeStyle == null ? void 0 : nodeStyle[key];
4660
4928
  };
4661
4929
  const res = {
4662
- fontFamily: (_a = str(node.fontFamily)) != null ? _a : parent.fontFamily,
4930
+ fontFamily: (_a2 = str(node.fontFamily)) != null ? _a2 : parent.fontFamily,
4663
4931
  fontSize: (_b = parseLen(node.fontSize)) != null ? _b : parent.fontSize,
4664
4932
  fill: (_c = node.fill) != null ? _c : parent.fill,
4665
4933
  stroke: (_d = node.stroke) != null ? _d : parent.stroke,
@@ -4676,10 +4944,10 @@ var PixodeskAnimator = (() => {
4676
4944
  return res;
4677
4945
  }
4678
4946
  function rootStyleOf(node) {
4679
- var _a, _b, _c;
4947
+ var _a2, _b, _c;
4680
4948
  return {
4681
4949
  fontFamily: str(node.fontFamily),
4682
- fontSize: (_a = parseLen(node.fontSize)) != null ? _a : DEFAULT_FONT_SIZE,
4950
+ fontSize: (_a2 = parseLen(node.fontSize)) != null ? _a2 : DEFAULT_FONT_SIZE,
4683
4951
  fill: node.fill,
4684
4952
  stroke: node.stroke,
4685
4953
  strokeWidth: node.strokeWidth,
@@ -4700,9 +4968,9 @@ var PixodeskAnimator = (() => {
4700
4968
  return p;
4701
4969
  }
4702
4970
  function glyphFontFor(s, glyphs, soleFont, warnings) {
4703
- var _a;
4971
+ var _a2;
4704
4972
  const gf = s.fontFamily ? glyphs[s.fontFamily] : soleFont;
4705
- if (!gf) warnings == null ? void 0 : warnings.push('textGlyphs: no glyphs for font "' + ((_a = s.fontFamily) != null ? _a : "") + '"');
4973
+ if (!gf) warnings == null ? void 0 : warnings.push('textGlyphs: no glyphs for font "' + ((_a2 = s.fontFamily) != null ? _a2 : "") + '"');
4706
4974
  return gf;
4707
4975
  }
4708
4976
  function soleFontOf(glyphs) {
@@ -4723,26 +4991,26 @@ var PixodeskAnimator = (() => {
4723
4991
  const ix0 = x0 + t, ix1 = x1 - t, iyb = -t, iyt = y1 + t;
4724
4992
  return outer + "M" + ix0 + " " + iyb + "L" + ix0 + " " + iyt + "L" + ix1 + " " + iyt + "L" + ix1 + " " + iyb + "Z";
4725
4993
  }
4726
- function materialiseGlyphTextHorizontal(node, opts) {
4727
- var _a, _b, _c, _d;
4994
+ function materializeGlyphTextHorizontal(node, opts) {
4995
+ var _a2, _b, _c;
4728
4996
  const { glyphs, create = jsonElementFactory, warnings } = opts;
4729
4997
  const soleFont = soleFontOf(glyphs);
4730
- const pen = { x: (_a = parseLen(node.x)) != null ? _a : 0, y: (_b = parseLen(node.y)) != null ? _b : 0 };
4998
+ const pen = { x: (_a2 = parseLen(node.x)) != null ? _a2 : 0, y: (_b = parseLen(node.y)) != null ? _b : 0 };
4731
4999
  const placements = [];
4732
5000
  const lines = [{ start: pen.x, end: pen.x }];
4733
5001
  let line = 0;
4734
5002
  const renderChars = (content, s) => {
4735
- var _a2;
5003
+ var _a3;
4736
5004
  const gf = glyphFontFor(s, glyphs, soleFont, warnings);
4737
5005
  const upm = (gf == null ? void 0 : gf.unitsPerEm) || 1e3;
4738
5006
  const scale = s.fontSize / upm;
4739
- const ascentEm = (_a2 = gf == null ? void 0 : gf.ascent) != null ? _a2 : 0.9 * upm;
5007
+ const ascentEm = (_a3 = gf == null ? void 0 : gf.ascent) != null ? _a3 : 0.9 * upm;
4740
5008
  const paint = paintOf(s);
4741
5009
  for (let i = 0; i < content.length; i++) {
4742
5010
  const ch = content.charAt(i);
4743
5011
  const g = gf == null ? void 0 : gf.glyphs[ch];
4744
- if (g && g.d) {
4745
- placements.push({ glyphD: g.d, m: [scale, 0, 0, scale, pen.x, pen.y], paint, line, x: pen.x, y: pen.y, scale });
5012
+ if (g && g.pathData) {
5013
+ placements.push({ glyphD: g.pathData, m: [scale, 0, 0, scale, pen.x, pen.y], paint, line, x: pen.x, y: pen.y, scale });
4746
5014
  pen.x += g.width * scale;
4747
5015
  } else if (/\S/.test(ch)) {
4748
5016
  const advEm = g && g.width > 0 ? g.width : MISSING_GLYPH_ADVANCE_EM * upm;
@@ -4756,7 +5024,7 @@ var PixodeskAnimator = (() => {
4756
5024
  }
4757
5025
  };
4758
5026
  const walk = (el, parentStyle) => {
4759
- var _a2, _b2, _c2, _d2;
5027
+ var _a3, _b2, _c2;
4760
5028
  const s = resolveStyle2(el, parentStyle);
4761
5029
  const x = parseLen(el.x);
4762
5030
  const y = parseLen(el.y);
@@ -4766,16 +5034,16 @@ var PixodeskAnimator = (() => {
4766
5034
  lines.push({ start: pen.x, end: pen.x });
4767
5035
  }
4768
5036
  if (y !== void 0) pen.y = y;
4769
- pen.x += (_a2 = parseLen(el.dx)) != null ? _a2 : 0;
5037
+ pen.x += (_a3 = parseLen(el.dx)) != null ? _a3 : 0;
4770
5038
  pen.y += (_b2 = parseLen(el.dy)) != null ? _b2 : 0;
4771
- const content = (_c2 = str(el[TEXT_CONTENT_ATTR])) != null ? _c2 : str(el[TEXT_ATTR]);
4772
- if (content && !((_d2 = el.children) == null ? void 0 : _d2.length)) renderChars(content, s);
5039
+ const content = str(el[TEXT_CONTENT_ATTR]);
5040
+ if (content && !((_c2 = el.children) == null ? void 0 : _c2.length)) renderChars(content, s);
4773
5041
  if (el.children) for (const ch of el.children) walk(ch, s);
4774
5042
  };
4775
5043
  const rootStyle = rootStyleOf(node);
4776
5044
  if (node.children) for (const ch of node.children) walk(ch, rootStyle);
4777
- const rootContent = (_c = str(node[TEXT_CONTENT_ATTR])) != null ? _c : str(node[TEXT_ATTR]);
4778
- if (rootContent && !((_d = node.children) == null ? void 0 : _d.length)) renderChars(rootContent, rootStyle);
5045
+ const rootContent = str(node[TEXT_CONTENT_ATTR]);
5046
+ if (rootContent && !((_c = node.children) == null ? void 0 : _c.length)) renderChars(rootContent, rootStyle);
4779
5047
  const anchor = str(node.textAnchor);
4780
5048
  if (anchor === "middle" || anchor === "end") {
4781
5049
  for (const p of placements) {
@@ -4790,21 +5058,21 @@ var PixodeskAnimator = (() => {
4790
5058
  const cells = [];
4791
5059
  let adv = 0;
4792
5060
  const walk = (el, parentStyle) => {
4793
- var _a, _b, _c;
5061
+ var _a2, _b;
4794
5062
  const s = resolveStyle2(el, parentStyle);
4795
- const content = (_a = str(el[TEXT_CONTENT_ATTR])) != null ? _a : str(el[TEXT_ATTR]);
4796
- if (content && !((_b = el.children) == null ? void 0 : _b.length)) {
5063
+ const content = str(el[TEXT_CONTENT_ATTR]);
5064
+ if (content && !((_a2 = el.children) == null ? void 0 : _a2.length)) {
4797
5065
  const gf = glyphFontFor(s, glyphs, soleFont, warnings);
4798
5066
  if (gf) {
4799
5067
  const scale = s.fontSize / gf.unitsPerEm;
4800
- const ascentEm = (_c = gf.ascent) != null ? _c : 0.9 * gf.unitsPerEm;
5068
+ const ascentEm = (_b = gf.ascent) != null ? _b : 0.9 * gf.unitsPerEm;
4801
5069
  const paint = paintOf(s);
4802
5070
  for (let i = 0; i < content.length; i++) {
4803
5071
  const ch = content.charAt(i);
4804
5072
  const g = gf.glyphs[ch];
4805
- if (g && g.d) {
5073
+ if (g && g.pathData) {
4806
5074
  const glyphAdv = g.width * scale;
4807
- cells.push({ glyphD: g.d, widthEm: g.width, scale, paint, midBase: adv + glyphAdv / 2 });
5075
+ cells.push({ glyphD: g.pathData, widthEm: g.width, scale, paint, midBase: adv + glyphAdv / 2 });
4808
5076
  adv += glyphAdv;
4809
5077
  } else if (/\S/.test(ch)) {
4810
5078
  const wEm = g && g.width > 0 ? g.width : MISSING_GLYPH_ADVANCE_EM * gf.unitsPerEm;
@@ -4829,13 +5097,13 @@ var PixodeskAnimator = (() => {
4829
5097
  return [scale * cos, scale * sin, -scale * sin, scale * cos, x - scale * cos * hw - perp * sin, y - scale * sin * hw + perp * cos];
4830
5098
  }
4831
5099
  function alongPathNodeOffsets(node) {
4832
- var _a, _b, _c;
5100
+ var _a2, _b, _c;
4833
5101
  return {
4834
- along: ((_a = parseLen(node.x)) != null ? _a : 0) + ((_b = parseLen(node.dx)) != null ? _b : 0),
5102
+ along: ((_a2 = parseLen(node.x)) != null ? _a2 : 0) + ((_b = parseLen(node.dx)) != null ? _b : 0),
4835
5103
  perp: (_c = parseLen(node.dy)) != null ? _c : 0
4836
5104
  };
4837
5105
  }
4838
- function materialiseGlyphTextAlongPath(node, pathD, startOffset, opts, textLength, pathOverflow) {
5106
+ function materializeGlyphTextAlongPath(node, pathD, startOffset, opts, textLength, pathOverflow) {
4839
5107
  const { glyphs, create = jsonElementFactory, warnings } = opts;
4840
5108
  const sampler = pathD ? createPathSampler(pathD) : null;
4841
5109
  if (!sampler) {
@@ -4871,7 +5139,7 @@ var PixodeskAnimator = (() => {
4871
5139
  return toGroup(node, buildPaths(placements, create, warnings), create);
4872
5140
  }
4873
5141
  function numTrackOf(raw) {
4874
- var _a;
5142
+ var _a2;
4875
5143
  const r = readAnimatable(raw);
4876
5144
  if (r.kind === "animated" /* Animated */ && r.keyframes.length >= 2) {
4877
5145
  const kfs = [...r.keyframes].sort((k1, k2) => (Number(k1.time) || 0) - (Number(k2.time) || 0));
@@ -4894,7 +5162,7 @@ var PixodeskAnimator = (() => {
4894
5162
  }
4895
5163
  };
4896
5164
  }
4897
- const v = r.kind === "animated" /* Animated */ ? Number((_a = r.keyframes[0]) == null ? void 0 : _a.value) || 0 : r.kind === "static" /* Static */ ? Number(r.value) || 0 : 0;
5165
+ const v = r.kind === "animated" /* Animated */ ? Number((_a2 = r.keyframes[0]) == null ? void 0 : _a2.value) || 0 : r.kind === "static" /* Static */ ? Number(r.value) || 0 : 0;
4898
5166
  return { animated: false, times: [], at: () => v };
4899
5167
  }
4900
5168
  function mergeTrackTimes(a, b) {
@@ -4914,8 +5182,8 @@ var PixodeskAnimator = (() => {
4914
5182
  const onPath = (dist) => dist >= 0 && dist <= sampler.totalLength;
4915
5183
  const out = [];
4916
5184
  for (const c of cells) {
4917
- const centred = [c.scale, 0, 0, c.scale, -c.scale * (c.widthEm / 2), 0];
4918
- const d = transformPathData(c.glyphD, centred);
5185
+ const centered = [c.scale, 0, 0, c.scale, -c.scale * (c.widthEm / 2), 0];
5186
+ const d = transformPathData(c.glyphD, centered);
4919
5187
  const sampleKf = (dist, time) => {
4920
5188
  const { x, y, angle } = sampler.sampleAtDistance(dist);
4921
5189
  const cos = Math.cos(angle), sin = Math.sin(angle);
@@ -4970,7 +5238,7 @@ var PixodeskAnimator = (() => {
4970
5238
  return p;
4971
5239
  }
4972
5240
  function missingGlyphProps(isMissing) {
4973
- return isMissing ? { class: MISSING_GLYPH_CLASS_NAME } : {};
5241
+ return isMissing ? { [CLASS_ATTR]: MISSING_GLYPH_CLASS_NAME } : {};
4974
5242
  }
4975
5243
  function buildPaths(placements, create, warnings) {
4976
5244
  if (!placements.length) {
@@ -5010,20 +5278,20 @@ var PixodeskAnimator = (() => {
5010
5278
  function applyTextGlyphsEffect(node, fx, ctx) {
5011
5279
  if (!(fx == null ? void 0 : fx.useGlyphs)) return node;
5012
5280
  if (!ctx.glyphs) {
5013
- ctx.warnings.push("textGlyphs: no definitions.glyphs \u2014 left as native <text>");
5281
+ ctx.warnings.push("textGlyphs: no definitions.fonts \u2014 left as native <text>");
5014
5282
  return node;
5015
5283
  }
5016
- return materialiseGlyphTextHorizontal(node, { glyphs: ctx.glyphs, warnings: ctx.warnings });
5284
+ return materializeGlyphTextHorizontal(node, { glyphs: ctx.glyphs, warnings: ctx.warnings });
5017
5285
  }
5018
5286
  function applyTextGlyphsAlongPath(node, ctx, pathD, startOffset, textLength, pathOverflow) {
5019
5287
  if (!ctx.glyphs) {
5020
- ctx.warnings.push("textGlyphs: no definitions.glyphs");
5288
+ ctx.warnings.push("textGlyphs: no definitions.fonts");
5021
5289
  return null;
5022
5290
  }
5023
- return materialiseGlyphTextAlongPath(node, pathD, startOffset, { glyphs: ctx.glyphs, warnings: ctx.warnings }, textLength, pathOverflow);
5291
+ return materializeGlyphTextAlongPath(node, pathD, startOffset, { glyphs: ctx.glyphs, warnings: ctx.warnings }, textLength, pathOverflow);
5024
5292
  }
5025
5293
 
5026
- // ../svg-animator-core/src/effects/strokeTrimEffect.ts
5294
+ // ../svg-animator-core/src/effects/stroke/strokeTrimEffect.ts
5027
5295
  function applyStrokeTrimEffect(node, strokeTrim, ctx) {
5028
5296
  if (!strokeTrim) return node;
5029
5297
  const combined = strokeTrim.subPaths === PxStrokeTrimSubPaths.combined;
@@ -5159,12 +5427,11 @@ var PixodeskAnimator = (() => {
5159
5427
  ];
5160
5428
  }
5161
5429
  function readScalarValues(r) {
5162
- var _a;
5163
5430
  if (r.kind === "absent" /* Absent */) return [];
5164
5431
  if (r.kind === "static" /* Static */) return [r.value];
5165
5432
  const out = [];
5166
5433
  for (const kf of r.keyframes) {
5167
- const v = (_a = kf.value) != null ? _a : kf.v;
5434
+ const v = kfValue(kf);
5168
5435
  if (typeof v === "number") out.push(v);
5169
5436
  }
5170
5437
  return out;
@@ -5174,14 +5441,11 @@ var PixodeskAnimator = (() => {
5174
5441
  if (read.kind === "static" /* Static */) return { kind: "static" /* Static */, value: map(read.value) };
5175
5442
  return {
5176
5443
  kind: "animated" /* Animated */,
5177
- keyframes: read.keyframes.map((kf) => {
5178
- var _a, _b, _c, _d;
5179
- return {
5180
- time: (_b = (_a = kf.time) != null ? _a : kf.t) != null ? _b : 0,
5181
- value: map((_c = kf.value) != null ? _c : kf.v),
5182
- easing: (_d = kf.easing) != null ? _d : kf.e
5183
- };
5184
- }),
5444
+ keyframes: read.keyframes.map((kf) => ({
5445
+ time: kfTime(kf),
5446
+ value: map(kfValue(kf)),
5447
+ easing: kfEasing(kf)
5448
+ })),
5185
5449
  loop: read.loop
5186
5450
  };
5187
5451
  }
@@ -5191,7 +5455,6 @@ var PixodeskAnimator = (() => {
5191
5455
  }
5192
5456
  var OPACITY_STEP_MS = 10;
5193
5457
  function computeOpacityFromRange(rangeRead) {
5194
- var _a, _b, _c, _d, _e, _f;
5195
5458
  const hide = (v) => v[0] === v[1];
5196
5459
  if (rangeRead.kind === "absent" /* Absent */) return void 0;
5197
5460
  if (rangeRead.kind === "static" /* Static */) return hide(rangeRead.value) ? { kind: "static" /* Static */, value: 0 } : void 0;
@@ -5199,7 +5462,7 @@ var PixodeskAnimator = (() => {
5199
5462
  let anyHide = false;
5200
5463
  let allHide = true;
5201
5464
  for (const kf of kfs) {
5202
- if (hide((_a = kf.value) != null ? _a : kf.v)) anyHide = true;
5465
+ if (hide(kfValue(kf))) anyHide = true;
5203
5466
  else allHide = false;
5204
5467
  }
5205
5468
  if (!anyHide) return void 0;
@@ -5209,10 +5472,10 @@ var PixodeskAnimator = (() => {
5209
5472
  const kf = kfs[i];
5210
5473
  const prevKf = i > 0 ? kfs[i - 1] : void 0;
5211
5474
  const nextKf = i < kfs.length - 1 ? kfs[i + 1] : void 0;
5212
- const t = (_c = (_b = kf.time) != null ? _b : kf.t) != null ? _c : 0;
5213
- const thisHide = hide((_d = kf.value) != null ? _d : kf.v);
5214
- const prevHide = prevKf ? thisHide && hide((_e = prevKf.value) != null ? _e : prevKf.v) : thisHide;
5215
- const nextHide = nextKf ? thisHide && hide((_f = nextKf.value) != null ? _f : nextKf.v) : thisHide;
5475
+ const t = kfTime(kf);
5476
+ const thisHide = hide(kfValue(kf));
5477
+ const prevHide = prevKf ? thisHide && hide(kfValue(prevKf)) : thisHide;
5478
+ const nextHide = nextKf ? thisHide && hide(kfValue(nextKf)) : thisHide;
5216
5479
  if (prevHide && !nextHide) {
5217
5480
  out.push({ time: t, value: 0 });
5218
5481
  out.push({ time: t + OPACITY_STEP_MS, value: 1 });
@@ -5227,14 +5490,11 @@ var PixodeskAnimator = (() => {
5227
5490
  function readRangeWithCrossings(raw) {
5228
5491
  const r = readAnimatable(raw);
5229
5492
  if (r.kind !== "animated" /* Animated */) return r;
5230
- const kfs = r.keyframes.map((kf) => {
5231
- var _a, _b, _c, _d;
5232
- return {
5233
- time: (_b = (_a = kf.time) != null ? _a : kf.t) != null ? _b : 0,
5234
- value: (_c = kf.value) != null ? _c : kf.v,
5235
- easing: (_d = kf.easing) != null ? _d : kf.e
5236
- };
5237
- });
5493
+ const kfs = r.keyframes.map((kf) => ({
5494
+ time: kfTime(kf),
5495
+ value: kfValue(kf),
5496
+ easing: kfEasing(kf)
5497
+ }));
5238
5498
  const hasReverse = kfs.some((kf) => kf.value[0] > kf.value[1]);
5239
5499
  if (!hasReverse) {
5240
5500
  return {
@@ -5331,20 +5591,20 @@ var PixodeskAnimator = (() => {
5331
5591
  return total;
5332
5592
  }
5333
5593
  function segmentLength(path, from, to) {
5334
- var _a, _b, _c, _d;
5594
+ var _a2, _b, _c, _d;
5335
5595
  const v = path.v;
5336
5596
  const p0 = v[from];
5337
5597
  const p3 = v[to];
5338
- const p1 = (_b = (_a = path.o) == null ? void 0 : _a[from]) != null ? _b : p0;
5598
+ const p1 = (_b = (_a2 = path.o) == null ? void 0 : _a2[from]) != null ? _b : p0;
5339
5599
  const p2 = (_d = (_c = path.i) == null ? void 0 : _c[to]) != null ? _d : p3;
5340
5600
  const lut = bezier2D_arcLengthLUT(p0, p1, p2, p3);
5341
5601
  return lut.ds[lut.ds.length - 1];
5342
5602
  }
5343
5603
  var ARC_KAPPA = 0.5522847498307936;
5344
5604
  function shapeToPathD(node) {
5345
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
5605
+ var _a2, _b, _c, _d, _e, _f, _g, _h, _i, _j;
5346
5606
  if (node.type === "rect") {
5347
- const x = Number((_a = node.x) != null ? _a : 0), y = Number((_b = node.y) != null ? _b : 0);
5607
+ const x = Number((_a2 = node.x) != null ? _a2 : 0), y = Number((_b = node.y) != null ? _b : 0);
5348
5608
  const w = Number((_c = node.width) != null ? _c : 0), h = Number((_d = node.height) != null ? _d : 0);
5349
5609
  return "M" + (x + w) + "," + y + "L" + (x + w) + "," + (y + h) + "L" + x + "," + (y + h) + "L" + x + "," + y + "L" + (x + w) + "," + y + "z";
5350
5610
  }
@@ -5362,7 +5622,7 @@ var PixodeskAnimator = (() => {
5362
5622
 
5363
5623
  // ../svg-animator-core/src/effects/PlayerEffectsUtil.ts
5364
5624
  function applyPlayerEffects(root) {
5365
- var _a, _b;
5625
+ var _a2, _b;
5366
5626
  const ctx = {
5367
5627
  defs: [],
5368
5628
  warnings: [],
@@ -5373,8 +5633,8 @@ var PixodeskAnimator = (() => {
5373
5633
  maskAncestorChains: /* @__PURE__ */ new Map(),
5374
5634
  // Resolved engine: `frames` ONLY when explicitly set; auto/waapi/unset →
5375
5635
  // waapi (we're not 100% sure it's frames, and CSS/WAAPI need the inline form).
5376
- engine: ((_a = getAnimatorConfig(root)) == null ? void 0 : _a.mode) === PxAnimatorMode.frames ? PxAnimatorEngine.frames : PxAnimatorEngine.waapi,
5377
- glyphs: (_b = getDefs(root)) == null ? void 0 : _b.glyphs
5636
+ engine: resolveTimelineEngine((_a2 = getAnimatorConfig(root)) == null ? void 0 : _a2.engine),
5637
+ glyphs: (_b = getDefs(root)) == null ? void 0 : _b.fonts
5378
5638
  };
5379
5639
  const working = clone(root);
5380
5640
  indexById(working, ctx.idMap);
@@ -5397,7 +5657,7 @@ var PixodeskAnimator = (() => {
5397
5657
  let consumedByGlyphs = false;
5398
5658
  if (text == null ? void 0 : text.useGlyphs) {
5399
5659
  if (textPath) {
5400
- const pathD = typeof textPath.path === "string" ? textPath.path : void 0;
5660
+ const pathD = typeof textPath.pathData === "string" ? textPath.pathData : void 0;
5401
5661
  const glyphed = applyTextGlyphsAlongPath(n, ctx, pathD, textPath.startOffset, textPath.textLength, textPath.pathOverflow);
5402
5662
  if (glyphed) {
5403
5663
  n = glyphed;
@@ -5430,27 +5690,7 @@ var PixodeskAnimator = (() => {
5430
5690
  return node;
5431
5691
  }
5432
5692
 
5433
- // ../svg-animator-core/src/PxOffsetPathMaterialiser.ts
5434
- var kfTime = (kf) => {
5435
- var _a, _b;
5436
- return (_b = (_a = kf.t) != null ? _a : kf.time) != null ? _b : 0;
5437
- };
5438
- var kfValue = (kf) => {
5439
- var _a;
5440
- return (_a = kf.v) != null ? _a : kf.value;
5441
- };
5442
- var kfEasing = (kf) => {
5443
- var _a;
5444
- return (_a = kf.e) != null ? _a : kf.easing;
5445
- };
5446
- var kfTangentIn = (kf) => {
5447
- var _a;
5448
- return (_a = kf.tangentIn) != null ? _a : kf.ti;
5449
- };
5450
- var kfTangentOut = (kf) => {
5451
- var _a;
5452
- return (_a = kf.tangentOut) != null ? _a : kf.to;
5453
- };
5693
+ // ../svg-animator-core/src/materialize/PxOffsetPathMaterializer.ts
5454
5694
  function cubicAt(p0, c1, c2, p1, t) {
5455
5695
  const u = 1 - t;
5456
5696
  const a = u * u * u, b = 3 * u * u * t, c = 3 * u * t * t, d = t * t * t;
@@ -5474,7 +5714,7 @@ var PixodeskAnimator = (() => {
5474
5714
  return Object.is(r, -0) ? "0" : String(r);
5475
5715
  };
5476
5716
  function buildOffsetPath(propAnim) {
5477
- var _a, _b, _c;
5717
+ var _a2, _b, _c;
5478
5718
  if (propAnim.alongPathMode !== "offsetPath") return void 0;
5479
5719
  const kfs = propAnim.keyframes;
5480
5720
  if (!kfs || kfs.length < 2) return void 0;
@@ -5487,7 +5727,7 @@ var PixodeskAnimator = (() => {
5487
5727
  if (!tr || tr.length < 2) return void 0;
5488
5728
  const parts = Object.keys(v);
5489
5729
  if (parts.some((p) => p !== "translate" && p !== "origin")) return void 0;
5490
- const o = (_a = v == null ? void 0 : v.origin) != null ? _a : [0, 0];
5730
+ const o = (_a2 = v == null ? void 0 : v.origin) != null ? _a2 : [0, 0];
5491
5731
  if (o[0] !== anchor[0] || o[1] !== anchor[1]) return void 0;
5492
5732
  points.push([tr[0] + anchor[0], tr[1] + anchor[1]]);
5493
5733
  }
@@ -5516,9 +5756,9 @@ var PixodeskAnimator = (() => {
5516
5756
  }
5517
5757
  return { pathStr: d, distanceKfs, autoOrient: !!propAnim.autoOrient, anchor };
5518
5758
  }
5519
- function materialiseOffsetPathsInTree(root) {
5759
+ function materializeOffsetPathsInTree(root) {
5520
5760
  const walk = (node) => {
5521
- var _a;
5761
+ var _a2;
5522
5762
  let out = node;
5523
5763
  const anim = node.animate;
5524
5764
  const transform = anim == null ? void 0 : anim["transform"];
@@ -5526,16 +5766,16 @@ var PixodeskAnimator = (() => {
5526
5766
  const built = buildOffsetPath(transform);
5527
5767
  if (built) {
5528
5768
  const newAnimate = __spreadValues({}, anim);
5529
- delete newAnimate["transform"];
5769
+ delete newAnimate[TRANSFORM_ATTR];
5530
5770
  const distance = { keyframes: built.distanceKfs };
5531
5771
  if (transform.loop !== void 0) distance.loop = transform.loop;
5532
- newAnimate["offsetDistance"] = distance;
5772
+ newAnimate[OFFSET_DISTANCE_ATTR] = distance;
5533
5773
  const staticTr = node.transform;
5534
5774
  let newTransform = staticTr;
5535
5775
  if (staticTr && typeof staticTr === "object") {
5536
5776
  const t = __spreadValues({}, staticTr);
5537
- delete t["translate"];
5538
- delete t["origin"];
5777
+ delete t[TRANSFORM_PART.translate];
5778
+ delete t[TRANSFORM_PART.origin];
5539
5779
  newTransform = Object.keys(t).length ? t : void 0;
5540
5780
  }
5541
5781
  out = __spreadProps(__spreadValues({}, node), {
@@ -5551,7 +5791,7 @@ var PixodeskAnimator = (() => {
5551
5791
  else delete out.transform;
5552
5792
  }
5553
5793
  }
5554
- if ((_a = out.children) == null ? void 0 : _a.length) {
5794
+ if ((_a2 = out.children) == null ? void 0 : _a2.length) {
5555
5795
  const children = out.children.map(walk);
5556
5796
  if (children.some((c, i) => c !== out.children[i])) out = __spreadProps(__spreadValues({}, out), { children });
5557
5797
  }
@@ -5560,16 +5800,16 @@ var PixodeskAnimator = (() => {
5560
5800
  return walk(root);
5561
5801
  }
5562
5802
 
5563
- // ../svg-animator-core/src/PxAnimatorMaterialiseAll.ts
5564
- function materialiseAllInTree(doc, engine, opts) {
5565
- var _a, _b;
5803
+ // ../svg-animator-core/src/materialize/PxAnimatorMaterializeAll.ts
5804
+ function materializeAllInTree(doc, engine, opts) {
5805
+ var _a2, _b;
5566
5806
  let root = applyPlayerEffects(doc).root;
5567
- root = materialiseOffsetPathsInTree(root);
5568
- const duration = (_b = (_a = getAnimatorConfig(root)) == null ? void 0 : _a.duration) != null ? _b : DEFAULT_DURATION_MS;
5569
- root = materialiseInternalLoopsInTree(root, duration);
5570
- if (engine === PxAnimatorEngine.waapi) {
5571
- root = materialiseMotionPathsInTree(root, opts == null ? void 0 : opts.motionPath);
5572
- root = materialiseAnimatedUseInstances(root);
5807
+ root = materializeOffsetPathsInTree(root);
5808
+ const duration = (_b = (_a2 = getAnimatorConfig(root)) == null ? void 0 : _a2.duration) != null ? _b : DEFAULT_DURATION_MS;
5809
+ root = materializeInternalLoopsInTree(root, duration);
5810
+ if (engine === PxTimelineEngine.native) {
5811
+ root = materializeMotionPathsInTree(root, opts == null ? void 0 : opts.motionPath);
5812
+ root = materializeAnimatedUseInstances(root);
5573
5813
  root = pruneUnreferencedDefs(root);
5574
5814
  }
5575
5815
  return root;
@@ -5577,9 +5817,9 @@ var PixodeskAnimator = (() => {
5577
5817
  function pruneUnreferencedDefs(root) {
5578
5818
  const stripHash3 = (h) => h.startsWith("#") ? h.slice(1) : h;
5579
5819
  const walk = (n, fn) => {
5580
- var _a;
5820
+ var _a2;
5581
5821
  fn(n);
5582
- (_a = n.children) == null ? void 0 : _a.forEach((c) => walk(c, fn));
5822
+ (_a2 = n.children) == null ? void 0 : _a2.forEach((c) => walk(c, fn));
5583
5823
  };
5584
5824
  let changed = true;
5585
5825
  while (changed) {
@@ -5604,7 +5844,41 @@ var PixodeskAnimator = (() => {
5604
5844
  return root;
5605
5845
  }
5606
5846
 
5607
- // ../svg-animator-core/src/PxFrameLoop.ts
5847
+ // ../svg-animator-core/src/playback/PxPlaybackTime.ts
5848
+ var PX_RATE_REJECTED = "setPlaybackRate: rate must be finite and non-zero";
5849
+ function isValidPlaybackRate(rate) {
5850
+ return Number.isFinite(rate) && rate !== 0;
5851
+ }
5852
+ function seekCeilingMs(durationMs, iterations) {
5853
+ if (!(durationMs > 0)) return 0;
5854
+ if (iterations === Infinity) return Infinity;
5855
+ return durationMs * (iterations > 0 ? iterations : 1);
5856
+ }
5857
+ function progressSpanMs(durationMs, iterations) {
5858
+ if (!(durationMs > 0)) return 0;
5859
+ if (iterations === Infinity) return durationMs;
5860
+ return durationMs * (iterations > 0 ? iterations : 1);
5861
+ }
5862
+ function clampSeekMs(timeMs, ceilingMs) {
5863
+ if (Number.isNaN(timeMs) || timeMs < 0) return 0;
5864
+ if (Number.isFinite(ceilingMs)) return timeMs > ceilingMs ? ceilingMs : timeMs;
5865
+ return Number.isFinite(timeMs) ? timeMs : 0;
5866
+ }
5867
+ function timeToProgress(timeMs, durationMs, iterations) {
5868
+ const span = progressSpanMs(durationMs, iterations);
5869
+ if (!(span > 0) || !Number.isFinite(timeMs)) return 0;
5870
+ if (timeMs <= 0) return 0;
5871
+ if (iterations === Infinity) return timeMs % span / span;
5872
+ return timeMs >= span ? 1 : timeMs / span;
5873
+ }
5874
+ function progressToTimeMs(progress, durationMs, iterations) {
5875
+ const span = progressSpanMs(durationMs, iterations);
5876
+ if (!(span > 0) || !Number.isFinite(progress)) return 0;
5877
+ if (progress <= 0) return 0;
5878
+ return progress >= 1 ? span : progress * span;
5879
+ }
5880
+
5881
+ // ../svg-animator-core/src/playback/PxFrameLoop.ts
5608
5882
  function requestFrame(cb) {
5609
5883
  const g = globalThis;
5610
5884
  if (typeof g.requestAnimationFrame === "function") return g.requestAnimationFrame(cb);
@@ -5619,9 +5893,9 @@ var PixodeskAnimator = (() => {
5619
5893
  g.clearTimeout(handle);
5620
5894
  }
5621
5895
  function createBasicFrameLoopAnimator(doc, adapter, callbacks) {
5622
- var _a;
5896
+ var _a2;
5623
5897
  const config = getAnimatorConfig(doc) || {};
5624
- const bindings = getNormalisedBindings(doc, PxAnimatorEngine.frames);
5898
+ const bindings = getNormalizedBindings(doc, PxTimelineEngine.js);
5625
5899
  const _iterations = config.iterations;
5626
5900
  let iterations = 1;
5627
5901
  if (typeof _iterations === "number") iterations = _iterations || 1;
@@ -5630,7 +5904,7 @@ var PixodeskAnimator = (() => {
5630
5904
  const duration = +(config.duration || DEFAULT_DURATION_MS);
5631
5905
  const totalDuration = duration && iterations ? duration * (iterations === Infinity ? Infinity : iterations) : duration ? (iterations != null ? iterations : 1) * duration : 0;
5632
5906
  const direction = config.direction || "normal";
5633
- const fill = (_a = config.fill) != null ? _a : "forwards";
5907
+ const fill = (_a2 = config.fill) != null ? _a2 : "forwards";
5634
5908
  const fillsForwards = fill === "forwards" || fill === "both";
5635
5909
  const fillsBackwards = fill === "backwards" || fill === "both";
5636
5910
  let timerId = null;
@@ -5692,7 +5966,7 @@ var PixodeskAnimator = (() => {
5692
5966
  }
5693
5967
  }
5694
5968
  const tick = () => {
5695
- var _a2, _b;
5969
+ var _a3, _b;
5696
5970
  if (!adapter.isConnected()) {
5697
5971
  pauseAnim();
5698
5972
  return;
@@ -5708,7 +5982,7 @@ var PixodeskAnimator = (() => {
5708
5982
  renderFrame(0);
5709
5983
  if (!finishCalled) {
5710
5984
  finishCalled = true;
5711
- (_a2 = callbacks == null ? void 0 : callbacks.onFinish) == null ? void 0 : _a2.call(callbacks);
5985
+ (_a3 = callbacks == null ? void 0 : callbacks.onFinish) == null ? void 0 : _a3.call(callbacks);
5712
5986
  }
5713
5987
  return;
5714
5988
  }
@@ -5800,17 +6074,17 @@ var PixodeskAnimator = (() => {
5800
6074
  }
5801
6075
  };
5802
6076
  const cancelAnim = () => {
5803
- var _a2;
6077
+ var _a3;
5804
6078
  pauseAnim();
5805
6079
  timeBeforeLastStartMs = 0;
5806
6080
  lastStartedTs = 0;
5807
6081
  playing = false;
5808
6082
  finishCalled = false;
5809
6083
  renderFrame(timeBeforeLastStartMs);
5810
- (_a2 = callbacks == null ? void 0 : callbacks.onCancel) == null ? void 0 : _a2.call(callbacks);
6084
+ (_a3 = callbacks == null ? void 0 : callbacks.onCancel) == null ? void 0 : _a3.call(callbacks);
5811
6085
  };
5812
6086
  const finishAnim = (callOnFinish = true) => {
5813
- var _a2;
6087
+ var _a3;
5814
6088
  if (Number.isFinite(totalDuration)) {
5815
6089
  timeBeforeLastStartMs = totalDuration;
5816
6090
  } else {
@@ -5825,7 +6099,7 @@ var PixodeskAnimator = (() => {
5825
6099
  renderFrame(fillsForwards ? timeBeforeLastStartMs : 0);
5826
6100
  if (callOnFinish && !finishCalled) {
5827
6101
  finishCalled = true;
5828
- (_a2 = callbacks == null ? void 0 : callbacks.onFinish) == null ? void 0 : _a2.call(callbacks);
6102
+ (_a3 = callbacks == null ? void 0 : callbacks.onFinish) == null ? void 0 : _a3.call(callbacks);
5829
6103
  }
5830
6104
  };
5831
6105
  const api = {
@@ -5835,14 +6109,14 @@ var PixodeskAnimator = (() => {
5835
6109
  return _isPlaying();
5836
6110
  },
5837
6111
  "play": () => {
5838
- var _a2;
6112
+ var _a3;
5839
6113
  startAnim();
5840
- (_a2 = callbacks == null ? void 0 : callbacks.onPlay) == null ? void 0 : _a2.call(callbacks);
6114
+ (_a3 = callbacks == null ? void 0 : callbacks.onPlay) == null ? void 0 : _a3.call(callbacks);
5841
6115
  },
5842
6116
  "pause": () => {
5843
- var _a2;
6117
+ var _a3;
5844
6118
  pauseAnim();
5845
- (_a2 = callbacks == null ? void 0 : callbacks.onPause) == null ? void 0 : _a2.call(callbacks);
6119
+ (_a3 = callbacks == null ? void 0 : callbacks.onPause) == null ? void 0 : _a3.call(callbacks);
5846
6120
  },
5847
6121
  "cancel": () => {
5848
6122
  cancelAnim();
@@ -5851,8 +6125,8 @@ var PixodeskAnimator = (() => {
5851
6125
  finishAnim(true);
5852
6126
  },
5853
6127
  "setPlaybackRate": (rate) => {
5854
- if (!isFinite(rate) || rate === 0) {
5855
- console.warn("setPlaybackRate: rate must be finite and non-zero");
6128
+ if (!isValidPlaybackRate(rate)) {
6129
+ console.warn(PX_RATE_REJECTED);
5856
6130
  return;
5857
6131
  }
5858
6132
  let current = getRawAnimTime();
@@ -5866,29 +6140,272 @@ var PixodeskAnimator = (() => {
5866
6140
  return getAnimCurrentTime();
5867
6141
  },
5868
6142
  "setCurrentTime": (newTime) => {
5869
- if (newTime < 0) newTime = 0;
5870
- if (Number.isFinite(totalDuration) && newTime > totalDuration) newTime = totalDuration;
6143
+ newTime = clampSeekMs(newTime, totalDuration);
5871
6144
  timeBeforeLastStartMs = newTime;
5872
6145
  if (playing) lastStartedTs = Date.now();
5873
6146
  if (!Number.isFinite(totalDuration) || newTime < totalDuration) finishCalled = false;
5874
6147
  renderFrame(getAnimCurrentTime());
5875
6148
  },
6149
+ "getCurrentProgress": () => timeToProgress(getAnimCurrentTime(), duration, iterations),
6150
+ "setCurrentProgress": (progress) => {
6151
+ api.setCurrentTime(progressToTimeMs(progress, duration, iterations));
6152
+ },
5876
6153
  "destroy": () => {
5877
- var _a2;
6154
+ var _a3;
5878
6155
  api.cancel();
5879
- (_a2 = callbacks == null ? void 0 : callbacks.onRemove) == null ? void 0 : _a2.call(callbacks);
6156
+ (_a3 = callbacks == null ? void 0 : callbacks.onRemove) == null ? void 0 : _a3.call(callbacks);
5880
6157
  }
5881
6158
  };
5882
6159
  return api;
5883
6160
  }
5884
6161
 
5885
- // src/PxAnimatorTriggers.ts
5886
- function setupAnimationTriggers(api, config) {
5887
- const { startOn, outAction = "continue", scrollIntoViewThreshold = 0 } = config;
6162
+ // ../svg-animator-core/src/playback/PxDiagnostics.ts
6163
+ var PxDiagnosticKind = {
6164
+ /** The document is wrong — regenerate or repair the file. */
6165
+ document: "document",
6166
+ /** The page or app cannot provide what the document asks for — fix the mount. */
6167
+ host: "host",
6168
+ /** The platform cannot do it and the player degraded — usually nothing to fix. */
6169
+ platform: "platform",
6170
+ /** The call is wrong or self-contradictory — fix the options or props you passed. */
6171
+ usage: "usage",
6172
+ /** The player failed where it did not expect to — report it to us. */
6173
+ internal: "internal"
6174
+ };
6175
+ function asError(error) {
6176
+ return typeof error === "string" ? new Error(error) : error;
6177
+ }
6178
+ function isSilenced(silent, kind) {
6179
+ if (!silent) return false;
6180
+ return silent === true || silent.includes(kind);
6181
+ }
6182
+ function createDiagnostics(config, prefix) {
6183
+ const tag = prefix ? prefix + " " : "";
6184
+ return {
6185
+ warn: (kind, message, detail) => {
6186
+ if (config == null ? void 0 : config.onWarn) {
6187
+ config.onWarn({ kind, message, detail });
6188
+ return;
6189
+ }
6190
+ if (isSilenced(config == null ? void 0 : config.silent, kind)) return;
6191
+ const line = tag + kind + ": " + message;
6192
+ if (detail === void 0) console.warn(line);
6193
+ else console.warn(line, detail);
6194
+ },
6195
+ error: (kind, error) => {
6196
+ const err = asError(error);
6197
+ if (config == null ? void 0 : config.onError) {
6198
+ config.onError({ kind, message: err.message, error: err });
6199
+ return;
6200
+ }
6201
+ if (isSilenced(config == null ? void 0 : config.silent, kind)) return;
6202
+ console.error(tag + kind + ": " + err.message);
6203
+ }
6204
+ };
6205
+ }
6206
+
6207
+ // ../svg-animator-core/src/playback/PxAnimatorConfigPatch.ts
6208
+ var FLAT_ONLY_KEYS = [
6209
+ "timelineSource",
6210
+ "scroll",
6211
+ "trigger",
6212
+ "delay",
6213
+ "iterations",
6214
+ "direction",
6215
+ "fill",
6216
+ "resetOnFinish",
6217
+ "duration",
6218
+ "mode",
6219
+ "frameRate"
6220
+ ];
6221
+ var CONTENT_KEYS = ["definitions", "animateById"];
6222
+ var isPlainObject = (v) => !!v && typeof v === "object" && !Array.isArray(v);
6223
+ var timelineTypeOf = (t) => isPlainObject(t) && typeof t.type === "string" ? t.type : "time";
6224
+ var isScrollish = (type) => type === "scroll" || type === "view";
6225
+ function mergePlain(base, patch) {
6226
+ const out = isPlainObject(base) ? __spreadValues({}, base) : {};
6227
+ for (const key of Object.keys(patch)) {
6228
+ const value = patch[key];
6229
+ if (value === null) {
6230
+ delete out[key];
6231
+ continue;
6232
+ }
6233
+ if (isPlainObject(value)) {
6234
+ out[key] = mergePlain(out[key], value);
6235
+ continue;
6236
+ }
6237
+ out[key] = value;
6238
+ }
6239
+ return out;
6240
+ }
6241
+ function mergeTimeline(base, patch, warn) {
6242
+ const baseType = timelineTypeOf(base);
6243
+ const patchNamesType = isPlainObject(patch) && typeof patch.type === "string";
6244
+ const patchType = patchNamesType ? String(patch.type) : baseType;
6245
+ let merged;
6246
+ if (patchType !== baseType) {
6247
+ const carried = {};
6248
+ if (isPlainObject(base)) {
6249
+ for (const k of PX_TIMELINE_SHARED_KEYS) {
6250
+ if (base[k] !== void 0) carried[k] = base[k];
6251
+ }
6252
+ }
6253
+ merged = mergePlain(carried, patch);
6254
+ } else {
6255
+ merged = mergePlain(base, patch);
6256
+ }
6257
+ if (isScrollish(patchType)) {
6258
+ for (const k of PX_TIME_ONLY_TIMELINE_KEYS) {
6259
+ if (merged[k] === void 0) continue;
6260
+ warn("animator.timeline." + k + ": no slot on a '" + patchType + "' timeline \u2014 dropped");
6261
+ delete merged[k];
6262
+ }
6263
+ if (merged.iterations === "infinite") {
6264
+ warn("animator.timeline.iterations: 'infinite' cannot map onto a scroll range \u2014 dropped");
6265
+ delete merged.iterations;
6266
+ }
6267
+ }
6268
+ return merged;
6269
+ }
6270
+ function foldTimelineOverride(timeline, shortcuts) {
6271
+ let base;
6272
+ if (typeof timeline === "string") {
6273
+ try {
6274
+ base = JSON.parse(timeline);
6275
+ } catch (e) {
6276
+ console.warn("timeline override: not valid JSON \u2014 ignored", e);
6277
+ base = void 0;
6278
+ }
6279
+ } else {
6280
+ base = timeline != null ? timeline : void 0;
6281
+ }
6282
+ const { duration, delay, iterations, startOn } = shortcuts;
6283
+ if (duration === void 0 && delay === void 0 && iterations === void 0 && startOn === void 0) {
6284
+ return base === void 0 ? void 0 : { timeline: base };
6285
+ }
6286
+ const out = isPlainObject(base) ? __spreadValues({}, base) : {};
6287
+ if (duration !== void 0) out.duration = duration;
6288
+ if (delay !== void 0) out.delay = delay;
6289
+ if (iterations !== void 0) out.iterations = iterations;
6290
+ if (startOn !== void 0) {
6291
+ out.trigger = __spreadProps(__spreadValues({}, out.trigger), { startOn });
6292
+ }
6293
+ return { timeline: out };
6294
+ }
6295
+ function mergeAnimatorConfig(base, patch) {
6296
+ const warnings = [];
6297
+ const warn = (m) => warnings.push(m);
6298
+ if (patch === null) return { config: void 0, warnings };
6299
+ if (!isPlainObject(patch) || Object.keys(patch).length === 0) {
6300
+ return { config: base, warnings };
6301
+ }
6302
+ const flatInBase = isPlainObject(base) ? FLAT_ONLY_KEYS.filter((k) => base[k] !== void 0) : [];
6303
+ if (flatInBase.length) {
6304
+ warn("animator: the base carries the flat runtime spelling (" + flatInBase.join(", ") + "); the patch merges the wire spelling only");
6305
+ }
6306
+ const out = isPlainObject(base) ? __spreadValues({}, base) : {};
6307
+ for (const key of Object.keys(patch)) {
6308
+ const value = patch[key];
6309
+ if (value === null) {
6310
+ delete out[key];
6311
+ continue;
6312
+ }
6313
+ if (key === "timeline") {
6314
+ out.timeline = isPlainObject(value) ? mergeTimeline(out.timeline, value, warn) : value;
6315
+ continue;
6316
+ }
6317
+ if (isPlainObject(value)) {
6318
+ out[key] = mergePlain(out[key], value);
6319
+ continue;
6320
+ }
6321
+ out[key] = value;
6322
+ }
6323
+ return { config: out, warnings };
6324
+ }
6325
+ function applyAnimatorConfig(doc, patch, opts) {
6326
+ var _a2, _b;
6327
+ const reset = !!(opts == null ? void 0 : opts.resetDefaults);
6328
+ if (!doc || (patch === void 0 || !reset && (patch === null || !isPlainObject(patch) || !Object.keys(patch).length))) {
6329
+ return { doc, warnings: [] };
6330
+ }
6331
+ const anyDoc = doc;
6332
+ const atRoot = isPlainObject(anyDoc.animator);
6333
+ const atMeta = !atRoot && isPlainObject((_a2 = anyDoc.meta) == null ? void 0 : _a2.animator);
6334
+ const current = atRoot ? anyDoc.animator : atMeta ? anyDoc.meta.animator : void 0;
6335
+ const warnings = [];
6336
+ if (atRoot && isPlainObject((_b = anyDoc.meta) == null ? void 0 : _b.animator)) {
6337
+ warnings.push("animator: doc.meta.animator is shadowed by doc.animator and was not patched");
6338
+ }
6339
+ let base = current;
6340
+ if (reset) {
6341
+ const kept = {};
6342
+ for (const k of CONTENT_KEYS) {
6343
+ if (isPlainObject(current) && current[k] !== void 0) kept[k] = current[k];
6344
+ }
6345
+ base = kept;
6346
+ }
6347
+ const merged = mergeAnimatorConfig(base, patch != null ? patch : {});
6348
+ warnings.push(...merged.warnings);
6349
+ if (merged.config === current) return { doc, warnings };
6350
+ if (atMeta) {
6351
+ return {
6352
+ doc: __spreadProps(__spreadValues({}, anyDoc), { meta: __spreadProps(__spreadValues({}, anyDoc.meta), { animator: merged.config }) }),
6353
+ warnings
6354
+ };
6355
+ }
6356
+ return { doc: __spreadProps(__spreadValues({}, anyDoc), { animator: merged.config }), warnings };
6357
+ }
6358
+
6359
+ // ../svg-animator-core/src/format/PxDocumentDiagnostic.ts
6360
+ var MAX_REPORTED = 6;
6361
+ function diagnoseDocument(doc) {
6362
+ try {
6363
+ return { problems: validateDocument(doc) };
6364
+ } catch (e) {
6365
+ return { problems: [] };
6366
+ }
6367
+ }
6368
+ function reportDocumentDiagnostics(doc, where) {
6369
+ const { problems } = diagnoseDocument(doc);
6370
+ if (!problems.length) return;
6371
+ const shown = problems.slice(0, MAX_REPORTED);
6372
+ const more = problems.length - shown.length;
6373
+ console.warn(
6374
+ 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."
6375
+ );
6376
+ }
6377
+
6378
+ // src/shared/PxAnimatorCallbacks.ts
6379
+ function toEngineCallbacks(inline) {
6380
+ const { onPlay, onPause, onCancel, onFinish, onRemove, onStop, onWarn, onError, silent } = inline != null ? inline : {};
6381
+ const withStop = (own) => own || onStop ? () => {
6382
+ own == null ? void 0 : own();
6383
+ onStop == null ? void 0 : onStop();
6384
+ } : void 0;
6385
+ return {
6386
+ onPlay,
6387
+ onPause: withStop(onPause),
6388
+ onCancel: withStop(onCancel),
6389
+ onFinish: withStop(onFinish),
6390
+ onRemove: withStop(onRemove),
6391
+ onWarn,
6392
+ onError,
6393
+ silent
6394
+ };
6395
+ }
6396
+
6397
+ // src/triggers/PxAnimatorTriggers.ts
6398
+ function setupAnimationTriggers(api, config, diag) {
6399
+ const report = diag != null ? diag : createDiagnostics(void 0, "[PxAnimator]");
6400
+ const cleanups = [];
6401
+ const dispose = () => {
6402
+ for (const undo of cleanups.splice(0)) undo();
6403
+ };
6404
+ const { startOn, outAction, scrollIntoViewThreshold } = resolveTrigger(config);
5888
6405
  const root = api.getRootElement();
5889
6406
  if (!root) {
5890
- console.warn("setupAnimationTriggers: No root element found for animation.");
5891
- return api;
6407
+ report.warn(PxDiagnosticKind.host, "setupAnimationTriggers: No root element found for animation.");
6408
+ return dispose;
5892
6409
  }
5893
6410
  let reversed = false;
5894
6411
  const start = () => {
@@ -5923,6 +6440,7 @@ var PixodeskAnimator = (() => {
5923
6440
  startHandler();
5924
6441
  } else {
5925
6442
  window.addEventListener("load", startHandler, { once: true });
6443
+ cleanups.push(() => window.removeEventListener("load", startHandler));
5926
6444
  }
5927
6445
  break;
5928
6446
  }
@@ -5937,6 +6455,10 @@ var PixodeskAnimator = (() => {
5937
6455
  };
5938
6456
  root.addEventListener("mouseenter", mouseOverHandler);
5939
6457
  root.addEventListener("mouseleave", mouseOutHandler);
6458
+ cleanups.push(() => {
6459
+ root.removeEventListener("mouseenter", mouseOverHandler);
6460
+ root.removeEventListener("mouseleave", mouseOutHandler);
6461
+ });
5940
6462
  break;
5941
6463
  }
5942
6464
  case "click": {
@@ -5948,16 +6470,17 @@ var PixodeskAnimator = (() => {
5948
6470
  }
5949
6471
  };
5950
6472
  root.addEventListener("click", clickHandler);
6473
+ cleanups.push(() => root.removeEventListener("click", clickHandler));
5951
6474
  break;
5952
6475
  }
5953
6476
  case "scrollIntoView": {
5954
6477
  const effectiveRatio = (entry) => {
5955
- var _a, _b;
6478
+ var _a2, _b;
5956
6479
  const target = entry.boundingClientRect;
5957
6480
  const visible = entry.intersectionRect;
5958
6481
  if (!(target == null ? void 0 : target.height) || !visible) return entry.intersectionRatio;
5959
6482
  const live = typeof window !== "undefined" && window.innerHeight ? window.innerHeight : Infinity;
5960
- const declared = (_b = (_a = entry.rootBounds) == null ? void 0 : _a.height) != null ? _b : Infinity;
6483
+ const declared = (_b = (_a2 = entry.rootBounds) == null ? void 0 : _a2.height) != null ? _b : Infinity;
5961
6484
  const viewport = Math.min(live, declared);
5962
6485
  const denom = Math.min(target.height, Number.isFinite(viewport) ? viewport : target.height);
5963
6486
  return denom > 0 ? visible.height / denom : entry.intersectionRatio;
@@ -5979,48 +6502,55 @@ var PixodeskAnimator = (() => {
5979
6502
  { threshold: thresholdSteps }
5980
6503
  );
5981
6504
  observer.observe(root);
6505
+ cleanups.push(() => observer.disconnect());
5982
6506
  break;
5983
6507
  }
5984
6508
  case "programmatic":
5985
6509
  break;
5986
6510
  }
5987
- return api;
6511
+ return dispose;
5988
6512
  }
5989
6513
 
5990
- // src/PxAnimatorFrameLoop.ts
6514
+ // src/engines/PxAnimatorFrameLoop.ts
5991
6515
  function getSelector(id) {
5992
6516
  return "#" + id;
5993
6517
  }
5994
6518
  function createFrameLoopAnimator(doc, adapter, callbacks, rootElement) {
6519
+ var _a2;
5995
6520
  const config = getAnimatorConfig(doc) || {};
6521
+ const diag = createDiagnostics(callbacks, "[PxAnimator]");
5996
6522
  if (!rootElement) {
5997
6523
  if (doc.id) {
5998
6524
  const rootSelector = getSelector(doc.id);
5999
6525
  rootElement = document.querySelector(rootSelector);
6000
- if (!rootElement) console.warn("createFrameLoopAnimator: No root element found for selector: ", rootSelector);
6526
+ if (!rootElement) diag.warn(PxDiagnosticKind.host, "createFrameLoopAnimator: No root element found for selector: " + rootSelector);
6001
6527
  } else {
6002
- console.warn("createFrameLoopAnimator: No root element provided");
6528
+ diag.warn(PxDiagnosticKind.host, "createFrameLoopAnimator: No root element provided");
6003
6529
  }
6004
6530
  }
6005
6531
  const basicApi = createBasicFrameLoopAnimator(
6006
6532
  doc,
6007
- adapter || createDomAdapter(rootElement),
6533
+ adapter || createDomAdapter(rootElement, diag),
6008
6534
  callbacks
6009
6535
  );
6010
6536
  const api = __spreadProps(__spreadValues({}, basicApi), {
6011
6537
  "getRootElement": () => rootElement || null
6012
6538
  });
6013
- if (config.trigger) {
6014
- if (isScrollTimeline(config)) {
6015
- console.warn("scroll timeline: `animator.trigger` is ignored (triggers do not apply to scroll-driven playback)");
6016
- } else {
6017
- setupAnimationTriggers(api, config.trigger);
6018
- }
6539
+ if (isScrollTimeline(config)) {
6540
+ if (config.trigger) diag.warn(PxDiagnosticKind.usage, "scroll timeline: `animator.trigger` is ignored (triggers do not apply to scroll-driven playback)");
6541
+ } else {
6542
+ const detachTriggers = setupAnimationTriggers(api, (_a2 = config.trigger) != null ? _a2 : {}, diag);
6543
+ const destroyEngine = api.destroy.bind(api);
6544
+ api.destroy = () => {
6545
+ detachTriggers();
6546
+ destroyEngine();
6547
+ };
6019
6548
  }
6020
6549
  return api;
6021
6550
  }
6022
- function createDomAdapter(rootElement) {
6551
+ function createDomAdapter(rootElement, diag) {
6023
6552
  const warnedSelectors = /* @__PURE__ */ new Set();
6553
+ const report = diag != null ? diag : createDiagnostics(void 0, "[PxAnimator]");
6024
6554
  const adapter = {
6025
6555
  isConnected: () => {
6026
6556
  if (!rootElement) return true;
@@ -6032,7 +6562,7 @@ var PixodeskAnimator = (() => {
6032
6562
  const elements = (rootElement == null ? void 0 : rootElement.querySelectorAll(selector)) || document.querySelectorAll(selector);
6033
6563
  if (elements.length === 0 && !warnedSelectors.has(selector)) {
6034
6564
  warnedSelectors.add(selector);
6035
- console.warn('setAttribute: No elements found for selector "' + selector + '"');
6565
+ report.warn(PxDiagnosticKind.host, 'setAttribute: No elements found for selector "' + selector + '"');
6036
6566
  }
6037
6567
  for (let i = 0; i < elements.length; i++) {
6038
6568
  const element = elements[i];
@@ -6047,18 +6577,17 @@ var PixodeskAnimator = (() => {
6047
6577
  return adapter;
6048
6578
  }
6049
6579
 
6050
- // src/PxAnimatorWebApi.ts
6580
+ // src/engines/PxAnimatorWebApi.ts
6051
6581
  function createCssKf(kf, t, propName, unsupportedSet) {
6052
- var _a, _b;
6053
- let value = (_a = kf.v) != null ? _a : kf.value;
6054
- const e = (_b = kf.e) != null ? _b : kf.easing;
6582
+ let value = kfValue(kf);
6583
+ const e = kfEasing(kf);
6055
6584
  const cssKf = {
6056
6585
  offset: t,
6057
6586
  easing: e && Array.isArray(e) ? "cubic-bezier(" + e.join(",") + ")" : void 0
6058
6587
  };
6059
6588
  let cssValue;
6060
6589
  let cssKey = propName;
6061
- if (COLOUR_ATTR_NAMES.has(propName) && Array.isArray(value)) {
6590
+ if (COLOR_ATTR_NAMES.has(propName) && Array.isArray(value)) {
6062
6591
  cssValue = toRGBA(value);
6063
6592
  } else if (propName === "transform" && value !== null && typeof value === "object" && !Array.isArray(value)) {
6064
6593
  cssValue = composeTransformParts(value, { withUnits: true });
@@ -6085,11 +6614,11 @@ var PixodeskAnimator = (() => {
6085
6614
  return cssKf;
6086
6615
  }
6087
6616
  function clipKeyframesToDuration(propName, keyframes, duration) {
6088
- var _a, _b, _c, _d, _e;
6617
+ var _a2, _b, _c, _d, _e;
6089
6618
  const result = [];
6090
6619
  for (let i = 0; i < keyframes.length; i++) {
6091
6620
  const kf = keyframes[i];
6092
- const t = (_a = kf.t) != null ? _a : 0;
6621
+ const t = (_a2 = kf.t) != null ? _a2 : 0;
6093
6622
  if (t < 0) {
6094
6623
  const next = keyframes[i + 1];
6095
6624
  if (next && ((_b = next.t) != null ? _b : 0) >= 0) {
@@ -6118,7 +6647,7 @@ var PixodeskAnimator = (() => {
6118
6647
  return result;
6119
6648
  }
6120
6649
  function convertToWebApiKeyframes(animDef, unsupportedSet, config) {
6121
- var _a;
6650
+ var _a2;
6122
6651
  const result = /* @__PURE__ */ new Map();
6123
6652
  for (const [propName, propAnim] of Object.entries(animDef)) {
6124
6653
  const duration = config.duration || 1;
@@ -6126,7 +6655,7 @@ var PixodeskAnimator = (() => {
6126
6655
  const cssKeyframes = [];
6127
6656
  for (let i = 0; i < clippedKeyframes.length; i++) {
6128
6657
  const kf = clippedKeyframes[i];
6129
- const t = clamp(((_a = kf.t) != null ? _a : 0) / duration, 0, 1);
6658
+ const t = clamp(((_a2 = kf.t) != null ? _a2 : 0) / duration, 0, 1);
6130
6659
  const cssKf = createCssKf(kf, t, propName, unsupportedSet);
6131
6660
  if (i === 0 && (cssKf.offset || 0) > 0) {
6132
6661
  cssKeyframes.push(__spreadProps(__spreadValues({}, cssKf), { offset: 0 }));
@@ -6145,18 +6674,19 @@ var PixodeskAnimator = (() => {
6145
6674
  return result;
6146
6675
  }
6147
6676
  function createWebApiAnimator(doc, callbacks, rootElement, forceEvenIfHasUnsupportedAttrs, scrollTimeline) {
6148
- var _a;
6677
+ var _a2, _b;
6149
6678
  const config = getAnimatorConfig(doc) || {};
6679
+ const diag = createDiagnostics(callbacks, "[PxAnimator]");
6150
6680
  if (!rootElement) {
6151
6681
  if (doc.id) {
6152
6682
  const rootSelector = getSelector(doc.id);
6153
6683
  rootElement = document.querySelector(rootSelector);
6154
- if (!rootElement) console.warn("createFrameLoopAnimator: No root element found for selector: ", rootSelector);
6684
+ if (!rootElement) diag.warn(PxDiagnosticKind.host, "createWebApiAnimator: No root element found for selector: " + rootSelector);
6155
6685
  } else {
6156
- console.warn("createFrameLoopAnimator: No root element provided");
6686
+ diag.warn(PxDiagnosticKind.host, "createWebApiAnimator: No root element provided");
6157
6687
  }
6158
6688
  }
6159
- const bindings = getNormalisedBindings(doc, PxAnimatorEngine.waapi);
6689
+ const bindings = getNormalizedBindings(doc, PxTimelineEngine.native);
6160
6690
  const animations = [];
6161
6691
  const _iterations = config.iterations;
6162
6692
  let iterations;
@@ -6166,18 +6696,18 @@ var PixodeskAnimator = (() => {
6166
6696
  let finishNotified = false;
6167
6697
  let removeCalled = false;
6168
6698
  if (!(bindings == null ? void 0 : bindings.length)) {
6169
- console.warn("createWebApiAnimator: No animation bindings defined");
6699
+ diag.warn(PxDiagnosticKind.document, "createWebApiAnimator: No animation bindings defined");
6170
6700
  }
6171
6701
  for (const binding of bindings || []) {
6172
6702
  const animDef = binding.animate;
6173
6703
  if (!animDef || typeof animDef !== "object" || Array.isArray(animDef)) {
6174
- console.warn("createWebApiAnimator: Empty or unresolved binding", binding);
6704
+ diag.warn(PxDiagnosticKind.document, "createWebApiAnimator: Empty or unresolved binding", binding);
6175
6705
  continue;
6176
6706
  }
6177
6707
  const selector = getSelector(binding.id);
6178
6708
  const elements = (rootElement == null ? void 0 : rootElement.querySelectorAll(selector)) || document.querySelectorAll(selector);
6179
6709
  if (elements.length === 0) {
6180
- console.warn('createWebApiAnimator: No elements found for selector "' + selector + '"');
6710
+ diag.warn(PxDiagnosticKind.host, 'createWebApiAnimator: No elements found for selector "' + selector + '"');
6181
6711
  }
6182
6712
  const keyframesMap = convertToWebApiKeyframes(animDef, unsupportedSet, config);
6183
6713
  const positiveDelay = config.delay && config.delay > 0 ? config.delay : void 0;
@@ -6193,7 +6723,7 @@ var PixodeskAnimator = (() => {
6193
6723
  // animation ends — consistent with Lottie and other animation runtimes.
6194
6724
  // Without this, seeking to the last frame reverts elements to their
6195
6725
  // pre-animation state (the Web Animations API "after" phase with fill:'none').
6196
- fill: (_a = config.fill) != null ? _a : "forwards",
6726
+ fill: (_a2 = config.fill) != null ? _a2 : "forwards",
6197
6727
  direction: config.direction,
6198
6728
  iterations
6199
6729
  };
@@ -6210,61 +6740,61 @@ var PixodeskAnimator = (() => {
6210
6740
  if (scrollTimeline.rangeEnd) a.rangeEnd = scrollTimeline.rangeEnd;
6211
6741
  }
6212
6742
  if (callbacks == null ? void 0 : callbacks.onFinish) anim.onfinish = () => {
6213
- var _a2;
6743
+ var _a3;
6214
6744
  if (finishNotified) return;
6215
6745
  finishNotified = true;
6216
- (_a2 = callbacks.onFinish) == null ? void 0 : _a2.call(callbacks);
6746
+ (_a3 = callbacks.onFinish) == null ? void 0 : _a3.call(callbacks);
6217
6747
  };
6218
6748
  if (callbacks == null ? void 0 : callbacks.onRemove) anim.onremove = () => {
6219
- var _a2;
6749
+ var _a3;
6220
6750
  if (removeCalled) return;
6221
6751
  removeCalled = true;
6222
- (_a2 = callbacks.onRemove) == null ? void 0 : _a2.call(callbacks);
6752
+ (_a3 = callbacks.onRemove) == null ? void 0 : _a3.call(callbacks);
6223
6753
  };
6224
6754
  if (seekPosition !== void 0) {
6225
6755
  anim.currentTime = seekPosition;
6226
6756
  }
6227
6757
  animations.push(anim);
6228
6758
  } catch (e) {
6229
- console.warn(e);
6759
+ diag.warn(PxDiagnosticKind.internal, "createWebApiAnimator: could not build the animation", e);
6230
6760
  }
6231
6761
  }
6232
6762
  }
6233
6763
  }
6234
6764
  }
6235
6765
  if (!forceEvenIfHasUnsupportedAttrs && unsupportedSet.size) {
6236
- console.warn("Unsupported CSS attrs: " + [...unsupportedSet].join(", "));
6766
+ diag.warn(PxDiagnosticKind.platform, "Unsupported CSS attrs: " + [...unsupportedSet].join(", "));
6237
6767
  return null;
6238
6768
  }
6239
6769
  const api = {
6240
6770
  "isReady": () => true,
6241
6771
  "getRootElement": () => rootElement || null,
6242
6772
  "isPlaying": () => {
6243
- var _a2;
6244
- return ((_a2 = animations[0]) == null ? void 0 : _a2.playState) === "running";
6773
+ var _a3;
6774
+ return ((_a3 = animations[0]) == null ? void 0 : _a3.playState) === "running";
6245
6775
  },
6246
6776
  "play": () => {
6247
- var _a2;
6777
+ var _a3;
6248
6778
  finishNotified = false;
6249
6779
  animations.forEach((a) => a.play());
6250
- (_a2 = callbacks == null ? void 0 : callbacks.onPlay) == null ? void 0 : _a2.call(callbacks);
6780
+ (_a3 = callbacks == null ? void 0 : callbacks.onPlay) == null ? void 0 : _a3.call(callbacks);
6251
6781
  },
6252
6782
  "pause": () => {
6253
- var _a2;
6783
+ var _a3;
6254
6784
  animations.forEach((a) => a.pause());
6255
- (_a2 = callbacks == null ? void 0 : callbacks.onPause) == null ? void 0 : _a2.call(callbacks);
6785
+ (_a3 = callbacks == null ? void 0 : callbacks.onPause) == null ? void 0 : _a3.call(callbacks);
6256
6786
  },
6257
6787
  "cancel": () => {
6258
- var _a2;
6788
+ var _a3;
6259
6789
  finishNotified = false;
6260
6790
  animations.forEach((a) => a.cancel());
6261
- (_a2 = callbacks == null ? void 0 : callbacks.onCancel) == null ? void 0 : _a2.call(callbacks);
6791
+ (_a3 = callbacks == null ? void 0 : callbacks.onCancel) == null ? void 0 : _a3.call(callbacks);
6262
6792
  },
6263
6793
  "finish": () => {
6264
- var _a2;
6794
+ var _a3;
6265
6795
  for (const a of animations) {
6266
6796
  try {
6267
- if (((_a2 = a.effect) == null ? void 0 : _a2.getTiming().iterations) === Infinity) {
6797
+ if (((_a3 = a.effect) == null ? void 0 : _a3.getTiming().iterations) === Infinity) {
6268
6798
  a.effect.updateTiming({ iterations: 1 });
6269
6799
  a.finish();
6270
6800
  a.effect.updateTiming({ iterations: Infinity });
@@ -6277,36 +6807,55 @@ var PixodeskAnimator = (() => {
6277
6807
  }
6278
6808
  },
6279
6809
  "setPlaybackRate": (rate) => {
6810
+ if (!isValidPlaybackRate(rate)) {
6811
+ diag.warn(PxDiagnosticKind.usage, PX_RATE_REJECTED);
6812
+ return api;
6813
+ }
6280
6814
  animations.forEach((a) => a.playbackRate = rate);
6281
6815
  return api;
6282
6816
  },
6283
6817
  "getCurrentTime": () => {
6284
- var _a2, _b;
6285
- const res = (_b = (_a2 = animations[0]) == null ? void 0 : _a2.currentTime) != null ? _b : null;
6818
+ var _a3, _b2;
6819
+ const res = (_b2 = (_a3 = animations[0]) == null ? void 0 : _a3.currentTime) != null ? _b2 : null;
6286
6820
  return res !== null ? +res : null;
6287
6821
  },
6288
6822
  "setCurrentTime": (time) => {
6823
+ var _a3;
6824
+ const ceiling = seekCeilingMs((_a3 = config.duration) != null ? _a3 : 0, iterations != null ? iterations : 1);
6825
+ const seek = ceiling > 0 ? clampSeekMs(time, ceiling) : Math.max(0, time);
6289
6826
  finishNotified = false;
6290
6827
  animations.forEach((a) => {
6291
- a.currentTime = time;
6828
+ a.currentTime = seek;
6292
6829
  });
6293
6830
  },
6831
+ "getCurrentProgress": () => {
6832
+ var _a3;
6833
+ const t = api.getCurrentTime();
6834
+ return t === null ? null : timeToProgress(t, (_a3 = config.duration) != null ? _a3 : 0, iterations != null ? iterations : 1);
6835
+ },
6836
+ "setCurrentProgress": (progress) => {
6837
+ var _a3;
6838
+ api.setCurrentTime(progressToTimeMs(progress, (_a3 = config.duration) != null ? _a3 : 0, iterations != null ? iterations : 1));
6839
+ },
6294
6840
  "destroy": () => {
6295
- var _a2;
6841
+ var _a3;
6296
6842
  api.cancel();
6297
6843
  animations.splice(0, animations.length);
6298
6844
  if (!removeCalled) {
6299
6845
  removeCalled = true;
6300
- (_a2 = callbacks == null ? void 0 : callbacks.onRemove) == null ? void 0 : _a2.call(callbacks);
6846
+ (_a3 = callbacks == null ? void 0 : callbacks.onRemove) == null ? void 0 : _a3.call(callbacks);
6301
6847
  }
6302
6848
  }
6303
6849
  };
6304
- if (config.trigger) {
6305
- if (config.timelineSource === "scroll") {
6306
- console.warn("scroll timeline: `animator.trigger` is ignored (triggers do not apply to scroll-driven playback)");
6307
- } else {
6308
- setupAnimationTriggers(api, config.trigger);
6309
- }
6850
+ if (config.timelineSource === "scroll") {
6851
+ if (config.trigger) diag.warn(PxDiagnosticKind.usage, "scroll timeline: `animator.trigger` is ignored (triggers do not apply to scroll-driven playback)");
6852
+ } else {
6853
+ const detachTriggers = setupAnimationTriggers(api, (_b = config.trigger) != null ? _b : {}, diag);
6854
+ const destroyEngine = api.destroy.bind(api);
6855
+ api.destroy = () => {
6856
+ detachTriggers();
6857
+ destroyEngine();
6858
+ };
6310
6859
  }
6311
6860
  if (scrollTimeline) {
6312
6861
  animations.forEach((a) => a.play());
@@ -6314,21 +6863,22 @@ var PixodeskAnimator = (() => {
6314
6863
  return api;
6315
6864
  }
6316
6865
 
6317
- // src/PxScrollDriver.ts
6866
+ // src/scroll/PxScrollDriver.ts
6318
6867
  function nativeRangeOffset(point, defaultFraction, view) {
6319
- var _a, _b, _c;
6868
+ var _a2, _b, _c;
6320
6869
  const fraction = typeof (point == null ? void 0 : point.fraction) === "number" ? point.fraction : defaultFraction;
6321
- const pct = (_b = (_a = globalThis.CSS) == null ? void 0 : _a.percent) == null ? void 0 : _b.call(_a, fraction * 100);
6870
+ const pct = (_b = (_a2 = globalThis.CSS) == null ? void 0 : _a2.percent) == null ? void 0 : _b.call(_a2, fraction * 100);
6322
6871
  if (pct === void 0) return void 0;
6323
6872
  return view ? { rangeName: (_c = point == null ? void 0 : point.phase) != null ? _c : "cover", offset: pct } : { offset: pct };
6324
6873
  }
6325
- function createNativeScrollTimeline(subject, config) {
6326
- var _a, _b, _c, _d;
6874
+ function createNativeScrollTimeline(subject, config, diag) {
6875
+ var _a2, _b, _c, _d;
6876
+ const report = diag != null ? diag : createDiagnostics(void 0, "[PxAnimator]");
6327
6877
  if (!config || !isScrollTimeline(config)) return null;
6328
6878
  const scroll = config.scroll || {};
6329
- const kind = (_a = scroll.kind) != null ? _a : "view";
6879
+ const kind = (_a2 = scroll.kind) != null ? _a2 : "view";
6330
6880
  if (scroll.smoothing) {
6331
- console.warn('scroll timeline: `smoothing` needs the built-in driver \u2014 ignoring `driver: "native"`');
6881
+ report.warn(PxDiagnosticKind.platform, "scroll timeline: `smoothing` needs the built-in driver \u2014 using the built-in driver instead of the browser timeline");
6332
6882
  return null;
6333
6883
  }
6334
6884
  const g = globalThis;
@@ -6339,13 +6889,13 @@ var PixodeskAnimator = (() => {
6339
6889
  let timeline;
6340
6890
  try {
6341
6891
  if (view) {
6342
- timeline = new Ctor({ subject: resolveScrollSubject(subject, scroll.subject), axis });
6892
+ timeline = new Ctor({ subject: resolveScrollSubject(subject, scroll.subject, report), axis });
6343
6893
  } else {
6344
6894
  const source = scroll.source === "root" ? documentScroller() : findNearestScroller(subject, "y") || findNearestScroller(subject, "x") || documentScroller();
6345
6895
  timeline = new Ctor({ source, axis });
6346
6896
  }
6347
6897
  } catch (e) {
6348
- console.warn("scroll timeline: native timeline construction failed \u2014 falling back to the custom driver", e);
6898
+ report.warn(PxDiagnosticKind.platform, "scroll timeline: native timeline construction failed \u2014 falling back to the player measuring progress itself", e);
6349
6899
  return null;
6350
6900
  }
6351
6901
  return {
@@ -6372,8 +6922,9 @@ var PixodeskAnimator = (() => {
6372
6922
  }
6373
6923
  var SUBJECT_PARENT = "parent";
6374
6924
  var SUBJECT_SCROLLER = "scroller";
6375
- function resolveScrollSubject(svgRoot, subject) {
6376
- var _a, _b;
6925
+ function resolveScrollSubject(svgRoot, subject, diag) {
6926
+ var _a2, _b;
6927
+ const report = diag != null ? diag : createDiagnostics(void 0, "[PxAnimator]");
6377
6928
  const spec = subject == null ? void 0 : subject.trim();
6378
6929
  if (!spec) return svgRoot;
6379
6930
  if (spec === SUBJECT_PARENT) {
@@ -6382,7 +6933,7 @@ var PixodeskAnimator = (() => {
6382
6933
  const position = getComputedStyle(p).position;
6383
6934
  if (position === "sticky" || position === "fixed") outermostPinned = p;
6384
6935
  }
6385
- return (_b = (_a = outermostPinned == null ? void 0 : outermostPinned.parentElement) != null ? _a : svgRoot.parentElement) != null ? _b : svgRoot;
6936
+ return (_b = (_a2 = outermostPinned == null ? void 0 : outermostPinned.parentElement) != null ? _a2 : svgRoot.parentElement) != null ? _b : svgRoot;
6386
6937
  }
6387
6938
  if (spec === SUBJECT_SCROLLER) {
6388
6939
  return findNearestScroller(svgRoot, "y") || findNearestScroller(svgRoot, "x") || documentScroller();
@@ -6391,21 +6942,22 @@ var PixodeskAnimator = (() => {
6391
6942
  try {
6392
6943
  found = document.querySelector(spec);
6393
6944
  } catch (e) {
6394
- console.warn('scroll timeline: subject "' + spec + '" is not a valid selector \u2014 measuring the SVG itself');
6945
+ report.warn(PxDiagnosticKind.document, 'scroll timeline: subject "' + spec + '" is not a valid selector \u2014 measuring the SVG itself');
6395
6946
  return svgRoot;
6396
6947
  }
6397
6948
  if (!found) {
6398
- console.warn('scroll timeline: subject "' + spec + '" matched no element \u2014 measuring the SVG itself');
6949
+ report.warn(PxDiagnosticKind.host, 'scroll timeline: subject "' + spec + '" matched no element \u2014 measuring the SVG itself');
6399
6950
  return svgRoot;
6400
6951
  }
6401
6952
  return found;
6402
6953
  }
6403
- function createScrollDriver(subject, config, onProgress) {
6404
- var _a, _b;
6954
+ function createScrollDriver(subject, config, onProgress, diag) {
6955
+ var _a2, _b;
6405
6956
  if (!config || !isScrollTimeline(config)) return null;
6957
+ const report = diag != null ? diag : createDiagnostics(void 0, "[PxAnimator]");
6406
6958
  const scroll = config.scroll || {};
6407
- const kind = (_a = scroll.kind) != null ? _a : "view";
6408
- const measured = resolveScrollSubject(subject, scroll.subject);
6959
+ const kind = (_a2 = scroll.kind) != null ? _a2 : "view";
6960
+ const measured = resolveScrollSubject(subject, scroll.subject, report);
6409
6961
  const nearest = findNearestScroller(subject, "y") || findNearestScroller(subject, "x");
6410
6962
  const scroller = kind === "scroll" && scroll.source === "root" ? documentScroller() : nearest || documentScroller();
6411
6963
  const isRootScroller = scroller === documentScroller();
@@ -6523,8 +7075,8 @@ var PixodeskAnimator = (() => {
6523
7075
  style.position = "sticky";
6524
7076
  const alignFactor = scroll.pinAlign === "center" ? 0.5 : scroll.pinAlign === "bottom" ? 1 : 0;
6525
7077
  const applyTop = () => {
6526
- var _a;
6527
- const extra = (_a = scroll.pinTop) != null ? _a : 0;
7078
+ var _a2;
7079
+ const extra = (_a2 = scroll.pinOffset) != null ? _a2 : 0;
6528
7080
  if (!alignFactor) {
6529
7081
  style.top = extra + "px";
6530
7082
  return;
@@ -6564,42 +7116,43 @@ var PixodeskAnimator = (() => {
6564
7116
  };
6565
7117
  }
6566
7118
 
6567
- // src/PxAnimatorBind.ts
7119
+ // src/engines/PxAnimatorBind.ts
6568
7120
  function finaliseAnimator(animatorConfig, callbacks, make) {
6569
7121
  let apiRef;
6570
7122
  let effectiveCallbacks = callbacks;
6571
7123
  if (animatorConfig.resetOnFinish) {
6572
7124
  effectiveCallbacks = __spreadProps(__spreadValues({}, callbacks), {
6573
7125
  onFinish: () => {
6574
- var _a;
6575
- (_a = callbacks == null ? void 0 : callbacks.onFinish) == null ? void 0 : _a.call(callbacks);
7126
+ var _a2;
7127
+ (_a2 = callbacks == null ? void 0 : callbacks.onFinish) == null ? void 0 : _a2.call(callbacks);
6576
7128
  apiRef == null ? void 0 : apiRef.cancel();
6577
7129
  }
6578
7130
  });
6579
7131
  }
6580
7132
  const res = make(effectiveCallbacks);
6581
7133
  apiRef = res;
6582
- if (animatorConfig.debugInstName) {
6583
- window[animatorConfig.debugInstName] = res;
7134
+ if (animatorConfig.debugGlobalName) {
7135
+ window[animatorConfig.debugGlobalName] = res;
6584
7136
  }
6585
7137
  return res;
6586
7138
  }
6587
7139
  function bindWithEngineChoice(doc, adapter, callbacks, rootElement) {
6588
7140
  const animatorConfig = getAnimatorConfig(doc) || {};
7141
+ const diag = createDiagnostics(callbacks, "[PxAnimator]");
6589
7142
  if (isScrollTimeline(animatorConfig)) {
6590
7143
  return finaliseAnimator(animatorConfig, callbacks, (cb) => {
6591
- var _a, _b;
7144
+ var _a2;
6592
7145
  let unpin = () => {
6593
7146
  };
6594
- if (animatorConfig.mode !== PxAnimatorMode.frames && ((_a = animatorConfig.scroll) == null ? void 0 : _a.driver) === "native" && rootElement) {
7147
+ if (mayUseNativeScrollTimeline(animatorConfig.engine) && rootElement) {
6595
7148
  unpin = applyScrollPin(rootElement, animatorConfig.scroll);
6596
- const native = createNativeScrollTimeline(rootElement, animatorConfig);
7149
+ const native = createNativeScrollTimeline(rootElement, animatorConfig, diag);
6597
7150
  if (native) {
6598
7151
  const api2 = createWebApiAnimator(
6599
7152
  doc,
6600
7153
  cb,
6601
7154
  rootElement,
6602
- animatorConfig.mode === PxAnimatorMode.waapi,
7155
+ isNativeForced(animatorConfig.engine),
6603
7156
  native
6604
7157
  );
6605
7158
  if (api2) {
@@ -6615,15 +7168,16 @@ var PixodeskAnimator = (() => {
6615
7168
  unpin = () => {
6616
7169
  };
6617
7170
  }
6618
- const api = (animatorConfig.mode !== PxAnimatorMode.frames ? createWebApiAnimator(doc, cb, rootElement, animatorConfig.mode === PxAnimatorMode.waapi) : null) || createFrameLoopAnimator(doc, adapter, cb, rootElement);
6619
- const subject = ((_b = api.getRootElement) == null ? void 0 : _b.call(api)) || rootElement;
7171
+ const api = (animatorConfig.engine !== PxTimelineEngineExtra.js ? createWebApiAnimator(doc, cb, rootElement, isNativeForced(animatorConfig.engine)) : null) || createFrameLoopAnimator(doc, adapter, cb, rootElement);
7172
+ const subject = ((_a2 = api.getRootElement) == null ? void 0 : _a2.call(api)) || rootElement;
6620
7173
  if (subject) {
6621
7174
  unpin = applyScrollPin(subject, animatorConfig.scroll);
6622
7175
  const totalMs = scrollTotalDurationMs(animatorConfig);
6623
7176
  const driver = createScrollDriver(
6624
7177
  subject,
6625
7178
  animatorConfig,
6626
- (progress) => api.setCurrentTime(progress * totalMs)
7179
+ (progress) => api.setCurrentTime(progress * totalMs),
7180
+ diag
6627
7181
  );
6628
7182
  if (driver) {
6629
7183
  const destroy = api.destroy.bind(api);
@@ -6634,58 +7188,58 @@ var PixodeskAnimator = (() => {
6634
7188
  };
6635
7189
  }
6636
7190
  } else {
6637
- console.warn("scroll timeline: no root element to observe \u2014 animation will stay at frame 0");
7191
+ diag.warn(PxDiagnosticKind.host, "scroll timeline: no root element to observe \u2014 animation will stay at frame 0");
6638
7192
  }
6639
7193
  return api;
6640
7194
  });
6641
7195
  }
6642
7196
  return finaliseAnimator(animatorConfig, callbacks, (cb) => {
6643
- if (animatorConfig.mode === PxAnimatorMode.frames) {
7197
+ if (animatorConfig.engine === PxTimelineEngineExtra.js) {
6644
7198
  return createFrameLoopAnimator(doc, adapter, cb, rootElement);
6645
7199
  }
6646
7200
  return createWebApiAnimator(
6647
7201
  doc,
6648
7202
  cb,
6649
7203
  rootElement,
6650
- animatorConfig.mode === PxAnimatorMode.waapi
6651
- // forcing waapi
7204
+ isNativeForced(animatorConfig.engine)
6652
7205
  ) || createFrameLoopAnimator(doc, adapter, cb, rootElement);
6653
7206
  });
6654
7207
  }
6655
7208
 
6656
- // src/PxAnimatorDOM.ts
7209
+ // src/dom/PxAnimatorDOM.ts
6657
7210
  var SVG_NS = "http://www.w3.org/2000/svg";
6658
- function createElement(tagName, normalisedProps, style, children, textContent) {
7211
+ function createElement(tagName, normalizedProps, style, children, textContent, diag) {
6659
7212
  if (DISALLOWED_SVG_TAGS_LOWER.has(tagName.toLowerCase())) {
6660
- console.warn("SVG tag blocked (dangerous): ", tagName);
7213
+ (diag != null ? diag : createDiagnostics(void 0, "[PxAnimator]")).warn(PxDiagnosticKind.document, "SVG tag blocked (dangerous): " + tagName);
6661
7214
  return null;
6662
7215
  }
6663
7216
  const element = document.createElementNS(SVG_NS, tagName);
6664
- for (const propName in normalisedProps) {
6665
- const sanitised = sanitiseAttributeValue(propName, normalisedProps[propName]);
6666
- if (sanitised === void 0) continue;
7217
+ for (const propName in normalizedProps) {
7218
+ const sanitized = sanitizeAttributeValue(propName, normalizedProps[propName]);
7219
+ if (sanitized === void 0) continue;
6667
7220
  if (CSS_ONLY_STYLE_PROPS.has(propName)) {
6668
- element.style[propName] = String(sanitised);
7221
+ element.style[propName] = String(sanitized);
6669
7222
  continue;
6670
7223
  }
6671
- element.setAttribute(camelCaseToKebabWordIfNeeded(propName), sanitised);
7224
+ element.setAttribute(camelCaseToKebabWordIfNeeded(propName), sanitized);
6672
7225
  }
6673
7226
  if (style) {
6674
7227
  for (const styleProp in style) {
6675
7228
  element.style[styleProp] = String(style[styleProp]);
6676
7229
  }
6677
7230
  }
6678
- if (children) {
7231
+ if (children == null ? void 0 : children.length) {
6679
7232
  for (const child of children) {
6680
7233
  element.appendChild(child);
6681
7234
  }
7235
+ } else if (textContent) {
7236
+ element.textContent = textContent;
6682
7237
  }
6683
- if (textContent) element.textContent = textContent;
6684
7238
  return element;
6685
7239
  }
6686
- function renderNode(node, defs) {
7240
+ function renderNode(node, defs, diag) {
6687
7241
  if (!node) return null;
6688
- const _a = node, { type, children, style } = _a, props = __objRest(_a, ["type", "children", "style"]);
7242
+ const _a2 = node, { type, children, style } = _a2, props = __objRest(_a2, ["type", "children", "style"]);
6689
7243
  const domType = props.domType;
6690
7244
  if (domType !== void 0) delete props.domType;
6691
7245
  const nodeDefs = getDefs(node) || defs;
@@ -6693,7 +7247,7 @@ var PixodeskAnimator = (() => {
6693
7247
  let childElements;
6694
7248
  if (children) {
6695
7249
  for (const ch of children) {
6696
- const child = renderNode(ch, nodeDefs);
7250
+ const child = renderNode(ch, nodeDefs, diag);
6697
7251
  if (child) {
6698
7252
  if (!childElements) childElements = [];
6699
7253
  childElements.push(child);
@@ -6705,31 +7259,39 @@ var PixodeskAnimator = (() => {
6705
7259
  getNormalizedProps(props),
6706
7260
  resolvedStyle,
6707
7261
  childElements,
6708
- props[TEXT_CONTENT_ATTR] || props[TEXT_ATTR]
7262
+ props[TEXT_CONTENT_ATTR],
7263
+ diag
6709
7264
  );
6710
7265
  if (element && domType !== void 0) element.setAttribute("type", domType);
6711
7266
  return element;
6712
7267
  }
6713
7268
 
6714
- // src/PxAnimatorKeys.ts
6715
- var PX_ANIMATOR_DATA_KEY = "data";
7269
+ // src/shared/PxAnimatorKeys.ts
7270
+ var PX_ANIMATOR_DOC_KEY = "doc";
6716
7271
 
6717
- // src/PxAnimator.ts
7272
+ // src/animator/PxAnimator.ts
6718
7273
  function createAnimatorFromConfig(doc, adapter, callbacks, rootElement) {
6719
7274
  return bindWithEngineChoice(doc, adapter, callbacks, rootElement);
6720
7275
  }
6721
- function createAnimatorImpl(doc, adapter, callbacks, containerElement) {
7276
+ function createAnimatorImpl(doc, adapter, callbacks, containerElement, patch, resetTimeline) {
7277
+ const diag = createDiagnostics(callbacks, "[PxAnimator]");
6722
7278
  const effectsWarnings = validateNodeEffects(doc);
6723
- for (const w of effectsWarnings) console.warn("[PxAnimator] effects shape warning:", w);
7279
+ for (const w of effectsWarnings) diag.warn(PxDiagnosticKind.document, "effects shape: " + w);
7280
+ reportDocumentDiagnostics(doc, "[PxAnimator] createAnimator");
7281
+ if (patch !== void 0 || resetTimeline) {
7282
+ const patched = applyAnimatorConfig(doc, patch != null ? patch : {}, { resetDefaults: !!resetTimeline });
7283
+ for (const w of patched.warnings) diag.warn(PxDiagnosticKind.usage, "timeline override: " + w);
7284
+ doc = patched.doc;
7285
+ }
6724
7286
  const animatorConfig = getAnimatorConfig(doc) || {};
6725
- const engine = animatorConfig.mode === PxAnimatorMode.frames ? PxAnimatorEngine.frames : PxAnimatorEngine.waapi;
6726
- doc = materialiseAllInTree(doc, engine);
7287
+ const engine = resolveTimelineEngine(animatorConfig.engine);
7288
+ doc = materializeAllInTree(doc, engine);
6727
7289
  let rootElement = null;
6728
7290
  if (containerElement) {
6729
7291
  doc = generateNewIds(doc);
6730
7292
  const containerEl = typeof containerElement === "string" ? document.querySelector(containerElement) : containerElement;
6731
7293
  if (containerEl) {
6732
- rootElement = renderNode(doc);
7294
+ rootElement = renderNode(doc, void 0, diag);
6733
7295
  if (rootElement) {
6734
7296
  containerEl.replaceChildren(rootElement);
6735
7297
  }
@@ -6746,16 +7308,22 @@ var PixodeskAnimator = (() => {
6746
7308
  }
6747
7309
  return api;
6748
7310
  }
7311
+ function resolveTimelineOption(options) {
7312
+ const { timeline, duration, delay, iterations, startOn } = options;
7313
+ return foldTimelineOverride(timeline, { duration, delay, iterations, startOn });
7314
+ }
6749
7315
  function createAnimator(options) {
6750
- const { src, data, adapter, callbacks, container } = options;
6751
- if (data !== void 0 && src !== void 0) {
6752
- throw new Error("createAnimator: provide either `src` or `data`, not both");
7316
+ const { src, doc, adapter, container, resetTimeline } = options;
7317
+ const patch = resolveTimelineOption(options);
7318
+ const callbacks = toEngineCallbacks(options);
7319
+ if (doc !== void 0 && src !== void 0) {
7320
+ throw new Error("createAnimator: provide either `src` or `doc`, not both");
6753
7321
  }
6754
- if (data === void 0 && src === void 0) {
6755
- throw new Error("createAnimator: either `src` or `data` is required");
7322
+ if (doc === void 0 && src === void 0) {
7323
+ throw new Error("createAnimator: either `src` or `doc` is required");
6756
7324
  }
6757
- if (data !== void 0) {
6758
- return createAnimatorImpl(data, adapter, callbacks, container);
7325
+ if (doc !== void 0) {
7326
+ return createAnimatorImpl(doc, adapter, callbacks, container, patch, resetTimeline);
6759
7327
  }
6760
7328
  let animator = null;
6761
7329
  let pending = [];
@@ -6767,19 +7335,27 @@ var PixodeskAnimator = (() => {
6767
7335
  pending.push(call);
6768
7336
  }
6769
7337
  };
7338
+ const loadDiag = createDiagnostics(callbacks, "[PxAnimator]");
6770
7339
  fetch(src).then((res) => res.json()).then((json) => {
6771
7340
  if (destroyed) return;
6772
7341
  if (isPxElementFileFormat(json)) {
6773
- animator = createAnimatorImpl(json, adapter, callbacks, container);
7342
+ animator = createAnimatorImpl(json, adapter, callbacks, container, patch, resetTimeline);
6774
7343
  const queued = pending;
6775
7344
  pending = null;
6776
7345
  queued == null ? void 0 : queued.forEach((call) => call(animator));
6777
7346
  } else {
6778
- console.error('createAnimator: invalid animation document format at "' + src + '"');
7347
+ loadDiag.error(
7348
+ PxDiagnosticKind.document,
7349
+ 'createAnimator: invalid animation document format at "' + src + '"'
7350
+ );
6779
7351
  }
6780
7352
  }).catch((err) => {
7353
+ var _a2;
6781
7354
  pending = null;
6782
- console.error('createAnimator: failed to load "' + src + '"', err);
7355
+ loadDiag.error(
7356
+ PxDiagnosticKind.host,
7357
+ 'createAnimator: failed to load "' + src + '" \u2014 ' + ((_a2 = err == null ? void 0 : err.message) != null ? _a2 : String(err))
7358
+ );
6783
7359
  });
6784
7360
  return {
6785
7361
  "isReady": () => !!animator,
@@ -6804,6 +7380,10 @@ var PixodeskAnimator = (() => {
6804
7380
  "setCurrentTime": (time) => {
6805
7381
  enqueue((api) => api.setCurrentTime(time));
6806
7382
  },
7383
+ "getCurrentProgress": () => animator ? animator.getCurrentProgress() : null,
7384
+ "setCurrentProgress": (progress) => {
7385
+ enqueue((api) => api.setCurrentProgress(progress));
7386
+ },
6807
7387
  "destroy": () => {
6808
7388
  destroyed = true;
6809
7389
  pending = null;
@@ -6811,23 +7391,18 @@ var PixodeskAnimator = (() => {
6811
7391
  }
6812
7392
  };
6813
7393
  }
6814
- function loadTagAnimators() {
7394
+ function loadTagAnimators(options) {
6815
7395
  const elements = document.querySelectorAll("[" + PX_ANIM_SRC_ATTR_NAME + "]");
6816
7396
  for (let i = 0; i < elements.length; i++) {
6817
7397
  const element = elements[i];
6818
7398
  if (!element[PX_ANIM_ATTR_NAME]) {
6819
7399
  const src = element.getAttribute(PX_ANIM_SRC_ATTR_NAME);
6820
7400
  if (src) {
6821
- element[PX_ANIM_ATTR_NAME] = createAnimator({ src, container: element });
7401
+ element[PX_ANIM_ATTR_NAME] = createAnimator(__spreadProps(__spreadValues({}, options), { src, container: element }));
6822
7402
  }
6823
7403
  }
6824
7404
  }
6825
7405
  }
6826
- if (typeof window !== "undefined") {
6827
- window["loadTagAnimators"] = loadTagAnimators;
6828
- window["createAnimator"] = createAnimator;
6829
- window["setupAnimationTriggers"] = setupAnimationTriggers;
6830
- }
6831
7406
  return __toCommonJS(index_player_exports);
6832
7407
  })();
6833
7408
  //# sourceMappingURL=pixodesk-svg-animator.umd.js.map