@pixodesk/svg-animator-web 1.0.30 → 1.0.35

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -54,16 +54,17 @@ var PixodeskAnimator = (() => {
54
54
  PX_ANIMATOR_DATA_KEY: () => PX_ANIMATOR_DATA_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
60
  createAnimatorImpl: () => createAnimatorImpl,
61
61
  generateNewIds: () => generateNewIds,
62
62
  loadTagAnimators: () => loadTagAnimators,
63
- setupAnimationTriggers: () => setupAnimationTriggers
63
+ setupAnimationTriggers: () => setupAnimationTriggers,
64
+ validateDocument: () => validateDocument
64
65
  });
65
66
 
66
- // ../svg-animator-core/src/PxAnimatorUtil.ts
67
+ // ../svg-animator-core/src/util/PxAnimatorUtil.ts
67
68
  function bezierToSvgPath(path, forceCurves = false) {
68
69
  var _a, _b, _c, _d;
69
70
  const v = path.v;
@@ -316,6 +317,38 @@ var PixodeskAnimator = (() => {
316
317
  if (o) segs.push("translate(" + -o[0] + tu + "," + -o[1] + tu + ")");
317
318
  return segs.join("");
318
319
  }
320
+ function parseTransformParts(str2) {
321
+ var _a, _b;
322
+ if (!str2 || typeof str2 !== "string") return void 0;
323
+ const out = {};
324
+ const re = /([a-zA-Z]+)\s*\(([^)]*)\)/g;
325
+ const order = ["translate", "rotate", "skewX", "scale"];
326
+ let lastIdx = -1;
327
+ let m;
328
+ while ((m = re.exec(str2)) !== null) {
329
+ const fn = m[1];
330
+ const idx = order.indexOf(fn);
331
+ if (idx < 0 || idx <= lastIdx) return void 0;
332
+ lastIdx = idx;
333
+ const nums = m[2].split(/[\s,]+/).filter(Boolean).map(Number);
334
+ if (nums.some((n) => Number.isNaN(n))) return void 0;
335
+ if (fn === "translate") {
336
+ if (nums.length < 1 || nums.length > 2) return void 0;
337
+ out.translate = [nums[0], (_a = nums[1]) != null ? _a : 0];
338
+ } else if (fn === "rotate") {
339
+ if (nums.length !== 1) return void 0;
340
+ out.rotate = nums[0];
341
+ } else if (fn === "skewX") {
342
+ if (nums.length !== 1) return void 0;
343
+ out.skew = nums[0];
344
+ } else {
345
+ if (nums.length < 1 || nums.length > 2) return void 0;
346
+ out.scale = [nums[0], (_b = nums[1]) != null ? _b : nums[0]];
347
+ }
348
+ }
349
+ if (str2.replace(/([a-zA-Z]+)\s*\(([^)]*)\)/g, "").replace(/[\s,]/g, "").length) return void 0;
350
+ return Object.keys(out).length ? out : void 0;
351
+ }
319
352
  var STYLE_ATTR_NAMES = /* @__PURE__ */ new Set(["offset-distance", "offsetDistance"]);
320
353
  var DEFAULT_DURATION_MS = 1e3;
321
354
  function kebabToCamelCaseWord(kebab) {
@@ -479,7 +512,7 @@ var PixodeskAnimator = (() => {
479
512
  return cubicBezier(flipped);
480
513
  }
481
514
 
482
- // ../svg-animator-core/src/PxScrollMath.ts
515
+ // ../svg-animator-core/src/playback/PxScrollMath.ts
483
516
  function isScrollTimeline(config) {
484
517
  return (config == null ? void 0 : config.timelineSource) === "scroll";
485
518
  }
@@ -535,7 +568,8 @@ var PixodeskAnimator = (() => {
535
568
  return vertical ? "x" : "y";
536
569
  }
537
570
 
538
- // ../svg-animator-core/src/PxSchema.ts
571
+ // ../svg-animator-core/src/schema/PxSchema.ts
572
+ var PX_UNKNOWN_KEY_ERROR = "unexpected extra key";
539
573
  function pathStr(path) {
540
574
  if (!path.length) return ".";
541
575
  let result = "";
@@ -647,6 +681,8 @@ var PixodeskAnimator = (() => {
647
681
  constructor(schemas, defaultVal) {
648
682
  super();
649
683
  this.schemas = schemas;
684
+ /** Structural tag read by {@link describeSchema} — `schemas` alone cannot tell Union from Tuple. */
685
+ this._kind = "union";
650
686
  this._default = defaultVal != null ? defaultVal : schemas[0]._default;
651
687
  }
652
688
  sanitize(raw) {
@@ -668,20 +704,26 @@ var PixodeskAnimator = (() => {
668
704
  };
669
705
  var DiscriminatedUnion = class extends Base {
670
706
  constructor(_key, _schemas, defaultVal) {
707
+ var _a;
671
708
  super();
672
709
  this._key = _key;
673
710
  this._schemas = _schemas;
711
+ /** Structural tag read by {@link describeSchema}. */
712
+ this._kind = "discriminatedUnion";
674
713
  this._default = defaultVal != null ? defaultVal : _schemas[0]._default;
675
714
  this._map = /* @__PURE__ */ new Map();
676
715
  for (const s of _schemas) {
677
716
  const keySchema = s._shape[_key];
678
- if (keySchema) this._map.set(keySchema._default, s);
717
+ if (!keySchema) continue;
718
+ const literal = (_a = keySchema.inner) != null ? _a : keySchema;
719
+ this._map.set(literal._default, s);
720
+ if (keySchema.inner) this._absentMember = s;
679
721
  }
680
722
  }
681
723
  _findSchema(raw) {
682
724
  if (raw === null || typeof raw !== "object" || Array.isArray(raw)) return void 0;
683
725
  const val = raw[this._key];
684
- if (val === void 0 || val === null) return void 0;
726
+ if (val === void 0 || val === null) return this._absentMember;
685
727
  return this._map.get(val);
686
728
  }
687
729
  sanitize(raw) {
@@ -715,7 +757,8 @@ var PixodeskAnimator = (() => {
715
757
  const src = raw && typeof raw === "object" && !Array.isArray(raw) ? raw : {};
716
758
  const out = {};
717
759
  for (const key of Object.keys(this._shape)) {
718
- out[key] = this._shape[key].sanitize(src[key]);
760
+ const v = this._shape[key].sanitize(src[key]);
761
+ if (v !== void 0) out[key] = v;
719
762
  }
720
763
  return out;
721
764
  }
@@ -737,7 +780,7 @@ var PixodeskAnimator = (() => {
737
780
  if (key in this._shape) continue;
738
781
  if (obj[key] === void 0) continue;
739
782
  p.push(key);
740
- ctx.errors.push(pathStr(p) + ": unexpected extra key");
783
+ ctx.errors.push(pathStr(p) + ": " + PX_UNKNOWN_KEY_ERROR);
741
784
  p.pop();
742
785
  ok = false;
743
786
  }
@@ -761,7 +804,8 @@ var PixodeskAnimator = (() => {
761
804
  const src = raw && typeof raw === "object" && !Array.isArray(raw) ? raw : {};
762
805
  const out = __spreadValues({}, src);
763
806
  for (const key of Object.keys(this._shape)) {
764
- out[key] = this._shape[key].sanitize(src[key]);
807
+ const v = this._shape[key].sanitize(src[key]);
808
+ if (v !== void 0) out[key] = v;
765
809
  }
766
810
  if (this._openSchema) {
767
811
  for (const key of Object.keys(src)) {
@@ -833,6 +877,8 @@ var PixodeskAnimator = (() => {
833
877
  constructor(value) {
834
878
  super();
835
879
  this.value = value;
880
+ /** Structural tag read by {@link describeSchema}. */
881
+ this._kind = "record";
836
882
  this._default = {};
837
883
  }
838
884
  sanitize(raw) {
@@ -918,6 +964,8 @@ var PixodeskAnimator = (() => {
918
964
  constructor(schemas) {
919
965
  super();
920
966
  this.schemas = schemas;
967
+ /** Structural tag read by {@link describeSchema} — `schemas` alone cannot tell Tuple from Union. */
968
+ this._kind = "tuple";
921
969
  this._default = schemas.map((s) => s._default);
922
970
  }
923
971
  sanitize(raw) {
@@ -998,25 +1046,40 @@ var PixodeskAnimator = (() => {
998
1046
  lazy: (fn, defaultVal) => new Lazy(fn, defaultVal)
999
1047
  };
1000
1048
 
1001
- // ../svg-animator-core/src/PxAnimatorConstants.ts
1049
+ // ../svg-animator-core/src/format/PxAnimatorConstants.ts
1002
1050
  var PX_ANIM_SRC_ATTR_NAME = "data-px-animation-src";
1003
1051
  var PX_ANIM_ATTR_NAME = "_px_animator";
1004
- var PxAnimatorMode = {
1005
- auto: "auto",
1006
- waapi: "waapi",
1007
- frames: "frames"
1052
+ var PX_TIMELINE_SHARED_KEYS = ["duration", "iterations", "engine", "frameRate"];
1053
+ var PX_TIME_ONLY_TIMELINE_KEYS = ["trigger", "delay", "fillMode", "direction"];
1054
+ var PxTimelineEngine = {
1055
+ native: "native",
1056
+ js: "js"
1008
1057
  };
1009
- var PxAnimatorEngine = {
1010
- waapi: PxAnimatorMode.waapi,
1011
- frames: PxAnimatorMode.frames
1058
+ var PxTimelineEngineExtra = __spreadProps(__spreadValues({}, PxTimelineEngine), {
1059
+ auto: "auto"
1060
+ });
1061
+ function resolveTimelineEngine(engine) {
1062
+ return engine === PxTimelineEngineExtra.js ? PxTimelineEngine.js : PxTimelineEngine.native;
1063
+ }
1064
+ function isNativeForced(engine) {
1065
+ return engine === PxTimelineEngineExtra.native;
1066
+ }
1067
+ function mayUseNativeScrollTimeline(engine) {
1068
+ return engine !== PxTimelineEngineExtra.js;
1069
+ }
1070
+ var PxLoopRepeatAt = {
1071
+ /** Segment from the START; the repetition runs BEFORE the first keyframe
1072
+ * (intro loops that play until the main timeline begins). */
1073
+ start: "start",
1074
+ /** DEFAULT — segment from the END; the repetition runs AFTER the last keyframe
1075
+ * (idle/outro loops that continue once the main timeline has finished). */
1076
+ end: "end"
1012
1077
  };
1013
- var PxLoopExtend = {
1014
- /** Segment from the START; the animation is extended BEFORE the first keyframe
1015
- * (intro loops that run before the main timeline begins). */
1016
- before: "before",
1017
- /** DEFAULT — segment from the END; extended AFTER the last keyframe (idle/outro
1018
- * loops that continue once the main timeline has finished). */
1019
- after: "after"
1078
+ var PxLoopDirection = {
1079
+ /** DEFAULT — cycle: every repetition replays the segment the same way round. */
1080
+ normal: "normal",
1081
+ /** Ping-pong: repetitions alternate forward / backward. */
1082
+ alternate: "alternate"
1020
1083
  };
1021
1084
  var PxMaskType = {
1022
1085
  luminance: "luminance",
@@ -1026,8 +1089,9 @@ var PixodeskAnimator = (() => {
1026
1089
  userSpaceOnUse: "userSpaceOnUse",
1027
1090
  objectBoundingBox: "objectBoundingBox"
1028
1091
  };
1029
- var PxCloneType = {
1030
- content: "content"
1092
+ var PxCloneWithout = {
1093
+ translate: "translate"
1094
+ // transform: 'transform', // future: drop rotate/scale too (content only)
1031
1095
  };
1032
1096
  var PxPathOverflow = {
1033
1097
  clip: "clip",
@@ -1051,6 +1115,9 @@ var PixodeskAnimator = (() => {
1051
1115
  };
1052
1116
  var TEXT_ATTR = "text";
1053
1117
  var TEXT_CONTENT_ATTR = "textContent";
1118
+ var CLASS_ATTR = "class";
1119
+ var TRANSFORM_ATTR = "transform";
1120
+ var OFFSET_DISTANCE_ATTR = "offsetDistance";
1054
1121
  var INTERNAL_ATTRS = /* @__PURE__ */ new Set([
1055
1122
  "type",
1056
1123
  "children",
@@ -1061,6 +1128,18 @@ var PixodeskAnimator = (() => {
1061
1128
  TEXT_ATTR,
1062
1129
  TEXT_CONTENT_ATTR
1063
1130
  ]);
1131
+ var TRANSFORM_PART = {
1132
+ translate: "translate",
1133
+ rotate: "rotate",
1134
+ scale: "scale",
1135
+ origin: "origin"
1136
+ };
1137
+ var PX_TRANSFORM_PART_KEYS = [
1138
+ TRANSFORM_PART.translate,
1139
+ TRANSFORM_PART.rotate,
1140
+ TRANSFORM_PART.scale,
1141
+ TRANSFORM_PART.origin
1142
+ ];
1064
1143
  var PxGradientUnits = {
1065
1144
  userSpaceOnUse: "userSpaceOnUse",
1066
1145
  objectBoundingBox: "objectBoundingBox"
@@ -1078,11 +1157,56 @@ var PixodeskAnimator = (() => {
1078
1157
  if (!(fileJson && typeof fileJson === "object" && !Array.isArray(fileJson))) {
1079
1158
  return false;
1080
1159
  }
1081
- return fileJson["type"] === "svg";
1160
+ return fileJson.type === "svg";
1082
1161
  }
1083
1162
  function getAnimatorConfig(doc) {
1084
1163
  var _a;
1085
- return (doc == null ? void 0 : doc.animator) || ((_a = doc == null ? void 0 : doc.meta) == null ? void 0 : _a.animator);
1164
+ const cfg = (doc == null ? void 0 : doc.animator) || ((_a = doc == null ? void 0 : doc.meta) == null ? void 0 : _a.animator);
1165
+ return cfg ? flattenAnimatorTimeline(cfg) : void 0;
1166
+ }
1167
+ var flattenMemo = /* @__PURE__ */ new WeakMap();
1168
+ function flattenAnimatorTimeline(cfg) {
1169
+ const timeline = cfg.timeline;
1170
+ if (timeline === void 0 || timeline === null || typeof timeline !== "object") return cfg;
1171
+ const memoised = flattenMemo.get(cfg);
1172
+ if (memoised) return memoised;
1173
+ const _a = cfg, { timeline: _dropped } = _a, flat = __objRest(_a, ["timeline"]);
1174
+ if (timeline.engine !== void 0) flat.engine = timeline.engine;
1175
+ if (timeline.frameRate !== void 0) flat.frameRate = timeline.frameRate;
1176
+ if (timeline.type === "scroll" || timeline.type === "view") {
1177
+ flat.timelineSource = "scroll";
1178
+ if (timeline.duration !== void 0) flat.duration = timeline.duration;
1179
+ if (timeline.iterations !== void 0) flat.iterations = timeline.iterations;
1180
+ const scroll = __spreadValues({}, flat.scroll || {});
1181
+ scroll.kind = timeline.type;
1182
+ if (timeline.axis !== void 0) scroll.axis = timeline.axis;
1183
+ if (timeline.source !== void 0) scroll.source = timeline.source;
1184
+ if (timeline.subject !== void 0) scroll.subject = timeline.subject;
1185
+ if (timeline.smoothing !== void 0) scroll.smoothing = timeline.smoothing;
1186
+ if (timeline.range !== void 0) scroll.range = timeline.range;
1187
+ const pin = timeline.pin;
1188
+ if (typeof pin === "boolean") scroll.pin = pin;
1189
+ else if (pin && typeof pin === "object") {
1190
+ scroll.pin = true;
1191
+ if (pin.align !== void 0) scroll.pinAlign = pin.align;
1192
+ if (pin.top !== void 0) scroll.pinTop = pin.top;
1193
+ if (pin.distance !== void 0) scroll.pinDistance = pin.distance;
1194
+ }
1195
+ flat.scroll = scroll;
1196
+ } else {
1197
+ if (timeline.duration !== void 0) flat.duration = timeline.duration;
1198
+ if (timeline.trigger !== void 0) {
1199
+ const _b = timeline.trigger, { finishAction } = _b, restTrigger = __objRest(_b, ["finishAction"]);
1200
+ if (Object.keys(restTrigger).length) flat.trigger = restTrigger;
1201
+ if (finishAction !== void 0) flat.resetOnFinish = finishAction === "reset";
1202
+ }
1203
+ if (timeline.delay !== void 0) flat.delay = timeline.delay;
1204
+ if (timeline.iterations !== void 0) flat.iterations = timeline.iterations;
1205
+ if (timeline.direction !== void 0) flat.direction = timeline.direction;
1206
+ if (timeline.fillMode !== void 0) flat.fill = timeline.fillMode;
1207
+ }
1208
+ flattenMemo.set(cfg, flat);
1209
+ return flat;
1086
1210
  }
1087
1211
  function getDefs(doc) {
1088
1212
  var _a;
@@ -1094,10 +1218,10 @@ var PixodeskAnimator = (() => {
1094
1218
  if (!doc) return void 0;
1095
1219
  const animateById = (_a = getAnimatorConfig(doc)) == null ? void 0 : _a.animateById;
1096
1220
  if (!animateById) return void 0;
1097
- return Object.entries(animateById).map(([id, anim]) => ({ id, animate: anim }));
1221
+ return Object.entries(animateById).map(([id, anim]) => ({ id: id.startsWith("#") ? id.slice(1) : id, animate: anim }));
1098
1222
  }
1099
1223
 
1100
- // ../svg-animator-core/src/PxAnimatorTypes.ts
1224
+ // ../svg-animator-core/src/format/PxAnimatorTypes.ts
1101
1225
  var PxEasingOrRefSchema = px.union([
1102
1226
  px.string(),
1103
1227
  px.tuple([px.number(), px.number(), px.number(), px.number()])
@@ -1107,39 +1231,54 @@ var PixodeskAnimator = (() => {
1107
1231
  // e.g. for colors
1108
1232
  px.number(),
1109
1233
  px.array(px.number()),
1110
- px.lazy(() => PxTransformPartsSchema, {}),
1234
+ // ORDER LAW: the key-discriminated object shapes (`{path}`, `{paths}`) come BEFORE the
1235
+ // all-optional transform-parts record. In default (non-strict) mode that record accepts
1236
+ // ANY object (every key optional, unknown keys ignored), so listing it earlier made
1237
+ // Union.sanitize route `{path}`/`{paths}` values into it and strip them to `{}` —
1238
+ // silent morph-data loss (repro: the editor's keyframeValueSanitize spec). Validity is
1239
+ // order-independent (`some()`); only sanitize routing depends on this order.
1111
1240
  px.object({ path: px.string() }),
1112
1241
  px.lazy(() => px.object({ paths: px.array(PxBezierPathSchema) }), { paths: [] }),
1113
1242
  // Gradient `stops` timeline — each kf value is the full stops-array snapshot.
1114
- px.lazy(() => px.array(PxGradientStopSchema), [])
1243
+ px.lazy(() => px.array(PxGradientStopSchema), []),
1244
+ px.lazy(() => PxTransformPartsSchema, {})
1115
1245
  ]));
1116
1246
  var PxKeyframeSchema = implementsInterface()(px.object({
1117
1247
  time: px.number().optional(),
1118
- t: px.number().optional(),
1119
1248
  value: PxKeyframeValueSchema.optional(),
1120
- v: PxKeyframeValueSchema.optional(),
1121
1249
  easing: PxEasingOrRefSchema.optional(),
1122
- e: PxEasingOrRefSchema.optional(),
1123
1250
  tangentOut: px.tuple([px.number(), px.number()]).optional(),
1124
- to: px.tuple([px.number(), px.number()]).optional(),
1125
- // short alias
1126
- tangentIn: px.tuple([px.number(), px.number()]).optional(),
1127
- ti: px.tuple([px.number(), px.number()]).optional(),
1128
- // short alias
1129
- selected: px.boolean().optional()
1130
- // editor-side UI state (Player ignores it)
1251
+ tangentIn: px.tuple([px.number(), px.number()]).optional()
1252
+ // (`selected` — editor timeline-selection UI state — was REMOVED from the wire
1253
+ // (review §1.3): editor data lives under `meta`. The editor still carries it on
1254
+ // its internal COPY-PASTE payload, which never validates against this schema.)
1131
1255
  }));
1256
+ var anyKf = (kf) => kf;
1257
+ var kfTime = (kf) => {
1258
+ var _a, _b;
1259
+ return (_b = (_a = anyKf(kf).time) != null ? _a : anyKf(kf).t) != null ? _b : 0;
1260
+ };
1261
+ var kfValue = (kf) => {
1262
+ var _a;
1263
+ return (_a = anyKf(kf).value) != null ? _a : anyKf(kf).v;
1264
+ };
1265
+ var kfEasing = (kf) => {
1266
+ var _a;
1267
+ return (_a = anyKf(kf).easing) != null ? _a : anyKf(kf).e;
1268
+ };
1269
+ var kfTangentIn = (kf) => anyKf(kf).tangentIn;
1270
+ var kfTangentOut = (kf) => anyKf(kf).tangentOut;
1132
1271
  var PxLoopSchema = implementsInterface()(px.object({
1133
1272
  segmentCount: px.number().optional(),
1134
- extend: px.enum([PxLoopExtend.before, PxLoopExtend.after]).optional(),
1135
- alternate: px.boolean().optional()
1273
+ repeatAt: px.enum([PxLoopRepeatAt.start, PxLoopRepeatAt.end]).optional(),
1274
+ direction: px.enum([PxLoopDirection.normal, PxLoopDirection.alternate]).optional()
1136
1275
  }));
1137
1276
  var PxPropertyAnimationSchema = implementsInterface()(px.object({
1138
1277
  value: PxKeyframeValueSchema.optional(),
1139
1278
  keyframes: px.array(PxKeyframeSchema).optional(),
1140
- kfs: px.array(PxKeyframeSchema).optional(),
1141
1279
  loop: px.union([PxLoopSchema, px.boolean()]).optional(),
1142
- autoOrient: px.boolean().optional()
1280
+ autoOrient: px.boolean().optional(),
1281
+ alongPathMode: px.enum(["sampled", "offsetPath"]).optional()
1143
1282
  }));
1144
1283
  var PxTransformPartsSchema = implementsInterface()(px.object({
1145
1284
  translate: px.tuple([px.number(), px.number()]).optional(),
@@ -1165,6 +1304,10 @@ var PixodeskAnimator = (() => {
1165
1304
  var PxTriggerSchema = implementsInterface()(px.object({
1166
1305
  startOn: px.enum(["load", "mouseOver", "click", "scrollIntoView", "programmatic"]).optional(),
1167
1306
  outAction: px.enum(["continue", "pause", "reset", "reverse"]).optional(),
1307
+ // What happens after a NATURAL finish — `'hold'` (default: keep the end state per
1308
+ // `fill`) or `'reset'` (snap back to the start state). Pairs with `outAction` ("what
1309
+ // happens when the trigger condition ends"); both end-of-life knobs now read alike.
1310
+ finishAction: px.enum(["hold", "reset"]).optional(),
1168
1311
  scrollIntoViewThreshold: px.number().optional()
1169
1312
  }));
1170
1313
  var PxGlyphSchema = implementsInterface()(px.object({
@@ -1172,8 +1315,8 @@ var PixodeskAnimator = (() => {
1172
1315
  d: px.string()
1173
1316
  }));
1174
1317
  var PxGlyphFontSchema = implementsInterface()(px.object({
1175
- fFamily: px.string(),
1176
- style: px.string(),
1318
+ fontFamily: px.string(),
1319
+ fontStyle: px.string(),
1177
1320
  ascent: px.number(),
1178
1321
  unitsPerEm: px.number(),
1179
1322
  glyphs: px.record(PxGlyphSchema)
@@ -1181,8 +1324,10 @@ var PixodeskAnimator = (() => {
1181
1324
  var PxDefsSchema = implementsInterface()(px.object({
1182
1325
  easings: px.record(px.tuple([px.number(), px.number(), px.number(), px.number()])).optional(),
1183
1326
  animations: px.record(PxAnimationDefinitionSchema).optional(),
1184
- styles: px.record(px.any()).optional(),
1185
- glyphs: px.record(PxGlyphFontSchema).optional()
1327
+ // Review §2.6: the schema now matches the declared type — a style preset is a flat
1328
+ // record of string|number attribute values, nothing nested.
1329
+ styles: px.record(px.record(px.union([px.string(), px.number()]))).optional(),
1330
+ fonts: px.record(PxGlyphFontSchema).optional()
1186
1331
  }));
1187
1332
  var PX_SCROLL_PHASES = ["cover", "contain", "entry", "exit", "entry-crossing", "exit-crossing"];
1188
1333
  var PxScrollRangePointSchema = implementsInterface()(px.object({
@@ -1194,7 +1339,6 @@ var PixodeskAnimator = (() => {
1194
1339
  end: PxScrollRangePointSchema.optional()
1195
1340
  });
1196
1341
  var PxScrollSchema = implementsInterface()(px.object({
1197
- driver: px.enum(["custom", "native"]).optional(),
1198
1342
  kind: px.enum(["view", "scroll"]).optional(),
1199
1343
  axis: px.enum(["block", "inline", "x", "y"]).optional(),
1200
1344
  source: px.enum(["nearest", "root"]).optional(),
@@ -1207,23 +1351,67 @@ var PixodeskAnimator = (() => {
1207
1351
  pinDistance: px.number().optional(),
1208
1352
  range: PxScrollRangeSchema.optional()
1209
1353
  }));
1210
- var PxAnimatorConfigSchema = implementsInterface()(px.object({
1211
- mode: px.enum([PxAnimatorMode.auto, PxAnimatorMode.waapi, PxAnimatorMode.frames]).optional(),
1354
+ var PxTimelinePinSchema = implementsInterface()(px.object({
1355
+ align: px.enum(["top", "center", "bottom"]).optional(),
1356
+ top: px.number().optional(),
1357
+ distance: px.number().optional()
1358
+ }));
1359
+ var PxTimelineEngineSchema = px.enum([PxTimelineEngineExtra.auto, PxTimelineEngineExtra.native, PxTimelineEngineExtra.js]).optional();
1360
+ var PxTimeTimelineSchema = implementsInterface()(px.object({
1361
+ type: px.literal("time").optional(),
1362
+ engine: PxTimelineEngineSchema,
1363
+ frameRate: px.number().optional(),
1364
+ // §2.8: duration is a property of the TIMELINE — how long one pass takes.
1212
1365
  duration: px.number().optional(),
1366
+ trigger: PxTriggerSchema.optional(),
1213
1367
  delay: px.number().optional(),
1214
- // LAW (SCHEMA-DESIGN R3, S10): the ONE sanctioned string-in-number union
1215
- // (CSS animation-iteration-count familiarity) — do not add more mixed unions.
1216
1368
  iterations: px.union([px.number(), px.literal("infinite")]).optional(),
1217
- fill: px.enum(["forwards", "backwards", "both", "none"]).optional(),
1218
- direction: px.enum(["normal", "reverse", "alternate", "alternate-reverse"]).optional(),
1369
+ // `fillMode` on the wire (CSS `animation-fill-mode`; the runtime view calls it `fill`)
1370
+ // — never `fill`, which is paint everywhere else in the format.
1371
+ fillMode: px.enum(["forwards", "backwards", "both", "none"]).optional(),
1372
+ direction: px.enum(["normal", "reverse", "alternate", "alternate-reverse"]).optional()
1373
+ }));
1374
+ var scrollishTimelineShape = {
1375
+ // §2.8: duration is a property of the TIMELINE — under scrubbing it is the keyframe
1376
+ // span the scroll range maps onto.
1377
+ duration: px.number().optional(),
1378
+ // Finite repeat count IS meaningful when scrubbing — the scroll range maps onto
1379
+ // duration × iterations (rule D4; `'infinite'` cannot map to a range, so no literal here).
1380
+ iterations: px.number().optional(),
1381
+ engine: PxTimelineEngineSchema,
1219
1382
  frameRate: px.number().optional(),
1220
- trigger: PxTriggerSchema.optional(),
1221
- resetOnFinish: px.boolean().optional(),
1383
+ axis: px.enum(["block", "inline", "x", "y"]).optional(),
1384
+ source: px.enum(["nearest", "root"]).optional(),
1385
+ subject: px.string().optional(),
1386
+ // 'parent' | 'scroller' | any CSS selector
1387
+ smoothing: px.number().optional(),
1388
+ // ms
1389
+ pin: px.union([px.boolean(), PxTimelinePinSchema]).optional(),
1390
+ range: PxScrollRangeSchema.optional()
1391
+ };
1392
+ var PxScrollTimelineSchema = implementsInterface()(
1393
+ px.object(__spreadValues({ type: px.literal("scroll") }, scrollishTimelineShape))
1394
+ );
1395
+ var PxViewTimelineSchema = implementsInterface()(
1396
+ px.object(__spreadValues({ type: px.literal("view") }, scrollishTimelineShape))
1397
+ );
1398
+ var PxTimelineSchema = px.discriminatedUnion("type", [
1399
+ PxTimeTimelineSchema,
1400
+ // first = the member an absent `type` selects
1401
+ PxScrollTimelineSchema,
1402
+ PxViewTimelineSchema
1403
+ ]);
1404
+ var PxAnimatorConfigSchema = implementsInterface()(px.object({
1405
+ // (`mode`, `duration` and `frameRate` live INSIDE `timeline` on the wire — §2.8; they exist
1406
+ // at this level only on the runtime view, like the rest of the playback dynamics.)
1407
+ // THE spelling of "what advances progress" — clock / scroll / view (review §2.1).
1408
+ timeline: PxTimelineSchema.optional(),
1222
1409
  definitions: PxDefsSchema.optional(),
1223
1410
  animateById: px.record(PxElementAnimationSchema).optional(),
1224
- timelineSource: px.string().optional(),
1225
- scroll: PxScrollSchema.optional(),
1226
- debugInstName: px.string().optional()
1411
+ debugGlobalName: px.string().optional(),
1412
+ // Declared HERE because this is a closed object: an undeclared key would be stripped by
1413
+ // `sanitize` and flagged by strict validation on our own files.
1414
+ version: px.string().optional()
1227
1415
  }));
1228
1416
  var PxBindingSchema = implementsInterface()(px.object({
1229
1417
  id: px.string(),
@@ -1241,18 +1429,18 @@ var PixodeskAnimator = (() => {
1241
1429
  ]);
1242
1430
  var PxAnimatableNumberSchema = px.union([
1243
1431
  px.number(),
1244
- px.object({ value: px.number() }),
1245
- PxPropertyAnimationSchema
1432
+ PxPropertyAnimationSchema,
1433
+ px.object({ value: px.number() })
1246
1434
  ]);
1247
1435
  var PxAnimatableVec2Schema = px.union([
1248
1436
  px.tuple([px.number(), px.number()]),
1249
- px.object({ value: px.tuple([px.number(), px.number()]) }),
1250
- PxPropertyAnimationSchema
1437
+ PxPropertyAnimationSchema,
1438
+ px.object({ value: px.tuple([px.number(), px.number()]) })
1251
1439
  ]);
1252
1440
  var PxAnimatableStringSchema = px.union([
1253
1441
  px.string(),
1254
- px.object({ value: px.string() }),
1255
- PxPropertyAnimationSchema
1442
+ PxPropertyAnimationSchema,
1443
+ px.object({ value: px.string() })
1256
1444
  ]);
1257
1445
  var PxTransformByEffectSchema = implementsInterface()(px.object({
1258
1446
  translate: PxAnimatableVec2Schema.optional(),
@@ -1272,7 +1460,7 @@ var PixodeskAnimator = (() => {
1272
1460
  origin: PxAnimatableVec2Schema.optional()
1273
1461
  }));
1274
1462
  var PxMaskedByEffectSchema = implementsInterface()(px.object({
1275
- sourceId: px.string().optional(),
1463
+ source: px.string().optional(),
1276
1464
  maskType: px.enum([PxMaskType.luminance, PxMaskType.alpha]).optional(),
1277
1465
  maskUnits: px.enum([PxUnits.userSpaceOnUse, PxUnits.objectBoundingBox]).optional(),
1278
1466
  maskContentUnits: px.enum([PxUnits.userSpaceOnUse, PxUnits.objectBoundingBox]).optional(),
@@ -1282,8 +1470,7 @@ var PixodeskAnimator = (() => {
1282
1470
  height: px.number().optional()
1283
1471
  }));
1284
1472
  var PxClipPathEffectSchema = implementsInterface()(px.object({
1285
- d: PxAnimatableStringSchema.optional(),
1286
- animate: PxPropertyAnimationSchema.optional()
1473
+ d: PxAnimatableStringSchema.optional()
1287
1474
  }));
1288
1475
  var PxStrokeTrimEffectSchema = implementsInterface()(px.object({
1289
1476
  offset: PxAnimatableNumberSchema.optional(),
@@ -1291,15 +1478,15 @@ var PixodeskAnimator = (() => {
1291
1478
  subPaths: px.enum([PxStrokeTrimSubPaths.separate, PxStrokeTrimSubPaths.combined]).optional()
1292
1479
  }));
1293
1480
  var PxRetimeEffectSchema = implementsInterface()(px.object({
1294
- sourceId: px.string().optional(),
1295
1481
  start: px.number().optional(),
1296
1482
  stretch: px.number().optional(),
1297
1483
  timeCrop: px.tuple([px.number(), px.number()]).optional()
1298
1484
  }));
1299
1485
  var PxCloneEffectSchema = implementsInterface()(px.object({
1300
- // Contextual kind — the `type` convention, see `PxNodeBase.type`.
1301
- type: px.enum([PxCloneType.content]).optional(),
1302
- sourceId: px.string().optional(),
1486
+ // Subtractive on purpose: the `<use>` can only point at one wrapper layer of the
1487
+ // source, so the choices form a ladder — 'translate' now, maybe 'transform' later.
1488
+ without: px.enum([PxCloneWithout.translate]).optional(),
1489
+ source: px.string().optional(),
1303
1490
  retime: PxRetimeEffectSchema.optional()
1304
1491
  }));
1305
1492
  var PxGradientStopSchema = implementsInterface()(px.object({
@@ -1314,11 +1501,11 @@ var PixodeskAnimator = (() => {
1314
1501
  var PxFillGradientEffectSchema = implementsInterface()(px.object({
1315
1502
  // Contextual kind — the `type` convention, see `PxNodeBase.type`.
1316
1503
  type: px.enum([PxGradientType.linear, PxGradientType.radial]),
1317
- p1: PxAnimatableVec2Schema.optional(),
1318
- p2: PxAnimatableVec2Schema.optional(),
1319
- c: PxAnimatableVec2Schema.optional(),
1320
- r: PxAnimatableNumberSchema.optional(),
1321
- fp: PxAnimatableVec2Schema.optional(),
1504
+ start: PxAnimatableVec2Schema.optional(),
1505
+ end: PxAnimatableVec2Schema.optional(),
1506
+ center: PxAnimatableVec2Schema.optional(),
1507
+ radius: PxAnimatableNumberSchema.optional(),
1508
+ focal: PxAnimatableVec2Schema.optional(),
1322
1509
  stops: PxAnimatableGradientStopsSchema.optional(),
1323
1510
  gradientUnits: px.enum([PxGradientUnits.userSpaceOnUse, PxGradientUnits.objectBoundingBox]).optional(),
1324
1511
  spreadMethod: px.enum([PxGradientSpreadMethod.pad, PxGradientSpreadMethod.reflect, PxGradientSpreadMethod.repeat]).optional(),
@@ -1326,7 +1513,7 @@ var PixodeskAnimator = (() => {
1326
1513
  }));
1327
1514
  var PxStrokeGradientEffectSchema = PxFillGradientEffectSchema;
1328
1515
  var PxTextPathEffectSchema = implementsInterface()(px.object({
1329
- path: px.string(),
1516
+ pathData: px.string(),
1330
1517
  pathOverflow: px.enum([PxPathOverflow.clip, PxPathOverflow.extend]).optional(),
1331
1518
  lengthAdjust: px.enum([PxLengthAdjust.spacing, PxLengthAdjust.spacingAndGlyphs]).optional(),
1332
1519
  method: px.enum([PxTextPathMethod.align, PxTextPathMethod.stretch]).optional(),
@@ -1366,16 +1553,33 @@ var PixodeskAnimator = (() => {
1366
1553
  walk(root, "root");
1367
1554
  return warnings;
1368
1555
  }
1556
+ function validateDocument(doc) {
1557
+ const ctx = { errors: [], warnings: [], strict: true };
1558
+ const problems = PxAnimatedSvgDocumentSchema.isValid(doc, ctx, ["root"]) ? [] : [...ctx.errors];
1559
+ if (doc && typeof doc === "object") {
1560
+ for (const w of validateNodeEffects(doc, { strict: true })) {
1561
+ if (!problems.includes(w)) problems.push(w);
1562
+ }
1563
+ }
1564
+ return problems;
1565
+ }
1369
1566
  var PxNodeBase = px.openObject({
1370
1567
  // CONVENTION (SCHEMA-DESIGN R1 / issues N4): `type` is the ONE word for "what
1371
1568
  // kind of thing is this", discriminated by its CARRIER — here the node TAG
1372
- // (`rect`, `text`), and inside a sub-object that object's kind (`clone.type`,
1569
+ // (`rect`, `text`), and inside a sub-object that object's kind (`fillGradient.type`,
1373
1570
  // `fillGradient.type`, editor `preset.type`). Each sits in its own object, so
1374
1571
  // the carrier disambiguates completely; synonyms (`cloneKind`, `presetShape`)
1375
1572
  // would add words that all mean "type" and still need the carrier to read.
1376
1573
  // Guarding a `type` SLOT against a wrong VALUE is the job of strict enums
1377
1574
  // (issues V3), never of distinct key names.
1378
1575
  type: px.string(),
1576
+ // The escape hatch for elements that carry a REAL `type` attribute — `<feTurbulence
1577
+ // type="fractalNoise">`, `<feFuncR type="table">`, `<feColorMatrix type="saturate">`.
1578
+ // `type` is taken by the tag name, so the attribute travels here and the renderer puts
1579
+ // it back (`PxAnimatorDOM.renderNode`, `PxRnRender`). Declared here — not merely
1580
+ // documented — because a wire key that is not in a schema is invisible to the
1581
+ // minifier's reserve list and gets renamed (MINIFICATION-BOUNDARY-PLAN.md §1.1).
1582
+ domType: px.string().optional(),
1379
1583
  id: px.string().optional(),
1380
1584
  meta: px.any().optional(),
1381
1585
  // Player-effects bucket emitted by the Editor's lightweight design format.
@@ -1411,7 +1615,7 @@ var PixodeskAnimator = (() => {
1411
1615
  c: px.boolean().optional()
1412
1616
  }));
1413
1617
 
1414
- // ../svg-animator-core/src/PxIdUtil.ts
1618
+ // ../svg-animator-core/src/util/PxIdUtil.ts
1415
1619
  var _idCounter = 0;
1416
1620
  function generateUniqueId() {
1417
1621
  const timestamp = Date.now().toString(36);
@@ -1448,7 +1652,8 @@ var PixodeskAnimator = (() => {
1448
1652
  "flood-color",
1449
1653
  "lighting-color"
1450
1654
  ]);
1451
- const directIdRefAttrs = /* @__PURE__ */ new Set(["sourceId", "targetId", "boundElementId"]);
1655
+ const directIdRefAttrs = /* @__PURE__ */ new Set(["targetId", "boundElementId"]);
1656
+ const isEffectSourceRef = (key, parentKey) => key === "source" && (parentKey === "maskedBy" || parentKey === "clone");
1452
1657
  function collectIds(node) {
1453
1658
  if (!node || typeof node !== "object") return;
1454
1659
  if (node.id && typeof node.id === "string") {
@@ -1465,7 +1670,7 @@ var PixodeskAnimator = (() => {
1465
1670
  }
1466
1671
  }
1467
1672
  }
1468
- function updateRefs(node) {
1673
+ function updateRefs(node, parentKey) {
1469
1674
  if (!node || typeof node !== "object") return;
1470
1675
  for (const [key, value] of Object.entries(node)) {
1471
1676
  if (key === "children") {
@@ -1485,7 +1690,7 @@ var PixodeskAnimator = (() => {
1485
1690
  }
1486
1691
  } else if (urlRefAttrs.has(key)) {
1487
1692
  node[key] = replaceUrlRefs(value, idMap);
1488
- } else if (directIdRefAttrs.has(key)) {
1693
+ } else if (directIdRefAttrs.has(key) || isEffectSourceRef(key, parentKey)) {
1489
1694
  const hasHash = value.startsWith("#");
1490
1695
  const newId = idMap.get(hasHash ? value.slice(1) : value);
1491
1696
  if (newId) {
@@ -1501,7 +1706,7 @@ var PixodeskAnimator = (() => {
1501
1706
  }
1502
1707
  }
1503
1708
  } else if (typeof value === "object" && value !== null) {
1504
- updateRefs(value);
1709
+ updateRefs(value, key);
1505
1710
  }
1506
1711
  }
1507
1712
  }
@@ -1510,9 +1715,11 @@ var PixodeskAnimator = (() => {
1510
1715
  const docAnimate = (_a = cloned.animator) == null ? void 0 : _a.animateById;
1511
1716
  if (docAnimate && typeof docAnimate === "object") {
1512
1717
  const updatedAnimate = {};
1513
- for (const [id, anim] of Object.entries(docAnimate)) {
1718
+ for (const [key, anim] of Object.entries(docAnimate)) {
1719
+ const hashed = key.startsWith("#");
1720
+ const id = hashed ? key.slice(1) : key;
1514
1721
  const newId = (_b = idMap.get(id)) != null ? _b : id;
1515
- updatedAnimate[newId] = anim;
1722
+ updatedAnimate[hashed ? "#" + newId : newId] = anim;
1516
1723
  }
1517
1724
  cloned.animator = __spreadProps(__spreadValues({}, cloned.animator), { animateById: updatedAnimate });
1518
1725
  }
@@ -1525,7 +1732,7 @@ var PixodeskAnimator = (() => {
1525
1732
  });
1526
1733
  }
1527
1734
 
1528
- // ../svg-animator-core/src/PxNodeProps.ts
1735
+ // ../svg-animator-core/src/util/PxNodeProps.ts
1529
1736
  var DISALLOWED_SVG_TAGS_LOWER = /* @__PURE__ */ new Set([
1530
1737
  "script",
1531
1738
  "foreignobject"
@@ -1605,16 +1812,16 @@ var PixodeskAnimator = (() => {
1605
1812
  let value = props[rawKey];
1606
1813
  if (COLOUR_ATTR_NAMES.has(key) && Array.isArray(value)) {
1607
1814
  propsCopy[key] = toRGBA(value);
1608
- } else if (key === "transform" && value !== null && typeof value === "object" && !Array.isArray(value) && !value.keyframes && !value.kfs) {
1815
+ } else if (key === "transform" && value !== null && typeof value === "object" && !Array.isArray(value) && !value.keyframes) {
1609
1816
  const parts = value.value && typeof value.value === "object" ? value.value : value;
1610
- propsCopy["transform"] = composeTransformParts(parts, { withUnits: false });
1817
+ propsCopy[TRANSFORM_ATTR] = composeTransformParts(parts, { withUnits: false });
1611
1818
  } else if (TRANSFORM_FN_NAMES.has(key)) {
1612
1819
  if (Array.isArray(value)) {
1613
1820
  if (key === "translate") value = value.map((v) => v + "px");
1614
1821
  value = value.join(",");
1615
1822
  }
1616
1823
  if (key === "rotate") value = value + "deg";
1617
- propsCopy["transform"] = key + "(" + value + ")";
1824
+ propsCopy[TRANSFORM_ATTR] = key + "(" + value + ")";
1618
1825
  } else if (Array.isArray(value)) {
1619
1826
  propsCopy[key] = value.join(",");
1620
1827
  } else if (value !== void 0 && value !== null) {
@@ -1624,10 +1831,9 @@ var PixodeskAnimator = (() => {
1624
1831
  return propsCopy;
1625
1832
  }
1626
1833
 
1627
- // ../svg-animator-core/src/PxMotionPath.ts
1834
+ // ../svg-animator-core/src/materialise/PxMotionPath.ts
1628
1835
  function getKfTranslate(kf) {
1629
- var _a;
1630
- const v = (_a = kf.value) != null ? _a : kf.v;
1836
+ const v = kfValue(kf);
1631
1837
  if (!v) return void 0;
1632
1838
  if (Array.isArray(v) && v.length >= 2 && typeof v[0] === "number" && typeof v[1] === "number") {
1633
1839
  return [v[0], v[1]];
@@ -1637,31 +1843,27 @@ var PixodeskAnimator = (() => {
1637
1843
  return void 0;
1638
1844
  }
1639
1845
  function getKfTime(kf) {
1640
- var _a, _b;
1641
- return (_b = (_a = kf.time) != null ? _a : kf.t) != null ? _b : 0;
1846
+ return kfTime(kf);
1642
1847
  }
1643
1848
  function getKfEasing(kf) {
1644
- var _a;
1645
- return (_a = kf.easing) != null ? _a : kf.e;
1849
+ return kfEasing(kf);
1646
1850
  }
1647
1851
  function propAnimIsMotionPath(anim) {
1648
- var _a, _b, _c;
1649
- const kfs = (_a = anim.keyframes) != null ? _a : anim.kfs;
1852
+ const kfs = anim.keyframes;
1650
1853
  if (!Array.isArray(kfs)) return false;
1651
1854
  if (anim.autoOrient) return true;
1652
1855
  for (const kf of kfs) {
1653
- if (((_b = kf.tangentIn) != null ? _b : kf.ti) || ((_c = kf.tangentOut) != null ? _c : kf.to)) return true;
1856
+ if (kfTangentIn(kf) || kfTangentOut(kf)) return true;
1654
1857
  }
1655
1858
  return false;
1656
1859
  }
1657
1860
  var _segmentCache = /* @__PURE__ */ new WeakMap();
1658
1861
  function getSegmentCache(prevKf, nextKf, prevPos, nextPos) {
1659
- var _a, _b;
1660
1862
  let byNext = _segmentCache.get(prevKf);
1661
1863
  const existing = byNext == null ? void 0 : byNext.get(nextKf);
1662
1864
  if (existing) return existing;
1663
- const to = (_a = prevKf.tangentOut) != null ? _a : prevKf.to;
1664
- const ti = (_b = nextKf.tangentIn) != null ? _b : nextKf.ti;
1865
+ const to = kfTangentOut(prevKf);
1866
+ const ti = kfTangentIn(nextKf);
1665
1867
  const P1 = [prevPos[0] + (to ? to[0] : 0), prevPos[1] + (to ? to[1] : 0)];
1666
1868
  const P2 = [nextPos[0] + (ti ? ti[0] : 0), nextPos[1] + (ti ? ti[1] : 0)];
1667
1869
  const lut = bezier2D_arcLengthLUT(prevPos, P1, P2, nextPos);
@@ -1711,14 +1913,14 @@ var PixodeskAnimator = (() => {
1711
1913
  var DEFAULT_ROTATION_TOL = 5;
1712
1914
  var DEFAULT_MAX_SAMPLES = 32;
1713
1915
  function materialiseMotionPathInPropAnim(anim, opts) {
1714
- var _a, _b, _c, _d;
1916
+ var _a, _b, _c;
1715
1917
  if (!propAnimIsMotionPath(anim)) return anim;
1716
- const kfs = (_a = anim.keyframes) != null ? _a : anim.kfs;
1918
+ const kfs = anim.keyframes;
1717
1919
  if (!Array.isArray(kfs) || kfs.length < 2) return anim;
1718
1920
  const autoOrient = !!anim.autoOrient;
1719
- const flatnessTol = (_b = opts == null ? void 0 : opts.flatnessTolerance) != null ? _b : DEFAULT_FLATNESS_TOL;
1720
- const rotationTol = (_c = opts == null ? void 0 : opts.rotationTolerance) != null ? _c : DEFAULT_ROTATION_TOL;
1721
- const maxSamples = (_d = opts == null ? void 0 : opts.maxSamplesPerSegment) != null ? _d : DEFAULT_MAX_SAMPLES;
1921
+ const flatnessTol = (_a = opts == null ? void 0 : opts.flatnessTolerance) != null ? _a : DEFAULT_FLATNESS_TOL;
1922
+ const rotationTol = (_b = opts == null ? void 0 : opts.rotationTolerance) != null ? _b : DEFAULT_ROTATION_TOL;
1923
+ const maxSamples = (_c = opts == null ? void 0 : opts.maxSamplesPerSegment) != null ? _c : DEFAULT_MAX_SAMPLES;
1722
1924
  const out = [];
1723
1925
  const firstPos = getKfTranslate(kfs[0]);
1724
1926
  if (!firstPos) return anim;
@@ -1747,15 +1949,14 @@ var PixodeskAnimator = (() => {
1747
1949
  const lastInE = getKfEasing(kfs[kfs.length - 1]);
1748
1950
  if (lastInE) out[out.length - 1].e = lastInE;
1749
1951
  if (autoOrient) unwrapAutoOrientRotations(out);
1750
- const result = { kfs: out };
1952
+ const result = { keyframes: out };
1751
1953
  if (anim.loop !== void 0) result.loop = anim.loop;
1752
1954
  return result;
1753
1955
  }
1754
1956
  function unwrapAutoOrientRotations(kfs) {
1755
- var _a;
1756
1957
  let prev;
1757
1958
  for (const kf of kfs) {
1758
- const v = (_a = kf.v) != null ? _a : kf.value;
1959
+ const v = kfValue(kf);
1759
1960
  if (!v || typeof v.rotate !== "number") continue;
1760
1961
  if (prev === void 0) {
1761
1962
  prev = v.rotate;
@@ -1772,8 +1973,7 @@ var PixodeskAnimator = (() => {
1772
1973
  return { t: time, v: value };
1773
1974
  }
1774
1975
  function getKfValueParts(kf) {
1775
- var _a;
1776
- const v = (_a = kf.value) != null ? _a : kf.v;
1976
+ const v = kfValue(kf);
1777
1977
  if (!v || typeof v !== "object" || Array.isArray(v)) return void 0;
1778
1978
  return v;
1779
1979
  }
@@ -1834,9 +2034,8 @@ var PixodeskAnimator = (() => {
1834
2034
  return d;
1835
2035
  }
1836
2036
  function insertSharpCornerStepKfIfNeeded(out, prevKf, nextKf, prevPos, nextPos, rotationTol) {
1837
- var _a;
1838
2037
  const lastKf = out[out.length - 1];
1839
- const lastV = (_a = lastKf.v) != null ? _a : lastKf.value;
2038
+ const lastV = kfValue(lastKf);
1840
2039
  const prevExit = lastV == null ? void 0 : lastV.rotate;
1841
2040
  if (typeof prevExit !== "number") return;
1842
2041
  const boundaryV = getKfValueParts(prevKf);
@@ -2017,7 +2216,7 @@ var PixodeskAnimator = (() => {
2017
2216
  return cloned;
2018
2217
  }
2019
2218
 
2020
- // ../svg-animator-core/src/PxDefinitions.ts
2219
+ // ../svg-animator-core/src/animation/PxDefinitions.ts
2021
2220
  var LOOP_JUMP_SHIFT_MS = 1;
2022
2221
  function deepEqualValue(a, b) {
2023
2222
  if (a === b) return true;
@@ -2230,7 +2429,7 @@ var PixodeskAnimator = (() => {
2230
2429
  const totalIntervals = keyframes.length - 1;
2231
2430
  const segCount = clamp((_a = loop.segmentCount) != null ? _a : totalIntervals, 1, totalIntervals);
2232
2431
  let segKfs;
2233
- if (loop.extend === PxLoopExtend.before) {
2432
+ if (loop.repeatAt === PxLoopRepeatAt.start) {
2234
2433
  segKfs = keyframes.slice(0, segCount + 1);
2235
2434
  } else {
2236
2435
  segKfs = keyframes.slice(totalIntervals - segCount);
@@ -2238,7 +2437,7 @@ var PixodeskAnimator = (() => {
2238
2437
  const firstT = (_b = keyframes[0].t) != null ? _b : 0;
2239
2438
  const lastT = (_c = keyframes[keyframes.length - 1].t) != null ? _c : 0;
2240
2439
  let fillStart, fillEnd;
2241
- if (loop.extend === PxLoopExtend.before) {
2440
+ if (loop.repeatAt === PxLoopRepeatAt.start) {
2242
2441
  fillStart = 0;
2243
2442
  fillEnd = firstT;
2244
2443
  } else {
@@ -2251,21 +2450,18 @@ var PixodeskAnimator = (() => {
2251
2450
  const segEndT = (_e = segKfs[segKfs.length - 1].t) != null ? _e : 0;
2252
2451
  const segDuration = segEndT - segStartT;
2253
2452
  if (segDuration <= 0) return keyframes;
2254
- const template = segKfs.map((kf) => {
2255
- var _a2, _b2;
2256
- return {
2257
- relT: (kf.t - segStartT) / segDuration,
2258
- v: kf.v,
2259
- e: kf.e,
2260
- tangentIn: (_a2 = kf.tangentIn) != null ? _a2 : kf.ti,
2261
- tangentOut: (_b2 = kf.tangentOut) != null ? _b2 : kf.to
2262
- };
2263
- });
2453
+ const template = segKfs.map((kf) => ({
2454
+ relT: (kf.t - segStartT) / segDuration,
2455
+ v: kf.v,
2456
+ e: kf.e,
2457
+ tangentIn: kfTangentIn(kf),
2458
+ tangentOut: kfTangentOut(kf)
2459
+ }));
2264
2460
  const fullReps = Math.floor(fillDuration / segDuration);
2265
2461
  const remainder = fillDuration - fullReps * segDuration;
2266
2462
  const partialFraction = remainder / segDuration;
2267
2463
  const looped = [];
2268
- const separateBoundary = loop.extend !== PxLoopExtend.before;
2464
+ const separateBoundary = loop.repeatAt !== PxLoopRepeatAt.start;
2269
2465
  const originalTerminalKf = keyframes[keyframes.length - 1];
2270
2466
  let terminalEasingOverride;
2271
2467
  let hasTerminalEasingOverride = false;
@@ -2373,30 +2569,30 @@ var PixodeskAnimator = (() => {
2373
2569
  looped.push(pushed);
2374
2570
  }
2375
2571
  }
2376
- if (loop.extend === PxLoopExtend.before) {
2572
+ if (loop.repeatAt === PxLoopRepeatAt.start) {
2377
2573
  if (partialFraction > 1e-9) {
2378
- const isReversed = !!loop.alternate && fullReps % 2 === 0;
2574
+ const isReversed = loop.direction === PxLoopDirection.alternate && fullReps % 2 === 0;
2379
2575
  appendRepTail(fillStart, isReversed, partialFraction);
2380
2576
  }
2381
2577
  for (let rep = 0; rep < fullReps; rep++) {
2382
2578
  const distFromBoundary = fullReps - 1 - rep;
2383
- const isReversed = !!loop.alternate && distFromBoundary % 2 === 0;
2579
+ const isReversed = loop.direction === PxLoopDirection.alternate && distFromBoundary % 2 === 0;
2384
2580
  const repStart = fillStart + remainder + rep * segDuration;
2385
2581
  appendRep(repStart, isReversed);
2386
2582
  }
2387
2583
  } else {
2388
2584
  for (let rep = 0; rep < fullReps; rep++) {
2389
- const isReversed = !!loop.alternate && rep % 2 === 0;
2585
+ const isReversed = loop.direction === PxLoopDirection.alternate && rep % 2 === 0;
2390
2586
  const repStart = fillStart + rep * segDuration;
2391
2587
  appendRep(repStart, isReversed);
2392
2588
  }
2393
2589
  if (partialFraction > 1e-9) {
2394
- const isReversed = !!loop.alternate && fullReps % 2 === 0;
2590
+ const isReversed = loop.direction === PxLoopDirection.alternate && fullReps % 2 === 0;
2395
2591
  const repStart = fillStart + fullReps * segDuration;
2396
2592
  appendRep(repStart, isReversed, partialFraction);
2397
2593
  }
2398
2594
  }
2399
- if (loop.extend === PxLoopExtend.before) {
2595
+ if (loop.repeatAt === PxLoopRepeatAt.start) {
2400
2596
  return [...looped, ...keyframes];
2401
2597
  } else {
2402
2598
  if (hasTerminalEasingOverride && keyframes.length > 0) {
@@ -2408,34 +2604,34 @@ var PixodeskAnimator = (() => {
2408
2604
  }
2409
2605
  }
2410
2606
  function normalizeKeyframes(propName, propAnim, duration, defs) {
2411
- var _a, _b, _c, _d, _e, _f, _g;
2412
- const keyframes = propAnim.keyframes || propAnim.kfs || [];
2607
+ var _a;
2608
+ const keyframes = propAnim.keyframes || [];
2413
2609
  const normalized = [];
2414
2610
  for (const kf of keyframes) {
2415
- const timePct = (_b = (_a = kf.time) != null ? _a : kf.t) != null ? _b : 0;
2416
- let value = (_c = kf.value) != null ? _c : kf.v;
2417
- const easing = (_d = kf.easing) != null ? _d : kf.e;
2611
+ const timePct = kfTime(kf);
2612
+ let value = kfValue(kf);
2613
+ const easing = kfEasing(kf);
2418
2614
  if (propName === "d") {
2419
2615
  value = normalizePathValue(value);
2420
2616
  }
2421
2617
  const propNameKebab = isCamelCaseWord(propName) ? camelCaseToKebabWordIfNeeded(propName) : propName;
2422
2618
  if (COLOUR_ATTR_NAMES.has(propNameKebab)) {
2423
- value = (_e = parseColor(value)) != null ? _e : value;
2619
+ value = (_a = parseColor(value)) != null ? _a : value;
2424
2620
  }
2425
2621
  const normKf = {
2426
2622
  t: timePct,
2427
2623
  v: value,
2428
2624
  e: resolveEasing(easing, defs)
2429
2625
  };
2430
- const tIn = (_f = kf.tangentIn) != null ? _f : kf.ti;
2431
- const tOut = (_g = kf.tangentOut) != null ? _g : kf.to;
2626
+ const tIn = kfTangentIn(kf);
2627
+ const tOut = kfTangentOut(kf);
2432
2628
  if (tIn) normKf.tangentIn = tIn;
2433
2629
  if (tOut) normKf.tangentOut = tOut;
2434
2630
  normalized.push(normKf);
2435
2631
  }
2436
2632
  normalized.sort((a, b) => {
2437
- var _a2, _b2;
2438
- return ((_a2 = a.t) != null ? _a2 : 0) - ((_b2 = b.t) != null ? _b2 : 0);
2633
+ var _a2, _b;
2634
+ return ((_a2 = a.t) != null ? _a2 : 0) - ((_b = b.t) != null ? _b : 0);
2439
2635
  });
2440
2636
  const loopRaw = propAnim.loop;
2441
2637
  const loop = loopRaw === true ? {} : loopRaw || void 0;
@@ -2454,28 +2650,29 @@ var PixodeskAnimator = (() => {
2454
2650
  return merged;
2455
2651
  }
2456
2652
  function materialiseInternalLoopsInPropAnim(propName, propAnim, duration) {
2457
- var _a;
2458
2653
  const loopRaw = propAnim.loop;
2459
2654
  if (loopRaw === void 0 || loopRaw === null || loopRaw === false) return propAnim;
2460
2655
  const loop = loopRaw === true ? {} : loopRaw;
2461
- const rawKfs = (_a = propAnim.keyframes) != null ? _a : propAnim.kfs;
2656
+ const rawKfs = propAnim.keyframes;
2462
2657
  if (!Array.isArray(rawKfs) || rawKfs.length < 2) return propAnim;
2463
2658
  const propNameKebab = isCamelCaseWord(propName) ? camelCaseToKebabWordIfNeeded(propName) : propName;
2464
2659
  const isColour = COLOUR_ATTR_NAMES.has(propNameKebab);
2465
2660
  const kfs = rawKfs.map((kf) => {
2466
- var _a2, _b, _c, _d, _e, _f, _g, _h;
2467
- const t = (_a2 = kf.t) != null ? _a2 : kf.time;
2468
- let v = (_b = kf.v) != null ? _b : kf.value;
2661
+ var _a;
2662
+ const t = kfTime(kf);
2663
+ let v = kfValue(kf);
2469
2664
  if (propName === "d") v = normalizePathValue(v);
2470
- if (isColour) v = (_c = parseColor(v)) != null ? _c : v;
2471
- const e = (_d = kf.e) != null ? _d : kf.easing;
2665
+ if (isColour) v = (_a = parseColor(v)) != null ? _a : v;
2666
+ const e = kfEasing(kf);
2472
2667
  const out2 = { t, v, e };
2473
- if ((_e = kf.tangentIn) != null ? _e : kf.ti) out2.tangentIn = (_f = kf.tangentIn) != null ? _f : kf.ti;
2474
- if ((_g = kf.tangentOut) != null ? _g : kf.to) out2.tangentOut = (_h = kf.tangentOut) != null ? _h : kf.to;
2668
+ const tIn = kfTangentIn(kf);
2669
+ const tOut = kfTangentOut(kf);
2670
+ if (tIn) out2.tangentIn = tIn;
2671
+ if (tOut) out2.tangentOut = tOut;
2475
2672
  return out2;
2476
2673
  });
2477
2674
  const expanded = expandLoopKeyframes(propName, kfs, loop, duration);
2478
- const out = { kfs: expanded };
2675
+ const out = { keyframes: expanded };
2479
2676
  if (propAnim.autoOrient !== void 0) out.autoOrient = propAnim.autoOrient;
2480
2677
  return out;
2481
2678
  }
@@ -2517,7 +2714,37 @@ var PixodeskAnimator = (() => {
2517
2714
  function generateElementId() {
2518
2715
  return "_px_el_" + ++_elementIdCounter;
2519
2716
  }
2520
- function normalizeAnimationDefinition(animDef, duration, defs, engine = PxAnimatorEngine.waapi) {
2717
+ function mergeStaticTransformIntoAnimDef(animDef, staticTransform) {
2718
+ if (!animDef) return animDef;
2719
+ const staticParts = staticTransform && typeof staticTransform === "object" && !Array.isArray(staticTransform) ? staticTransform : parseTransformParts(staticTransform);
2720
+ if (!staticParts || !Object.keys(staticParts).length) return animDef;
2721
+ const mergeKfValue = (v) => v && typeof v === "object" && !Array.isArray(v) ? __spreadValues(__spreadValues({}, staticParts), v) : v;
2722
+ const transformAnim = animDef[TRANSFORM_ATTR];
2723
+ if (transformAnim && typeof transformAnim === "object") {
2724
+ const anim = transformAnim;
2725
+ if (Array.isArray(anim.keyframes)) {
2726
+ const out = __spreadProps(__spreadValues({}, anim), {
2727
+ keyframes: anim.keyframes.map((kf) => __spreadProps(__spreadValues({}, kf), { value: mergeKfValue(kf.value) }))
2728
+ });
2729
+ if (out.value !== void 0) out.value = mergeKfValue(out.value);
2730
+ return __spreadProps(__spreadValues({}, animDef), { transform: out });
2731
+ }
2732
+ return animDef;
2733
+ }
2734
+ const channels = Object.keys(animDef).filter((k) => TRANSFORM_FN_NAMES.has(k));
2735
+ if (channels.length !== 1) return animDef;
2736
+ const ch = channels[0];
2737
+ const chAnim = animDef[ch];
2738
+ if (!chAnim || typeof chAnim !== "object" || !Array.isArray(chAnim.keyframes)) return animDef;
2739
+ const lifted = __spreadProps(__spreadValues({}, chAnim), {
2740
+ keyframes: chAnim.keyframes.map((kf) => __spreadProps(__spreadValues({}, kf), { value: __spreadProps(__spreadValues({}, staticParts), { [ch]: kf.value }) }))
2741
+ });
2742
+ if (lifted.value !== void 0) lifted.value = __spreadProps(__spreadValues({}, staticParts), { [ch]: lifted.value });
2743
+ const rest = __spreadValues({}, animDef);
2744
+ delete rest[ch];
2745
+ return __spreadProps(__spreadValues({}, rest), { transform: lifted });
2746
+ }
2747
+ function normalizeAnimationDefinition(animDef, duration, defs, engine = PxTimelineEngine.native) {
2521
2748
  const normalized = {};
2522
2749
  for (const [propName, propAnim] of Object.entries(animDef)) {
2523
2750
  if (propName === "transform" && propAnim.alongPathMode === "offsetPath" && animDef["offsetDistance"] !== void 0) {
@@ -2525,24 +2752,24 @@ var PixodeskAnimator = (() => {
2525
2752
  }
2526
2753
  const normalizedKfs = normalizeKeyframes(propName, propAnim, duration, defs);
2527
2754
  if (normalizedKfs.length > 0) {
2528
- const out = { kfs: normalizedKfs };
2755
+ const out = { keyframes: normalizedKfs };
2529
2756
  if (propAnim.autoOrient !== void 0) out.autoOrient = propAnim.autoOrient;
2530
2757
  if (propAnim.loop !== void 0) out.loop = propAnim.loop;
2531
- normalized[propName] = engine === PxAnimatorEngine.waapi && propName === "transform" ? materialiseMotionPathInPropAnim(out) : out;
2758
+ normalized[propName] = engine === PxTimelineEngine.native && propName === "transform" ? materialiseMotionPathInPropAnim(out) : out;
2532
2759
  }
2533
2760
  }
2534
2761
  return normalized;
2535
2762
  }
2536
- function getNormalisedBindings(doc, engine = PxAnimatorEngine.waapi) {
2763
+ function getNormalisedBindings(doc, engine = PxTimelineEngine.native) {
2537
2764
  const animatorConfig = getAnimatorConfig(doc) || {};
2538
2765
  const defs = getDefs(doc);
2539
2766
  const duration = animatorConfig.duration || 1e3;
2540
2767
  const bindings = [];
2541
- const processAnimation = (id, animate) => {
2768
+ const processAnimation = (id, animate, staticTransform) => {
2542
2769
  if (!animate) return null;
2543
2770
  const animDefs = resolveElementAnimation(animate, defs);
2544
2771
  if (animDefs.length === 0) return null;
2545
- const merged = mergeAnimationDefinitions(animDefs);
2772
+ const merged = mergeStaticTransformIntoAnimDef(mergeAnimationDefinitions(animDefs), staticTransform);
2546
2773
  const normalizedAnim = normalizeAnimationDefinition(merged, duration, defs, engine);
2547
2774
  if (Object.keys(normalizedAnim).length === 0) return null;
2548
2775
  return {
@@ -2562,7 +2789,7 @@ var PixodeskAnimator = (() => {
2562
2789
  if (inlineAnim && Object.keys(inlineAnim).length > 0) {
2563
2790
  const nodeId = node.id || generateElementId();
2564
2791
  node.id = nodeId;
2565
- const normalized = processAnimation(nodeId, inlineAnim);
2792
+ const normalized = processAnimation(nodeId, inlineAnim, node.transform);
2566
2793
  if (normalized) bindings.push(normalized);
2567
2794
  }
2568
2795
  if (node.children) {
@@ -2599,13 +2826,13 @@ var PixodeskAnimator = (() => {
2599
2826
  return { prevKf, nextKf };
2600
2827
  }
2601
2828
  function calcPropertyValue(propName, propAnim, progress) {
2602
- var _a, _b, _c, _d, _e, _f, _g;
2603
- const keyframes = propAnim.kfs || propAnim.keyframes || [];
2829
+ var _a, _b, _c, _d;
2830
+ const keyframes = propAnim.keyframes || [];
2604
2831
  if (keyframes.length === 0) return null;
2605
2832
  const { prevKf, nextKf } = getKeyframesPair(keyframes, progress);
2606
2833
  let localProgress = prevKf === nextKf ? 0 : remap(progress, (_a = prevKf.t) != null ? _a : 0, (_b = nextKf.t) != null ? _b : 0, 0, 1);
2607
2834
  localProgress = clamp(localProgress, 0, 1);
2608
- const easing = (_c = prevKf.e) != null ? _c : prevKf.easing;
2835
+ const easing = kfEasing(prevKf);
2609
2836
  if (easing && Array.isArray(easing)) {
2610
2837
  try {
2611
2838
  localProgress = cubicBezier(easing)(localProgress);
@@ -2614,11 +2841,11 @@ var PixodeskAnimator = (() => {
2614
2841
  }
2615
2842
  let cssAttrName = isCamelCaseWord(propName) ? camelCaseToKebabWordIfNeeded(propName) : propName;
2616
2843
  let cssValue = null;
2617
- const prevV = (_d = prevKf == null ? void 0 : prevKf.v) != null ? _d : prevKf == null ? void 0 : prevKf.value;
2618
- const nextV = (_e = nextKf == null ? void 0 : nextKf.v) != null ? _e : nextKf == null ? void 0 : nextKf.value;
2844
+ const prevV = prevKf == null ? void 0 : prevKf.v;
2845
+ const nextV = nextKf == null ? void 0 : nextKf.v;
2619
2846
  if (cssAttrName === "d") {
2620
- const prevPaths = (_f = prevV == null ? void 0 : prevV.paths) != null ? _f : Array.isArray(prevV) ? prevV : [];
2621
- const nextPaths = (_g = nextV == null ? void 0 : nextV.paths) != null ? _g : Array.isArray(nextV) ? nextV : [];
2847
+ const prevPaths = (_c = prevV == null ? void 0 : prevV.paths) != null ? _c : Array.isArray(prevV) ? prevV : [];
2848
+ const nextPaths = (_d = nextV == null ? void 0 : nextV.paths) != null ? _d : Array.isArray(nextV) ? nextV : [];
2622
2849
  cssValue = interpolateBeziers(
2623
2850
  prevPaths,
2624
2851
  nextPaths,
@@ -2721,7 +2948,7 @@ var PixodeskAnimator = (() => {
2721
2948
  return result;
2722
2949
  }
2723
2950
 
2724
- // ../svg-animator-core/src/PxNodeCloneUtil.ts
2951
+ // ../svg-animator-core/src/util/PxNodeCloneUtil.ts
2725
2952
  function deepClonePxNode(value) {
2726
2953
  if (value === null || typeof value !== "object") return value;
2727
2954
  if (Array.isArray(value)) return value.map(deepClonePxNode);
@@ -2785,7 +3012,7 @@ var PixodeskAnimator = (() => {
2785
3012
  return gNode;
2786
3013
  }
2787
3014
 
2788
- // ../svg-animator-core/src/PxAnimatorUseMaterialiser.ts
3015
+ // ../svg-animator-core/src/materialise/PxAnimatorUseMaterialiser.ts
2789
3016
  function materialiseAnimatedUseInstances(root) {
2790
3017
  var _a;
2791
3018
  const idMap = buildIdMap(root);
@@ -2933,7 +3160,7 @@ var PixodeskAnimator = (() => {
2933
3160
  return changed ? __spreadProps(__spreadValues({}, node), { children: newChildren }) : node;
2934
3161
  }
2935
3162
 
2936
- // ../svg-animator-core/src/effects/transformParts.ts
3163
+ // ../svg-animator-core/src/effects/shared/transformParts.ts
2937
3164
  function partsRecord(part, value, origin) {
2938
3165
  const rec = {};
2939
3166
  if (part === "translate" /* Translate */) rec.translate = value;
@@ -2944,19 +3171,19 @@ var PixodeskAnimator = (() => {
2944
3171
  return rec;
2945
3172
  }
2946
3173
  function readAnimatable(raw) {
2947
- var _a, _b, _c;
3174
+ var _a, _b;
2948
3175
  if (raw === void 0) return { kind: "absent" /* Absent */ };
2949
3176
  if (Array.isArray(raw)) return { kind: "static" /* Static */, value: raw };
2950
3177
  if (typeof raw === "object") {
2951
3178
  const obj = raw;
2952
- const kfs = (_a = obj.keyframes) != null ? _a : obj.kfs;
3179
+ const kfs = obj.keyframes;
2953
3180
  if (kfs) {
2954
3181
  const out = { kind: "animated" /* Animated */, keyframes: kfs.map(normaliseKeyframe), autoOrient: obj.autoOrient, loop: obj.loop };
2955
- const base = (_b = obj.value) != null ? _b : obj.v;
3182
+ const base = (_a = obj.value) != null ? _a : obj.v;
2956
3183
  if (base !== void 0 && out.kind === "animated" /* Animated */) out.base = base;
2957
3184
  return out;
2958
3185
  }
2959
- const staticValue = (_c = obj.value) != null ? _c : obj.v;
3186
+ const staticValue = (_b = obj.value) != null ? _b : obj.v;
2960
3187
  if (staticValue !== void 0) return { kind: "static" /* Static */, value: staticValue };
2961
3188
  }
2962
3189
  return { kind: "static" /* Static */, value: raw };
@@ -3010,7 +3237,7 @@ var PixodeskAnimator = (() => {
3010
3237
  return out;
3011
3238
  }
3012
3239
 
3013
- // ../svg-animator-core/src/effects/transformationEffect.ts
3240
+ // ../svg-animator-core/src/effects/transform/transformationEffect.ts
3014
3241
  function applyTransformByEffect(node, fx, ctx) {
3015
3242
  if (!fx) return node;
3016
3243
  delete node.transform;
@@ -3101,7 +3328,7 @@ var PixodeskAnimator = (() => {
3101
3328
  return inner;
3102
3329
  }
3103
3330
 
3104
- // ../svg-animator-core/src/effects/util.ts
3331
+ // ../svg-animator-core/src/effects/shared/util.ts
3105
3332
  function genId(ctx, prefix) {
3106
3333
  return "_lw_" + prefix + "_" + ctx.nextId++;
3107
3334
  }
@@ -3123,11 +3350,11 @@ var PixodeskAnimator = (() => {
3123
3350
  return regenerateIdsAndRewriteRefs(root, () => genId(ctx, "retimed"));
3124
3351
  }
3125
3352
 
3126
- // ../svg-animator-core/src/effects/contentRefSplit.ts
3353
+ // ../svg-animator-core/src/effects/reference/contentRefSplit.ts
3127
3354
  function identifyContentRefTargets(node, ctx, allocator) {
3128
3355
  var _a, _b, _c;
3129
- if (node.type === "use" && ((_b = (_a = node.effects) == null ? void 0 : _a.clone) == null ? void 0 : _b.type) === "content") {
3130
- const sourceId = stripHash2(node.effects.clone.sourceId);
3356
+ if (node.type === "use" && ((_b = (_a = node.effects) == null ? void 0 : _a.clone) == null ? void 0 : _b.without) === "translate") {
3357
+ const sourceId = stripHash2(node.effects.clone.source);
3131
3358
  if (typeof sourceId === "string" && sourceId && !ctx.contentRefInnerIds.has(sourceId)) {
3132
3359
  ctx.contentRefInnerIds.set(sourceId, allocator(sourceId));
3133
3360
  }
@@ -3224,7 +3451,7 @@ var PixodeskAnimator = (() => {
3224
3451
  if (split.rest) node.transform = split.rest;
3225
3452
  else delete node.transform;
3226
3453
  }
3227
- } else if (node.transform && typeof node.transform === "object" && !Array.isArray(node.transform) && !node.transform.keyframes && !node.transform.kfs) {
3454
+ } else if (node.transform && typeof node.transform === "object" && !Array.isArray(node.transform) && !node.transform.keyframes) {
3228
3455
  const wrapped = node.transform.value;
3229
3456
  const isWrapped = !!(wrapped && typeof wrapped === "object");
3230
3457
  const value = isWrapped ? wrapped : node.transform;
@@ -3338,7 +3565,7 @@ var PixodeskAnimator = (() => {
3338
3565
  return false;
3339
3566
  }
3340
3567
 
3341
- // ../svg-animator-core/src/effects/gradientEffect.ts
3568
+ // ../svg-animator-core/src/effects/paint/gradientEffect.ts
3342
3569
  function applyFillGradientEffect(node, fx, ctx) {
3343
3570
  return applyGradient(node, fx, ctx, "fill");
3344
3571
  }
@@ -3359,12 +3586,12 @@ var PixodeskAnimator = (() => {
3359
3586
  id
3360
3587
  };
3361
3588
  if (fx.type === PxGradientType.linear) {
3362
- applyGeomVec(out, "x1", "y1", fx.p1);
3363
- applyGeomVec(out, "x2", "y2", fx.p2);
3589
+ applyGeomVec(out, "x1", "y1", fx.start);
3590
+ applyGeomVec(out, "x2", "y2", fx.end);
3364
3591
  } else {
3365
- applyGeomVec(out, "cx", "cy", fx.c);
3366
- applyGeomNumber(out, "r", fx.r);
3367
- applyGeomVec(out, "fx", "fy", fx.fp);
3592
+ applyGeomVec(out, "cx", "cy", fx.center);
3593
+ applyGeomNumber(out, "r", fx.radius);
3594
+ applyGeomVec(out, "fx", "fy", fx.focal);
3368
3595
  }
3369
3596
  if (fx.gradientUnits) out.gradientUnits = fx.gradientUnits;
3370
3597
  if (fx.spreadMethod) out.spreadMethod = fx.spreadMethod;
@@ -3408,7 +3635,7 @@ var PixodeskAnimator = (() => {
3408
3635
  writeAnimatableChannel(out, attrName, read, { asString: true });
3409
3636
  }
3410
3637
  function buildStopChildren(stops, ctx) {
3411
- var _a, _b, _c, _d;
3638
+ var _a, _b;
3412
3639
  if (!stops) return [];
3413
3640
  const read = readAnimatable(stops);
3414
3641
  if (read.kind === "absent" /* Absent */) return [];
@@ -3418,14 +3645,14 @@ var PixodeskAnimator = (() => {
3418
3645
  const loopFromSource = read.loop;
3419
3646
  let stopCount = 0;
3420
3647
  for (const kf of kfs) {
3421
- const v = (_a = kf.value) != null ? _a : kf.v;
3648
+ const v = kfValue(kf);
3422
3649
  if (Array.isArray(v) && v.length > stopCount) stopCount = v.length;
3423
3650
  }
3424
3651
  if (!stopCount) return [];
3425
- const firstKfValue = (_b = kfs[0].value) != null ? _b : kfs[0].v;
3652
+ const firstKfValue = kfValue(kfs[0]);
3426
3653
  const baselineStops = [];
3427
3654
  for (let i = 0; i < stopCount; i++) {
3428
- 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" };
3655
+ const s = (_b = (_a = firstKfValue == null ? void 0 : firstKfValue[i]) != null ? _a : prevDefinedStop(kfs, 0, i)) != null ? _b : { offset: i / Math.max(1, stopCount - 1), color: "#000000" };
3429
3656
  baselineStops.push({ offset: s.offset, color: s.color });
3430
3657
  }
3431
3658
  return baselineStops.map((bs, i) => animatedStopNode(bs, kfs, i, ctx, loopFromSource));
@@ -3438,16 +3665,16 @@ var PixodeskAnimator = (() => {
3438
3665
  };
3439
3666
  }
3440
3667
  function animatedStopNode(baseline, kfs, stopIdx, _ctx, loop) {
3441
- var _a, _b, _c, _d, _e;
3668
+ var _a;
3442
3669
  const colorKfs = [];
3443
3670
  const offsetKfs = [];
3444
3671
  let offsetVaries = false;
3445
3672
  for (const kf of kfs) {
3446
- const t = (_b = (_a = kf.time) != null ? _a : kf.t) != null ? _b : 0;
3447
- const arr = (_c = kf.value) != null ? _c : kf.v;
3448
- const sliced = (_d = arr == null ? void 0 : arr[stopIdx]) != null ? _d : prevDefinedStop(kfs, kfs.indexOf(kf), stopIdx);
3673
+ const t = kfTime(kf);
3674
+ const arr = kfValue(kf);
3675
+ const sliced = (_a = arr == null ? void 0 : arr[stopIdx]) != null ? _a : prevDefinedStop(kfs, kfs.indexOf(kf), stopIdx);
3449
3676
  if (!sliced) continue;
3450
- const easing = (_e = kf.easing) != null ? _e : kf.e;
3677
+ const easing = kfEasing(kf);
3451
3678
  const colorOut = { time: t, value: sliced.color };
3452
3679
  if (easing !== void 0) colorOut.easing = easing;
3453
3680
  colorKfs.push(colorOut);
@@ -3474,13 +3701,12 @@ var PixodeskAnimator = (() => {
3474
3701
  return stop;
3475
3702
  }
3476
3703
  function prevDefinedStop(kfs, fromIdx, stopIdx) {
3477
- var _a, _b;
3478
3704
  for (let i = fromIdx; i >= 0; i--) {
3479
- const arr = (_a = kfs[i].value) != null ? _a : kfs[i].v;
3705
+ const arr = kfValue(kfs[i]);
3480
3706
  if (arr == null ? void 0 : arr[stopIdx]) return arr[stopIdx];
3481
3707
  }
3482
3708
  for (let i = fromIdx + 1; i < kfs.length; i++) {
3483
- const arr = (_b = kfs[i].value) != null ? _b : kfs[i].v;
3709
+ const arr = kfValue(kfs[i]);
3484
3710
  if (arr == null ? void 0 : arr[stopIdx]) return arr[stopIdx];
3485
3711
  }
3486
3712
  return void 0;
@@ -3490,10 +3716,9 @@ var PixodeskAnimator = (() => {
3490
3716
  return pct + "%";
3491
3717
  }
3492
3718
 
3493
- // ../svg-animator-core/src/effects/clipPathEffect.ts
3719
+ // ../svg-animator-core/src/effects/clipping/clipPathEffect.ts
3494
3720
  function applyClipPathEffect(node, fx, ctx) {
3495
- var _a, _b;
3496
- if (!fx || !fx.d && !fx.animate) return node;
3721
+ if (!(fx == null ? void 0 : fx.d)) return node;
3497
3722
  const clipId = genId(ctx, "clip");
3498
3723
  const pathChild = { type: "path" };
3499
3724
  const read = readAnimatable(fx.d);
@@ -3505,11 +3730,6 @@ var PixodeskAnimator = (() => {
3505
3730
  if (pathChild.d !== void 0) pathChild.d = pathString(pathChild.d);
3506
3731
  }
3507
3732
  }
3508
- if (fx.animate && !((_a = pathChild.animate) == null ? void 0 : _a.d)) {
3509
- const animate = (_b = pathChild.animate) != null ? _b : {};
3510
- animate.d = fx.animate;
3511
- pathChild.animate = animate;
3512
- }
3513
3733
  ctx.defs.push({ type: "clipPath", id: clipId, children: [pathChild] });
3514
3734
  node.clipPath = "url(#" + clipId + ")";
3515
3735
  return node;
@@ -3520,12 +3740,12 @@ var PixodeskAnimator = (() => {
3520
3740
  return void 0;
3521
3741
  }
3522
3742
 
3523
- // ../svg-animator-core/src/effects/maskedByEffect.ts
3743
+ // ../svg-animator-core/src/effects/clipping/maskedByEffect.ts
3524
3744
  function applyMaskedByEffect(node, fx, transformBy, ctx) {
3525
3745
  if (!fx) return node;
3526
- const sourceId = stripHash2(fx.sourceId);
3746
+ const sourceId = stripHash2(fx.source);
3527
3747
  if (!sourceId) {
3528
- ctx.errors.push("maskedBy.sourceId missing \u2014 cannot build mask");
3748
+ ctx.errors.push("maskedBy.source missing \u2014 cannot build mask");
3529
3749
  return node;
3530
3750
  }
3531
3751
  const maskId = genId(ctx, "mask");
@@ -3654,7 +3874,7 @@ var PixodeskAnimator = (() => {
3654
3874
  if (parts.origin) out.origin = parts.origin;
3655
3875
  return Object.keys(out).length ? out : void 0;
3656
3876
  }
3657
- if (node.transform && typeof node.transform === "object" && !node.transform.keyframes && !node.transform.kfs) {
3877
+ if (node.transform && typeof node.transform === "object" && !node.transform.keyframes) {
3658
3878
  const wrapped = node.transform.value;
3659
3879
  const value = wrapped && typeof wrapped === "object" ? wrapped : node.transform;
3660
3880
  if (value && typeof value === "object") {
@@ -3800,7 +4020,7 @@ var PixodeskAnimator = (() => {
3800
4020
  const interestingNodes = /* @__PURE__ */ new Set();
3801
4021
  const collectInterestingNodes = (n) => {
3802
4022
  var _a, _b;
3803
- const maskSourceId = stripHash2((_b = (_a = n.effects) == null ? void 0 : _a.maskedBy) == null ? void 0 : _b.sourceId);
4023
+ const maskSourceId = stripHash2((_b = (_a = n.effects) == null ? void 0 : _a.maskedBy) == null ? void 0 : _b.source);
3804
4024
  if (typeof maskSourceId === "string") {
3805
4025
  interestingNodes.add(n);
3806
4026
  const sourceNode = ctx.idMap.get(maskSourceId);
@@ -3829,7 +4049,7 @@ var PixodeskAnimator = (() => {
3829
4049
  if (typeof tr === "string") {
3830
4050
  const parts = parseTranslateOnlyFromString(tr, ctx);
3831
4051
  if (parts) out.translate = parts;
3832
- } else if (tr && typeof tr === "object" && !tr.keyframes && !tr.kfs) {
4052
+ } else if (tr && typeof tr === "object" && !tr.keyframes) {
3833
4053
  const wrapped = tr.value;
3834
4054
  const value = wrapped && typeof wrapped === "object" ? wrapped : tr;
3835
4055
  if (value && typeof value === "object" && Array.isArray(value.translate)) {
@@ -3877,16 +4097,15 @@ var PixodeskAnimator = (() => {
3877
4097
  return seen ? [x, y] : void 0;
3878
4098
  }
3879
4099
 
3880
- // ../svg-animator-core/src/effects/refEffect.ts
3881
- var CONTENT_SUBREF = "content";
4100
+ // ../svg-animator-core/src/effects/reference/refEffect.ts
3882
4101
  function applyRefHref(node, clone2, ctx) {
3883
4102
  if (!clone2) return;
3884
- const sourceId = stripHash2(clone2.sourceId);
4103
+ const sourceId = stripHash2(clone2.source);
3885
4104
  if (!sourceId) {
3886
- if (clone2.type === CONTENT_SUBREF) ctx.errors.push("clone: content ref missing sourceId");
4105
+ if (clone2.without === PxCloneWithout.translate) ctx.errors.push("clone: content ref missing `source`");
3887
4106
  return;
3888
4107
  }
3889
- const targetId = clone2.type === CONTENT_SUBREF ? ctx.contentRefInnerIds.get(sourceId) || sourceId : sourceId;
4108
+ const targetId = clone2.without === PxCloneWithout.translate ? ctx.contentRefInnerIds.get(sourceId) || sourceId : sourceId;
3890
4109
  node.href = "#" + targetId;
3891
4110
  }
3892
4111
  function applyRefAndTransformationEffect(node, clone2, transformBy, ctx) {
@@ -3894,7 +4113,7 @@ var PixodeskAnimator = (() => {
3894
4113
  return applyTransformByEffect(node, transformBy, ctx);
3895
4114
  }
3896
4115
 
3897
- // ../svg-animator-core/src/effects/repeaterEffect.ts
4116
+ // ../svg-animator-core/src/effects/transform/repeaterEffect.ts
3898
4117
  function applyRepeaterEffect(node, fx, ctx) {
3899
4118
  var _a, _b;
3900
4119
  if (!fx) return node;
@@ -3965,7 +4184,7 @@ var PixodeskAnimator = (() => {
3965
4184
  return mapAnimatable(raw, scalePower, true);
3966
4185
  }
3967
4186
 
3968
- // ../svg-animator-core/src/effects/retimeEffect.ts
4187
+ // ../svg-animator-core/src/effects/reference/retimeEffect.ts
3969
4188
  var RETIME_MATERIALISATION_MODE_INLINE_G = false;
3970
4189
  function asRetime(r) {
3971
4190
  var _a, _b;
@@ -4148,7 +4367,7 @@ var PixodeskAnimator = (() => {
4148
4367
  }
4149
4368
  }
4150
4369
 
4151
- // ../svg-animator-core/src/effects/pathSampler.ts
4370
+ // ../svg-animator-core/src/effects/text/pathSampler.ts
4152
4371
  var LUT_STEPS = 48;
4153
4372
  var CMD_RE = /[MmLlHhVvCcSsQqTtAaZz]/;
4154
4373
  function tokenize(d) {
@@ -4296,7 +4515,7 @@ var PixodeskAnimator = (() => {
4296
4515
  };
4297
4516
  }
4298
4517
 
4299
- // ../svg-animator-core/src/effects/textPathEffect.ts
4518
+ // ../svg-animator-core/src/effects/text/textPathEffect.ts
4300
4519
  var EXTEND_MARGIN_FRAC = 0.15;
4301
4520
  function numRange(v) {
4302
4521
  const read = readAnimatable(v);
@@ -4364,9 +4583,9 @@ var PixodeskAnimator = (() => {
4364
4583
  }
4365
4584
  function applyTextPathEffect(node, fx, ctx) {
4366
4585
  var _a;
4367
- if (!fx || typeof fx.path !== "string" || !fx.path) return node;
4586
+ if (!fx || typeof fx.pathData !== "string" || !fx.pathData) return node;
4368
4587
  const pathId = genId(ctx, "tpath");
4369
- const { d, startShift } = extendedPathForBrowser(fx.path, {
4588
+ const { d, startShift } = extendedPathForBrowser(fx.pathData, {
4370
4589
  pathOverflow: fx.pathOverflow,
4371
4590
  startOffset: fx.startOffset,
4372
4591
  textLength: fx.textLength,
@@ -4391,7 +4610,7 @@ var PixodeskAnimator = (() => {
4391
4610
  writeAnimatableChannel(node, attrName, readAnimatable(raw), { asString: true });
4392
4611
  }
4393
4612
 
4394
- // ../svg-animator-core/src/effects/elementFactory.ts
4613
+ // ../svg-animator-core/src/effects/text/elementFactory.ts
4395
4614
  var jsonElementFactory = (type, props, children) => {
4396
4615
  const node = { type };
4397
4616
  for (const k in props) if (props[k] !== void 0) node[k] = props[k];
@@ -4400,7 +4619,7 @@ var PixodeskAnimator = (() => {
4400
4619
  return node;
4401
4620
  };
4402
4621
 
4403
- // ../svg-animator-core/src/effects/glyphPathBake.ts
4622
+ // ../svg-animator-core/src/effects/text/glyphPathBake.ts
4404
4623
  function fmt(v, decimals) {
4405
4624
  return Math.round(v) === v ? "" + Math.round(v) : v.toFixed(decimals);
4406
4625
  }
@@ -4446,7 +4665,7 @@ var PixodeskAnimator = (() => {
4446
4665
  return out;
4447
4666
  }
4448
4667
 
4449
- // ../svg-animator-core/src/effects/textGlyphsEffect.ts
4668
+ // ../svg-animator-core/src/effects/text/textGlyphsEffect.ts
4450
4669
  var DEFAULT_FONT_SIZE = 16;
4451
4670
  var TEXT_ATTR_KEYS = [
4452
4671
  "fontFamily",
@@ -4825,7 +5044,7 @@ var PixodeskAnimator = (() => {
4825
5044
  return p;
4826
5045
  }
4827
5046
  function missingGlyphProps(isMissing) {
4828
- return isMissing ? { class: MISSING_GLYPH_CLASS_NAME } : {};
5047
+ return isMissing ? { [CLASS_ATTR]: MISSING_GLYPH_CLASS_NAME } : {};
4829
5048
  }
4830
5049
  function buildPaths(placements, create, warnings) {
4831
5050
  if (!placements.length) {
@@ -4865,20 +5084,20 @@ var PixodeskAnimator = (() => {
4865
5084
  function applyTextGlyphsEffect(node, fx, ctx) {
4866
5085
  if (!(fx == null ? void 0 : fx.useGlyphs)) return node;
4867
5086
  if (!ctx.glyphs) {
4868
- ctx.warnings.push("textGlyphs: no definitions.glyphs \u2014 left as native <text>");
5087
+ ctx.warnings.push("textGlyphs: no definitions.fonts \u2014 left as native <text>");
4869
5088
  return node;
4870
5089
  }
4871
5090
  return materialiseGlyphTextHorizontal(node, { glyphs: ctx.glyphs, warnings: ctx.warnings });
4872
5091
  }
4873
5092
  function applyTextGlyphsAlongPath(node, ctx, pathD, startOffset, textLength, pathOverflow) {
4874
5093
  if (!ctx.glyphs) {
4875
- ctx.warnings.push("textGlyphs: no definitions.glyphs");
5094
+ ctx.warnings.push("textGlyphs: no definitions.fonts");
4876
5095
  return null;
4877
5096
  }
4878
5097
  return materialiseGlyphTextAlongPath(node, pathD, startOffset, { glyphs: ctx.glyphs, warnings: ctx.warnings }, textLength, pathOverflow);
4879
5098
  }
4880
5099
 
4881
- // ../svg-animator-core/src/effects/strokeTrimEffect.ts
5100
+ // ../svg-animator-core/src/effects/stroke/strokeTrimEffect.ts
4882
5101
  function applyStrokeTrimEffect(node, strokeTrim, ctx) {
4883
5102
  if (!strokeTrim) return node;
4884
5103
  const combined = strokeTrim.subPaths === PxStrokeTrimSubPaths.combined;
@@ -5014,12 +5233,11 @@ var PixodeskAnimator = (() => {
5014
5233
  ];
5015
5234
  }
5016
5235
  function readScalarValues(r) {
5017
- var _a;
5018
5236
  if (r.kind === "absent" /* Absent */) return [];
5019
5237
  if (r.kind === "static" /* Static */) return [r.value];
5020
5238
  const out = [];
5021
5239
  for (const kf of r.keyframes) {
5022
- const v = (_a = kf.value) != null ? _a : kf.v;
5240
+ const v = kfValue(kf);
5023
5241
  if (typeof v === "number") out.push(v);
5024
5242
  }
5025
5243
  return out;
@@ -5029,14 +5247,11 @@ var PixodeskAnimator = (() => {
5029
5247
  if (read.kind === "static" /* Static */) return { kind: "static" /* Static */, value: map(read.value) };
5030
5248
  return {
5031
5249
  kind: "animated" /* Animated */,
5032
- keyframes: read.keyframes.map((kf) => {
5033
- var _a, _b, _c, _d;
5034
- return {
5035
- time: (_b = (_a = kf.time) != null ? _a : kf.t) != null ? _b : 0,
5036
- value: map((_c = kf.value) != null ? _c : kf.v),
5037
- easing: (_d = kf.easing) != null ? _d : kf.e
5038
- };
5039
- }),
5250
+ keyframes: read.keyframes.map((kf) => ({
5251
+ time: kfTime(kf),
5252
+ value: map(kfValue(kf)),
5253
+ easing: kfEasing(kf)
5254
+ })),
5040
5255
  loop: read.loop
5041
5256
  };
5042
5257
  }
@@ -5046,7 +5261,6 @@ var PixodeskAnimator = (() => {
5046
5261
  }
5047
5262
  var OPACITY_STEP_MS = 10;
5048
5263
  function computeOpacityFromRange(rangeRead) {
5049
- var _a, _b, _c, _d, _e, _f;
5050
5264
  const hide = (v) => v[0] === v[1];
5051
5265
  if (rangeRead.kind === "absent" /* Absent */) return void 0;
5052
5266
  if (rangeRead.kind === "static" /* Static */) return hide(rangeRead.value) ? { kind: "static" /* Static */, value: 0 } : void 0;
@@ -5054,7 +5268,7 @@ var PixodeskAnimator = (() => {
5054
5268
  let anyHide = false;
5055
5269
  let allHide = true;
5056
5270
  for (const kf of kfs) {
5057
- if (hide((_a = kf.value) != null ? _a : kf.v)) anyHide = true;
5271
+ if (hide(kfValue(kf))) anyHide = true;
5058
5272
  else allHide = false;
5059
5273
  }
5060
5274
  if (!anyHide) return void 0;
@@ -5064,10 +5278,10 @@ var PixodeskAnimator = (() => {
5064
5278
  const kf = kfs[i];
5065
5279
  const prevKf = i > 0 ? kfs[i - 1] : void 0;
5066
5280
  const nextKf = i < kfs.length - 1 ? kfs[i + 1] : void 0;
5067
- const t = (_c = (_b = kf.time) != null ? _b : kf.t) != null ? _c : 0;
5068
- const thisHide = hide((_d = kf.value) != null ? _d : kf.v);
5069
- const prevHide = prevKf ? thisHide && hide((_e = prevKf.value) != null ? _e : prevKf.v) : thisHide;
5070
- const nextHide = nextKf ? thisHide && hide((_f = nextKf.value) != null ? _f : nextKf.v) : thisHide;
5281
+ const t = kfTime(kf);
5282
+ const thisHide = hide(kfValue(kf));
5283
+ const prevHide = prevKf ? thisHide && hide(kfValue(prevKf)) : thisHide;
5284
+ const nextHide = nextKf ? thisHide && hide(kfValue(nextKf)) : thisHide;
5071
5285
  if (prevHide && !nextHide) {
5072
5286
  out.push({ time: t, value: 0 });
5073
5287
  out.push({ time: t + OPACITY_STEP_MS, value: 1 });
@@ -5082,14 +5296,11 @@ var PixodeskAnimator = (() => {
5082
5296
  function readRangeWithCrossings(raw) {
5083
5297
  const r = readAnimatable(raw);
5084
5298
  if (r.kind !== "animated" /* Animated */) return r;
5085
- const kfs = r.keyframes.map((kf) => {
5086
- var _a, _b, _c, _d;
5087
- return {
5088
- time: (_b = (_a = kf.time) != null ? _a : kf.t) != null ? _b : 0,
5089
- value: (_c = kf.value) != null ? _c : kf.v,
5090
- easing: (_d = kf.easing) != null ? _d : kf.e
5091
- };
5092
- });
5299
+ const kfs = r.keyframes.map((kf) => ({
5300
+ time: kfTime(kf),
5301
+ value: kfValue(kf),
5302
+ easing: kfEasing(kf)
5303
+ }));
5093
5304
  const hasReverse = kfs.some((kf) => kf.value[0] > kf.value[1]);
5094
5305
  if (!hasReverse) {
5095
5306
  return {
@@ -5228,8 +5439,8 @@ var PixodeskAnimator = (() => {
5228
5439
  maskAncestorChains: /* @__PURE__ */ new Map(),
5229
5440
  // Resolved engine: `frames` ONLY when explicitly set; auto/waapi/unset →
5230
5441
  // waapi (we're not 100% sure it's frames, and CSS/WAAPI need the inline form).
5231
- engine: ((_a = getAnimatorConfig(root)) == null ? void 0 : _a.mode) === PxAnimatorMode.frames ? PxAnimatorEngine.frames : PxAnimatorEngine.waapi,
5232
- glyphs: (_b = getDefs(root)) == null ? void 0 : _b.glyphs
5442
+ engine: resolveTimelineEngine((_a = getAnimatorConfig(root)) == null ? void 0 : _a.engine),
5443
+ glyphs: (_b = getDefs(root)) == null ? void 0 : _b.fonts
5233
5444
  };
5234
5445
  const working = clone(root);
5235
5446
  indexById(working, ctx.idMap);
@@ -5252,7 +5463,7 @@ var PixodeskAnimator = (() => {
5252
5463
  let consumedByGlyphs = false;
5253
5464
  if (text == null ? void 0 : text.useGlyphs) {
5254
5465
  if (textPath) {
5255
- const pathD = typeof textPath.path === "string" ? textPath.path : void 0;
5466
+ const pathD = typeof textPath.pathData === "string" ? textPath.pathData : void 0;
5256
5467
  const glyphed = applyTextGlyphsAlongPath(n, ctx, pathD, textPath.startOffset, textPath.textLength, textPath.pathOverflow);
5257
5468
  if (glyphed) {
5258
5469
  n = glyphed;
@@ -5285,27 +5496,7 @@ var PixodeskAnimator = (() => {
5285
5496
  return node;
5286
5497
  }
5287
5498
 
5288
- // ../svg-animator-core/src/PxOffsetPathMaterialiser.ts
5289
- var kfTime = (kf) => {
5290
- var _a, _b;
5291
- return (_b = (_a = kf.t) != null ? _a : kf.time) != null ? _b : 0;
5292
- };
5293
- var kfValue = (kf) => {
5294
- var _a;
5295
- return (_a = kf.v) != null ? _a : kf.value;
5296
- };
5297
- var kfEasing = (kf) => {
5298
- var _a;
5299
- return (_a = kf.e) != null ? _a : kf.easing;
5300
- };
5301
- var kfTangentIn = (kf) => {
5302
- var _a;
5303
- return (_a = kf.tangentIn) != null ? _a : kf.ti;
5304
- };
5305
- var kfTangentOut = (kf) => {
5306
- var _a;
5307
- return (_a = kf.tangentOut) != null ? _a : kf.to;
5308
- };
5499
+ // ../svg-animator-core/src/materialise/PxOffsetPathMaterialiser.ts
5309
5500
  function cubicAt(p0, c1, c2, p1, t) {
5310
5501
  const u = 1 - t;
5311
5502
  const a = u * u * u, b = 3 * u * u * t, c = 3 * u * t * t, d = t * t * t;
@@ -5329,9 +5520,9 @@ var PixodeskAnimator = (() => {
5329
5520
  return Object.is(r, -0) ? "0" : String(r);
5330
5521
  };
5331
5522
  function buildOffsetPath(propAnim) {
5332
- var _a, _b, _c, _d;
5523
+ var _a, _b, _c;
5333
5524
  if (propAnim.alongPathMode !== "offsetPath") return void 0;
5334
- const kfs = (_a = propAnim.keyframes) != null ? _a : propAnim.kfs;
5525
+ const kfs = propAnim.keyframes;
5335
5526
  if (!kfs || kfs.length < 2) return void 0;
5336
5527
  const first = kfValue(kfs[0]);
5337
5528
  const anchor = (first == null ? void 0 : first.origin) && first.origin.length >= 2 ? [first.origin[0], first.origin[1]] : [0, 0];
@@ -5342,7 +5533,7 @@ var PixodeskAnimator = (() => {
5342
5533
  if (!tr || tr.length < 2) return void 0;
5343
5534
  const parts = Object.keys(v);
5344
5535
  if (parts.some((p) => p !== "translate" && p !== "origin")) return void 0;
5345
- const o = (_b = v == null ? void 0 : v.origin) != null ? _b : [0, 0];
5536
+ const o = (_a = v == null ? void 0 : v.origin) != null ? _a : [0, 0];
5346
5537
  if (o[0] !== anchor[0] || o[1] !== anchor[1]) return void 0;
5347
5538
  points.push([tr[0] + anchor[0], tr[1] + anchor[1]]);
5348
5539
  }
@@ -5351,8 +5542,8 @@ var PixodeskAnimator = (() => {
5351
5542
  const segLens = [];
5352
5543
  for (let i = 0; i < points.length - 1; i++) {
5353
5544
  const p0 = points[i], p1 = points[i + 1];
5354
- const to = (_c = kfTangentOut(kfs[i])) != null ? _c : [0, 0];
5355
- const ti = (_d = kfTangentIn(kfs[i + 1])) != null ? _d : [0, 0];
5545
+ const to = (_b = kfTangentOut(kfs[i])) != null ? _b : [0, 0];
5546
+ const ti = (_c = kfTangentIn(kfs[i + 1])) != null ? _c : [0, 0];
5356
5547
  const c1 = [p0[0] + to[0], p0[1] + to[1]];
5357
5548
  const c2 = [p1[0] + ti[0], p1[1] + ti[1]];
5358
5549
  d += "C" + fmt2(c1[0]) + "," + fmt2(c1[1]) + "," + fmt2(c2[0]) + "," + fmt2(c2[1]) + "," + fmt2(p1[0]) + "," + fmt2(p1[1]);
@@ -5381,16 +5572,16 @@ var PixodeskAnimator = (() => {
5381
5572
  const built = buildOffsetPath(transform);
5382
5573
  if (built) {
5383
5574
  const newAnimate = __spreadValues({}, anim);
5384
- delete newAnimate["transform"];
5575
+ delete newAnimate[TRANSFORM_ATTR];
5385
5576
  const distance = { keyframes: built.distanceKfs };
5386
5577
  if (transform.loop !== void 0) distance.loop = transform.loop;
5387
- newAnimate["offsetDistance"] = distance;
5578
+ newAnimate[OFFSET_DISTANCE_ATTR] = distance;
5388
5579
  const staticTr = node.transform;
5389
5580
  let newTransform = staticTr;
5390
5581
  if (staticTr && typeof staticTr === "object") {
5391
5582
  const t = __spreadValues({}, staticTr);
5392
- delete t["translate"];
5393
- delete t["origin"];
5583
+ delete t[TRANSFORM_PART.translate];
5584
+ delete t[TRANSFORM_PART.origin];
5394
5585
  newTransform = Object.keys(t).length ? t : void 0;
5395
5586
  }
5396
5587
  out = __spreadProps(__spreadValues({}, node), {
@@ -5415,14 +5606,14 @@ var PixodeskAnimator = (() => {
5415
5606
  return walk(root);
5416
5607
  }
5417
5608
 
5418
- // ../svg-animator-core/src/PxAnimatorMaterialiseAll.ts
5609
+ // ../svg-animator-core/src/materialise/PxAnimatorMaterialiseAll.ts
5419
5610
  function materialiseAllInTree(doc, engine, opts) {
5420
5611
  var _a, _b;
5421
5612
  let root = applyPlayerEffects(doc).root;
5422
5613
  root = materialiseOffsetPathsInTree(root);
5423
5614
  const duration = (_b = (_a = getAnimatorConfig(root)) == null ? void 0 : _a.duration) != null ? _b : DEFAULT_DURATION_MS;
5424
5615
  root = materialiseInternalLoopsInTree(root, duration);
5425
- if (engine === PxAnimatorEngine.waapi) {
5616
+ if (engine === PxTimelineEngine.native) {
5426
5617
  root = materialiseMotionPathsInTree(root, opts == null ? void 0 : opts.motionPath);
5427
5618
  root = materialiseAnimatedUseInstances(root);
5428
5619
  root = pruneUnreferencedDefs(root);
@@ -5459,7 +5650,7 @@ var PixodeskAnimator = (() => {
5459
5650
  return root;
5460
5651
  }
5461
5652
 
5462
- // ../svg-animator-core/src/PxFrameLoop.ts
5653
+ // ../svg-animator-core/src/playback/PxFrameLoop.ts
5463
5654
  function requestFrame(cb) {
5464
5655
  const g = globalThis;
5465
5656
  if (typeof g.requestAnimationFrame === "function") return g.requestAnimationFrame(cb);
@@ -5476,7 +5667,7 @@ var PixodeskAnimator = (() => {
5476
5667
  function createBasicFrameLoopAnimator(doc, adapter, callbacks) {
5477
5668
  var _a;
5478
5669
  const config = getAnimatorConfig(doc) || {};
5479
- const bindings = getNormalisedBindings(doc, PxAnimatorEngine.frames);
5670
+ const bindings = getNormalisedBindings(doc, PxTimelineEngine.js);
5480
5671
  const _iterations = config.iterations;
5481
5672
  let iterations = 1;
5482
5673
  if (typeof _iterations === "number") iterations = _iterations || 1;
@@ -5737,7 +5928,194 @@ var PixodeskAnimator = (() => {
5737
5928
  return api;
5738
5929
  }
5739
5930
 
5740
- // src/PxAnimatorTriggers.ts
5931
+ // ../svg-animator-core/src/playback/PxAnimatorConfigPatch.ts
5932
+ var FLAT_ONLY_KEYS = [
5933
+ "timelineSource",
5934
+ "scroll",
5935
+ "trigger",
5936
+ "delay",
5937
+ "iterations",
5938
+ "direction",
5939
+ "fill",
5940
+ "resetOnFinish",
5941
+ "duration",
5942
+ "mode",
5943
+ "frameRate"
5944
+ ];
5945
+ var CONTENT_KEYS = ["definitions", "animateById"];
5946
+ var isPlainObject = (v) => !!v && typeof v === "object" && !Array.isArray(v);
5947
+ var timelineTypeOf = (t) => isPlainObject(t) && typeof t.type === "string" ? t.type : "time";
5948
+ var isScrollish = (type) => type === "scroll" || type === "view";
5949
+ function mergePlain(base, patch) {
5950
+ const out = isPlainObject(base) ? __spreadValues({}, base) : {};
5951
+ for (const key of Object.keys(patch)) {
5952
+ const value = patch[key];
5953
+ if (value === null) {
5954
+ delete out[key];
5955
+ continue;
5956
+ }
5957
+ if (isPlainObject(value)) {
5958
+ out[key] = mergePlain(out[key], value);
5959
+ continue;
5960
+ }
5961
+ out[key] = value;
5962
+ }
5963
+ return out;
5964
+ }
5965
+ function mergeTimeline(base, patch, warn) {
5966
+ const baseType = timelineTypeOf(base);
5967
+ const patchNamesType = isPlainObject(patch) && typeof patch.type === "string";
5968
+ const patchType = patchNamesType ? String(patch.type) : baseType;
5969
+ let merged;
5970
+ if (patchType !== baseType) {
5971
+ const carried = {};
5972
+ if (isPlainObject(base)) {
5973
+ for (const k of PX_TIMELINE_SHARED_KEYS) {
5974
+ if (base[k] !== void 0) carried[k] = base[k];
5975
+ }
5976
+ }
5977
+ merged = mergePlain(carried, patch);
5978
+ } else {
5979
+ merged = mergePlain(base, patch);
5980
+ }
5981
+ if (isScrollish(patchType)) {
5982
+ for (const k of PX_TIME_ONLY_TIMELINE_KEYS) {
5983
+ if (merged[k] === void 0) continue;
5984
+ warn("animator.timeline." + k + ": no slot on a '" + patchType + "' timeline \u2014 dropped");
5985
+ delete merged[k];
5986
+ }
5987
+ if (merged.iterations === "infinite") {
5988
+ warn("animator.timeline.iterations: 'infinite' cannot map onto a scroll range \u2014 dropped");
5989
+ delete merged.iterations;
5990
+ }
5991
+ }
5992
+ return merged;
5993
+ }
5994
+ function foldAnimatorConfigShortcuts(config, shortcuts) {
5995
+ let base;
5996
+ if (typeof config === "string") {
5997
+ try {
5998
+ base = JSON.parse(config);
5999
+ } catch (e) {
6000
+ console.warn("animator config: not valid JSON \u2014 ignored", e);
6001
+ base = void 0;
6002
+ }
6003
+ } else {
6004
+ base = config != null ? config : void 0;
6005
+ }
6006
+ const { duration, delay, iterations, startOn } = shortcuts;
6007
+ if (duration === void 0 && delay === void 0 && iterations === void 0 && startOn === void 0) {
6008
+ return base;
6009
+ }
6010
+ const out = isPlainObject(base) ? __spreadValues({}, base) : {};
6011
+ const timeline = __spreadValues({}, out.timeline);
6012
+ if (duration !== void 0) timeline.duration = duration;
6013
+ if (delay !== void 0) timeline.delay = delay;
6014
+ if (iterations !== void 0) timeline.iterations = iterations;
6015
+ if (startOn !== void 0) {
6016
+ timeline.trigger = __spreadProps(__spreadValues({}, timeline.trigger), { startOn });
6017
+ }
6018
+ out.timeline = timeline;
6019
+ return out;
6020
+ }
6021
+ function mergeAnimatorConfig(base, patch) {
6022
+ const warnings = [];
6023
+ const warn = (m) => warnings.push(m);
6024
+ if (patch === null) return { config: void 0, warnings };
6025
+ if (!isPlainObject(patch) || Object.keys(patch).length === 0) {
6026
+ return { config: base, warnings };
6027
+ }
6028
+ const flatInBase = isPlainObject(base) ? FLAT_ONLY_KEYS.filter((k) => base[k] !== void 0) : [];
6029
+ if (flatInBase.length) {
6030
+ warn("animator: the base carries the flat runtime spelling (" + flatInBase.join(", ") + "); the patch merges the wire spelling only");
6031
+ }
6032
+ const out = isPlainObject(base) ? __spreadValues({}, base) : {};
6033
+ for (const key of Object.keys(patch)) {
6034
+ const value = patch[key];
6035
+ if (value === null) {
6036
+ delete out[key];
6037
+ continue;
6038
+ }
6039
+ if (key === "timeline") {
6040
+ out.timeline = isPlainObject(value) ? mergeTimeline(out.timeline, value, warn) : value;
6041
+ continue;
6042
+ }
6043
+ if (isPlainObject(value)) {
6044
+ out[key] = mergePlain(out[key], value);
6045
+ continue;
6046
+ }
6047
+ out[key] = value;
6048
+ }
6049
+ return { config: out, warnings };
6050
+ }
6051
+ function applyAnimatorConfig(doc, patch, opts) {
6052
+ var _a, _b;
6053
+ const reset = !!(opts == null ? void 0 : opts.resetDefaults);
6054
+ if (!doc || (patch === void 0 || !reset && (patch === null || !isPlainObject(patch) || !Object.keys(patch).length))) {
6055
+ return { doc, warnings: [] };
6056
+ }
6057
+ const anyDoc = doc;
6058
+ const atRoot = isPlainObject(anyDoc.animator);
6059
+ const atMeta = !atRoot && isPlainObject((_a = anyDoc.meta) == null ? void 0 : _a.animator);
6060
+ const current = atRoot ? anyDoc.animator : atMeta ? anyDoc.meta.animator : void 0;
6061
+ const warnings = [];
6062
+ if (atRoot && isPlainObject((_b = anyDoc.meta) == null ? void 0 : _b.animator)) {
6063
+ warnings.push("animator: doc.meta.animator is shadowed by doc.animator and was not patched");
6064
+ }
6065
+ let base = current;
6066
+ if (reset) {
6067
+ const kept = {};
6068
+ for (const k of CONTENT_KEYS) {
6069
+ if (isPlainObject(current) && current[k] !== void 0) kept[k] = current[k];
6070
+ }
6071
+ base = kept;
6072
+ }
6073
+ const merged = mergeAnimatorConfig(base, patch != null ? patch : {});
6074
+ warnings.push(...merged.warnings);
6075
+ if (merged.config === current) return { doc, warnings };
6076
+ if (atMeta) {
6077
+ return {
6078
+ doc: __spreadProps(__spreadValues({}, anyDoc), { meta: __spreadProps(__spreadValues({}, anyDoc.meta), { animator: merged.config }) }),
6079
+ warnings
6080
+ };
6081
+ }
6082
+ return { doc: __spreadProps(__spreadValues({}, anyDoc), { animator: merged.config }), warnings };
6083
+ }
6084
+
6085
+ // ../svg-animator-core/src/format/PxDocumentDiagnostic.ts
6086
+ var MAX_REPORTED = 6;
6087
+ var LEGACY_FLAT_KEYS = [
6088
+ ...PX_TIMELINE_SHARED_KEYS,
6089
+ ...PX_TIME_ONLY_TIMELINE_KEYS,
6090
+ "fill",
6091
+ "resetOnFinish",
6092
+ "timelineSource",
6093
+ "scroll"
6094
+ ];
6095
+ var isLegacyFlatAnimatorKey = (w) => LEGACY_FLAT_KEYS.some((k) => w.indexOf("animator." + k + ":") >= 0);
6096
+ function diagnoseDocument(doc) {
6097
+ let all;
6098
+ try {
6099
+ all = validateDocument(doc);
6100
+ } catch (e) {
6101
+ return { problems: [], legacy: [] };
6102
+ }
6103
+ const problems = [];
6104
+ const legacy = [];
6105
+ for (const w of all) (isLegacyFlatAnimatorKey(w) ? legacy : problems).push(w);
6106
+ return { problems, legacy };
6107
+ }
6108
+ function reportDocumentDiagnostics(doc, where) {
6109
+ const { problems } = diagnoseDocument(doc);
6110
+ if (!problems.length) return;
6111
+ const shown = problems.slice(0, MAX_REPORTED);
6112
+ const more = problems.length - shown.length;
6113
+ console.warn(
6114
+ 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."
6115
+ );
6116
+ }
6117
+
6118
+ // src/triggers/PxAnimatorTriggers.ts
5741
6119
  function setupAnimationTriggers(api, config) {
5742
6120
  const { startOn, outAction = "continue", scrollIntoViewThreshold = 0 } = config;
5743
6121
  const root = api.getRootElement();
@@ -5842,7 +6220,7 @@ var PixodeskAnimator = (() => {
5842
6220
  return api;
5843
6221
  }
5844
6222
 
5845
- // src/PxAnimatorFrameLoop.ts
6223
+ // src/engines/PxAnimatorFrameLoop.ts
5846
6224
  function getSelector(id) {
5847
6225
  return "#" + id;
5848
6226
  }
@@ -5902,11 +6280,10 @@ var PixodeskAnimator = (() => {
5902
6280
  return adapter;
5903
6281
  }
5904
6282
 
5905
- // src/PxAnimatorWebApi.ts
6283
+ // src/engines/PxAnimatorWebApi.ts
5906
6284
  function createCssKf(kf, t, propName, unsupportedSet) {
5907
- var _a, _b;
5908
- let value = (_a = kf.v) != null ? _a : kf.value;
5909
- const e = (_b = kf.e) != null ? _b : kf.easing;
6285
+ let value = kfValue(kf);
6286
+ const e = kfEasing(kf);
5910
6287
  const cssKf = {
5911
6288
  offset: t,
5912
6289
  easing: e && Array.isArray(e) ? "cubic-bezier(" + e.join(",") + ")" : void 0
@@ -5977,7 +6354,7 @@ var PixodeskAnimator = (() => {
5977
6354
  const result = /* @__PURE__ */ new Map();
5978
6355
  for (const [propName, propAnim] of Object.entries(animDef)) {
5979
6356
  const duration = config.duration || 1;
5980
- const clippedKeyframes = clipKeyframesToDuration(propName, propAnim.kfs || propAnim.keyframes || [], duration);
6357
+ const clippedKeyframes = clipKeyframesToDuration(propName, propAnim.keyframes || [], duration);
5981
6358
  const cssKeyframes = [];
5982
6359
  for (let i = 0; i < clippedKeyframes.length; i++) {
5983
6360
  const kf = clippedKeyframes[i];
@@ -6011,7 +6388,7 @@ var PixodeskAnimator = (() => {
6011
6388
  console.warn("createFrameLoopAnimator: No root element provided");
6012
6389
  }
6013
6390
  }
6014
- const bindings = getNormalisedBindings(doc, PxAnimatorEngine.waapi);
6391
+ const bindings = getNormalisedBindings(doc, PxTimelineEngine.native);
6015
6392
  const animations = [];
6016
6393
  const _iterations = config.iterations;
6017
6394
  let iterations;
@@ -6169,7 +6546,7 @@ var PixodeskAnimator = (() => {
6169
6546
  return api;
6170
6547
  }
6171
6548
 
6172
- // src/PxScrollDriver.ts
6549
+ // src/scroll/PxScrollDriver.ts
6173
6550
  function nativeRangeOffset(point, defaultFraction, view) {
6174
6551
  var _a, _b, _c;
6175
6552
  const fraction = typeof (point == null ? void 0 : point.fraction) === "number" ? point.fraction : defaultFraction;
@@ -6183,7 +6560,7 @@ var PixodeskAnimator = (() => {
6183
6560
  const scroll = config.scroll || {};
6184
6561
  const kind = (_a = scroll.kind) != null ? _a : "view";
6185
6562
  if (scroll.smoothing) {
6186
- console.warn('scroll timeline: `smoothing` needs the built-in driver \u2014 ignoring `driver: "native"`');
6563
+ console.warn("scroll timeline: `smoothing` needs the built-in driver \u2014 using the built-in driver instead of the browser timeline");
6187
6564
  return null;
6188
6565
  }
6189
6566
  const g = globalThis;
@@ -6200,7 +6577,7 @@ var PixodeskAnimator = (() => {
6200
6577
  timeline = new Ctor({ source, axis });
6201
6578
  }
6202
6579
  } catch (e) {
6203
- console.warn("scroll timeline: native timeline construction failed \u2014 falling back to the custom driver", e);
6580
+ console.warn("scroll timeline: native timeline construction failed \u2014 falling back to the player measuring progress itself", e);
6204
6581
  return null;
6205
6582
  }
6206
6583
  return {
@@ -6419,7 +6796,7 @@ var PixodeskAnimator = (() => {
6419
6796
  };
6420
6797
  }
6421
6798
 
6422
- // src/PxAnimatorBind.ts
6799
+ // src/engines/PxAnimatorBind.ts
6423
6800
  function finaliseAnimator(animatorConfig, callbacks, make) {
6424
6801
  let apiRef;
6425
6802
  let effectiveCallbacks = callbacks;
@@ -6434,8 +6811,8 @@ var PixodeskAnimator = (() => {
6434
6811
  }
6435
6812
  const res = make(effectiveCallbacks);
6436
6813
  apiRef = res;
6437
- if (animatorConfig.debugInstName) {
6438
- window[animatorConfig.debugInstName] = res;
6814
+ if (animatorConfig.debugGlobalName) {
6815
+ window[animatorConfig.debugGlobalName] = res;
6439
6816
  }
6440
6817
  return res;
6441
6818
  }
@@ -6443,10 +6820,10 @@ var PixodeskAnimator = (() => {
6443
6820
  const animatorConfig = getAnimatorConfig(doc) || {};
6444
6821
  if (isScrollTimeline(animatorConfig)) {
6445
6822
  return finaliseAnimator(animatorConfig, callbacks, (cb) => {
6446
- var _a, _b;
6823
+ var _a;
6447
6824
  let unpin = () => {
6448
6825
  };
6449
- if (animatorConfig.mode !== PxAnimatorMode.frames && ((_a = animatorConfig.scroll) == null ? void 0 : _a.driver) === "native" && rootElement) {
6826
+ if (mayUseNativeScrollTimeline(animatorConfig.engine) && rootElement) {
6450
6827
  unpin = applyScrollPin(rootElement, animatorConfig.scroll);
6451
6828
  const native = createNativeScrollTimeline(rootElement, animatorConfig);
6452
6829
  if (native) {
@@ -6454,7 +6831,7 @@ var PixodeskAnimator = (() => {
6454
6831
  doc,
6455
6832
  cb,
6456
6833
  rootElement,
6457
- animatorConfig.mode === PxAnimatorMode.waapi,
6834
+ isNativeForced(animatorConfig.engine),
6458
6835
  native
6459
6836
  );
6460
6837
  if (api2) {
@@ -6470,8 +6847,8 @@ var PixodeskAnimator = (() => {
6470
6847
  unpin = () => {
6471
6848
  };
6472
6849
  }
6473
- const api = (animatorConfig.mode !== PxAnimatorMode.frames ? createWebApiAnimator(doc, cb, rootElement, animatorConfig.mode === PxAnimatorMode.waapi) : null) || createFrameLoopAnimator(doc, adapter, cb, rootElement);
6474
- const subject = ((_b = api.getRootElement) == null ? void 0 : _b.call(api)) || rootElement;
6850
+ const api = (animatorConfig.engine !== PxTimelineEngineExtra.js ? createWebApiAnimator(doc, cb, rootElement, isNativeForced(animatorConfig.engine)) : null) || createFrameLoopAnimator(doc, adapter, cb, rootElement);
6851
+ const subject = ((_a = api.getRootElement) == null ? void 0 : _a.call(api)) || rootElement;
6475
6852
  if (subject) {
6476
6853
  unpin = applyScrollPin(subject, animatorConfig.scroll);
6477
6854
  const totalMs = scrollTotalDurationMs(animatorConfig);
@@ -6495,20 +6872,19 @@ var PixodeskAnimator = (() => {
6495
6872
  });
6496
6873
  }
6497
6874
  return finaliseAnimator(animatorConfig, callbacks, (cb) => {
6498
- if (animatorConfig.mode === PxAnimatorMode.frames) {
6875
+ if (animatorConfig.engine === PxTimelineEngineExtra.js) {
6499
6876
  return createFrameLoopAnimator(doc, adapter, cb, rootElement);
6500
6877
  }
6501
6878
  return createWebApiAnimator(
6502
6879
  doc,
6503
6880
  cb,
6504
6881
  rootElement,
6505
- animatorConfig.mode === PxAnimatorMode.waapi
6506
- // forcing waapi
6882
+ isNativeForced(animatorConfig.engine)
6507
6883
  ) || createFrameLoopAnimator(doc, adapter, cb, rootElement);
6508
6884
  });
6509
6885
  }
6510
6886
 
6511
- // src/PxAnimatorDOM.ts
6887
+ // src/dom/PxAnimatorDOM.ts
6512
6888
  var SVG_NS = "http://www.w3.org/2000/svg";
6513
6889
  function createElement(tagName, normalisedProps, style, children, textContent) {
6514
6890
  if (DISALLOWED_SVG_TAGS_LOWER.has(tagName.toLowerCase())) {
@@ -6566,18 +6942,24 @@ var PixodeskAnimator = (() => {
6566
6942
  return element;
6567
6943
  }
6568
6944
 
6569
- // src/PxAnimatorKeys.ts
6945
+ // src/shared/PxAnimatorKeys.ts
6570
6946
  var PX_ANIMATOR_DATA_KEY = "data";
6571
6947
 
6572
- // src/PxAnimator.ts
6948
+ // src/animator/PxAnimator.ts
6573
6949
  function createAnimatorFromConfig(doc, adapter, callbacks, rootElement) {
6574
6950
  return bindWithEngineChoice(doc, adapter, callbacks, rootElement);
6575
6951
  }
6576
- function createAnimatorImpl(doc, adapter, callbacks, containerElement) {
6952
+ function createAnimatorImpl(doc, adapter, callbacks, containerElement, config, resetDocDefaults) {
6577
6953
  const effectsWarnings = validateNodeEffects(doc);
6578
6954
  for (const w of effectsWarnings) console.warn("[PxAnimator] effects shape warning:", w);
6955
+ reportDocumentDiagnostics(doc, "[PxAnimator] createAnimator");
6956
+ if (config !== void 0 || resetDocDefaults) {
6957
+ const patched = applyAnimatorConfig(doc, config != null ? config : {}, { resetDefaults: !!resetDocDefaults });
6958
+ for (const w of patched.warnings) console.warn("[PxAnimator] config override:", w);
6959
+ doc = patched.doc;
6960
+ }
6579
6961
  const animatorConfig = getAnimatorConfig(doc) || {};
6580
- const engine = animatorConfig.mode === PxAnimatorMode.frames ? PxAnimatorEngine.frames : PxAnimatorEngine.waapi;
6962
+ const engine = resolveTimelineEngine(animatorConfig.engine);
6581
6963
  doc = materialiseAllInTree(doc, engine);
6582
6964
  let rootElement = null;
6583
6965
  if (containerElement) {
@@ -6590,10 +6972,24 @@ var PixodeskAnimator = (() => {
6590
6972
  }
6591
6973
  }
6592
6974
  }
6593
- return createAnimatorFromConfig(doc, adapter, callbacks, rootElement);
6975
+ const api = createAnimatorFromConfig(doc, adapter, callbacks, rootElement);
6976
+ if (containerElement && rootElement) {
6977
+ const rendered = rootElement;
6978
+ const destroyNative = api.destroy.bind(api);
6979
+ api.destroy = () => {
6980
+ destroyNative();
6981
+ rendered.remove();
6982
+ };
6983
+ }
6984
+ return api;
6985
+ }
6986
+ function resolveAnimatorConfigOption(options) {
6987
+ const { config, duration, delay, iterations, startOn } = options;
6988
+ return foldAnimatorConfigShortcuts(config, { duration, delay, iterations, startOn });
6594
6989
  }
6595
6990
  function createAnimator(options) {
6596
- const { src, data, adapter, callbacks, container } = options;
6991
+ const { src, data, adapter, callbacks, container, resetDocDefaults } = options;
6992
+ const config = resolveAnimatorConfigOption(options);
6597
6993
  if (data !== void 0 && src !== void 0) {
6598
6994
  throw new Error("createAnimator: provide either `src` or `data`, not both");
6599
6995
  }
@@ -6601,7 +6997,7 @@ var PixodeskAnimator = (() => {
6601
6997
  throw new Error("createAnimator: either `src` or `data` is required");
6602
6998
  }
6603
6999
  if (data !== void 0) {
6604
- return createAnimatorImpl(data, adapter, callbacks, container);
7000
+ return createAnimatorImpl(data, adapter, callbacks, container, config, resetDocDefaults);
6605
7001
  }
6606
7002
  let animator = null;
6607
7003
  let pending = [];
@@ -6616,7 +7012,7 @@ var PixodeskAnimator = (() => {
6616
7012
  fetch(src).then((res) => res.json()).then((json) => {
6617
7013
  if (destroyed) return;
6618
7014
  if (isPxElementFileFormat(json)) {
6619
- animator = createAnimatorImpl(json, adapter, callbacks, container);
7015
+ animator = createAnimatorImpl(json, adapter, callbacks, container, config, resetDocDefaults);
6620
7016
  const queued = pending;
6621
7017
  pending = null;
6622
7018
  queued == null ? void 0 : queued.forEach((call) => call(animator));
@@ -6676,4 +7072,4 @@ var PixodeskAnimator = (() => {
6676
7072
  }
6677
7073
  return __toCommonJS(index_player_exports);
6678
7074
  })();
6679
- //# sourceMappingURL=index.umd.js.map
7075
+ //# sourceMappingURL=pixodesk-svg-animator.umd.js.map