@pixodesk/svg-animator-core 1.0.34 → 1.0.39

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -50,7 +50,8 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
50
50
  // src/index.ts
51
51
  var index_exports = {};
52
52
  __export(index_exports, {
53
- COLOUR_ATTR_NAMES: () => COLOUR_ATTR_NAMES,
53
+ BASELINE_PLAYER_VERSION: () => BASELINE_PLAYER_VERSION,
54
+ COLOR_ATTR_NAMES: () => COLOR_ATTR_NAMES,
54
55
  CSS_ONLY_STYLE_PROPS: () => CSS_ONLY_STYLE_PROPS,
55
56
  DEFAULT_DURATION_MS: () => DEFAULT_DURATION_MS,
56
57
  DISALLOWED_SVG_TAGS_LOWER: () => DISALLOWED_SVG_TAGS_LOWER,
@@ -58,123 +59,190 @@ __export(index_exports, {
58
59
  LOOP_JUMP_SHIFT_MS: () => LOOP_JUMP_SHIFT_MS,
59
60
  MISSING_GLYPH_CLASS_NAME: () => MISSING_GLYPH_CLASS_NAME,
60
61
  PCT_BASED_ATTR_NAMES: () => PCT_BASED_ATTR_NAMES,
62
+ PLAYER_WIRE_STEPS: () => PLAYER_WIRE_STEPS,
63
+ PLAYER_WIRE_VERSION: () => PLAYER_WIRE_VERSION,
61
64
  PX_ANIM_ATTR_NAME: () => PX_ANIM_ATTR_NAME,
62
65
  PX_ANIM_SRC_ATTR_NAME: () => PX_ANIM_SRC_ATTR_NAME,
66
+ PX_PLAYER_SCHEMA_VERSION: () => PX_PLAYER_SCHEMA_VERSION,
67
+ PX_RATE_REJECTED: () => PX_RATE_REJECTED,
63
68
  PX_TRANSFORM_PART_KEYS: () => PX_TRANSFORM_PART_KEYS,
69
+ PX_TRIGGER_DEFAULTS: () => PX_TRIGGER_DEFAULTS,
70
+ PX_UNKNOWN_KEY_ERROR: () => PX_UNKNOWN_KEY_ERROR,
71
+ PxAlongPathMode: () => PxAlongPathMode,
64
72
  PxAnimatedSvgDocumentSchema: () => PxAnimatedSvgDocumentSchema,
65
73
  PxAnimationDefinitionSchema: () => PxAnimationDefinitionSchema,
66
74
  PxAnimatorConfigSchema: () => PxAnimatorConfigSchema,
67
- PxAnimatorEngine: () => PxAnimatorEngine,
68
- PxAnimatorMode: () => PxAnimatorMode,
69
75
  PxAttrValueSchema: () => PxAttrValueSchema,
70
76
  PxBezierPathSchema: () => PxBezierPathSchema,
71
77
  PxBindingSchema: () => PxBindingSchema,
78
+ PxClipPathEffectSchema: () => PxClipPathEffectSchema,
72
79
  PxCloneEffectSchema: () => PxCloneEffectSchema,
80
+ PxCloneWithout: () => PxCloneWithout,
81
+ PxControlMode: () => PxControlMode,
73
82
  PxDefsSchema: () => PxDefsSchema,
83
+ PxDiagnosticKind: () => PxDiagnosticKind,
74
84
  PxEasingOrRefSchema: () => PxEasingOrRefSchema,
75
85
  PxEffectsSchema: () => PxEffectsSchema,
76
86
  PxElementAnimationSchema: () => PxElementAnimationSchema,
77
87
  PxFillGradientEffectSchema: () => PxFillGradientEffectSchema,
88
+ PxFillMode: () => PxFillMode,
89
+ PxFinishAction: () => PxFinishAction,
78
90
  PxGradientSpreadMethod: () => PxGradientSpreadMethod,
79
91
  PxGradientStopSchema: () => PxGradientStopSchema,
80
92
  PxGradientType: () => PxGradientType,
81
- PxGradientUnits: () => PxGradientUnits,
82
93
  PxKeyframeSchema: () => PxKeyframeSchema,
83
94
  PxKeyframeValueSchema: () => PxKeyframeValueSchema,
84
- PxLoopExtend: () => PxLoopExtend,
95
+ PxLengthAdjust: () => PxLengthAdjust,
96
+ PxLoopDirection: () => PxLoopDirection,
97
+ PxLoopRepeatAt: () => PxLoopRepeatAt,
85
98
  PxLoopSchema: () => PxLoopSchema,
99
+ PxMaskType: () => PxMaskType,
86
100
  PxMaskedByEffectSchema: () => PxMaskedByEffectSchema,
87
101
  PxNodeBase: () => PxNodeBase,
88
102
  PxNodeSchema: () => PxNodeSchema,
103
+ PxOutAction: () => PxOutAction,
104
+ PxPathOverflow: () => PxPathOverflow,
105
+ PxPinAlign: () => PxPinAlign,
106
+ PxPlaybackDirection: () => PxPlaybackDirection,
89
107
  PxPropertyAnimationSchema: () => PxPropertyAnimationSchema,
90
108
  PxRepeaterEffectSchema: () => PxRepeaterEffectSchema,
91
109
  PxRetimeEffectSchema: () => PxRetimeEffectSchema,
110
+ PxScrollAxis: () => PxScrollAxis,
111
+ PxScrollKind: () => PxScrollKind,
112
+ PxScrollPhase: () => PxScrollPhase,
92
113
  PxScrollRangePointSchema: () => PxScrollRangePointSchema,
93
114
  PxScrollRangeSchema: () => PxScrollRangeSchema,
94
115
  PxScrollSchema: () => PxScrollSchema,
116
+ PxScrollSource: () => PxScrollSource,
117
+ PxStartOn: () => PxStartOn,
95
118
  PxStrokeGradientEffectSchema: () => PxStrokeGradientEffectSchema,
96
119
  PxStrokeTrimEffectSchema: () => PxStrokeTrimEffectSchema,
97
120
  PxStrokeTrimSubPaths: () => PxStrokeTrimSubPaths,
98
121
  PxSvgNodeExtra: () => PxSvgNodeExtra,
99
122
  PxTextEffectSchema: () => PxTextEffectSchema,
100
123
  PxTextPathEffectSchema: () => PxTextPathEffectSchema,
124
+ PxTextPathMethod: () => PxTextPathMethod,
125
+ PxTextPathSpacing: () => PxTextPathSpacing,
126
+ PxTimelineEngine: () => PxTimelineEngine,
127
+ PxTimelineEngineExtra: () => PxTimelineEngineExtra,
101
128
  PxTimelinePinSchema: () => PxTimelinePinSchema,
102
129
  PxTimelineSchema: () => PxTimelineSchema,
103
130
  PxTransformByEffectSchema: () => PxTransformByEffectSchema,
104
131
  PxTransformPartsSchema: () => PxTransformPartsSchema,
105
132
  PxTransformValueSchema: () => PxTransformValueSchema,
106
133
  PxTriggerSchema: () => PxTriggerSchema,
134
+ PxUnits: () => PxUnits,
107
135
  STYLE_ATTR_NAMES: () => STYLE_ATTR_NAMES,
108
- TEXT_ATTR: () => TEXT_ATTR,
109
136
  TEXT_CONTENT_ATTR: () => TEXT_CONTENT_ATTR,
110
137
  TRANSFORM_FN_NAMES: () => TRANSFORM_FN_NAMES,
138
+ WIRE_VERSION_KEY: () => WIRE_VERSION_KEY,
139
+ WireStepKind: () => WireStepKind,
140
+ WireVersionRelation: () => WireVersionRelation,
141
+ applyAnimatorConfig: () => applyAnimatorConfig,
111
142
  applyPlayerEffects: () => applyPlayerEffects,
143
+ applyWireSteps: () => applyWireSteps,
144
+ applyWireStepsDown: () => applyWireStepsDown,
112
145
  bezierToSvgPath: () => bezierToSvgPath,
113
146
  calcAnimationValues: () => calcAnimationValues,
114
147
  camelCaseToKebabWordIfNeeded: () => camelCaseToKebabWordIfNeeded,
115
148
  clamp: () => clamp,
149
+ clampSeekMs: () => clampSeekMs,
116
150
  collectSampleTimes: () => collectSampleTimes,
151
+ compareWireVersion: () => compareWireVersion,
117
152
  composeTransformParts: () => composeTransformParts,
153
+ controlModeTakesOverTrigger: () => controlModeTakesOverTrigger,
154
+ convertPlayerDocument: () => convertPlayerDocument,
118
155
  createBasicFrameLoopAnimator: () => createBasicFrameLoopAnimator,
156
+ createDiagnostics: () => createDiagnostics,
119
157
  createPathSampler: () => createPathSampler,
158
+ createRunClock: () => createRunClock,
120
159
  cubicBezier: () => cubicBezier,
121
160
  deepClone: () => deepClone,
122
161
  describeSchema: () => describeSchema,
162
+ diagnoseDocument: () => diagnoseDocument,
163
+ diffFieldUniverse: () => diffFieldUniverse,
123
164
  diffInEffect: () => diffInEffect,
165
+ downgradePlayerDocument: () => downgradePlayerDocument,
124
166
  evaluateMotionPathSegment: () => evaluateMotionPathSegment,
125
167
  extendedPathForBrowser: () => extendedPathForBrowser,
126
168
  flattenAnimatorTimeline: () => flattenAnimatorTimeline,
169
+ foldTimelineOverride: () => foldTimelineOverride,
170
+ formatWireVersion: () => formatWireVersion,
127
171
  generateNewIds: () => generateNewIds,
128
172
  generateUniqueId: () => generateUniqueId,
129
173
  getAnimatorConfig: () => getAnimatorConfig,
130
174
  getBindings: () => getBindings,
131
175
  getChildren: () => getChildren,
132
176
  getDefs: () => getDefs,
133
- getNormalisedBindings: () => getNormalisedBindings,
177
+ getNormalizedBindings: () => getNormalizedBindings,
134
178
  getNormalizedProps: () => getNormalizedProps,
135
179
  interpolateBeziers: () => interpolateBeziers,
136
180
  interpolateValue: () => interpolateValue,
181
+ isNativeForced: () => isNativeForced,
137
182
  isPxElementFileFormat: () => isPxElementFileFormat,
138
183
  isPxElementFileFormatDeep: () => isPxElementFileFormatDeep,
139
184
  isScrollTimeline: () => isScrollTimeline,
185
+ isValidPlaybackRate: () => isValidPlaybackRate,
140
186
  jsonElementFactory: () => jsonElementFactory,
141
187
  kebabToCamelCaseWord: () => kebabToCamelCaseWord,
188
+ kfEasing: () => kfEasing,
189
+ kfTangentIn: () => kfTangentIn,
190
+ kfTangentOut: () => kfTangentOut,
191
+ kfTime: () => kfTime,
192
+ kfValue: () => kfValue,
142
193
  layoutGlyphTextChars: () => layoutGlyphTextChars,
143
- materialiseAllInTree: () => materialiseAllInTree,
144
- materialiseAnimatedUseInstances: () => materialiseAnimatedUseInstances,
145
- materialiseGlyphText: () => materialiseGlyphText,
146
- materialiseGlyphTextAlongPath: () => materialiseGlyphTextAlongPath,
147
- materialiseGlyphTextHorizontal: () => materialiseGlyphTextHorizontal,
148
- materialiseInternalLoopsInPropAnim: () => materialiseInternalLoopsInPropAnim,
149
- materialiseInternalLoopsInTree: () => materialiseInternalLoopsInTree,
150
- materialiseMotionPathInPropAnim: () => materialiseMotionPathInPropAnim,
151
- materialiseMotionPathsInTree: () => materialiseMotionPathsInTree,
194
+ materializeAllInTree: () => materializeAllInTree,
195
+ materializeAnimatedUseInstances: () => materializeAnimatedUseInstances,
196
+ materializeGlyphText: () => materializeGlyphText,
197
+ materializeGlyphTextAlongPath: () => materializeGlyphTextAlongPath,
198
+ materializeGlyphTextHorizontal: () => materializeGlyphTextHorizontal,
199
+ materializeInternalLoopsInPropAnim: () => materializeInternalLoopsInPropAnim,
200
+ materializeInternalLoopsInTree: () => materializeInternalLoopsInTree,
201
+ materializeMotionPathInPropAnim: () => materializeMotionPathInPropAnim,
202
+ materializeMotionPathsInTree: () => materializeMotionPathsInTree,
203
+ mayUseNativeScrollTimeline: () => mayUseNativeScrollTimeline,
204
+ mergeAnimatorConfig: () => mergeAnimatorConfig,
152
205
  mergeStaticTransformIntoAnimDef: () => mergeStaticTransformIntoAnimDef,
153
206
  nestAnimatorTimeline: () => nestAnimatorTimeline,
154
207
  parseTransformParts: () => parseTransformParts,
208
+ parseWireVersion: () => parseWireVersion,
209
+ planSchemaRelease: () => planSchemaRelease,
210
+ progressSpanMs: () => progressSpanMs,
211
+ progressToTimeMs: () => progressToTimeMs,
155
212
  propAnimIsMotionPath: () => propAnimIsMotionPath,
156
213
  px: () => px,
214
+ readWireVersion: () => readWireVersion,
215
+ releaseLogProblems: () => releaseLogProblems,
216
+ reportDocumentDiagnostics: () => reportDocumentDiagnostics,
217
+ resolveControlMode: () => resolveControlMode,
157
218
  resolveStyle: () => resolveStyle,
219
+ resolveTimelineEngine: () => resolveTimelineEngine,
220
+ resolveTrigger: () => resolveTrigger,
158
221
  reverseEasing: () => reverseEasing,
159
- sanitiseAttributeValue: () => sanitiseAttributeValue,
222
+ sanitizeAttributeValue: () => sanitizeAttributeValue,
223
+ schemaFieldUniverse: () => schemaFieldUniverse,
160
224
  schemaKeys: () => schemaKeys,
161
225
  scrollOffsetProgress: () => scrollOffsetProgress,
162
226
  scrollPhaseInterval: () => scrollPhaseInterval,
163
227
  scrollResolveAxis: () => scrollResolveAxis,
164
228
  scrollTotalDurationMs: () => scrollTotalDurationMs,
165
229
  scrollViewProgress: () => scrollViewProgress,
230
+ seekCeilingMs: () => seekCeilingMs,
166
231
  shiftAnimatable: () => shiftAnimatable,
167
232
  splitEasing: () => splitEasing,
168
233
  subdivideCubicBezier: () => subdivideCubicBezier,
234
+ timeToProgress: () => timeToProgress,
169
235
  toRGBA: () => toRGBA,
236
+ validateDocument: () => validateDocument,
170
237
  validateNodeEffects: () => validateNodeEffects,
238
+ versionAdvice: () => versionAdvice,
171
239
  visualModelAt: () => visualModelAt
172
240
  });
173
241
  module.exports = __toCommonJS(index_exports);
174
242
 
175
- // src/PxAnimatorUtil.ts
243
+ // src/util/PxAnimatorUtil.ts
176
244
  function bezierToSvgPath(path, forceCurves = false) {
177
- var _a, _b, _c, _d;
245
+ var _a2, _b, _c, _d;
178
246
  const v = path.v;
179
247
  const i = path.i;
180
248
  const o = path.o;
@@ -185,7 +253,7 @@ function bezierToSvgPath(path, forceCurves = false) {
185
253
  d.push("M" + v[0][0] + "," + v[0][1]);
186
254
  for (let idx = 1; idx < len; idx++) {
187
255
  const prevV = v[idx - 1];
188
- const prevO = (_a = o == null ? void 0 : o[idx - 1]) != null ? _a : prevV;
256
+ const prevO = (_a2 = o == null ? void 0 : o[idx - 1]) != null ? _a2 : prevV;
189
257
  const currI = (_b = i == null ? void 0 : i[idx]) != null ? _b : v[idx];
190
258
  const currV = v[idx];
191
259
  const isLine = !forceCurves && (prevO[0] === prevV[0] && prevO[1] === prevV[1]) && (currI[0] === currV[0] && currI[1] === currV[1]);
@@ -236,7 +304,7 @@ function interpolateBeziers(paths1, paths2, progress) {
236
304
  return res;
237
305
  }
238
306
  function interpolateBezier(path1, path2, progress) {
239
- var _a, _b, _c, _d, _e, _f, _g, _h, _i;
307
+ var _a2, _b, _c, _d, _e, _f, _g, _h, _i;
240
308
  if (!path1 || !path2) return path1 || path2 || { v: [] };
241
309
  const t = Math.min(Math.max(progress, 0), 1);
242
310
  const len = Math.min(path1.v.length, path2.v.length);
@@ -247,7 +315,7 @@ function interpolateBezier(path1, path2, progress) {
247
315
  const v1 = path1.v[idx];
248
316
  const v2 = path2.v[idx];
249
317
  v.push(interpolateVec(v1, v2, t));
250
- const i1 = (_b = (_a = path1.i) == null ? void 0 : _a[idx]) != null ? _b : v1;
318
+ const i1 = (_b = (_a2 = path1.i) == null ? void 0 : _a2[idx]) != null ? _b : v1;
251
319
  const i2 = (_d = (_c = path2.i) == null ? void 0 : _c[idx]) != null ? _d : v2;
252
320
  i.push(interpolateVec(i1, i2, t));
253
321
  const o1 = (_f = (_e = path1.o) == null ? void 0 : _e[idx]) != null ? _f : v1;
@@ -366,8 +434,8 @@ function toRGBA(color) {
366
434
  return color.length === 4 ? "rgba(" + r + "," + g + "," + b + "," + color[3] + ")" : "rgb(" + r + "," + g + "," + b + ")";
367
435
  }
368
436
  function parseRgba(s) {
369
- var _a;
370
- const inner = (_a = s.match(/rgba?\((.*)\)/)) == null ? void 0 : _a[1];
437
+ var _a2;
438
+ const inner = (_a2 = s.match(/rgba?\((.*)\)/)) == null ? void 0 : _a2[1];
371
439
  if (!inner) throw new Error("Invalid rgb/rgba format");
372
440
  const parts = inner.split(",").map((v) => +v.trim());
373
441
  return [parts[0] / 255, parts[1] / 255, parts[2] / 255, ...parts[3] !== void 0 ? [parts[3]] : []];
@@ -402,13 +470,13 @@ function parseColor(s) {
402
470
  }
403
471
  return void 0;
404
472
  }
405
- var COLOUR_ATTR_NAMES = /* @__PURE__ */ new Set(["color", "fill", "flood-color", "lighting-color", "stop-color", "stroke"]);
473
+ var COLOR_ATTR_NAMES = /* @__PURE__ */ new Set(["color", "fill", "flood-color", "lighting-color", "stop-color", "stroke"]);
406
474
  var TRANSFORM_FN_NAMES = /* @__PURE__ */ new Set(["translate", "rotate", "scale", "skew"]);
407
475
  var PCT_BASED_ATTR_NAMES = /* @__PURE__ */ new Set(["offset-distance", "offsetDistance"]);
408
476
  function composeTransformParts(parts, opts) {
409
- var _a;
477
+ var _a2;
410
478
  if (!parts) return "";
411
- const withUnits = (_a = opts == null ? void 0 : opts.withUnits) != null ? _a : true;
479
+ const withUnits = (_a2 = opts == null ? void 0 : opts.withUnits) != null ? _a2 : true;
412
480
  const segs = [];
413
481
  const t = parts.translate;
414
482
  const o = parts.origin;
@@ -426,7 +494,7 @@ function composeTransformParts(parts, opts) {
426
494
  return segs.join("");
427
495
  }
428
496
  function parseTransformParts(str2) {
429
- var _a, _b;
497
+ var _a2, _b;
430
498
  if (!str2 || typeof str2 !== "string") return void 0;
431
499
  const out = {};
432
500
  const re = /([a-zA-Z]+)\s*\(([^)]*)\)/g;
@@ -442,7 +510,7 @@ function parseTransformParts(str2) {
442
510
  if (nums.some((n) => Number.isNaN(n))) return void 0;
443
511
  if (fn === "translate") {
444
512
  if (nums.length < 1 || nums.length > 2) return void 0;
445
- out.translate = [nums[0], (_a = nums[1]) != null ? _a : 0];
513
+ out.translate = [nums[0], (_a2 = nums[1]) != null ? _a2 : 0];
446
514
  } else if (fn === "rotate") {
447
515
  if (nums.length !== 1) return void 0;
448
516
  out.rotate = nums[0];
@@ -620,7 +688,7 @@ function invertEasing(easing) {
620
688
  return cubicBezier(flipped);
621
689
  }
622
690
 
623
- // src/PxScrollMath.ts
691
+ // src/playback/PxScrollMath.ts
624
692
  function isScrollTimeline(config) {
625
693
  return (config == null ? void 0 : config.timelineSource) === "scroll";
626
694
  }
@@ -648,8 +716,8 @@ function scrollPhaseInterval(phase, subjectSize, scrollportSize) {
648
716
  }
649
717
  var DEFAULT_PHASE = "cover";
650
718
  function resolveRangePointU(point, defaultFraction, subjectSize, scrollportSize) {
651
- var _a;
652
- const [u0, u1] = scrollPhaseInterval((_a = point == null ? void 0 : point.phase) != null ? _a : DEFAULT_PHASE, subjectSize, scrollportSize);
719
+ var _a2;
720
+ const [u0, u1] = scrollPhaseInterval((_a2 = point == null ? void 0 : point.phase) != null ? _a2 : DEFAULT_PHASE, subjectSize, scrollportSize);
653
721
  const fraction = typeof (point == null ? void 0 : point.fraction) === "number" ? point.fraction : defaultFraction;
654
722
  return u0 + fraction * (u1 - u0);
655
723
  }
@@ -661,9 +729,9 @@ function scrollViewProgress(subjectStart, subjectSize, scrollportSize, range) {
661
729
  return clamp((u - uStart) / (uEnd - uStart), 0, 1);
662
730
  }
663
731
  function scrollOffsetProgress(offset, maxOffset, range) {
664
- var _a, _b;
732
+ var _a2, _b;
665
733
  const raw = maxOffset > 0 ? clamp(offset / maxOffset, 0, 1) : 1;
666
- const start = typeof ((_a = range == null ? void 0 : range.start) == null ? void 0 : _a.fraction) === "number" ? range.start.fraction : 0;
734
+ const start = typeof ((_a2 = range == null ? void 0 : range.start) == null ? void 0 : _a2.fraction) === "number" ? range.start.fraction : 0;
667
735
  const end = typeof ((_b = range == null ? void 0 : range.end) == null ? void 0 : _b.fraction) === "number" ? range.end.fraction : 1;
668
736
  if (end <= start) return raw >= end ? 1 : 0;
669
737
  return clamp((raw - start) / (end - start), 0, 1);
@@ -676,7 +744,8 @@ function scrollResolveAxis(axis, writingMode) {
676
744
  return vertical ? "x" : "y";
677
745
  }
678
746
 
679
- // src/PxSchema.ts
747
+ // src/schema/PxSchema.ts
748
+ var PX_UNKNOWN_KEY_ERROR = "unexpected extra key";
680
749
  function pathStr(path) {
681
750
  if (!path.length) return ".";
682
751
  let result = "";
@@ -784,6 +853,7 @@ var Enum = class extends Base {
784
853
  return false;
785
854
  }
786
855
  };
856
+ var UNION_MEMBER_ERROR_LIMIT = 4;
787
857
  var Union = class extends Base {
788
858
  constructor(schemas, defaultVal) {
789
859
  super();
@@ -799,10 +869,38 @@ var Union = class extends Base {
799
869
  return this._default;
800
870
  }
801
871
  isValid(raw, ctx, path) {
802
- var _a;
872
+ var _a2;
803
873
  const probe = ctx && { errors: [], warnings: [], strict: ctx.strict };
804
874
  if (this.schemas.some((s) => s.isValid(raw, probe, path ? [...path] : void 0))) return true;
805
- ctx == null ? void 0 : ctx.errors.push(pathStr(path != null ? path : []) + ": no union member matched for value " + ((_a = JSON.stringify(raw)) != null ? _a : "").slice(0, 240));
875
+ if (!ctx) return false;
876
+ const base = pathStr(path != null ? path : []);
877
+ ctx.errors.push(base + ": no union member matched for value " + ((_a2 = JSON.stringify(raw)) != null ? _a2 : "").slice(0, 240));
878
+ let best;
879
+ let bestDepth = -1;
880
+ const leafExpectations = [];
881
+ for (const member of this.schemas) {
882
+ const sink = { errors: [], warnings: [], strict: ctx.strict };
883
+ member.isValid(raw, sink, path ? [...path] : void 0);
884
+ if (!sink.errors.length) continue;
885
+ const depth = Math.max(...sink.errors.map((e) => e.slice(0, e.indexOf(":")).length));
886
+ if (depth > bestDepth || depth === bestDepth && best && sink.errors.length < best.length) {
887
+ bestDepth = depth;
888
+ best = sink.errors;
889
+ }
890
+ if (depth <= base.length) {
891
+ for (const e of sink.errors) {
892
+ const m = /: expected (.+?), got /.exec(e);
893
+ if (m && !leafExpectations.includes(m[1])) leafExpectations.push(m[1]);
894
+ }
895
+ }
896
+ }
897
+ if (best && bestDepth > base.length) {
898
+ for (const e of best.slice(0, UNION_MEMBER_ERROR_LIMIT)) {
899
+ if (!ctx.errors.includes(e)) ctx.errors.push(e);
900
+ }
901
+ } else if (leafExpectations.length) {
902
+ ctx.errors.push(base + ": expected " + leafExpectations.join(" | "));
903
+ }
806
904
  return false;
807
905
  }
808
906
  _canSanitize(raw) {
@@ -811,6 +909,7 @@ var Union = class extends Base {
811
909
  };
812
910
  var DiscriminatedUnion = class extends Base {
813
911
  constructor(_key, _schemas, defaultVal) {
912
+ var _a2;
814
913
  super();
815
914
  this._key = _key;
816
915
  this._schemas = _schemas;
@@ -820,18 +919,21 @@ var DiscriminatedUnion = class extends Base {
820
919
  this._map = /* @__PURE__ */ new Map();
821
920
  for (const s of _schemas) {
822
921
  const keySchema = s._shape[_key];
823
- if (keySchema) this._map.set(keySchema._default, s);
922
+ if (!keySchema) continue;
923
+ const literal = (_a2 = keySchema.inner) != null ? _a2 : keySchema;
924
+ this._map.set(literal._default, s);
925
+ if (keySchema.inner) this._absentMember = s;
824
926
  }
825
927
  }
826
928
  _findSchema(raw) {
827
929
  if (raw === null || typeof raw !== "object" || Array.isArray(raw)) return void 0;
828
930
  const val = raw[this._key];
829
- if (val === void 0 || val === null) return void 0;
931
+ if (val === void 0 || val === null) return this._absentMember;
830
932
  return this._map.get(val);
831
933
  }
832
934
  sanitize(raw) {
833
- var _a;
834
- return ((_a = this._findSchema(raw)) != null ? _a : this._schemas[0]).sanitize(raw);
935
+ var _a2;
936
+ return ((_a2 = this._findSchema(raw)) != null ? _a2 : this._schemas[0]).sanitize(raw);
835
937
  }
836
938
  isValid(raw, ctx, path) {
837
939
  const schema = this._findSchema(raw);
@@ -860,7 +962,8 @@ var Obj = class extends Base {
860
962
  const src = raw && typeof raw === "object" && !Array.isArray(raw) ? raw : {};
861
963
  const out = {};
862
964
  for (const key of Object.keys(this._shape)) {
863
- out[key] = this._shape[key].sanitize(src[key]);
965
+ const v = this._shape[key].sanitize(src[key]);
966
+ if (v !== void 0) out[key] = v;
864
967
  }
865
968
  return out;
866
969
  }
@@ -882,7 +985,7 @@ var Obj = class extends Base {
882
985
  if (key in this._shape) continue;
883
986
  if (obj[key] === void 0) continue;
884
987
  p.push(key);
885
- ctx.errors.push(pathStr(p) + ": unexpected extra key");
988
+ ctx.errors.push(pathStr(p) + ": " + PX_UNKNOWN_KEY_ERROR);
886
989
  p.pop();
887
990
  ok = false;
888
991
  }
@@ -906,7 +1009,8 @@ var OpenObj = class extends Base {
906
1009
  const src = raw && typeof raw === "object" && !Array.isArray(raw) ? raw : {};
907
1010
  const out = __spreadValues({}, src);
908
1011
  for (const key of Object.keys(this._shape)) {
909
- out[key] = this._shape[key].sanitize(src[key]);
1012
+ const v = this._shape[key].sanitize(src[key]);
1013
+ if (v !== void 0) out[key] = v;
910
1014
  }
911
1015
  if (this._openSchema) {
912
1016
  for (const key of Object.keys(src)) {
@@ -1048,8 +1152,8 @@ var Lazy = class extends Base {
1048
1152
  this.resolved = null;
1049
1153
  }
1050
1154
  get schema() {
1051
- var _a;
1052
- return (_a = this.resolved) != null ? _a : this.resolved = this.fn();
1155
+ var _a2;
1156
+ return (_a2 = this.resolved) != null ? _a2 : this.resolved = this.fn();
1053
1157
  }
1054
1158
  sanitize(raw) {
1055
1159
  return this.schema.sanitize(raw);
@@ -1101,7 +1205,7 @@ function schemaKeys(schema) {
1101
1205
  );
1102
1206
  }
1103
1207
  function describeSchema(schema) {
1104
- var _a;
1208
+ var _a2;
1105
1209
  const s = schema;
1106
1210
  switch (s._kind) {
1107
1211
  case "union":
@@ -1116,7 +1220,7 @@ function describeSchema(schema) {
1116
1220
  if ("_shape" in s) return { kind: "shape", shape: s._shape, openValue: s._openSchema };
1117
1221
  if ("item" in s) return { kind: "array", item: s.item };
1118
1222
  if ("inner" in s) return { kind: "optional", inner: s.inner };
1119
- if ("fn" in s) return { kind: "lazy", resolved: (_a = s.resolved) != null ? _a : s.resolved = s.fn() };
1223
+ if ("fn" in s) return { kind: "lazy", resolved: (_a2 = s.resolved) != null ? _a2 : s.resolved = s.fn() };
1120
1224
  return { kind: "leaf" };
1121
1225
  }
1122
1226
  var px = {
@@ -1171,25 +1275,455 @@ var px = {
1171
1275
  lazy: (fn, defaultVal) => new Lazy(fn, defaultVal)
1172
1276
  };
1173
1277
 
1174
- // src/PxAnimatorConstants.ts
1278
+ // src/version/PxSchemaVersion.ts
1279
+ var PX_PLAYER_SCHEMA_VERSION = "1.1";
1280
+
1281
+ // src/version/PxWireVersion.ts
1282
+ var WIRE_VERSION_KEY = "version";
1283
+ var ANIMATOR_KEY = "animator";
1284
+ var META_KEY = "meta";
1285
+ var WireVersionRelation = /* @__PURE__ */ ((WireVersionRelation2) => {
1286
+ WireVersionRelation2["unstamped"] = "unstamped";
1287
+ WireVersionRelation2["same"] = "same";
1288
+ WireVersionRelation2["older"] = "older";
1289
+ WireVersionRelation2["newer"] = "newer";
1290
+ WireVersionRelation2["otherGeneration"] = "otherGeneration";
1291
+ return WireVersionRelation2;
1292
+ })(WireVersionRelation || {});
1293
+ var VERSION_RE = /^(\d+)\.(\d+)(?:\.(\d+))?$/;
1294
+ function parseWireVersion(raw) {
1295
+ if (typeof raw !== "string") return void 0;
1296
+ const m = VERSION_RE.exec(raw.trim());
1297
+ if (!m) return void 0;
1298
+ return { a: Number(m[1]), b: Number(m[2]), c: m[3] === void 0 ? 0 : Number(m[3]) };
1299
+ }
1300
+ function formatWireVersion(v) {
1301
+ return v.a + "." + v.b + "." + v.c;
1302
+ }
1303
+ var _a;
1304
+ var PLAYER_WIRE_VERSION = (_a = parseWireVersion(PX_PLAYER_SCHEMA_VERSION)) != null ? _a : { a: 1, b: 1, c: 0 };
1305
+ function getAnimatorBlock(doc) {
1306
+ if (!doc || typeof doc !== "object") return void 0;
1307
+ const atRoot = readObjectProp(doc, ANIMATOR_KEY);
1308
+ if (atRoot) return atRoot;
1309
+ const meta = readObjectProp(doc, META_KEY);
1310
+ return meta ? readObjectProp(meta, ANIMATOR_KEY) : void 0;
1311
+ }
1312
+ function readObjectProp(obj, key) {
1313
+ const value = obj[key];
1314
+ return value && typeof value === "object" && !Array.isArray(value) ? value : void 0;
1315
+ }
1316
+ function readWireVersion(doc) {
1317
+ const animator = getAnimatorBlock(doc);
1318
+ return animator ? parseWireVersion(animator[WIRE_VERSION_KEY]) : void 0;
1319
+ }
1320
+ function compareWireVersion(file, mine, readerReadsEditorPart) {
1321
+ if (!file) return "unstamped" /* unstamped */;
1322
+ if (file.a !== mine.a) return "otherGeneration" /* otherGeneration */;
1323
+ if (file.b !== mine.b) return file.b > mine.b ? "newer" /* newer */ : "older" /* older */;
1324
+ if (!readerReadsEditorPart || file.c === mine.c) return "same" /* same */;
1325
+ return file.c > mine.c ? "newer" /* newer */ : "older" /* older */;
1326
+ }
1327
+ function versionAdvice(relation, file, mine, isPlayer) {
1328
+ if (!file) return void 0;
1329
+ const target = isPlayer ? "player" : "editor";
1330
+ const gap = "written for schema " + formatWireVersion(file) + ", this " + target + " reads " + formatWireVersion(mine);
1331
+ switch (relation) {
1332
+ case "newer" /* newer */:
1333
+ return "This file is " + gap + ". Update the " + target + " to open it fully.";
1334
+ case "older" /* older */:
1335
+ return "This file is " + gap + ". Saving it from this " + target + " rewrites it in the current format.";
1336
+ case "otherGeneration" /* otherGeneration */:
1337
+ return "This file is " + gap + " \u2014 a different format generation, which no conversion bridges. Open it in a " + target + " of that generation, or accept this document without the parts named above.";
1338
+ default:
1339
+ return void 0;
1340
+ }
1341
+ }
1342
+ var WireStepKind = /* @__PURE__ */ ((WireStepKind2) => {
1343
+ WireStepKind2["additive"] = "additive";
1344
+ WireStepKind2["converted"] = "converted";
1345
+ return WireStepKind2;
1346
+ })(WireStepKind || {});
1347
+ var BASELINE_PLAYER_VERSION = "1.1";
1348
+ var PLAYER_WIRE_STEPS = [];
1349
+ function applyWireSteps(doc, cfg) {
1350
+ const from = readWireVersion(doc);
1351
+ const relation = compareWireVersion(from, cfg.target, cfg.readerReadsEditorPart);
1352
+ if (!from || relation !== "older" /* older */) {
1353
+ return {
1354
+ doc,
1355
+ from,
1356
+ relation,
1357
+ applied: [],
1358
+ advice: versionAdvice(relation, from, cfg.target, !cfg.readerReadsEditorPart)
1359
+ };
1360
+ }
1361
+ const due = [];
1362
+ for (const step of cfg.steps) {
1363
+ const stepTo = parseWireVersion(step.to);
1364
+ if (!stepTo) continue;
1365
+ if (compareWireVersion(from, stepTo, cfg.readerReadsEditorPart) !== "older" /* older */) continue;
1366
+ if (!step.up) continue;
1367
+ due.push(step);
1368
+ }
1369
+ if (!due.length || !doc || typeof doc !== "object") return { doc, from, relation, applied: [] };
1370
+ const target = clonePlain(doc);
1371
+ const applied = [];
1372
+ for (const step of due) {
1373
+ try {
1374
+ step.up(target);
1375
+ applied.push(step);
1376
+ } catch (e) {
1377
+ break;
1378
+ }
1379
+ }
1380
+ if (!applied.length) return { doc, from, relation, applied: [] };
1381
+ stampVersion(target, cfg.target, cfg.readerReadsEditorPart);
1382
+ return { doc: target, from, relation, applied };
1383
+ }
1384
+ function convertPlayerDocument(doc) {
1385
+ return applyWireSteps(doc, {
1386
+ steps: PLAYER_WIRE_STEPS,
1387
+ target: PLAYER_WIRE_VERSION,
1388
+ readerReadsEditorPart: false
1389
+ });
1390
+ }
1391
+ function clonePlain(value) {
1392
+ const structured = globalThis.structuredClone;
1393
+ return structured ? structured(value) : JSON.parse(JSON.stringify(value));
1394
+ }
1395
+ function stampVersion(doc, target, readerReadsEditorPart) {
1396
+ const animator = getAnimatorBlock(doc);
1397
+ if (!animator) return;
1398
+ const previous = parseWireVersion(animator[WIRE_VERSION_KEY]);
1399
+ animator[WIRE_VERSION_KEY] = formatWireVersion({
1400
+ a: target.a,
1401
+ b: target.b,
1402
+ c: readerReadsEditorPart ? target.c : previous ? previous.c : 0
1403
+ });
1404
+ }
1405
+ function applyWireStepsDown(doc, cfg) {
1406
+ const from = readWireVersion(doc);
1407
+ if (!from) {
1408
+ return { ok: false, blocking: [], reason: "The document carries no version, so there is nothing to convert down from." };
1409
+ }
1410
+ const relation = compareWireVersion(from, cfg.target, cfg.readerReadsEditorPart);
1411
+ if (relation === "otherGeneration" /* otherGeneration */) {
1412
+ return {
1413
+ ok: false,
1414
+ blocking: [],
1415
+ reason: "Schema " + formatWireVersion(from) + " and " + formatWireVersion(cfg.target) + " are different generations; no conversion bridges them."
1416
+ };
1417
+ }
1418
+ if (relation !== "newer" /* newer */) return { ok: true, doc, applied: [] };
1419
+ const toUndo = [];
1420
+ for (const step of cfg.steps) {
1421
+ const stepTo = parseWireVersion(step.to);
1422
+ if (!stepTo) continue;
1423
+ if (compareWireVersion(stepTo, cfg.target, cfg.readerReadsEditorPart) !== "newer" /* newer */) continue;
1424
+ if (compareWireVersion(stepTo, from, cfg.readerReadsEditorPart) === "newer" /* newer */) continue;
1425
+ toUndo.push(step);
1426
+ }
1427
+ toUndo.reverse();
1428
+ const blocking = toUndo.filter((s) => s.kind === "converted" /* converted */ && !s.down);
1429
+ if (blocking.length) {
1430
+ return {
1431
+ ok: false,
1432
+ blocking,
1433
+ reason: "Cannot convert down to " + formatWireVersion(cfg.target) + ": " + blocking.map((s) => s.from + " \u2192 " + s.to + " (" + s.reason + ")").join("; ") + " cannot be undone."
1434
+ };
1435
+ }
1436
+ const target = clonePlain(doc);
1437
+ const applied = [];
1438
+ for (const step of toUndo) {
1439
+ if (!step.down) continue;
1440
+ try {
1441
+ step.down(target);
1442
+ applied.push(step);
1443
+ } catch (e) {
1444
+ return {
1445
+ ok: false,
1446
+ blocking: [step],
1447
+ reason: "Undoing " + step.from + " \u2192 " + step.to + " failed: " + String(e)
1448
+ };
1449
+ }
1450
+ }
1451
+ stampVersion(target, cfg.target, cfg.readerReadsEditorPart);
1452
+ return { ok: true, doc: target, applied };
1453
+ }
1454
+ function downgradePlayerDocument(doc, target) {
1455
+ return applyWireStepsDown(doc, { steps: PLAYER_WIRE_STEPS, target, readerReadsEditorPart: false });
1456
+ }
1457
+
1458
+ // src/version/PxSchemaFieldUniverse.ts
1459
+ function schemaFieldUniverse(root) {
1460
+ const fields = /* @__PURE__ */ new Set();
1461
+ const enumerated = /* @__PURE__ */ new Set();
1462
+ const queue = [{ schema: root, path: "" }];
1463
+ while (queue.length) {
1464
+ const { schema, path } = queue.shift();
1465
+ const d = describeSchema(schema);
1466
+ switch (d.kind) {
1467
+ case "shape": {
1468
+ if (enumerated.has(schema)) break;
1469
+ enumerated.add(schema);
1470
+ for (const key of Object.keys(d.shape)) {
1471
+ const id = path ? path + "." + key : key;
1472
+ fields.add(id);
1473
+ queue.push({ schema: d.shape[key], path: id });
1474
+ }
1475
+ if (d.openValue) queue.push({ schema: d.openValue, path: path + "{*}" });
1476
+ break;
1477
+ }
1478
+ case "optional":
1479
+ queue.push({ schema: d.inner, path });
1480
+ break;
1481
+ case "array":
1482
+ queue.push({ schema: d.item, path: path + "[]" });
1483
+ break;
1484
+ case "lazy":
1485
+ queue.push({ schema: d.resolved, path });
1486
+ break;
1487
+ case "record":
1488
+ queue.push({ schema: d.value, path: path + "{*}" });
1489
+ break;
1490
+ case "union":
1491
+ d.members.forEach((member, i) => queue.push({ schema: member, path: path + "|" + i }));
1492
+ break;
1493
+ case "discriminatedUnion":
1494
+ for (const member of d.members) queue.push({ schema: member, path: path + "|" + discriminantOf(member, d.key) });
1495
+ break;
1496
+ default:
1497
+ break;
1498
+ }
1499
+ }
1500
+ return [...fields].sort();
1501
+ }
1502
+ function discriminantOf(member, key) {
1503
+ const d = describeSchema(member);
1504
+ if (d.kind !== "shape") return "?";
1505
+ const keySchema = d.shape[key];
1506
+ if (keySchema === void 0) return "?";
1507
+ const kd = describeSchema(keySchema);
1508
+ return String((kd.kind === "optional" ? kd.inner : keySchema)._default);
1509
+ }
1510
+
1511
+ // src/version/PxSchemaRelease.ts
1512
+ function diffFieldUniverse(previous, current) {
1513
+ const prev = new Set(previous);
1514
+ const cur = new Set(current);
1515
+ return {
1516
+ added: current.filter((k) => !prev.has(k)).sort(),
1517
+ removed: previous.filter((k) => !cur.has(k)).sort()
1518
+ };
1519
+ }
1520
+ function planSchemaRelease(p) {
1521
+ const changed = p.added.length > 0 || p.removed.length > 0;
1522
+ const last = parseWireVersion(p.lastReleased);
1523
+ const declared = parseWireVersion(p.declared);
1524
+ if (!last || !declared) return { changed, refuse: "Unparseable version: " + p.lastReleased + " / " + p.declared + "." };
1525
+ const requiredVersion = last.a + "." + (last.b + 1);
1526
+ if (!changed) {
1527
+ if (declared.b === last.b && declared.a === last.a) return { changed };
1528
+ const step2 = p.steps.find((s) => s.to === p.declared);
1529
+ return step2 ? { changed, requiredVersion: p.declared } : { changed, refuse: "The version moved to " + p.declared + " with no key change and no step explaining it." };
1530
+ }
1531
+ const requiredKind = p.removed.length ? "converted" /* converted */ : "additive" /* additive */;
1532
+ const summary = p.added.length + " key(s) added, " + p.removed.length + " removed";
1533
+ if (declared.a !== last.a || declared.b !== last.b + 1) {
1534
+ return {
1535
+ changed,
1536
+ requiredKind,
1537
+ requiredVersion,
1538
+ refuse: "The player schema changed (" + summary + ") but PX_PLAYER_SCHEMA_VERSION is " + p.declared + ". Set it to " + requiredVersion + " and add the PLAYER_WIRE_STEPS entry."
1539
+ };
1540
+ }
1541
+ const step = p.steps.find((s) => s.to === p.declared);
1542
+ if (!step) {
1543
+ return { changed, requiredKind, requiredVersion, refuse: "No PLAYER_WIRE_STEPS entry reaches " + p.declared + "." };
1544
+ }
1545
+ if (requiredKind === "converted" /* converted */ && step.kind !== "converted" /* converted */) {
1546
+ return {
1547
+ changed,
1548
+ requiredKind,
1549
+ requiredVersion,
1550
+ refuse: "Keys were REMOVED (" + p.removed.join(", ") + "), which is never additive \u2014 the " + p.declared + " step must be `converted`, with an up()."
1551
+ };
1552
+ }
1553
+ return { changed, requiredKind, requiredVersion };
1554
+ }
1555
+ function releaseLogProblems(releases, steps, declared, baseline) {
1556
+ const problems = [];
1557
+ if (!releases.length) return ["The release log is empty."];
1558
+ if (!releases[0].baseline || releases[0].version !== baseline) {
1559
+ problems.push("The first release must be the baseline " + baseline + ".");
1560
+ }
1561
+ for (let i = 1; i < releases.length; i++) {
1562
+ const prev = parseWireVersion(releases[i - 1].version);
1563
+ const cur = parseWireVersion(releases[i].version);
1564
+ if (!prev || !cur || cur.a !== prev.a || cur.b !== prev.b + 1) {
1565
+ problems.push("Release " + releases[i].version + " does not follow " + releases[i - 1].version + " by one `b` step.");
1566
+ }
1567
+ if (releases[i].date < releases[i - 1].date) problems.push("Release " + releases[i].version + " is dated before its predecessor.");
1568
+ const step = steps.find((s) => s.to === releases[i].version);
1569
+ if (!step) problems.push("Release " + releases[i].version + " has no PLAYER_WIRE_STEPS entry.");
1570
+ else if (releases[i].removed.length && step.kind !== "converted" /* converted */) {
1571
+ problems.push("Release " + releases[i].version + " removed keys, but its step is not `converted`.");
1572
+ }
1573
+ }
1574
+ const latest = releases[releases.length - 1].version;
1575
+ if (latest !== declared) {
1576
+ problems.push("PX_PLAYER_SCHEMA_VERSION is " + declared + " but the last release record is " + latest + " \u2014 a bump needs its changelog entry (run scripts/schema-release.mjs --apply).");
1577
+ }
1578
+ return problems;
1579
+ }
1580
+
1581
+ // src/format/PxAnimatorConstants.ts
1582
+ var PxFillMode = {
1583
+ forwards: "forwards",
1584
+ backwards: "backwards",
1585
+ both: "both",
1586
+ none: "none"
1587
+ };
1588
+ var PxPlaybackDirection = {
1589
+ normal: "normal",
1590
+ reverse: "reverse",
1591
+ alternate: "alternate",
1592
+ alternateReverse: "alternate-reverse"
1593
+ };
1175
1594
  var PX_ANIM_SRC_ATTR_NAME = "data-px-animation-src";
1176
1595
  var PX_ANIM_ATTR_NAME = "_px_animator";
1177
- var PxAnimatorMode = {
1178
- auto: "auto",
1179
- waapi: "waapi",
1180
- frames: "frames"
1596
+ var PxStartOn = {
1597
+ load: "load",
1598
+ mouseOver: "mouseOver",
1599
+ click: "click",
1600
+ scrollIntoView: "scrollIntoView",
1601
+ programmatic: "programmatic"
1602
+ };
1603
+ var PxOutAction = {
1604
+ continue: "continue",
1605
+ pause: "pause",
1606
+ reset: "reset",
1607
+ reverse: "reverse"
1608
+ };
1609
+ var PxFinishAction = {
1610
+ hold: "hold",
1611
+ reset: "reset"
1612
+ };
1613
+ var PxScrollKind = {
1614
+ view: "view",
1615
+ scroll: "scroll"
1616
+ };
1617
+ var PxScrollAxis = {
1618
+ block: "block",
1619
+ inline: "inline",
1620
+ x: "x",
1621
+ y: "y"
1181
1622
  };
1182
- var PxAnimatorEngine = {
1183
- waapi: PxAnimatorMode.waapi,
1184
- frames: PxAnimatorMode.frames
1623
+ var PxScrollSource = {
1624
+ nearest: "nearest",
1625
+ root: "root"
1626
+ };
1627
+ var PxPinAlign = {
1628
+ top: "top",
1629
+ center: "center",
1630
+ bottom: "bottom"
1631
+ };
1632
+ var PxScrollPhase = {
1633
+ cover: "cover",
1634
+ contain: "contain",
1635
+ entry: "entry",
1636
+ exit: "exit",
1637
+ entryCrossing: "entry-crossing",
1638
+ exitCrossing: "exit-crossing"
1639
+ };
1640
+ var PxAlongPathMode = {
1641
+ sampled: "sampled",
1642
+ offsetPath: "offsetPath"
1643
+ };
1644
+ var PX_TIMELINE_SHARED_KEYS = ["duration", "iterations", "engine", "frameRate"];
1645
+ var PX_TIME_ONLY_TIMELINE_KEYS = ["trigger", "delay", "fillMode", "direction"];
1646
+ var PX_FLAT_RUNTIME_VIEW_KEYS = [
1647
+ ...PX_TIMELINE_SHARED_KEYS,
1648
+ ...PX_TIME_ONLY_TIMELINE_KEYS,
1649
+ "fill",
1650
+ "resetOnFinish",
1651
+ "timelineSource",
1652
+ "scroll"
1653
+ ];
1654
+ var PxTimelineEngine = {
1655
+ native: "native",
1656
+ js: "js"
1657
+ };
1658
+ var PxTimelineEngineExtra = __spreadProps(__spreadValues({}, PxTimelineEngine), {
1659
+ auto: "auto"
1660
+ });
1661
+ function resolveTimelineEngine(engine) {
1662
+ return engine === PxTimelineEngineExtra.js ? PxTimelineEngine.js : PxTimelineEngine.native;
1663
+ }
1664
+ function isNativeForced(engine) {
1665
+ return engine === PxTimelineEngineExtra.native;
1666
+ }
1667
+ function mayUseNativeScrollTimeline(engine) {
1668
+ return engine !== PxTimelineEngineExtra.js;
1669
+ }
1670
+ var PX_TRIGGER_DEFAULTS = {
1671
+ startOn: "load",
1672
+ outAction: "continue",
1673
+ scrollIntoViewThreshold: 0
1674
+ };
1675
+ var PxControlMode = {
1676
+ /** No control props — the document's trigger decides, and nothing is taken over. */
1677
+ static: "static",
1678
+ /** `progress` / `time` — the host scrubs; the component seeks and stays paused. */
1679
+ fixedTime: "fixedTime",
1680
+ /** `play` / `pause` — the host drives playback with booleans. */
1681
+ play: "play",
1682
+ /** `autoplay` — the document's own trigger starts it. */
1683
+ autoplay: "autoplay"
1684
+ };
1685
+ function resolveControlMode(props) {
1686
+ const hasFixedTime = props.progress !== void 0 || props.time !== void 0;
1687
+ const hasPlayPause = props.play !== void 0 || props.pause !== void 0;
1688
+ const hasAutoplay = !!props.autoplay;
1689
+ const warnings = [];
1690
+ const named = (a, b, winner) => a + " and " + b + " were both set \u2014 " + winner + " wins, " + (winner === a ? b : a) + " is ignored.";
1691
+ if (hasFixedTime) {
1692
+ if (hasPlayPause) warnings.push(named("progress/time", "play/pause", "progress/time"));
1693
+ if (hasAutoplay) warnings.push(named("progress/time", "autoplay", "progress/time"));
1694
+ return { mode: PxControlMode.fixedTime, warnings };
1695
+ }
1696
+ if (hasPlayPause) {
1697
+ if (hasAutoplay) warnings.push(named("play/pause", "autoplay", "play/pause"));
1698
+ return { mode: PxControlMode.play, warnings };
1699
+ }
1700
+ if (hasAutoplay) return { mode: PxControlMode.autoplay, warnings };
1701
+ return { mode: PxControlMode.static, warnings };
1702
+ }
1703
+ function controlModeTakesOverTrigger(mode) {
1704
+ return mode !== PxControlMode.autoplay;
1705
+ }
1706
+ function resolveTrigger(trigger) {
1707
+ var _a2, _b, _c;
1708
+ return {
1709
+ startOn: (_a2 = trigger == null ? void 0 : trigger.startOn) != null ? _a2 : PX_TRIGGER_DEFAULTS.startOn,
1710
+ outAction: (_b = trigger == null ? void 0 : trigger.outAction) != null ? _b : PX_TRIGGER_DEFAULTS.outAction,
1711
+ scrollIntoViewThreshold: (_c = trigger == null ? void 0 : trigger.scrollIntoViewThreshold) != null ? _c : PX_TRIGGER_DEFAULTS.scrollIntoViewThreshold
1712
+ };
1713
+ }
1714
+ var PxLoopRepeatAt = {
1715
+ /** Segment from the START; the repetition runs BEFORE the first keyframe
1716
+ * (intro loops that play until the main timeline begins). */
1717
+ start: "start",
1718
+ /** DEFAULT — segment from the END; the repetition runs AFTER the last keyframe
1719
+ * (idle/outro loops that continue once the main timeline has finished). */
1720
+ end: "end"
1185
1721
  };
1186
- var PxLoopExtend = {
1187
- /** Segment from the START; the animation is extended BEFORE the first keyframe
1188
- * (intro loops that run before the main timeline begins). */
1189
- before: "before",
1190
- /** DEFAULT — segment from the END; extended AFTER the last keyframe (idle/outro
1191
- * loops that continue once the main timeline has finished). */
1192
- after: "after"
1722
+ var PxLoopDirection = {
1723
+ /** DEFAULT — cycle: every repetition replays the segment the same way round. */
1724
+ normal: "normal",
1725
+ /** Ping-pong: repetitions alternate forward / backward. */
1726
+ alternate: "alternate"
1193
1727
  };
1194
1728
  var PxMaskType = {
1195
1729
  luminance: "luminance",
@@ -1199,8 +1733,9 @@ var PxUnits = {
1199
1733
  userSpaceOnUse: "userSpaceOnUse",
1200
1734
  objectBoundingBox: "objectBoundingBox"
1201
1735
  };
1202
- var PxCloneType = {
1203
- content: "content"
1736
+ var PxCloneWithout = {
1737
+ translate: "translate"
1738
+ // transform: 'transform', // future: drop rotate/scale too (content only)
1204
1739
  };
1205
1740
  var PxPathOverflow = {
1206
1741
  clip: "clip",
@@ -1222,8 +1757,10 @@ var PxStrokeTrimSubPaths = {
1222
1757
  separate: "separate",
1223
1758
  combined: "combined"
1224
1759
  };
1225
- var TEXT_ATTR = "text";
1226
1760
  var TEXT_CONTENT_ATTR = "textContent";
1761
+ var CLASS_ATTR = "class";
1762
+ var TRANSFORM_ATTR = "transform";
1763
+ var OFFSET_DISTANCE_ATTR = "offsetDistance";
1227
1764
  var INTERNAL_ATTRS = /* @__PURE__ */ new Set([
1228
1765
  "type",
1229
1766
  "children",
@@ -1231,14 +1768,20 @@ var INTERNAL_ATTRS = /* @__PURE__ */ new Set([
1231
1768
  "meta",
1232
1769
  "animate",
1233
1770
  "effects",
1234
- TEXT_ATTR,
1235
1771
  TEXT_CONTENT_ATTR
1236
1772
  ]);
1237
- var PX_TRANSFORM_PART_KEYS = ["translate", "rotate", "scale", "origin"];
1238
- var PxGradientUnits = {
1239
- userSpaceOnUse: "userSpaceOnUse",
1240
- objectBoundingBox: "objectBoundingBox"
1773
+ var TRANSFORM_PART = {
1774
+ translate: "translate",
1775
+ rotate: "rotate",
1776
+ scale: "scale",
1777
+ origin: "origin"
1241
1778
  };
1779
+ var PX_TRANSFORM_PART_KEYS = [
1780
+ TRANSFORM_PART.translate,
1781
+ TRANSFORM_PART.rotate,
1782
+ TRANSFORM_PART.scale,
1783
+ TRANSFORM_PART.origin
1784
+ ];
1242
1785
  var PxGradientSpreadMethod = {
1243
1786
  pad: "pad",
1244
1787
  reflect: "reflect",
@@ -1252,27 +1795,38 @@ function isPxElementFileFormat(fileJson) {
1252
1795
  if (!(fileJson && typeof fileJson === "object" && !Array.isArray(fileJson))) {
1253
1796
  return false;
1254
1797
  }
1255
- return fileJson["type"] === "svg";
1798
+ return fileJson.type === "svg";
1256
1799
  }
1257
1800
  function getAnimatorConfig(doc) {
1258
- var _a;
1259
- const cfg = (doc == null ? void 0 : doc.animator) || ((_a = doc == null ? void 0 : doc.meta) == null ? void 0 : _a.animator);
1260
- return cfg ? flattenAnimatorTimeline(cfg) : void 0;
1261
- }
1801
+ var _a2;
1802
+ const cfg = (doc == null ? void 0 : doc.animator) || ((_a2 = doc == null ? void 0 : doc.meta) == null ? void 0 : _a2.animator);
1803
+ if (!cfg) return void 0;
1804
+ const memoised = wireViewMemo.get(cfg);
1805
+ if (memoised) return memoised;
1806
+ const wire = cfg;
1807
+ const stray = PX_FLAT_RUNTIME_VIEW_KEYS.filter((k) => wire[k] !== void 0);
1808
+ const source = stray.length ? __spreadValues({}, wire) : cfg;
1809
+ for (const k of stray) delete source[k];
1810
+ const view = flattenAnimatorTimeline(source);
1811
+ wireViewMemo.set(cfg, view);
1812
+ return view;
1813
+ }
1814
+ var wireViewMemo = /* @__PURE__ */ new WeakMap();
1262
1815
  var flattenMemo = /* @__PURE__ */ new WeakMap();
1263
1816
  function flattenAnimatorTimeline(cfg) {
1264
1817
  const timeline = cfg.timeline;
1265
1818
  if (timeline === void 0 || timeline === null || typeof timeline !== "object") return cfg;
1266
1819
  const memoised = flattenMemo.get(cfg);
1267
1820
  if (memoised) return memoised;
1268
- const _a = cfg, { timeline: _dropped } = _a, flat = __objRest(_a, ["timeline"]);
1821
+ const _a2 = cfg, { timeline: _dropped } = _a2, flat = __objRest(_a2, ["timeline"]);
1822
+ if (timeline.engine !== void 0) flat.engine = timeline.engine;
1823
+ if (timeline.frameRate !== void 0) flat.frameRate = timeline.frameRate;
1269
1824
  if (timeline.type === "scroll" || timeline.type === "view") {
1270
1825
  flat.timelineSource = "scroll";
1271
1826
  if (timeline.duration !== void 0) flat.duration = timeline.duration;
1272
1827
  if (timeline.iterations !== void 0) flat.iterations = timeline.iterations;
1273
1828
  const scroll = __spreadValues({}, flat.scroll || {});
1274
1829
  scroll.kind = timeline.type;
1275
- if (timeline.engine !== void 0) scroll.driver = timeline.engine;
1276
1830
  if (timeline.axis !== void 0) scroll.axis = timeline.axis;
1277
1831
  if (timeline.source !== void 0) scroll.source = timeline.source;
1278
1832
  if (timeline.subject !== void 0) scroll.subject = timeline.subject;
@@ -1283,28 +1837,31 @@ function flattenAnimatorTimeline(cfg) {
1283
1837
  else if (pin && typeof pin === "object") {
1284
1838
  scroll.pin = true;
1285
1839
  if (pin.align !== void 0) scroll.pinAlign = pin.align;
1286
- if (pin.top !== void 0) scroll.pinTop = pin.top;
1840
+ if (pin.offset !== void 0) scroll.pinOffset = pin.offset;
1287
1841
  if (pin.distance !== void 0) scroll.pinDistance = pin.distance;
1288
1842
  }
1289
1843
  flat.scroll = scroll;
1290
1844
  } else {
1291
1845
  if (timeline.duration !== void 0) flat.duration = timeline.duration;
1292
1846
  if (timeline.trigger !== void 0) {
1293
- const _b = timeline.trigger, { onFinish } = _b, restTrigger = __objRest(_b, ["onFinish"]);
1847
+ const _b = timeline.trigger, { finishAction } = _b, restTrigger = __objRest(_b, ["finishAction"]);
1294
1848
  if (Object.keys(restTrigger).length) flat.trigger = restTrigger;
1295
- if (onFinish !== void 0) flat.resetOnFinish = onFinish === "reset";
1849
+ if (finishAction !== void 0) flat.resetOnFinish = finishAction === "reset";
1296
1850
  }
1297
1851
  if (timeline.delay !== void 0) flat.delay = timeline.delay;
1298
1852
  if (timeline.iterations !== void 0) flat.iterations = timeline.iterations;
1299
1853
  if (timeline.direction !== void 0) flat.direction = timeline.direction;
1300
- if (timeline.fill !== void 0) flat.fill = timeline.fill;
1854
+ if (timeline.fillMode !== void 0) flat.fill = timeline.fillMode;
1301
1855
  }
1302
1856
  flattenMemo.set(cfg, flat);
1303
1857
  return flat;
1304
1858
  }
1859
+ function scrollKindOrDefault(kind) {
1860
+ return kind === "scroll" ? "scroll" : "view";
1861
+ }
1305
1862
  function nestAnimatorTimeline(cfg) {
1306
1863
  if (!cfg || cfg.timeline !== void 0) return cfg;
1307
- const _a = cfg, {
1864
+ const _a2 = cfg, {
1308
1865
  timelineSource,
1309
1866
  scroll,
1310
1867
  trigger,
@@ -1313,8 +1870,10 @@ function nestAnimatorTimeline(cfg) {
1313
1870
  direction,
1314
1871
  fill,
1315
1872
  resetOnFinish,
1316
- duration
1317
- } = _a, shared = __objRest(_a, [
1873
+ duration,
1874
+ engine,
1875
+ frameRate
1876
+ } = _a2, shared = __objRest(_a2, [
1318
1877
  "timelineSource",
1319
1878
  "scroll",
1320
1879
  "trigger",
@@ -1323,50 +1882,55 @@ function nestAnimatorTimeline(cfg) {
1323
1882
  "direction",
1324
1883
  "fill",
1325
1884
  "resetOnFinish",
1326
- "duration"
1885
+ "duration",
1886
+ "engine",
1887
+ "frameRate"
1327
1888
  ]);
1328
1889
  if (timelineSource === "scroll") {
1329
- const timeline2 = { type: (scroll == null ? void 0 : scroll.kind) === "view" ? "view" : "scroll" };
1890
+ const timeline2 = { type: scrollKindOrDefault(scroll == null ? void 0 : scroll.kind) };
1891
+ if (engine !== void 0) timeline2.engine = engine;
1892
+ if (frameRate !== void 0) timeline2.frameRate = frameRate;
1330
1893
  if (duration !== void 0) timeline2.duration = duration;
1331
1894
  if (typeof iterations === "number") timeline2.iterations = iterations;
1332
1895
  if (scroll) {
1333
- if (scroll.driver !== void 0) timeline2.engine = scroll.driver;
1334
1896
  if (scroll.axis !== void 0) timeline2.axis = scroll.axis;
1335
1897
  if (scroll.source !== void 0) timeline2.source = scroll.source;
1336
1898
  if (scroll.subject !== void 0) timeline2.subject = scroll.subject;
1337
1899
  if (scroll.smoothing !== void 0) timeline2.smoothing = scroll.smoothing;
1338
1900
  if (scroll.range !== void 0) timeline2.range = scroll.range;
1339
- const hasPinParams = scroll.pinAlign !== void 0 || scroll.pinTop !== void 0 || scroll.pinDistance !== void 0;
1901
+ const hasPinParams = scroll.pinAlign !== void 0 || scroll.pinOffset !== void 0 || scroll.pinDistance !== void 0;
1340
1902
  if (hasPinParams) {
1341
- timeline2.pin = __spreadValues(__spreadValues(__spreadValues({}, scroll.pinAlign !== void 0 ? { align: scroll.pinAlign } : {}), scroll.pinTop !== void 0 ? { top: scroll.pinTop } : {}), scroll.pinDistance !== void 0 ? { distance: scroll.pinDistance } : {});
1903
+ timeline2.pin = __spreadValues(__spreadValues(__spreadValues({}, scroll.pinAlign !== void 0 ? { align: scroll.pinAlign } : {}), scroll.pinOffset !== void 0 ? { offset: scroll.pinOffset } : {}), scroll.pinDistance !== void 0 ? { distance: scroll.pinDistance } : {});
1342
1904
  } else if (scroll.pin !== void 0) {
1343
1905
  timeline2.pin = scroll.pin;
1344
1906
  }
1345
1907
  }
1346
1908
  return __spreadProps(__spreadValues({}, shared), { timeline: timeline2 });
1347
1909
  }
1348
- const timeline = { type: "clock" };
1910
+ const timeline = {};
1911
+ if (engine !== void 0) timeline.engine = engine;
1912
+ if (frameRate !== void 0) timeline.frameRate = frameRate;
1349
1913
  if (duration !== void 0) timeline.duration = duration;
1350
1914
  if (trigger !== void 0 || resetOnFinish) {
1351
1915
  const t = __spreadValues({}, trigger || {});
1352
- if (resetOnFinish) t.onFinish = "reset";
1916
+ if (resetOnFinish) t.finishAction = "reset";
1353
1917
  timeline.trigger = t;
1354
1918
  }
1355
1919
  if (delay !== void 0) timeline.delay = delay;
1356
1920
  if (iterations !== void 0) timeline.iterations = iterations;
1357
1921
  if (direction !== void 0) timeline.direction = direction;
1358
- if (fill !== void 0) timeline.fill = fill;
1359
- return Object.keys(timeline).length > 1 ? __spreadProps(__spreadValues({}, shared), { timeline }) : shared;
1922
+ if (fill !== void 0) timeline.fillMode = fill;
1923
+ return Object.keys(timeline).length > 0 ? __spreadProps(__spreadValues({}, shared), { timeline }) : shared;
1360
1924
  }
1361
1925
  function getDefs(doc) {
1362
- var _a;
1926
+ var _a2;
1363
1927
  if (!doc) return void 0;
1364
- return (_a = getAnimatorConfig(doc)) == null ? void 0 : _a.definitions;
1928
+ return (_a2 = getAnimatorConfig(doc)) == null ? void 0 : _a2.definitions;
1365
1929
  }
1366
1930
  function getBindings(doc) {
1367
- var _a;
1931
+ var _a2;
1368
1932
  if (!doc) return void 0;
1369
- const animateById = (_a = getAnimatorConfig(doc)) == null ? void 0 : _a.animateById;
1933
+ const animateById = (_a2 = getAnimatorConfig(doc)) == null ? void 0 : _a2.animateById;
1370
1934
  if (!animateById) return void 0;
1371
1935
  return Object.entries(animateById).map(([id, anim]) => ({ id: id.startsWith("#") ? id.slice(1) : id, animate: anim }));
1372
1936
  }
@@ -1374,7 +1938,7 @@ function getChildren(doc) {
1374
1938
  return doc == null ? void 0 : doc.children;
1375
1939
  }
1376
1940
 
1377
- // src/PxAnimatorTypes.ts
1941
+ // src/format/PxAnimatorTypes.ts
1378
1942
  var PxEasingOrRefSchema = px.union([
1379
1943
  px.string(),
1380
1944
  px.tuple([px.number(), px.number(), px.number(), px.number()])
@@ -1384,14 +1948,13 @@ var PxKeyframeValueSchema = implementsInterface()(px.union([
1384
1948
  // e.g. for colors
1385
1949
  px.number(),
1386
1950
  px.array(px.number()),
1387
- // ORDER LAW: the key-discriminated object shapes (`{path}`, `{paths}`) come BEFORE the
1951
+ // ORDER LAW: the key-discriminated object shape (`{pathData}`) comes BEFORE the
1388
1952
  // all-optional transform-parts record. In default (non-strict) mode that record accepts
1389
1953
  // ANY object (every key optional, unknown keys ignored), so listing it earlier made
1390
- // Union.sanitize route `{path}`/`{paths}` values into it and strip them to `{}` —
1954
+ // Union.sanitize route `{pathData}` values into it and strip them to `{}` —
1391
1955
  // silent morph-data loss (repro: the editor's keyframeValueSanitize spec). Validity is
1392
1956
  // order-independent (`some()`); only sanitize routing depends on this order.
1393
- px.object({ path: px.string() }),
1394
- px.lazy(() => px.object({ paths: px.array(PxBezierPathSchema) }), { paths: [] }),
1957
+ px.object({ pathData: px.string() }),
1395
1958
  // Gradient `stops` timeline — each kf value is the full stops-array snapshot.
1396
1959
  px.lazy(() => px.array(PxGradientStopSchema), []),
1397
1960
  px.lazy(() => PxTransformPartsSchema, {})
@@ -1406,16 +1969,32 @@ var PxKeyframeSchema = implementsInterface()(px.object({
1406
1969
  // (review §1.3): editor data lives under `meta`. The editor still carries it on
1407
1970
  // its internal COPY-PASTE payload, which never validates against this schema.)
1408
1971
  }));
1972
+ var anyKf = (kf) => kf;
1973
+ var kfTime = (kf) => {
1974
+ var _a2, _b;
1975
+ return (_b = (_a2 = anyKf(kf).time) != null ? _a2 : anyKf(kf).t) != null ? _b : 0;
1976
+ };
1977
+ var kfValue = (kf) => {
1978
+ var _a2;
1979
+ return (_a2 = anyKf(kf).value) != null ? _a2 : anyKf(kf).v;
1980
+ };
1981
+ var kfEasing = (kf) => {
1982
+ var _a2;
1983
+ return (_a2 = anyKf(kf).easing) != null ? _a2 : anyKf(kf).e;
1984
+ };
1985
+ var kfTangentIn = (kf) => anyKf(kf).tangentIn;
1986
+ var kfTangentOut = (kf) => anyKf(kf).tangentOut;
1409
1987
  var PxLoopSchema = implementsInterface()(px.object({
1410
1988
  segmentCount: px.number().optional(),
1411
- extend: px.enum([PxLoopExtend.before, PxLoopExtend.after]).optional(),
1412
- alternate: px.boolean().optional()
1989
+ repeatAt: px.enum([PxLoopRepeatAt.start, PxLoopRepeatAt.end]).optional(),
1990
+ direction: px.enum([PxLoopDirection.normal, PxLoopDirection.alternate]).optional()
1413
1991
  }));
1414
1992
  var PxPropertyAnimationSchema = implementsInterface()(px.object({
1415
1993
  value: PxKeyframeValueSchema.optional(),
1416
1994
  keyframes: px.array(PxKeyframeSchema).optional(),
1417
1995
  loop: px.union([PxLoopSchema, px.boolean()]).optional(),
1418
- autoOrient: px.boolean().optional()
1996
+ autoOrient: px.boolean().optional(),
1997
+ alongPathMode: px.enum([PxAlongPathMode.sampled, PxAlongPathMode.offsetPath]).optional()
1419
1998
  }));
1420
1999
  var PxTransformPartsSchema = implementsInterface()(px.object({
1421
2000
  translate: px.tuple([px.number(), px.number()]).optional(),
@@ -1439,18 +2018,17 @@ var PxElementAnimationSchema = implementsInterface()(px.union([
1439
2018
  PxAnimationDefinitionSchema
1440
2019
  ]));
1441
2020
  var PxTriggerSchema = implementsInterface()(px.object({
1442
- startOn: px.enum(["load", "mouseOver", "click", "scrollIntoView", "programmatic"]).optional(),
1443
- outAction: px.enum(["continue", "pause", "reset", "reverse"]).optional(),
2021
+ startOn: px.enum([PxStartOn.load, PxStartOn.mouseOver, PxStartOn.click, PxStartOn.scrollIntoView, PxStartOn.programmatic], PX_TRIGGER_DEFAULTS.startOn).optional(),
2022
+ outAction: px.enum([PxOutAction.continue, PxOutAction.pause, PxOutAction.reset, PxOutAction.reverse], PX_TRIGGER_DEFAULTS.outAction).optional(),
1444
2023
  // What happens after a NATURAL finish — `'hold'` (default: keep the end state per
1445
- // `fill`) or `'reset'` (snap back to the start state). The trigger-vocabulary home of
1446
- // the old top-level `resetOnFinish: boolean` (read-legacy) — review §2.3: both
1447
- // "what happens at the end" knobs now sit side by side and share one style of value.
1448
- onFinish: px.enum(["hold", "reset"]).optional(),
2024
+ // `fill`) or `'reset'` (snap back to the start state). Pairs with `outAction` ("what
2025
+ // happens when the trigger condition ends"); both end-of-life knobs now read alike.
2026
+ finishAction: px.enum([PxFinishAction.hold, PxFinishAction.reset]).optional(),
1449
2027
  scrollIntoViewThreshold: px.number().optional()
1450
2028
  }));
1451
2029
  var PxGlyphSchema = implementsInterface()(px.object({
1452
2030
  width: px.number(),
1453
- d: px.string()
2031
+ pathData: px.string()
1454
2032
  }));
1455
2033
  var PxGlyphFontSchema = implementsInterface()(px.object({
1456
2034
  fontFamily: px.string(),
@@ -1465,11 +2043,17 @@ var PxDefsSchema = implementsInterface()(px.object({
1465
2043
  // Review §2.6: the schema now matches the declared type — a style preset is a flat
1466
2044
  // record of string|number attribute values, nothing nested.
1467
2045
  styles: px.record(px.record(px.union([px.string(), px.number()]))).optional(),
1468
- glyphs: px.record(PxGlyphFontSchema).optional()
2046
+ fonts: px.record(PxGlyphFontSchema).optional()
1469
2047
  }));
1470
- var PX_SCROLL_PHASES = ["cover", "contain", "entry", "exit", "entry-crossing", "exit-crossing"];
1471
2048
  var PxScrollRangePointSchema = implementsInterface()(px.object({
1472
- phase: px.enum(PX_SCROLL_PHASES).optional(),
2049
+ phase: px.enum([
2050
+ PxScrollPhase.cover,
2051
+ PxScrollPhase.contain,
2052
+ PxScrollPhase.entry,
2053
+ PxScrollPhase.exit,
2054
+ PxScrollPhase.entryCrossing,
2055
+ PxScrollPhase.exitCrossing
2056
+ ]).optional(),
1473
2057
  fraction: px.number().optional()
1474
2058
  }));
1475
2059
  var PxScrollRangeSchema = px.object({
@@ -1477,34 +2061,38 @@ var PxScrollRangeSchema = px.object({
1477
2061
  end: PxScrollRangePointSchema.optional()
1478
2062
  });
1479
2063
  var PxScrollSchema = implementsInterface()(px.object({
1480
- driver: px.enum(["custom", "native"]).optional(),
1481
- kind: px.enum(["view", "scroll"]).optional(),
1482
- axis: px.enum(["block", "inline", "x", "y"]).optional(),
1483
- source: px.enum(["nearest", "root"]).optional(),
2064
+ kind: px.enum([PxScrollKind.view, PxScrollKind.scroll]).optional(),
2065
+ axis: px.enum([PxScrollAxis.block, PxScrollAxis.inline, PxScrollAxis.x, PxScrollAxis.y]).optional(),
2066
+ source: px.enum([PxScrollSource.nearest, PxScrollSource.root]).optional(),
1484
2067
  // Free-form: the two keywords `parent`/`scroller` plus any CSS selector.
1485
2068
  subject: px.string().optional(),
1486
2069
  smoothing: px.number().optional(),
1487
2070
  pin: px.boolean().optional(),
1488
- pinAlign: px.enum(["top", "center", "bottom"]).optional(),
1489
- pinTop: px.number().optional(),
2071
+ pinAlign: px.enum([PxPinAlign.top, PxPinAlign.center, PxPinAlign.bottom]).optional(),
2072
+ pinOffset: px.number().optional(),
1490
2073
  pinDistance: px.number().optional(),
1491
2074
  range: PxScrollRangeSchema.optional()
1492
2075
  }));
1493
- var PxTimelinePinSchema = px.object({
1494
- align: px.enum(["top", "center", "bottom"]).optional(),
1495
- top: px.number().optional(),
2076
+ var PxTimelinePinSchema = implementsInterface()(px.object({
2077
+ align: px.enum([PxPinAlign.top, PxPinAlign.center, PxPinAlign.bottom]).optional(),
2078
+ offset: px.number().optional(),
1496
2079
  distance: px.number().optional()
1497
- });
1498
- var PxClockTimelineSchema = px.object({
1499
- type: px.literal("clock"),
2080
+ }));
2081
+ var PxTimelineEngineSchema = px.enum([PxTimelineEngineExtra.auto, PxTimelineEngineExtra.native, PxTimelineEngineExtra.js]).optional();
2082
+ var PxTimeTimelineSchema = implementsInterface()(px.object({
2083
+ type: px.literal("time").optional(),
2084
+ engine: PxTimelineEngineSchema,
2085
+ frameRate: px.number().optional(),
1500
2086
  // §2.8: duration is a property of the TIMELINE — how long one pass takes.
1501
2087
  duration: px.number().optional(),
1502
2088
  trigger: PxTriggerSchema.optional(),
1503
2089
  delay: px.number().optional(),
1504
2090
  iterations: px.union([px.number(), px.literal("infinite")]).optional(),
1505
- fill: px.enum(["forwards", "backwards", "both", "none"]).optional(),
1506
- direction: px.enum(["normal", "reverse", "alternate", "alternate-reverse"]).optional()
1507
- });
2091
+ // `fillMode` on the wire (CSS `animation-fill-mode`; the runtime view calls it `fill`)
2092
+ // — never `fill`, which is paint everywhere else in the format.
2093
+ fillMode: px.enum([PxFillMode.forwards, PxFillMode.backwards, PxFillMode.both, PxFillMode.none]).optional(),
2094
+ direction: px.enum([PxPlaybackDirection.normal, PxPlaybackDirection.reverse, PxPlaybackDirection.alternate, PxPlaybackDirection.alternateReverse]).optional()
2095
+ }));
1508
2096
  var scrollishTimelineShape = {
1509
2097
  // §2.8: duration is a property of the TIMELINE — under scrubbing it is the keyframe
1510
2098
  // span the scroll range maps onto.
@@ -1512,9 +2100,10 @@ var scrollishTimelineShape = {
1512
2100
  // Finite repeat count IS meaningful when scrubbing — the scroll range maps onto
1513
2101
  // duration × iterations (rule D4; `'infinite'` cannot map to a range, so no literal here).
1514
2102
  iterations: px.number().optional(),
1515
- engine: px.enum(["custom", "native"]).optional(),
1516
- axis: px.enum(["block", "inline", "x", "y"]).optional(),
1517
- source: px.enum(["nearest", "root"]).optional(),
2103
+ engine: PxTimelineEngineSchema,
2104
+ frameRate: px.number().optional(),
2105
+ axis: px.enum([PxScrollAxis.block, PxScrollAxis.inline, PxScrollAxis.x, PxScrollAxis.y]).optional(),
2106
+ source: px.enum([PxScrollSource.nearest, PxScrollSource.root]).optional(),
1518
2107
  subject: px.string().optional(),
1519
2108
  // 'parent' | 'scroller' | any CSS selector
1520
2109
  smoothing: px.number().optional(),
@@ -1522,23 +2111,29 @@ var scrollishTimelineShape = {
1522
2111
  pin: px.union([px.boolean(), PxTimelinePinSchema]).optional(),
1523
2112
  range: PxScrollRangeSchema.optional()
1524
2113
  };
1525
- var PxScrollTimelineSchema = px.object(__spreadValues({ type: px.literal("scroll") }, scrollishTimelineShape));
1526
- var PxViewTimelineSchema = px.object(__spreadValues({ type: px.literal("view") }, scrollishTimelineShape));
2114
+ var PxScrollTimelineSchema = implementsInterface()(
2115
+ px.object(__spreadValues({ type: px.literal("scroll") }, scrollishTimelineShape))
2116
+ );
2117
+ var PxViewTimelineSchema = implementsInterface()(
2118
+ px.object(__spreadValues({ type: px.literal("view") }, scrollishTimelineShape))
2119
+ );
1527
2120
  var PxTimelineSchema = px.discriminatedUnion("type", [
1528
- PxClockTimelineSchema,
2121
+ PxTimeTimelineSchema,
2122
+ // first = the member an absent `type` selects
1529
2123
  PxScrollTimelineSchema,
1530
2124
  PxViewTimelineSchema
1531
2125
  ]);
1532
2126
  var PxAnimatorConfigSchema = implementsInterface()(px.object({
1533
- mode: px.enum([PxAnimatorMode.auto, PxAnimatorMode.waapi, PxAnimatorMode.frames]).optional(),
1534
- // (`duration` lives INSIDE `timeline` on the wire — §2.8; the flat field below
1535
- // exists only on the runtime view, like the rest of the playback dynamics.)
1536
- frameRate: px.number().optional(),
2127
+ // (`mode`, `duration` and `frameRate` live INSIDE `timeline` on the wire — §2.8; they exist
2128
+ // at this level only on the runtime view, like the rest of the playback dynamics.)
1537
2129
  // THE spelling of "what advances progress" — clock / scroll / view (review §2.1).
1538
2130
  timeline: PxTimelineSchema.optional(),
1539
2131
  definitions: PxDefsSchema.optional(),
1540
2132
  animateById: px.record(PxElementAnimationSchema).optional(),
1541
- debugInstName: px.string().optional()
2133
+ debugGlobalName: px.string().optional(),
2134
+ // Declared HERE because this is a closed object: an undeclared key would be stripped by
2135
+ // `sanitize` and flagged by strict validation on our own files.
2136
+ version: px.string().optional()
1542
2137
  }));
1543
2138
  var PxBindingSchema = implementsInterface()(px.object({
1544
2139
  id: px.string(),
@@ -1587,7 +2182,7 @@ var PxRepeaterEffectSchema = implementsInterface()(px.object({
1587
2182
  origin: PxAnimatableVec2Schema.optional()
1588
2183
  }));
1589
2184
  var PxMaskedByEffectSchema = implementsInterface()(px.object({
1590
- sourceId: px.string().optional(),
2185
+ source: px.string().optional(),
1591
2186
  maskType: px.enum([PxMaskType.luminance, PxMaskType.alpha]).optional(),
1592
2187
  maskUnits: px.enum([PxUnits.userSpaceOnUse, PxUnits.objectBoundingBox]).optional(),
1593
2188
  maskContentUnits: px.enum([PxUnits.userSpaceOnUse, PxUnits.objectBoundingBox]).optional(),
@@ -1597,7 +2192,7 @@ var PxMaskedByEffectSchema = implementsInterface()(px.object({
1597
2192
  height: px.number().optional()
1598
2193
  }));
1599
2194
  var PxClipPathEffectSchema = implementsInterface()(px.object({
1600
- d: PxAnimatableStringSchema.optional()
2195
+ pathData: PxAnimatableStringSchema.optional()
1601
2196
  }));
1602
2197
  var PxStrokeTrimEffectSchema = implementsInterface()(px.object({
1603
2198
  offset: PxAnimatableNumberSchema.optional(),
@@ -1610,9 +2205,10 @@ var PxRetimeEffectSchema = implementsInterface()(px.object({
1610
2205
  timeCrop: px.tuple([px.number(), px.number()]).optional()
1611
2206
  }));
1612
2207
  var PxCloneEffectSchema = implementsInterface()(px.object({
1613
- // Contextual kind — the `type` convention, see `PxNodeBase.type`.
1614
- type: px.enum([PxCloneType.content]).optional(),
1615
- sourceId: px.string().optional(),
2208
+ // Subtractive on purpose: the `<use>` can only point at one wrapper layer of the
2209
+ // source, so the choices form a ladder — 'translate' now, maybe 'transform' later.
2210
+ without: px.enum([PxCloneWithout.translate]).optional(),
2211
+ source: px.string().optional(),
1616
2212
  retime: PxRetimeEffectSchema.optional()
1617
2213
  }));
1618
2214
  var PxGradientStopSchema = implementsInterface()(px.object({
@@ -1633,13 +2229,13 @@ var PxFillGradientEffectSchema = implementsInterface()(px.object({
1633
2229
  radius: PxAnimatableNumberSchema.optional(),
1634
2230
  focal: PxAnimatableVec2Schema.optional(),
1635
2231
  stops: PxAnimatableGradientStopsSchema.optional(),
1636
- gradientUnits: px.enum([PxGradientUnits.userSpaceOnUse, PxGradientUnits.objectBoundingBox]).optional(),
2232
+ gradientUnits: px.enum([PxUnits.userSpaceOnUse, PxUnits.objectBoundingBox]).optional(),
1637
2233
  spreadMethod: px.enum([PxGradientSpreadMethod.pad, PxGradientSpreadMethod.reflect, PxGradientSpreadMethod.repeat]).optional(),
1638
2234
  gradientTransform: px.string().optional()
1639
2235
  }));
1640
2236
  var PxStrokeGradientEffectSchema = PxFillGradientEffectSchema;
1641
2237
  var PxTextPathEffectSchema = implementsInterface()(px.object({
1642
- path: px.string(),
2238
+ pathData: px.string(),
1643
2239
  pathOverflow: px.enum([PxPathOverflow.clip, PxPathOverflow.extend]).optional(),
1644
2240
  lengthAdjust: px.enum([PxLengthAdjust.spacing, PxLengthAdjust.spacingAndGlyphs]).optional(),
1645
2241
  method: px.enum([PxTextPathMethod.align, PxTextPathMethod.stretch]).optional(),
@@ -1679,20 +2275,100 @@ function validateNodeEffects(root, opts) {
1679
2275
  walk(root, "root");
1680
2276
  return warnings;
1681
2277
  }
2278
+ function validateGlyphFontRefs(root, fonts) {
2279
+ if (!fonts || !Object.keys(fonts).length) return [];
2280
+ const problems = [];
2281
+ const walk = (node, path, inherited, inGlyphText) => {
2282
+ var _a2, _b;
2283
+ if (!node) return;
2284
+ const own = typeof node.fontFamily === "string" ? node.fontFamily : void 0;
2285
+ const family = own != null ? own : inherited;
2286
+ const isGlyphText = inGlyphText || node.type === "text" && !!((_b = (_a2 = node.effects) == null ? void 0 : _a2.text) == null ? void 0 : _b.useGlyphs);
2287
+ if (isGlyphText && own && !Object.prototype.hasOwnProperty.call(fonts, own)) {
2288
+ const problem = path + ': glyph-mode text uses font-family "' + own + '", which has no entry in animator.definitions.fonts';
2289
+ if (!problems.includes(problem)) problems.push(problem);
2290
+ }
2291
+ if (Array.isArray(node.children)) {
2292
+ node.children.forEach((c, i) => walk(c, path + ".children[" + i + "]", family, isGlyphText));
2293
+ }
2294
+ };
2295
+ walk(root, "root", void 0, false);
2296
+ return problems;
2297
+ }
2298
+ function validateEasingRefs(root, easings) {
2299
+ const problems = [];
2300
+ const walk = (node, path) => {
2301
+ if (Array.isArray(node)) {
2302
+ node.forEach((item, i) => walk(item, path + "[" + i + "]"));
2303
+ return;
2304
+ }
2305
+ if (!node || typeof node !== "object") return;
2306
+ const easing = node.easing;
2307
+ if (typeof easing === "string" && !(easings && Object.prototype.hasOwnProperty.call(easings, easing))) {
2308
+ const problem = path + '.easing: "' + easing + '" names no entry in animator.definitions.easings \u2014 it will play linear';
2309
+ if (!problems.includes(problem)) problems.push(problem);
2310
+ }
2311
+ for (const [key, value] of Object.entries(node)) {
2312
+ if (key === "easing") continue;
2313
+ if (value && typeof value === "object") walk(value, path + "." + key);
2314
+ }
2315
+ };
2316
+ walk(root, "root");
2317
+ return problems;
2318
+ }
2319
+ function validateVersionStamp(doc) {
2320
+ var _a2;
2321
+ const version = (_a2 = getAnimatorConfig(doc)) == null ? void 0 : _a2.version;
2322
+ if (version === void 0) return [];
2323
+ if (parseWireVersion(version) !== void 0) return [];
2324
+ return ["root.animator.version: " + JSON.stringify(version) + ' is not a version stamp ("a.b" or "a.b.c") \u2014 it reads as unstamped'];
2325
+ }
2326
+ function validateDocument(doc, opts) {
2327
+ var _a2;
2328
+ const strict = (opts == null ? void 0 : opts.strict) !== false;
2329
+ const ctx = { errors: [], warnings: [], strict };
2330
+ const problems = PxAnimatedSvgDocumentSchema.isValid(doc, ctx, ["root"]) ? [] : [...ctx.errors];
2331
+ if (doc && typeof doc === "object") {
2332
+ for (const w of validateNodeEffects(doc, { strict })) {
2333
+ if (!problems.includes(w)) problems.push(w);
2334
+ }
2335
+ const defs = (_a2 = getAnimatorConfig(doc)) == null ? void 0 : _a2.definitions;
2336
+ for (const w of validateGlyphFontRefs(doc, defs == null ? void 0 : defs.fonts)) {
2337
+ if (!problems.includes(w)) problems.push(w);
2338
+ }
2339
+ for (const w of validateEasingRefs(doc, defs == null ? void 0 : defs.easings)) {
2340
+ if (!problems.includes(w)) problems.push(w);
2341
+ }
2342
+ for (const w of validateVersionStamp(doc)) {
2343
+ if (!problems.includes(w)) problems.push(w);
2344
+ }
2345
+ }
2346
+ return problems;
2347
+ }
1682
2348
  var PxNodeBase = px.openObject({
1683
2349
  // CONVENTION (SCHEMA-DESIGN R1 / issues N4): `type` is the ONE word for "what
1684
2350
  // kind of thing is this", discriminated by its CARRIER — here the node TAG
1685
- // (`rect`, `text`), and inside a sub-object that object's kind (`clone.type`,
2351
+ // (`rect`, `text`), and inside a sub-object that object's kind (`fillGradient.type`,
1686
2352
  // `fillGradient.type`, editor `preset.type`). Each sits in its own object, so
1687
2353
  // the carrier disambiguates completely; synonyms (`cloneKind`, `presetShape`)
1688
2354
  // would add words that all mean "type" and still need the carrier to read.
1689
2355
  // Guarding a `type` SLOT against a wrong VALUE is the job of strict enums
1690
2356
  // (issues V3), never of distinct key names.
1691
2357
  type: px.string(),
2358
+ // The escape hatch for elements that carry a REAL `type` attribute — `<feTurbulence
2359
+ // type="fractalNoise">`, `<feFuncR type="table">`, `<feColorMatrix type="saturate">`.
2360
+ // `type` is taken by the tag name, so the attribute travels here and the renderer puts
2361
+ // it back (`PxAnimatorDOM.renderNode`, `PxRnRender`). Declared here — not merely
2362
+ // documented — because a wire key that is not in a schema is invisible to the
2363
+ // minifier's reserve list and gets renamed (MINIFICATION-BOUNDARY-PLAN.md §1.1).
2364
+ domType: px.string().optional(),
2365
+ // Text content of a `<text>` / `<tspan>`. Declared, so a non-string value is a schema error
2366
+ // and the minifier reserves the key; `text` is NOT an alias for it and is not read anywhere.
2367
+ textContent: px.string().optional(),
1692
2368
  id: px.string().optional(),
1693
2369
  meta: px.any().optional(),
1694
2370
  // Player-effects bucket emitted by the Editor's lightweight design format.
1695
- // Consumed and removed by `applyPlayerEffects` before any other normalisation
2371
+ // Consumed and removed by `applyPlayerEffects` before any other normalization
1696
2372
  // (see `createAnimatorImpl`), so downstream code never sees it.
1697
2373
  effects: PxEffectsSchema.optional(),
1698
2374
  // `PxElementAnimation` (not just `PxAnimationDefinition`) — accepts
@@ -1724,11 +2400,11 @@ var PxBezierPathSchema = implementsInterface()(px.object({
1724
2400
  c: px.boolean().optional()
1725
2401
  }));
1726
2402
  function isPxElementFileFormatDeep(fileJson) {
1727
- const valid = PxAnimatedSvgDocumentSchema.isValid(fileJson);
1728
- return { valid, errors: valid ? [] : ["Document failed schema validation"] };
2403
+ const errors = validateDocument(fileJson, { strict: false });
2404
+ return { valid: errors.length === 0, errors };
1729
2405
  }
1730
2406
 
1731
- // src/PxIdUtil.ts
2407
+ // src/util/PxIdUtil.ts
1732
2408
  var _idCounter = 0;
1733
2409
  function generateUniqueId() {
1734
2410
  const timestamp = Date.now().toString(36);
@@ -1747,7 +2423,7 @@ function deepClone(value) {
1747
2423
  return cloned;
1748
2424
  }
1749
2425
  function generateNewIds(doc) {
1750
- var _a, _b;
2426
+ var _a2, _b;
1751
2427
  const cloned = deepClone(doc);
1752
2428
  const idMap = /* @__PURE__ */ new Map();
1753
2429
  const hashRefAttrs = /* @__PURE__ */ new Set(["href", "xlink:href"]);
@@ -1765,7 +2441,8 @@ function generateNewIds(doc) {
1765
2441
  "flood-color",
1766
2442
  "lighting-color"
1767
2443
  ]);
1768
- const directIdRefAttrs = /* @__PURE__ */ new Set(["sourceId", "targetId", "boundElementId"]);
2444
+ const directIdRefAttrs = /* @__PURE__ */ new Set(["targetId", "boundElementId"]);
2445
+ const isEffectSourceRef = (key, parentKey) => key === "source" && (parentKey === "maskedBy" || parentKey === "clone");
1769
2446
  function collectIds(node) {
1770
2447
  if (!node || typeof node !== "object") return;
1771
2448
  if (node.id && typeof node.id === "string") {
@@ -1782,7 +2459,7 @@ function generateNewIds(doc) {
1782
2459
  }
1783
2460
  }
1784
2461
  }
1785
- function updateRefs(node) {
2462
+ function updateRefs(node, parentKey) {
1786
2463
  if (!node || typeof node !== "object") return;
1787
2464
  for (const [key, value] of Object.entries(node)) {
1788
2465
  if (key === "children") {
@@ -1802,7 +2479,7 @@ function generateNewIds(doc) {
1802
2479
  }
1803
2480
  } else if (urlRefAttrs.has(key)) {
1804
2481
  node[key] = replaceUrlRefs(value, idMap);
1805
- } else if (directIdRefAttrs.has(key)) {
2482
+ } else if (directIdRefAttrs.has(key) || isEffectSourceRef(key, parentKey)) {
1806
2483
  const hasHash = value.startsWith("#");
1807
2484
  const newId = idMap.get(hasHash ? value.slice(1) : value);
1808
2485
  if (newId) {
@@ -1818,13 +2495,13 @@ function generateNewIds(doc) {
1818
2495
  }
1819
2496
  }
1820
2497
  } else if (typeof value === "object" && value !== null) {
1821
- updateRefs(value);
2498
+ updateRefs(value, key);
1822
2499
  }
1823
2500
  }
1824
2501
  }
1825
2502
  collectIds(cloned);
1826
2503
  updateRefs(cloned);
1827
- const docAnimate = (_a = cloned.animator) == null ? void 0 : _a.animateById;
2504
+ const docAnimate = (_a2 = cloned.animator) == null ? void 0 : _a2.animateById;
1828
2505
  if (docAnimate && typeof docAnimate === "object") {
1829
2506
  const updatedAnimate = {};
1830
2507
  for (const [key, anim] of Object.entries(docAnimate)) {
@@ -1844,7 +2521,7 @@ function replaceUrlRefs(value, idMap) {
1844
2521
  });
1845
2522
  }
1846
2523
 
1847
- // src/PxNodeProps.ts
2524
+ // src/util/PxNodeProps.ts
1848
2525
  var DISALLOWED_SVG_TAGS_LOWER = /* @__PURE__ */ new Set([
1849
2526
  "script",
1850
2527
  "foreignobject"
@@ -1883,7 +2560,7 @@ function isDangerousAttrName(nameLower) {
1883
2560
  if (nameLower.startsWith("on")) return true;
1884
2561
  return false;
1885
2562
  }
1886
- function sanitiseAttributeValue(name, value) {
2563
+ function sanitizeAttributeValue(name, value) {
1887
2564
  const nameLower = name.toLowerCase();
1888
2565
  if (isDangerousAttrName(nameLower)) {
1889
2566
  console.warn("Attribute blocked (event handler / dangerous): ", nameLower);
@@ -1908,10 +2585,10 @@ function sanitiseAttributeValue(name, value) {
1908
2585
  return value;
1909
2586
  }
1910
2587
  function resolveStyle(style, defs) {
1911
- var _a;
2588
+ var _a2;
1912
2589
  if (!style) return void 0;
1913
2590
  if (typeof style === "string") {
1914
- return (_a = defs == null ? void 0 : defs.styles) == null ? void 0 : _a[style];
2591
+ return (_a2 = defs == null ? void 0 : defs.styles) == null ? void 0 : _a2[style];
1915
2592
  }
1916
2593
  return style;
1917
2594
  }
@@ -1922,18 +2599,18 @@ function getNormalizedProps(props) {
1922
2599
  if (INTERNAL_ATTRS.has(key)) continue;
1923
2600
  if (key === "style") continue;
1924
2601
  let value = props[rawKey];
1925
- if (COLOUR_ATTR_NAMES.has(key) && Array.isArray(value)) {
2602
+ if (COLOR_ATTR_NAMES.has(key) && Array.isArray(value)) {
1926
2603
  propsCopy[key] = toRGBA(value);
1927
2604
  } else if (key === "transform" && value !== null && typeof value === "object" && !Array.isArray(value) && !value.keyframes) {
1928
2605
  const parts = value.value && typeof value.value === "object" ? value.value : value;
1929
- propsCopy["transform"] = composeTransformParts(parts, { withUnits: false });
2606
+ propsCopy[TRANSFORM_ATTR] = composeTransformParts(parts, { withUnits: false });
1930
2607
  } else if (TRANSFORM_FN_NAMES.has(key)) {
1931
2608
  if (Array.isArray(value)) {
1932
2609
  if (key === "translate") value = value.map((v) => v + "px");
1933
2610
  value = value.join(",");
1934
2611
  }
1935
2612
  if (key === "rotate") value = value + "deg";
1936
- propsCopy["transform"] = key + "(" + value + ")";
2613
+ propsCopy[TRANSFORM_ATTR] = key + "(" + value + ")";
1937
2614
  } else if (Array.isArray(value)) {
1938
2615
  propsCopy[key] = value.join(",");
1939
2616
  } else if (value !== void 0 && value !== null) {
@@ -1943,10 +2620,9 @@ function getNormalizedProps(props) {
1943
2620
  return propsCopy;
1944
2621
  }
1945
2622
 
1946
- // src/PxMotionPath.ts
2623
+ // src/materialize/PxMotionPath.ts
1947
2624
  function getKfTranslate(kf) {
1948
- var _a;
1949
- const v = (_a = kf.value) != null ? _a : kf.v;
2625
+ const v = kfValue(kf);
1950
2626
  if (!v) return void 0;
1951
2627
  if (Array.isArray(v) && v.length >= 2 && typeof v[0] === "number" && typeof v[1] === "number") {
1952
2628
  return [v[0], v[1]];
@@ -1956,31 +2632,27 @@ function getKfTranslate(kf) {
1956
2632
  return void 0;
1957
2633
  }
1958
2634
  function getKfTime(kf) {
1959
- var _a, _b;
1960
- return (_b = (_a = kf.time) != null ? _a : kf.t) != null ? _b : 0;
2635
+ return kfTime(kf);
1961
2636
  }
1962
2637
  function getKfEasing(kf) {
1963
- var _a;
1964
- return (_a = kf.easing) != null ? _a : kf.e;
2638
+ return kfEasing(kf);
1965
2639
  }
1966
2640
  function propAnimIsMotionPath(anim) {
1967
- var _a, _b;
1968
2641
  const kfs = anim.keyframes;
1969
2642
  if (!Array.isArray(kfs)) return false;
1970
2643
  if (anim.autoOrient) return true;
1971
2644
  for (const kf of kfs) {
1972
- if (((_a = kf.tangentIn) != null ? _a : kf.ti) || ((_b = kf.tangentOut) != null ? _b : kf.to)) return true;
2645
+ if (kfTangentIn(kf) || kfTangentOut(kf)) return true;
1973
2646
  }
1974
2647
  return false;
1975
2648
  }
1976
2649
  var _segmentCache = /* @__PURE__ */ new WeakMap();
1977
2650
  function getSegmentCache(prevKf, nextKf, prevPos, nextPos) {
1978
- var _a, _b;
1979
2651
  let byNext = _segmentCache.get(prevKf);
1980
2652
  const existing = byNext == null ? void 0 : byNext.get(nextKf);
1981
2653
  if (existing) return existing;
1982
- const to = (_a = prevKf.tangentOut) != null ? _a : prevKf.to;
1983
- const ti = (_b = nextKf.tangentIn) != null ? _b : nextKf.ti;
2654
+ const to = kfTangentOut(prevKf);
2655
+ const ti = kfTangentIn(nextKf);
1984
2656
  const P1 = [prevPos[0] + (to ? to[0] : 0), prevPos[1] + (to ? to[1] : 0)];
1985
2657
  const P2 = [nextPos[0] + (ti ? ti[0] : 0), nextPos[1] + (ti ? ti[1] : 0)];
1986
2658
  const lut = bezier2D_arcLengthLUT(prevPos, P1, P2, nextPos);
@@ -2029,13 +2701,13 @@ function tFromArcFraction(lut, arcFrac) {
2029
2701
  var DEFAULT_FLATNESS_TOL = 0.5;
2030
2702
  var DEFAULT_ROTATION_TOL = 5;
2031
2703
  var DEFAULT_MAX_SAMPLES = 32;
2032
- function materialiseMotionPathInPropAnim(anim, opts) {
2033
- var _a, _b, _c;
2704
+ function materializeMotionPathInPropAnim(anim, opts) {
2705
+ var _a2, _b, _c;
2034
2706
  if (!propAnimIsMotionPath(anim)) return anim;
2035
2707
  const kfs = anim.keyframes;
2036
2708
  if (!Array.isArray(kfs) || kfs.length < 2) return anim;
2037
2709
  const autoOrient = !!anim.autoOrient;
2038
- const flatnessTol = (_a = opts == null ? void 0 : opts.flatnessTolerance) != null ? _a : DEFAULT_FLATNESS_TOL;
2710
+ const flatnessTol = (_a2 = opts == null ? void 0 : opts.flatnessTolerance) != null ? _a2 : DEFAULT_FLATNESS_TOL;
2039
2711
  const rotationTol = (_b = opts == null ? void 0 : opts.rotationTolerance) != null ? _b : DEFAULT_ROTATION_TOL;
2040
2712
  const maxSamples = (_c = opts == null ? void 0 : opts.maxSamplesPerSegment) != null ? _c : DEFAULT_MAX_SAMPLES;
2041
2713
  const out = [];
@@ -2061,7 +2733,7 @@ function materialiseMotionPathInPropAnim(anim, opts) {
2061
2733
  if (autoOrient && i > 0) {
2062
2734
  insertSharpCornerStepKfIfNeeded(out, prevKf, nextKf, prevPos, nextPos, rotationTol);
2063
2735
  }
2064
- materialiseSegment(out, prevKf, nextKf, prevPos, nextPos, autoOrient, flatnessTol, rotationTol, maxSamples);
2736
+ materializeSegment(out, prevKf, nextKf, prevPos, nextPos, autoOrient, flatnessTol, rotationTol, maxSamples);
2065
2737
  }
2066
2738
  const lastInE = getKfEasing(kfs[kfs.length - 1]);
2067
2739
  if (lastInE) out[out.length - 1].e = lastInE;
@@ -2071,10 +2743,9 @@ function materialiseMotionPathInPropAnim(anim, opts) {
2071
2743
  return result;
2072
2744
  }
2073
2745
  function unwrapAutoOrientRotations(kfs) {
2074
- var _a;
2075
2746
  let prev;
2076
2747
  for (const kf of kfs) {
2077
- const v = (_a = kf.v) != null ? _a : kf.value;
2748
+ const v = kfValue(kf);
2078
2749
  if (!v || typeof v.rotate !== "number") continue;
2079
2750
  if (prev === void 0) {
2080
2751
  prev = v.rotate;
@@ -2091,8 +2762,7 @@ function makeOutKf(time, value) {
2091
2762
  return { t: time, v: value };
2092
2763
  }
2093
2764
  function getKfValueParts(kf) {
2094
- var _a;
2095
- const v = (_a = kf.value) != null ? _a : kf.v;
2765
+ const v = kfValue(kf);
2096
2766
  if (!v || typeof v !== "object" || Array.isArray(v)) return void 0;
2097
2767
  return v;
2098
2768
  }
@@ -2153,9 +2823,8 @@ function wrappedAngleDelta(a, b) {
2153
2823
  return d;
2154
2824
  }
2155
2825
  function insertSharpCornerStepKfIfNeeded(out, prevKf, nextKf, prevPos, nextPos, rotationTol) {
2156
- var _a;
2157
2826
  const lastKf = out[out.length - 1];
2158
- const lastV = (_a = lastKf.v) != null ? _a : lastKf.value;
2827
+ const lastV = kfValue(lastKf);
2159
2828
  const prevExit = lastV == null ? void 0 : lastV.rotate;
2160
2829
  if (typeof prevExit !== "number") return;
2161
2830
  const boundaryV = getKfValueParts(prevKf);
@@ -2178,7 +2847,7 @@ function insertSharpCornerStepKfIfNeeded(out, prevKf, nextKf, prevPos, nextPos,
2178
2847
  out.push(makeOutKf(stepTime, dupValue));
2179
2848
  }
2180
2849
  var CORNER_STEP_AFTER_BOUNDARY_MS = 0.05;
2181
- function materialiseSegment(out, prevKf, nextKf, prevPos, nextPos, autoOrient, flatnessTol, rotationTol, maxSamples) {
2850
+ function materializeSegment(out, prevKf, nextKf, prevPos, nextPos, autoOrient, flatnessTol, rotationTol, maxSamples) {
2182
2851
  const seg = getSegmentCache(prevKf, nextKf, prevPos, nextPos);
2183
2852
  const prevTime = getKfTime(prevKf);
2184
2853
  const nextTime = getKfTime(nextKf);
@@ -2301,16 +2970,16 @@ function perpDist(q, pA, pB) {
2301
2970
  const cross = (q[0] - pA[0]) * dy - (q[1] - pA[1]) * dx;
2302
2971
  return Math.abs(cross) / Math.sqrt(len2);
2303
2972
  }
2304
- function materialiseMotionPathsInTree(root, opts) {
2305
- const out = walkAndMaterialise(root, opts);
2973
+ function materializeMotionPathsInTree(root, opts) {
2974
+ const out = walkAndMaterialize(root, opts);
2306
2975
  return out != null ? out : root;
2307
2976
  }
2308
- function walkAndMaterialise(node, opts) {
2977
+ function walkAndMaterialize(node, opts) {
2309
2978
  let newChildren;
2310
2979
  if (node.children) {
2311
2980
  for (let i = 0; i < node.children.length; i++) {
2312
2981
  const ch = node.children[i];
2313
- const ret = walkAndMaterialise(ch, opts);
2982
+ const ret = walkAndMaterialize(ch, opts);
2314
2983
  if (ret !== null) {
2315
2984
  if (!newChildren) newChildren = node.children.slice();
2316
2985
  newChildren[i] = ret;
@@ -2323,9 +2992,9 @@ function walkAndMaterialise(node, opts) {
2323
2992
  const animDef = animBucket;
2324
2993
  const transformAnim = animDef.transform;
2325
2994
  if (transformAnim && typeof transformAnim === "object" && propAnimIsMotionPath(transformAnim)) {
2326
- const materialised = materialiseMotionPathInPropAnim(transformAnim, opts);
2327
- if (materialised !== transformAnim) {
2328
- newAnimate = __spreadProps(__spreadValues({}, animDef), { transform: materialised });
2995
+ const materialized = materializeMotionPathInPropAnim(transformAnim, opts);
2996
+ if (materialized !== transformAnim) {
2997
+ newAnimate = __spreadProps(__spreadValues({}, animDef), { transform: materialized });
2329
2998
  }
2330
2999
  }
2331
3000
  }
@@ -2336,7 +3005,7 @@ function walkAndMaterialise(node, opts) {
2336
3005
  return cloned;
2337
3006
  }
2338
3007
 
2339
- // src/PxDefinitions.ts
3008
+ // src/animation/PxDefinitions.ts
2340
3009
  var LOOP_JUMP_SHIFT_MS = 1;
2341
3010
  function deepEqualValue(a, b) {
2342
3011
  if (a === b) return true;
@@ -2428,8 +3097,8 @@ function isPathString(value) {
2428
3097
  return typeof value === "string" && extractPathData(value) !== void 0;
2429
3098
  }
2430
3099
  function normalizePathValue(value) {
2431
- if (value && typeof value === "object" && typeof value.path === "string") {
2432
- const d = extractPathData(value.path);
3100
+ if (value && typeof value === "object" && typeof value.pathData === "string") {
3101
+ const d = extractPathData(value.pathData);
2433
3102
  return d ? { paths: parseSvgPathToBezier(d) } : value;
2434
3103
  }
2435
3104
  if (value && typeof value === "object" && "paths" in value) {
@@ -2468,21 +3137,21 @@ function normalizePathValue(value) {
2468
3137
  return value;
2469
3138
  }
2470
3139
  function resolveEasing(easing, defs) {
2471
- var _a;
3140
+ var _a2;
2472
3141
  if (!easing) return void 0;
2473
3142
  if (Array.isArray(easing)) {
2474
3143
  return easing;
2475
3144
  }
2476
- if ((_a = defs == null ? void 0 : defs.easings) == null ? void 0 : _a[easing]) {
3145
+ if ((_a2 = defs == null ? void 0 : defs.easings) == null ? void 0 : _a2[easing]) {
2477
3146
  return defs.easings[easing];
2478
3147
  }
2479
3148
  console.warn("Unknown easing name: " + easing);
2480
3149
  return void 0;
2481
3150
  }
2482
3151
  function resolveAnimation(animRef, defs) {
2483
- var _a;
3152
+ var _a2;
2484
3153
  if (typeof animRef === "string") {
2485
- const resolved = (_a = defs == null ? void 0 : defs.animations) == null ? void 0 : _a[animRef];
3154
+ const resolved = (_a2 = defs == null ? void 0 : defs.animations) == null ? void 0 : _a2[animRef];
2486
3155
  if (!resolved) {
2487
3156
  console.warn("Unknown animation name: " + animRef);
2488
3157
  }
@@ -2507,13 +3176,13 @@ function resolveElementAnimation(animate, defs) {
2507
3176
  return results;
2508
3177
  }
2509
3178
  function interpolateValue(propName, a, b, t) {
2510
- var _a, _b;
3179
+ var _a2, _b;
2511
3180
  if (propName === "d") {
2512
- const aPaths = (_a = a == null ? void 0 : a.paths) != null ? _a : Array.isArray(a) ? a : [];
3181
+ const aPaths = (_a2 = a == null ? void 0 : a.paths) != null ? _a2 : Array.isArray(a) ? a : [];
2513
3182
  const bPaths = (_b = b == null ? void 0 : b.paths) != null ? _b : Array.isArray(b) ? b : [];
2514
3183
  return { paths: interpolateBeziers(aPaths, bPaths, t) };
2515
3184
  }
2516
- if (COLOUR_ATTR_NAMES.has(propName)) {
3185
+ if (COLOR_ATTR_NAMES.has(propName)) {
2517
3186
  return interpolateColor(a || [0, 0, 0, 1], b || [0, 0, 0, 1], t);
2518
3187
  }
2519
3188
  if (propName === "transform" && typeof a === "object" && a !== null && !Array.isArray(a) && typeof b === "object" && b !== null && !Array.isArray(b)) {
@@ -2545,11 +3214,11 @@ function interpolateTransformParts(a, b, t) {
2545
3214
  return out;
2546
3215
  }
2547
3216
  function expandLoopKeyframes(propName, keyframes, loop, duration) {
2548
- var _a, _b, _c, _d, _e;
3217
+ var _a2, _b, _c, _d, _e;
2549
3218
  const totalIntervals = keyframes.length - 1;
2550
- const segCount = clamp((_a = loop.segmentCount) != null ? _a : totalIntervals, 1, totalIntervals);
3219
+ const segCount = clamp((_a2 = loop.segmentCount) != null ? _a2 : totalIntervals, 1, totalIntervals);
2551
3220
  let segKfs;
2552
- if (loop.extend === PxLoopExtend.before) {
3221
+ if (loop.repeatAt === PxLoopRepeatAt.start) {
2553
3222
  segKfs = keyframes.slice(0, segCount + 1);
2554
3223
  } else {
2555
3224
  segKfs = keyframes.slice(totalIntervals - segCount);
@@ -2557,7 +3226,7 @@ function expandLoopKeyframes(propName, keyframes, loop, duration) {
2557
3226
  const firstT = (_b = keyframes[0].t) != null ? _b : 0;
2558
3227
  const lastT = (_c = keyframes[keyframes.length - 1].t) != null ? _c : 0;
2559
3228
  let fillStart, fillEnd;
2560
- if (loop.extend === PxLoopExtend.before) {
3229
+ if (loop.repeatAt === PxLoopRepeatAt.start) {
2561
3230
  fillStart = 0;
2562
3231
  fillEnd = firstT;
2563
3232
  } else {
@@ -2570,26 +3239,23 @@ function expandLoopKeyframes(propName, keyframes, loop, duration) {
2570
3239
  const segEndT = (_e = segKfs[segKfs.length - 1].t) != null ? _e : 0;
2571
3240
  const segDuration = segEndT - segStartT;
2572
3241
  if (segDuration <= 0) return keyframes;
2573
- const template = segKfs.map((kf) => {
2574
- var _a2, _b2;
2575
- return {
2576
- relT: (kf.t - segStartT) / segDuration,
2577
- v: kf.v,
2578
- e: kf.e,
2579
- tangentIn: (_a2 = kf.tangentIn) != null ? _a2 : kf.ti,
2580
- tangentOut: (_b2 = kf.tangentOut) != null ? _b2 : kf.to
2581
- };
2582
- });
3242
+ const template = segKfs.map((kf) => ({
3243
+ relT: (kf.t - segStartT) / segDuration,
3244
+ v: kf.v,
3245
+ e: kf.e,
3246
+ tangentIn: kfTangentIn(kf),
3247
+ tangentOut: kfTangentOut(kf)
3248
+ }));
2583
3249
  const fullReps = Math.floor(fillDuration / segDuration);
2584
3250
  const remainder = fillDuration - fullReps * segDuration;
2585
3251
  const partialFraction = remainder / segDuration;
2586
3252
  const looped = [];
2587
- const separateBoundary = loop.extend !== PxLoopExtend.before;
3253
+ const separateBoundary = loop.repeatAt !== PxLoopRepeatAt.start;
2588
3254
  const originalTerminalKf = keyframes[keyframes.length - 1];
2589
3255
  let terminalEasingOverride;
2590
3256
  let hasTerminalEasingOverride = false;
2591
3257
  function appendRep(repStart, isReversed, partial) {
2592
- var _a2;
3258
+ var _a3;
2593
3259
  let entries;
2594
3260
  if (isReversed) {
2595
3261
  entries = [];
@@ -2626,7 +3292,7 @@ function expandLoopKeyframes(propName, keyframes, loop, duration) {
2626
3292
  return;
2627
3293
  }
2628
3294
  const prevKf = looped.length > 0 ? looped[looped.length - 1] : originalTerminalKf;
2629
- const isBoundary = separateBoundary && i === 0 && prevKf !== void 0 && Math.abs(((_a2 = prevKf.t) != null ? _a2 : 0) - (repStart + entry.relT * segDuration)) < 1e-9;
3295
+ const isBoundary = separateBoundary && i === 0 && prevKf !== void 0 && Math.abs(((_a3 = prevKf.t) != null ? _a3 : 0) - (repStart + entry.relT * segDuration)) < 1e-9;
2630
3296
  if (isBoundary) {
2631
3297
  if (deepEqualValue(prevKf.v, entry.v)) {
2632
3298
  if (looped.length > 0) {
@@ -2692,30 +3358,30 @@ function expandLoopKeyframes(propName, keyframes, loop, duration) {
2692
3358
  looped.push(pushed);
2693
3359
  }
2694
3360
  }
2695
- if (loop.extend === PxLoopExtend.before) {
3361
+ if (loop.repeatAt === PxLoopRepeatAt.start) {
2696
3362
  if (partialFraction > 1e-9) {
2697
- const isReversed = !!loop.alternate && fullReps % 2 === 0;
3363
+ const isReversed = loop.direction === PxLoopDirection.alternate && fullReps % 2 === 0;
2698
3364
  appendRepTail(fillStart, isReversed, partialFraction);
2699
3365
  }
2700
3366
  for (let rep = 0; rep < fullReps; rep++) {
2701
3367
  const distFromBoundary = fullReps - 1 - rep;
2702
- const isReversed = !!loop.alternate && distFromBoundary % 2 === 0;
3368
+ const isReversed = loop.direction === PxLoopDirection.alternate && distFromBoundary % 2 === 0;
2703
3369
  const repStart = fillStart + remainder + rep * segDuration;
2704
3370
  appendRep(repStart, isReversed);
2705
3371
  }
2706
3372
  } else {
2707
3373
  for (let rep = 0; rep < fullReps; rep++) {
2708
- const isReversed = !!loop.alternate && rep % 2 === 0;
3374
+ const isReversed = loop.direction === PxLoopDirection.alternate && rep % 2 === 0;
2709
3375
  const repStart = fillStart + rep * segDuration;
2710
3376
  appendRep(repStart, isReversed);
2711
3377
  }
2712
3378
  if (partialFraction > 1e-9) {
2713
- const isReversed = !!loop.alternate && fullReps % 2 === 0;
3379
+ const isReversed = loop.direction === PxLoopDirection.alternate && fullReps % 2 === 0;
2714
3380
  const repStart = fillStart + fullReps * segDuration;
2715
3381
  appendRep(repStart, isReversed, partialFraction);
2716
3382
  }
2717
3383
  }
2718
- if (loop.extend === PxLoopExtend.before) {
3384
+ if (loop.repeatAt === PxLoopRepeatAt.start) {
2719
3385
  return [...looped, ...keyframes];
2720
3386
  } else {
2721
3387
  if (hasTerminalEasingOverride && keyframes.length > 0) {
@@ -2727,34 +3393,34 @@ function expandLoopKeyframes(propName, keyframes, loop, duration) {
2727
3393
  }
2728
3394
  }
2729
3395
  function normalizeKeyframes(propName, propAnim, duration, defs) {
2730
- var _a, _b, _c, _d, _e, _f, _g;
3396
+ var _a2;
2731
3397
  const keyframes = propAnim.keyframes || [];
2732
3398
  const normalized = [];
2733
3399
  for (const kf of keyframes) {
2734
- const timePct = (_b = (_a = kf.time) != null ? _a : kf.t) != null ? _b : 0;
2735
- let value = (_c = kf.value) != null ? _c : kf.v;
2736
- const easing = (_d = kf.easing) != null ? _d : kf.e;
3400
+ const timePct = kfTime(kf);
3401
+ let value = kfValue(kf);
3402
+ const easing = kfEasing(kf);
2737
3403
  if (propName === "d") {
2738
3404
  value = normalizePathValue(value);
2739
3405
  }
2740
3406
  const propNameKebab = isCamelCaseWord(propName) ? camelCaseToKebabWordIfNeeded(propName) : propName;
2741
- if (COLOUR_ATTR_NAMES.has(propNameKebab)) {
2742
- value = (_e = parseColor(value)) != null ? _e : value;
3407
+ if (COLOR_ATTR_NAMES.has(propNameKebab)) {
3408
+ value = (_a2 = parseColor(value)) != null ? _a2 : value;
2743
3409
  }
2744
3410
  const normKf = {
2745
3411
  t: timePct,
2746
3412
  v: value,
2747
3413
  e: resolveEasing(easing, defs)
2748
3414
  };
2749
- const tIn = (_f = kf.tangentIn) != null ? _f : kf.ti;
2750
- const tOut = (_g = kf.tangentOut) != null ? _g : kf.to;
3415
+ const tIn = kfTangentIn(kf);
3416
+ const tOut = kfTangentOut(kf);
2751
3417
  if (tIn) normKf.tangentIn = tIn;
2752
3418
  if (tOut) normKf.tangentOut = tOut;
2753
3419
  normalized.push(normKf);
2754
3420
  }
2755
3421
  normalized.sort((a, b) => {
2756
- var _a2, _b2;
2757
- return ((_a2 = a.t) != null ? _a2 : 0) - ((_b2 = b.t) != null ? _b2 : 0);
3422
+ var _a3, _b;
3423
+ return ((_a3 = a.t) != null ? _a3 : 0) - ((_b = b.t) != null ? _b : 0);
2758
3424
  });
2759
3425
  const loopRaw = propAnim.loop;
2760
3426
  const loop = loopRaw === true ? {} : loopRaw || void 0;
@@ -2772,24 +3438,26 @@ function mergeAnimationDefinitions(animations) {
2772
3438
  }
2773
3439
  return merged;
2774
3440
  }
2775
- function materialiseInternalLoopsInPropAnim(propName, propAnim, duration) {
3441
+ function materializeInternalLoopsInPropAnim(propName, propAnim, duration) {
2776
3442
  const loopRaw = propAnim.loop;
2777
3443
  if (loopRaw === void 0 || loopRaw === null || loopRaw === false) return propAnim;
2778
3444
  const loop = loopRaw === true ? {} : loopRaw;
2779
3445
  const rawKfs = propAnim.keyframes;
2780
3446
  if (!Array.isArray(rawKfs) || rawKfs.length < 2) return propAnim;
2781
3447
  const propNameKebab = isCamelCaseWord(propName) ? camelCaseToKebabWordIfNeeded(propName) : propName;
2782
- const isColour = COLOUR_ATTR_NAMES.has(propNameKebab);
3448
+ const isColor = COLOR_ATTR_NAMES.has(propNameKebab);
2783
3449
  const kfs = rawKfs.map((kf) => {
2784
- var _a, _b, _c, _d, _e, _f, _g, _h;
2785
- const t = (_a = kf.t) != null ? _a : kf.time;
2786
- let v = (_b = kf.v) != null ? _b : kf.value;
3450
+ var _a2;
3451
+ const t = kfTime(kf);
3452
+ let v = kfValue(kf);
2787
3453
  if (propName === "d") v = normalizePathValue(v);
2788
- if (isColour) v = (_c = parseColor(v)) != null ? _c : v;
2789
- const e = (_d = kf.e) != null ? _d : kf.easing;
3454
+ if (isColor) v = (_a2 = parseColor(v)) != null ? _a2 : v;
3455
+ const e = kfEasing(kf);
2790
3456
  const out2 = { t, v, e };
2791
- if ((_e = kf.tangentIn) != null ? _e : kf.ti) out2.tangentIn = (_f = kf.tangentIn) != null ? _f : kf.ti;
2792
- if ((_g = kf.tangentOut) != null ? _g : kf.to) out2.tangentOut = (_h = kf.tangentOut) != null ? _h : kf.to;
3457
+ const tIn = kfTangentIn(kf);
3458
+ const tOut = kfTangentOut(kf);
3459
+ if (tIn) out2.tangentIn = tIn;
3460
+ if (tOut) out2.tangentOut = tOut;
2793
3461
  return out2;
2794
3462
  });
2795
3463
  const expanded = expandLoopKeyframes(propName, kfs, loop, duration);
@@ -2797,15 +3465,15 @@ function materialiseInternalLoopsInPropAnim(propName, propAnim, duration) {
2797
3465
  if (propAnim.autoOrient !== void 0) out.autoOrient = propAnim.autoOrient;
2798
3466
  return out;
2799
3467
  }
2800
- function materialiseInternalLoopsInTree(root, duration) {
2801
- const ret = walkAndMaterialiseLoops(root, duration);
3468
+ function materializeInternalLoopsInTree(root, duration) {
3469
+ const ret = walkAndMaterializeLoops(root, duration);
2802
3470
  return ret != null ? ret : root;
2803
3471
  }
2804
- function walkAndMaterialiseLoops(node, duration) {
3472
+ function walkAndMaterializeLoops(node, duration) {
2805
3473
  let newChildren;
2806
3474
  if (node.children) {
2807
3475
  for (let i = 0; i < node.children.length; i++) {
2808
- const ret = walkAndMaterialiseLoops(node.children[i], duration);
3476
+ const ret = walkAndMaterializeLoops(node.children[i], duration);
2809
3477
  if (ret !== null) {
2810
3478
  if (!newChildren) newChildren = node.children.slice();
2811
3479
  newChildren[i] = ret;
@@ -2818,10 +3486,10 @@ function walkAndMaterialiseLoops(node, duration) {
2818
3486
  const animDef = animBucket;
2819
3487
  for (const propName of Object.keys(animDef)) {
2820
3488
  const propAnim = animDef[propName];
2821
- const materialised = materialiseInternalLoopsInPropAnim(propName, propAnim, duration);
2822
- if (materialised !== propAnim) {
3489
+ const materialized = materializeInternalLoopsInPropAnim(propName, propAnim, duration);
3490
+ if (materialized !== propAnim) {
2823
3491
  if (!newAnimate) newAnimate = __spreadValues({}, animDef);
2824
- newAnimate[propName] = materialised;
3492
+ newAnimate[propName] = materialized;
2825
3493
  }
2826
3494
  }
2827
3495
  }
@@ -2840,7 +3508,7 @@ function mergeStaticTransformIntoAnimDef(animDef, staticTransform) {
2840
3508
  const staticParts = staticTransform && typeof staticTransform === "object" && !Array.isArray(staticTransform) ? staticTransform : parseTransformParts(staticTransform);
2841
3509
  if (!staticParts || !Object.keys(staticParts).length) return animDef;
2842
3510
  const mergeKfValue = (v) => v && typeof v === "object" && !Array.isArray(v) ? __spreadValues(__spreadValues({}, staticParts), v) : v;
2843
- const transformAnim = animDef["transform"];
3511
+ const transformAnim = animDef[TRANSFORM_ATTR];
2844
3512
  if (transformAnim && typeof transformAnim === "object") {
2845
3513
  const anim = transformAnim;
2846
3514
  if (Array.isArray(anim.keyframes)) {
@@ -2865,7 +3533,7 @@ function mergeStaticTransformIntoAnimDef(animDef, staticTransform) {
2865
3533
  delete rest[ch];
2866
3534
  return __spreadProps(__spreadValues({}, rest), { transform: lifted });
2867
3535
  }
2868
- function normalizeAnimationDefinition(animDef, duration, defs, engine = PxAnimatorEngine.waapi) {
3536
+ function normalizeAnimationDefinition(animDef, duration, defs, engine = PxTimelineEngine.native) {
2869
3537
  const normalized = {};
2870
3538
  for (const [propName, propAnim] of Object.entries(animDef)) {
2871
3539
  if (propName === "transform" && propAnim.alongPathMode === "offsetPath" && animDef["offsetDistance"] !== void 0) {
@@ -2876,12 +3544,12 @@ function normalizeAnimationDefinition(animDef, duration, defs, engine = PxAnimat
2876
3544
  const out = { keyframes: normalizedKfs };
2877
3545
  if (propAnim.autoOrient !== void 0) out.autoOrient = propAnim.autoOrient;
2878
3546
  if (propAnim.loop !== void 0) out.loop = propAnim.loop;
2879
- normalized[propName] = engine === PxAnimatorEngine.waapi && propName === "transform" ? materialiseMotionPathInPropAnim(out) : out;
3547
+ normalized[propName] = engine === PxTimelineEngine.native && propName === "transform" ? materializeMotionPathInPropAnim(out) : out;
2880
3548
  }
2881
3549
  }
2882
3550
  return normalized;
2883
3551
  }
2884
- function getNormalisedBindings(doc, engine = PxAnimatorEngine.waapi) {
3552
+ function getNormalizedBindings(doc, engine = PxTimelineEngine.native) {
2885
3553
  const animatorConfig = getAnimatorConfig(doc) || {};
2886
3554
  const defs = getDefs(doc);
2887
3555
  const duration = animatorConfig.duration || 1e3;
@@ -2927,12 +3595,12 @@ function getNormalisedBindings(doc, engine = PxAnimatorEngine.waapi) {
2927
3595
  return bindings;
2928
3596
  }
2929
3597
  function getKeyframesPair(keyframes, progress) {
2930
- var _a, _b;
3598
+ var _a2, _b;
2931
3599
  const last = keyframes.length - 1;
2932
3600
  let prevKf = keyframes[0];
2933
3601
  let nextKf = keyframes[last > 0 ? 1 : 0];
2934
3602
  for (let j = 0; j < last; j++) {
2935
- const aOff = (_a = keyframes[j].t) != null ? _a : 0;
3603
+ const aOff = (_a2 = keyframes[j].t) != null ? _a2 : 0;
2936
3604
  const bOff = (_b = keyframes[j + 1].t) != null ? _b : 0;
2937
3605
  if (aOff <= progress && progress <= bOff) {
2938
3606
  prevKf = keyframes[j];
@@ -2947,13 +3615,13 @@ function getKeyframesPair(keyframes, progress) {
2947
3615
  return { prevKf, nextKf };
2948
3616
  }
2949
3617
  function calcPropertyValue(propName, propAnim, progress) {
2950
- var _a, _b, _c, _d, _e, _f, _g;
3618
+ var _a2, _b, _c, _d;
2951
3619
  const keyframes = propAnim.keyframes || [];
2952
3620
  if (keyframes.length === 0) return null;
2953
3621
  const { prevKf, nextKf } = getKeyframesPair(keyframes, progress);
2954
- let localProgress = prevKf === nextKf ? 0 : remap(progress, (_a = prevKf.t) != null ? _a : 0, (_b = nextKf.t) != null ? _b : 0, 0, 1);
3622
+ let localProgress = prevKf === nextKf ? 0 : remap(progress, (_a2 = prevKf.t) != null ? _a2 : 0, (_b = nextKf.t) != null ? _b : 0, 0, 1);
2955
3623
  localProgress = clamp(localProgress, 0, 1);
2956
- const easing = (_c = prevKf.e) != null ? _c : prevKf.easing;
3624
+ const easing = kfEasing(prevKf);
2957
3625
  if (easing && Array.isArray(easing)) {
2958
3626
  try {
2959
3627
  localProgress = cubicBezier(easing)(localProgress);
@@ -2962,17 +3630,17 @@ function calcPropertyValue(propName, propAnim, progress) {
2962
3630
  }
2963
3631
  let cssAttrName = isCamelCaseWord(propName) ? camelCaseToKebabWordIfNeeded(propName) : propName;
2964
3632
  let cssValue = null;
2965
- const prevV = (_d = prevKf == null ? void 0 : prevKf.v) != null ? _d : prevKf == null ? void 0 : prevKf.value;
2966
- const nextV = (_e = nextKf == null ? void 0 : nextKf.v) != null ? _e : nextKf == null ? void 0 : nextKf.value;
3633
+ const prevV = prevKf == null ? void 0 : prevKf.v;
3634
+ const nextV = nextKf == null ? void 0 : nextKf.v;
2967
3635
  if (cssAttrName === "d") {
2968
- const prevPaths = (_f = prevV == null ? void 0 : prevV.paths) != null ? _f : Array.isArray(prevV) ? prevV : [];
2969
- const nextPaths = (_g = nextV == null ? void 0 : nextV.paths) != null ? _g : Array.isArray(nextV) ? nextV : [];
3636
+ const prevPaths = (_c = prevV == null ? void 0 : prevV.paths) != null ? _c : Array.isArray(prevV) ? prevV : [];
3637
+ const nextPaths = (_d = nextV == null ? void 0 : nextV.paths) != null ? _d : Array.isArray(nextV) ? nextV : [];
2970
3638
  cssValue = interpolateBeziers(
2971
3639
  prevPaths,
2972
3640
  nextPaths,
2973
3641
  localProgress
2974
3642
  ).map((bz) => bezierToSvgPath(bz)).join("");
2975
- } else if (COLOUR_ATTR_NAMES.has(cssAttrName)) {
3643
+ } else if (COLOR_ATTR_NAMES.has(cssAttrName)) {
2976
3644
  cssValue = toRGBA(interpolateColor(
2977
3645
  prevV || [0, 0, 0, 1],
2978
3646
  nextV || [0, 0, 0, 1],
@@ -3069,7 +3737,7 @@ function calcAnimationValues(animDef, progress) {
3069
3737
  return result;
3070
3738
  }
3071
3739
 
3072
- // src/PxNodeCloneUtil.ts
3740
+ // src/util/PxNodeCloneUtil.ts
3073
3741
  function deepClonePxNode(value) {
3074
3742
  if (value === null || typeof value !== "object") return value;
3075
3743
  if (Array.isArray(value)) return value.map(deepClonePxNode);
@@ -3080,13 +3748,13 @@ function deepClonePxNode(value) {
3080
3748
  function regenerateIdsAndRewriteRefs(root, genId3) {
3081
3749
  const oldToNew = /* @__PURE__ */ new Map();
3082
3750
  const walkAssign = (n) => {
3083
- var _a;
3751
+ var _a2;
3084
3752
  if (typeof n.id === "string") {
3085
3753
  const newId = genId3();
3086
3754
  oldToNew.set(n.id, newId);
3087
3755
  n.id = newId;
3088
3756
  }
3089
- (_a = n.children) == null ? void 0 : _a.forEach(walkAssign);
3757
+ (_a2 = n.children) == null ? void 0 : _a2.forEach(walkAssign);
3090
3758
  };
3091
3759
  walkAssign(root);
3092
3760
  const rewriteUrl = (s) => s.replace(/url\(#([^)]+)\)/g, (m, oldId) => {
@@ -3094,7 +3762,7 @@ function regenerateIdsAndRewriteRefs(root, genId3) {
3094
3762
  return newId ? "url(#" + newId + ")" : m;
3095
3763
  });
3096
3764
  const walkRewrite = (n) => {
3097
- var _a;
3765
+ var _a2;
3098
3766
  if (typeof n.href === "string" && n.href.startsWith("#")) {
3099
3767
  const newId = oldToNew.get(n.href.slice(1));
3100
3768
  if (newId) n.href = "#" + newId;
@@ -3106,7 +3774,7 @@ function regenerateIdsAndRewriteRefs(root, genId3) {
3106
3774
  n[k] = rewriteUrl(v);
3107
3775
  }
3108
3776
  }
3109
- (_a = n.children) == null ? void 0 : _a.forEach(walkRewrite);
3777
+ (_a2 = n.children) == null ? void 0 : _a2.forEach(walkRewrite);
3110
3778
  };
3111
3779
  walkRewrite(root);
3112
3780
  return oldToNew;
@@ -3116,7 +3784,7 @@ function toFiniteNum(v) {
3116
3784
  return Number.isFinite(n) ? n : 0;
3117
3785
  }
3118
3786
  function applyUseOffsetToG(gNode) {
3119
- var _a;
3787
+ var _a2;
3120
3788
  const x = toFiniteNum(gNode.x);
3121
3789
  const y = toFiniteNum(gNode.y);
3122
3790
  delete gNode.x;
@@ -3125,7 +3793,7 @@ function applyUseOffsetToG(gNode) {
3125
3793
  const offset = "translate(" + x + "," + y + ")";
3126
3794
  const carriesTransform = gNode.transform !== void 0 || gNode.animate !== void 0;
3127
3795
  if (carriesTransform) {
3128
- const inner = { type: "g", transform: offset, children: (_a = gNode.children) != null ? _a : [] };
3796
+ const inner = { type: "g", transform: offset, children: (_a2 = gNode.children) != null ? _a2 : [] };
3129
3797
  gNode.children = [inner];
3130
3798
  } else {
3131
3799
  gNode.transform = offset;
@@ -3133,9 +3801,9 @@ function applyUseOffsetToG(gNode) {
3133
3801
  return gNode;
3134
3802
  }
3135
3803
 
3136
- // src/PxAnimatorUseMaterialiser.ts
3137
- function materialiseAnimatedUseInstances(root) {
3138
- var _a;
3804
+ // src/materialize/PxAnimatorUseMaterializer.ts
3805
+ function materializeAnimatedUseInstances(root) {
3806
+ var _a2;
3139
3807
  const idMap = buildIdMap(root);
3140
3808
  const animatedIds = computeAnimatedSubtreeIds(root, idMap);
3141
3809
  if (animatedIds.size === 0) return root;
@@ -3143,10 +3811,10 @@ function materialiseAnimatedUseInstances(root) {
3143
3811
  const genId3 = () => "_lw_use_mat_" + ++idCounter;
3144
3812
  const rootViewport = readRootViewport(root);
3145
3813
  const defsCollector = [];
3146
- const walked = walkAndMaterialise2(root, idMap, animatedIds, genId3, defsCollector, rootViewport);
3814
+ const walked = walkAndMaterialize2(root, idMap, animatedIds, genId3, defsCollector, rootViewport);
3147
3815
  if (defsCollector.length === 0) return walked;
3148
3816
  const defsNode = { type: "defs", children: defsCollector };
3149
- const newChildren = [...(_a = walked.children) != null ? _a : [], defsNode];
3817
+ const newChildren = [...(_a2 = walked.children) != null ? _a2 : [], defsNode];
3150
3818
  return __spreadProps(__spreadValues({}, walked), { children: newChildren });
3151
3819
  }
3152
3820
  function readRootViewport(root) {
@@ -3168,9 +3836,9 @@ function numericAttr(v) {
3168
3836
  function buildIdMap(root) {
3169
3837
  const map = /* @__PURE__ */ new Map();
3170
3838
  const visit = (n) => {
3171
- var _a;
3839
+ var _a2;
3172
3840
  if (typeof n.id === "string") map.set(n.id, n);
3173
- (_a = n.children) == null ? void 0 : _a.forEach(visit);
3841
+ (_a2 = n.children) == null ? void 0 : _a2.forEach(visit);
3174
3842
  };
3175
3843
  visit(root);
3176
3844
  return map;
@@ -3216,16 +3884,16 @@ function stripHash(href) {
3216
3884
  if (typeof href !== "string") return void 0;
3217
3885
  return href.startsWith("#") ? href.slice(1) : href;
3218
3886
  }
3219
- function materialiseOneUse(useNode, target, idMap, animatedIds, genId3, defsCollector, rootViewport) {
3220
- var _a, _b, _c, _d;
3887
+ function materializeOneUse(useNode, target, idMap, animatedIds, genId3, defsCollector, rootViewport) {
3888
+ var _a2, _b, _c, _d;
3221
3889
  const clone2 = deepClonePxNode(target);
3222
3890
  regenerateIdsAndRewriteRefs(clone2, genId3);
3223
3891
  const symbolViewBox = clone2.type === "symbol" ? parseViewBox(clone2.viewBox) : void 0;
3224
- const useW = (_b = (_a = numericAttr(useNode.width)) != null ? _a : symbolViewBox == null ? void 0 : symbolViewBox[2]) != null ? _b : rootViewport[0];
3892
+ const useW = (_b = (_a2 = numericAttr(useNode.width)) != null ? _a2 : symbolViewBox == null ? void 0 : symbolViewBox[2]) != null ? _b : rootViewport[0];
3225
3893
  const useH = (_d = (_c = numericAttr(useNode.height)) != null ? _c : symbolViewBox == null ? void 0 : symbolViewBox[3]) != null ? _d : rootViewport[1];
3226
3894
  const rewrittenClone = clone2.type === "symbol" ? rewriteSymbolRootToGroup(clone2, genId3, defsCollector, useW, useH) : clone2;
3227
- const materialisedClone = walkAndMaterialise2(rewrittenClone, idMap, animatedIds, genId3, defsCollector, rootViewport);
3228
- const newNode = __spreadProps(__spreadValues({}, useNode), { type: "g", children: [materialisedClone] });
3895
+ const materializedClone = walkAndMaterialize2(rewrittenClone, idMap, animatedIds, genId3, defsCollector, rootViewport);
3896
+ const newNode = __spreadProps(__spreadValues({}, useNode), { type: "g", children: [materializedClone] });
3229
3897
  delete newNode.href;
3230
3898
  delete newNode.width;
3231
3899
  delete newNode.height;
@@ -3263,25 +3931,25 @@ function parseViewBox(v) {
3263
3931
  if (parts.length < 4 || parts.some((n) => !Number.isFinite(n))) return void 0;
3264
3932
  return [parts[0], parts[1], parts[2], parts[3]];
3265
3933
  }
3266
- function walkAndMaterialise2(node, idMap, animatedIds, genId3, defsCollector, rootViewport) {
3934
+ function walkAndMaterialize2(node, idMap, animatedIds, genId3, defsCollector, rootViewport) {
3267
3935
  if (node.type === "use" && typeof node.href === "string") {
3268
3936
  const targetId = stripHash(node.href);
3269
3937
  if (targetId && animatedIds.has(targetId)) {
3270
3938
  const target = idMap.get(targetId);
3271
- if (target) return materialiseOneUse(node, target, idMap, animatedIds, genId3, defsCollector, rootViewport);
3939
+ if (target) return materializeOneUse(node, target, idMap, animatedIds, genId3, defsCollector, rootViewport);
3272
3940
  }
3273
3941
  }
3274
3942
  if (!node.children) return node;
3275
3943
  let changed = false;
3276
3944
  const newChildren = node.children.map((ch) => {
3277
- const m = walkAndMaterialise2(ch, idMap, animatedIds, genId3, defsCollector, rootViewport);
3945
+ const m = walkAndMaterialize2(ch, idMap, animatedIds, genId3, defsCollector, rootViewport);
3278
3946
  if (m !== ch) changed = true;
3279
3947
  return m;
3280
3948
  });
3281
3949
  return changed ? __spreadProps(__spreadValues({}, node), { children: newChildren }) : node;
3282
3950
  }
3283
3951
 
3284
- // src/effects/transformParts.ts
3952
+ // src/effects/shared/transformParts.ts
3285
3953
  function partsRecord(part, value, origin) {
3286
3954
  const rec = {};
3287
3955
  if (part === "translate" /* Translate */) rec.translate = value;
@@ -3292,25 +3960,25 @@ function partsRecord(part, value, origin) {
3292
3960
  return rec;
3293
3961
  }
3294
3962
  function readAnimatable(raw) {
3295
- var _a, _b, _c;
3963
+ var _a2, _b;
3296
3964
  if (raw === void 0) return { kind: "absent" /* Absent */ };
3297
3965
  if (Array.isArray(raw)) return { kind: "static" /* Static */, value: raw };
3298
3966
  if (typeof raw === "object") {
3299
3967
  const obj = raw;
3300
- const kfs = (_a = obj.keyframes) != null ? _a : obj.kfs;
3968
+ const kfs = obj.keyframes;
3301
3969
  if (kfs) {
3302
- const out = { kind: "animated" /* Animated */, keyframes: kfs.map(normaliseKeyframe), autoOrient: obj.autoOrient, loop: obj.loop };
3303
- const base = (_b = obj.value) != null ? _b : obj.v;
3970
+ const out = { kind: "animated" /* Animated */, keyframes: kfs.map(normalizeKeyframe), autoOrient: obj.autoOrient, loop: obj.loop };
3971
+ const base = (_a2 = obj.value) != null ? _a2 : obj.v;
3304
3972
  if (base !== void 0 && out.kind === "animated" /* Animated */) out.base = base;
3305
3973
  return out;
3306
3974
  }
3307
- const staticValue = (_c = obj.value) != null ? _c : obj.v;
3975
+ const staticValue = (_b = obj.value) != null ? _b : obj.v;
3308
3976
  if (staticValue !== void 0) return { kind: "static" /* Static */, value: staticValue };
3309
3977
  }
3310
3978
  return { kind: "static" /* Static */, value: raw };
3311
3979
  }
3312
3980
  function writeAnimatableChannel(node, attrName, read, opts) {
3313
- var _a, _b, _c, _d;
3981
+ var _a2, _b, _c, _d;
3314
3982
  const toOut = (v) => (opts == null ? void 0 : opts.asString) && v !== void 0 && v !== null ? String(v) : v;
3315
3983
  if (read.kind === "absent" /* Absent */) return;
3316
3984
  if (read.kind === "static" /* Static */) {
@@ -3324,10 +3992,10 @@ function writeAnimatableChannel(node, attrName, read, opts) {
3324
3992
  if (read.autoOrient !== void 0) block.autoOrient = read.autoOrient;
3325
3993
  animate[attrName] = block;
3326
3994
  node.animate = animate;
3327
- const baseline = (_d = (_b = read.base) != null ? _b : (_a = read.keyframes[0]) == null ? void 0 : _a.value) != null ? _d : (_c = read.keyframes[0]) == null ? void 0 : _c.v;
3995
+ const baseline = (_d = (_b = read.base) != null ? _b : (_a2 = read.keyframes[0]) == null ? void 0 : _a2.value) != null ? _d : (_c = read.keyframes[0]) == null ? void 0 : _c.v;
3328
3996
  if (baseline !== void 0) node[attrName] = toOut(baseline);
3329
3997
  }
3330
- function normaliseKeyframe(kf) {
3998
+ function normalizeKeyframe(kf) {
3331
3999
  if (!kf || typeof kf !== "object") return kf;
3332
4000
  const k = kf;
3333
4001
  if (k.t === void 0 && k.v === void 0 && k.e === void 0 && k.to === void 0 && k.ti === void 0) {
@@ -3342,12 +4010,12 @@ function normaliseKeyframe(kf) {
3342
4010
  return out;
3343
4011
  }
3344
4012
  function readStaticOrigin(raw, ctx) {
3345
- var _a;
4013
+ var _a2;
3346
4014
  const o = readAnimatable(raw);
3347
4015
  if (o.kind === "absent" /* Absent */) return void 0;
3348
4016
  if (o.kind === "static" /* Static */) return o.value;
3349
4017
  ctx.warnings.push("transformBy.origin: animated origin approximated by its first keyframe");
3350
- return (_a = o.keyframes[0]) == null ? void 0 : _a.value;
4018
+ return (_a2 = o.keyframes[0]) == null ? void 0 : _a2.value;
3351
4019
  }
3352
4020
  function keyframeWith(kf, value) {
3353
4021
  const out = { value };
@@ -3358,7 +4026,7 @@ function keyframeWith(kf, value) {
3358
4026
  return out;
3359
4027
  }
3360
4028
 
3361
- // src/effects/transformationEffect.ts
4029
+ // src/effects/transform/transformationEffect.ts
3362
4030
  function applyTransformByEffect(node, fx, ctx) {
3363
4031
  if (!fx) return node;
3364
4032
  delete node.transform;
@@ -3449,7 +4117,7 @@ function wrapOrigin(inner, raw, invert) {
3449
4117
  return inner;
3450
4118
  }
3451
4119
 
3452
- // src/effects/util.ts
4120
+ // src/effects/shared/util.ts
3453
4121
  function genId(ctx, prefix) {
3454
4122
  return "_lw_" + prefix + "_" + ctx.nextId++;
3455
4123
  }
@@ -3457,9 +4125,9 @@ function stripHash2(href) {
3457
4125
  return typeof href === "string" ? href.replace(/^#/, "") : void 0;
3458
4126
  }
3459
4127
  function indexById(node, map) {
3460
- var _a;
4128
+ var _a2;
3461
4129
  if (typeof node.id === "string") map.set(node.id, node);
3462
- (_a = node.children) == null ? void 0 : _a.forEach((child) => indexById(child, map));
4130
+ (_a2 = node.children) == null ? void 0 : _a2.forEach((child) => indexById(child, map));
3463
4131
  }
3464
4132
  function spliceDefs(root, defs) {
3465
4133
  if (!defs.length) return;
@@ -3471,11 +4139,11 @@ function regenerateIdsInClone(root, ctx) {
3471
4139
  return regenerateIdsAndRewriteRefs(root, () => genId(ctx, "retimed"));
3472
4140
  }
3473
4141
 
3474
- // src/effects/contentRefSplit.ts
4142
+ // src/effects/reference/contentRefSplit.ts
3475
4143
  function identifyContentRefTargets(node, ctx, allocator) {
3476
- var _a, _b, _c;
3477
- if (node.type === "use" && ((_b = (_a = node.effects) == null ? void 0 : _a.clone) == null ? void 0 : _b.type) === "content") {
3478
- const sourceId = stripHash2(node.effects.clone.sourceId);
4144
+ var _a2, _b, _c;
4145
+ if (node.type === "use" && ((_b = (_a2 = node.effects) == null ? void 0 : _a2.clone) == null ? void 0 : _b.without) === "translate") {
4146
+ const sourceId = stripHash2(node.effects.clone.source);
3479
4147
  if (typeof sourceId === "string" && sourceId && !ctx.contentRefInnerIds.has(sourceId)) {
3480
4148
  ctx.contentRefInnerIds.set(sourceId, allocator(sourceId));
3481
4149
  }
@@ -3500,10 +4168,10 @@ function splitForContentRef(node, transformBy, originalId, innerId, ctx) {
3500
4168
  return outerWrapper;
3501
4169
  }
3502
4170
  function liftBodyTranslate(node, transformBy) {
3503
- var _a, _b, _c;
4171
+ var _a2, _b, _c;
3504
4172
  const out = {};
3505
4173
  let didLiftAnimate = false;
3506
- const animTr = (_a = node.animate) == null ? void 0 : _a.transform;
4174
+ const animTr = (_a2 = node.animate) == null ? void 0 : _a2.transform;
3507
4175
  if (animTr && typeof animTr === "object" && Array.isArray(animTr.keyframes)) {
3508
4176
  const kfs = animTr.keyframes;
3509
4177
  const hasTranslate = kfs.some((kf) => kf.value && kf.value.translate);
@@ -3686,7 +4354,7 @@ function needsOriginOnOuter(translateAnim) {
3686
4354
  return false;
3687
4355
  }
3688
4356
 
3689
- // src/effects/gradientEffect.ts
4357
+ // src/effects/paint/gradientEffect.ts
3690
4358
  function applyFillGradientEffect(node, fx, ctx) {
3691
4359
  return applyGradient(node, fx, ctx, "fill");
3692
4360
  }
@@ -3721,7 +4389,7 @@ function synthesiseGradientDef(fx, id, ctx) {
3721
4389
  return out;
3722
4390
  }
3723
4391
  function applyGeomVec(out, xAttr, yAttr, raw) {
3724
- var _a, _b, _c;
4392
+ var _a2, _b, _c;
3725
4393
  const read = readAnimatable(raw);
3726
4394
  if (read.kind === "absent" /* Absent */) return;
3727
4395
  if (read.kind === "static" /* Static */) {
@@ -3740,7 +4408,7 @@ function applyGeomVec(out, xAttr, yAttr, raw) {
3740
4408
  if (read.loop !== void 0) block.loop = read.loop;
3741
4409
  return block;
3742
4410
  };
3743
- const animate = (_a = out.animate) != null ? _a : {};
4411
+ const animate = (_a2 = out.animate) != null ? _a2 : {};
3744
4412
  animate[xAttr] = axisChannel(0);
3745
4413
  animate[yAttr] = axisChannel(1);
3746
4414
  out.animate = animate;
@@ -3756,7 +4424,7 @@ function applyGeomNumber(out, attrName, raw) {
3756
4424
  writeAnimatableChannel(out, attrName, read, { asString: true });
3757
4425
  }
3758
4426
  function buildStopChildren(stops, ctx) {
3759
- var _a, _b, _c, _d;
4427
+ var _a2, _b;
3760
4428
  if (!stops) return [];
3761
4429
  const read = readAnimatable(stops);
3762
4430
  if (read.kind === "absent" /* Absent */) return [];
@@ -3766,14 +4434,14 @@ function buildStopChildren(stops, ctx) {
3766
4434
  const loopFromSource = read.loop;
3767
4435
  let stopCount = 0;
3768
4436
  for (const kf of kfs) {
3769
- const v = (_a = kf.value) != null ? _a : kf.v;
4437
+ const v = kfValue(kf);
3770
4438
  if (Array.isArray(v) && v.length > stopCount) stopCount = v.length;
3771
4439
  }
3772
4440
  if (!stopCount) return [];
3773
- const firstKfValue = (_b = kfs[0].value) != null ? _b : kfs[0].v;
4441
+ const firstKfValue = kfValue(kfs[0]);
3774
4442
  const baselineStops = [];
3775
4443
  for (let i = 0; i < stopCount; i++) {
3776
- 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" };
4444
+ const s = (_b = (_a2 = firstKfValue == null ? void 0 : firstKfValue[i]) != null ? _a2 : prevDefinedStop(kfs, 0, i)) != null ? _b : { offset: i / Math.max(1, stopCount - 1), color: "#000000" };
3777
4445
  baselineStops.push({ offset: s.offset, color: s.color });
3778
4446
  }
3779
4447
  return baselineStops.map((bs, i) => animatedStopNode(bs, kfs, i, ctx, loopFromSource));
@@ -3786,16 +4454,16 @@ function staticStopNode(s) {
3786
4454
  };
3787
4455
  }
3788
4456
  function animatedStopNode(baseline, kfs, stopIdx, _ctx, loop) {
3789
- var _a, _b, _c, _d, _e;
4457
+ var _a2;
3790
4458
  const colorKfs = [];
3791
4459
  const offsetKfs = [];
3792
4460
  let offsetVaries = false;
3793
4461
  for (const kf of kfs) {
3794
- const t = (_b = (_a = kf.time) != null ? _a : kf.t) != null ? _b : 0;
3795
- const arr = (_c = kf.value) != null ? _c : kf.v;
3796
- const sliced = (_d = arr == null ? void 0 : arr[stopIdx]) != null ? _d : prevDefinedStop(kfs, kfs.indexOf(kf), stopIdx);
4462
+ const t = kfTime(kf);
4463
+ const arr = kfValue(kf);
4464
+ const sliced = (_a2 = arr == null ? void 0 : arr[stopIdx]) != null ? _a2 : prevDefinedStop(kfs, kfs.indexOf(kf), stopIdx);
3797
4465
  if (!sliced) continue;
3798
- const easing = (_e = kf.easing) != null ? _e : kf.e;
4466
+ const easing = kfEasing(kf);
3799
4467
  const colorOut = { time: t, value: sliced.color };
3800
4468
  if (easing !== void 0) colorOut.easing = easing;
3801
4469
  colorKfs.push(colorOut);
@@ -3822,13 +4490,12 @@ function animatedStopNode(baseline, kfs, stopIdx, _ctx, loop) {
3822
4490
  return stop;
3823
4491
  }
3824
4492
  function prevDefinedStop(kfs, fromIdx, stopIdx) {
3825
- var _a, _b;
3826
4493
  for (let i = fromIdx; i >= 0; i--) {
3827
- const arr = (_a = kfs[i].value) != null ? _a : kfs[i].v;
4494
+ const arr = kfValue(kfs[i]);
3828
4495
  if (arr == null ? void 0 : arr[stopIdx]) return arr[stopIdx];
3829
4496
  }
3830
4497
  for (let i = fromIdx + 1; i < kfs.length; i++) {
3831
- const arr = (_b = kfs[i].value) != null ? _b : kfs[i].v;
4498
+ const arr = kfValue(kfs[i]);
3832
4499
  if (arr == null ? void 0 : arr[stopIdx]) return arr[stopIdx];
3833
4500
  }
3834
4501
  return void 0;
@@ -3838,12 +4505,12 @@ function formatOffset(o) {
3838
4505
  return pct + "%";
3839
4506
  }
3840
4507
 
3841
- // src/effects/clipPathEffect.ts
4508
+ // src/effects/clipping/clipPathEffect.ts
3842
4509
  function applyClipPathEffect(node, fx, ctx) {
3843
- if (!(fx == null ? void 0 : fx.d)) return node;
4510
+ if (!(fx == null ? void 0 : fx.pathData)) return node;
3844
4511
  const clipId = genId(ctx, "clip");
3845
4512
  const pathChild = { type: "path" };
3846
- const read = readAnimatable(fx.d);
4513
+ const read = readAnimatable(fx.pathData);
3847
4514
  if (read.kind !== "absent" /* Absent */) {
3848
4515
  if (read.kind === "static" /* Static */) {
3849
4516
  pathChild.d = pathString(read.value);
@@ -3858,16 +4525,16 @@ function applyClipPathEffect(node, fx, ctx) {
3858
4525
  }
3859
4526
  function pathString(v) {
3860
4527
  if (typeof v === "string") return v;
3861
- if (v && typeof v === "object" && typeof v.path === "string") return v.path;
4528
+ if (v && typeof v === "object" && typeof v.pathData === "string") return v.pathData;
3862
4529
  return void 0;
3863
4530
  }
3864
4531
 
3865
- // src/effects/maskedByEffect.ts
4532
+ // src/effects/clipping/maskedByEffect.ts
3866
4533
  function applyMaskedByEffect(node, fx, transformBy, ctx) {
3867
4534
  if (!fx) return node;
3868
- const sourceId = stripHash2(fx.sourceId);
4535
+ const sourceId = stripHash2(fx.source);
3869
4536
  if (!sourceId) {
3870
- ctx.errors.push("maskedBy.sourceId missing \u2014 cannot build mask");
4537
+ ctx.errors.push("maskedBy.source missing \u2014 cannot build mask");
3871
4538
  return node;
3872
4539
  }
3873
4540
  const maskId = genId(ctx, "mask");
@@ -3905,8 +4572,8 @@ function wrapInverseTransform(inner, fx, ctx) {
3905
4572
  }
3906
4573
  function wrapInversePart(inner, part, raw, origin, ctx) {
3907
4574
  if (raw === void 0) return inner;
3908
- const normalisedRaw = part === "scale" /* Scale */ && Array.isArray(raw) ? [raw[0] / 100, raw[1] / 100] : raw;
3909
- const v = readAnimatable(normalisedRaw);
4575
+ const normalizedRaw = part === "scale" /* Scale */ && Array.isArray(raw) ? [raw[0] / 100, raw[1] / 100] : raw;
4576
+ const v = readAnimatable(normalizedRaw);
3910
4577
  if (v.kind === "static" /* Static */) {
3911
4578
  return { type: "g", transform: { value: partsRecord(part, invertPartValue(part, v.value), origin) }, children: [inner] };
3912
4579
  }
@@ -3930,16 +4597,16 @@ function invertPartValue(part, value) {
3930
4597
  return [1 / value[0], 1 / value[1]];
3931
4598
  }
3932
4599
  function negatedSpatialTangents(kf) {
3933
- var _a, _b;
4600
+ var _a2, _b;
3934
4601
  const out = {};
3935
- const to = (_a = kf.tangentOut) != null ? _a : kf.to;
4602
+ const to = (_a2 = kf.tangentOut) != null ? _a2 : kf.to;
3936
4603
  const ti = (_b = kf.tangentIn) != null ? _b : kf.ti;
3937
4604
  if (Array.isArray(to)) out.tangentOut = [-to[0], -to[1]];
3938
4605
  if (Array.isArray(ti)) out.tangentIn = [-ti[0], -ti[1]];
3939
4606
  return out;
3940
4607
  }
3941
4608
  function wrapInverseAnimatedBodyTransform(inner, node, _ctx) {
3942
- var _a;
4609
+ var _a2;
3943
4610
  const animate = node.animate && typeof node.animate === "object" && !Array.isArray(node.animate) ? node.animate : void 0;
3944
4611
  const animTr = animate == null ? void 0 : animate.transform;
3945
4612
  const kfs = animTr && typeof animTr === "object" && Array.isArray(animTr.keyframes) ? animTr.keyframes : void 0;
@@ -3948,7 +4615,7 @@ function wrapInverseAnimatedBodyTransform(inner, node, _ctx) {
3948
4615
  const rotateKfs = [];
3949
4616
  const scaleKfs = [];
3950
4617
  for (const kf of kfs) {
3951
- const v = ((_a = kf.value) != null ? _a : kf.v) || {};
4618
+ const v = ((_a2 = kf.value) != null ? _a2 : kf.v) || {};
3952
4619
  const baseKf = keyframeWith(kf, void 0);
3953
4620
  if (Array.isArray(v.translate)) {
3954
4621
  translateKfs.push(__spreadProps(__spreadValues(__spreadValues({}, baseKf), negatedSpatialTangents(kf)), { value: { translate: [-v.translate[0], -v.translate[1]] } }));
@@ -4012,7 +4679,7 @@ function readTransformationFromBody(node) {
4012
4679
  return void 0;
4013
4680
  }
4014
4681
  function parseTransformStringToParts(s) {
4015
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m;
4682
+ var _a2, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m;
4016
4683
  const re = /([a-zA-Z]+)\s*\(([^)]*)\)/g;
4017
4684
  let m;
4018
4685
  const ops = [];
@@ -4026,7 +4693,7 @@ function parseTransformStringToParts(s) {
4026
4693
  for (let j = ops.length - 2; j >= 0; j--) {
4027
4694
  const cand = ops[j];
4028
4695
  if (cand.name !== "translate") continue;
4029
- const ox = (_a = cand.args[0]) != null ? _a : 0;
4696
+ const ox = (_a2 = cand.args[0]) != null ? _a2 : 0;
4030
4697
  const oy = (_b = cand.args[1]) != null ? _b : 0;
4031
4698
  const lx = (_c = last.args[0]) != null ? _c : 0;
4032
4699
  const ly = (_d = last.args[1]) != null ? _d : 0;
@@ -4141,8 +4808,8 @@ function interpKfs(kfs, t) {
4141
4808
  function collectMaskAncestorChains(root, ctx) {
4142
4809
  const interestingNodes = /* @__PURE__ */ new Set();
4143
4810
  const collectInterestingNodes = (n) => {
4144
- var _a, _b;
4145
- const maskSourceId = stripHash2((_b = (_a = n.effects) == null ? void 0 : _a.maskedBy) == null ? void 0 : _b.sourceId);
4811
+ var _a2, _b;
4812
+ const maskSourceId = stripHash2((_b = (_a2 = n.effects) == null ? void 0 : _a2.maskedBy) == null ? void 0 : _b.source);
4146
4813
  if (typeof maskSourceId === "string") {
4147
4814
  interestingNodes.add(n);
4148
4815
  const sourceNode = ctx.idMap.get(maskSourceId);
@@ -4163,7 +4830,7 @@ function collectMaskAncestorChains(root, ctx) {
4163
4830
  walk(root, []);
4164
4831
  }
4165
4832
  function extractTranslateOnly(node, ctx) {
4166
- var _a, _b, _c;
4833
+ var _a2, _b, _c;
4167
4834
  const tr = node.transform;
4168
4835
  const animateBlock = node.animate && typeof node.animate === "object" && !Array.isArray(node.animate) ? node.animate.transform : void 0;
4169
4836
  if (tr === void 0 && !animateBlock) return void 0;
@@ -4171,7 +4838,7 @@ function extractTranslateOnly(node, ctx) {
4171
4838
  if (typeof tr === "string") {
4172
4839
  const parts = parseTranslateOnlyFromString(tr, ctx);
4173
4840
  if (parts) out.translate = parts;
4174
- } else if (tr && typeof tr === "object" && !tr.keyframes && !tr.kfs) {
4841
+ } else if (tr && typeof tr === "object" && !tr.keyframes) {
4175
4842
  const wrapped = tr.value;
4176
4843
  const value = wrapped && typeof wrapped === "object" ? wrapped : tr;
4177
4844
  if (value && typeof value === "object" && Array.isArray(value.translate)) {
@@ -4185,7 +4852,7 @@ function extractTranslateOnly(node, ctx) {
4185
4852
  const kfs = animateBlock.keyframes;
4186
4853
  const translateKfs = [];
4187
4854
  for (const kf of kfs) {
4188
- const v = (_a = kf.value) != null ? _a : kf.v;
4855
+ const v = (_a2 = kf.value) != null ? _a2 : kf.v;
4189
4856
  const t = (_c = (_b = kf.time) != null ? _b : kf.t) != null ? _c : 0;
4190
4857
  if (v && typeof v === "object" && Array.isArray(v.translate)) {
4191
4858
  translateKfs.push({ time: t, value: [v.translate[0] || 0, v.translate[1] || 0] });
@@ -4219,16 +4886,15 @@ function parseTranslateOnlyFromString(s, ctx) {
4219
4886
  return seen ? [x, y] : void 0;
4220
4887
  }
4221
4888
 
4222
- // src/effects/refEffect.ts
4223
- var CONTENT_SUBREF = "content";
4889
+ // src/effects/reference/refEffect.ts
4224
4890
  function applyRefHref(node, clone2, ctx) {
4225
4891
  if (!clone2) return;
4226
- const sourceId = stripHash2(clone2.sourceId);
4892
+ const sourceId = stripHash2(clone2.source);
4227
4893
  if (!sourceId) {
4228
- if (clone2.type === CONTENT_SUBREF) ctx.errors.push("clone: content ref missing sourceId");
4894
+ if (clone2.without === PxCloneWithout.translate) ctx.errors.push("clone: content ref missing `source`");
4229
4895
  return;
4230
4896
  }
4231
- const targetId = clone2.type === CONTENT_SUBREF ? ctx.contentRefInnerIds.get(sourceId) || sourceId : sourceId;
4897
+ const targetId = clone2.without === PxCloneWithout.translate ? ctx.contentRefInnerIds.get(sourceId) || sourceId : sourceId;
4232
4898
  node.href = "#" + targetId;
4233
4899
  }
4234
4900
  function applyRefAndTransformationEffect(node, clone2, transformBy, ctx) {
@@ -4236,11 +4902,11 @@ function applyRefAndTransformationEffect(node, clone2, transformBy, ctx) {
4236
4902
  return applyTransformByEffect(node, transformBy, ctx);
4237
4903
  }
4238
4904
 
4239
- // src/effects/repeaterEffect.ts
4905
+ // src/effects/transform/repeaterEffect.ts
4240
4906
  function applyRepeaterEffect(node, fx, ctx) {
4241
- var _a, _b;
4907
+ var _a2, _b;
4242
4908
  if (!fx) return node;
4243
- const copies = (_a = fx.copies) != null ? _a : 1;
4909
+ const copies = (_a2 = fx.copies) != null ? _a2 : 1;
4244
4910
  if (copies < 1) {
4245
4911
  ctx.errors.push("repeater.copies invalid: " + fx.copies);
4246
4912
  return node;
@@ -4307,11 +4973,11 @@ function synthesiseScale(raw, i) {
4307
4973
  return mapAnimatable(raw, scalePower, true);
4308
4974
  }
4309
4975
 
4310
- // src/effects/retimeEffect.ts
4311
- var RETIME_MATERIALISATION_MODE_INLINE_G = false;
4976
+ // src/effects/reference/retimeEffect.ts
4977
+ var RETIME_MATERIALIZATION_MODE_INLINE_G = false;
4312
4978
  function asRetime(r) {
4313
- var _a, _b;
4314
- return { start: (_a = r.start) != null ? _a : 0, stretch: (_b = r.stretch) != null ? _b : 1 };
4979
+ var _a2, _b;
4980
+ return { start: (_a2 = r.start) != null ? _a2 : 0, stretch: (_b = r.stretch) != null ? _b : 1 };
4315
4981
  }
4316
4982
  var CROP_EDGE_MS = 1;
4317
4983
  function applyTimeCrop(useNode, crop, ctx) {
@@ -4339,12 +5005,12 @@ function concatRetime(child, parent) {
4339
5005
  };
4340
5006
  }
4341
5007
  function readCloneRetime(n) {
4342
- var _a, _b;
4343
- return (_b = (_a = n.effects) == null ? void 0 : _a.clone) == null ? void 0 : _b.retime;
5008
+ var _a2, _b;
5009
+ return (_b = (_a2 = n.effects) == null ? void 0 : _a2.clone) == null ? void 0 : _b.retime;
4344
5010
  }
4345
5011
  function clearCloneRetime(n) {
4346
- var _a;
4347
- const clone2 = (_a = n.effects) == null ? void 0 : _a.clone;
5012
+ var _a2;
5013
+ const clone2 = (_a2 = n.effects) == null ? void 0 : _a2.clone;
4348
5014
  if (!clone2) return;
4349
5015
  delete clone2.retime;
4350
5016
  if (Object.keys(clone2).length === 0) delete n.effects.clone;
@@ -4355,9 +5021,9 @@ function applyAllRetimeEffects(root, ctx) {
4355
5021
  indexById(root, ctx.idMap);
4356
5022
  const sites = [];
4357
5023
  const collect = (n) => {
4358
- var _a;
5024
+ var _a2;
4359
5025
  if (readCloneRetime(n)) sites.push(n);
4360
- (_a = n.children) == null ? void 0 : _a.forEach(collect);
5026
+ (_a2 = n.children) == null ? void 0 : _a2.forEach(collect);
4361
5027
  };
4362
5028
  collect(root);
4363
5029
  const reachCount = /* @__PURE__ */ new Map();
@@ -4365,7 +5031,7 @@ function applyAllRetimeEffects(root, ctx) {
4365
5031
  let count = 0;
4366
5032
  const visited = /* @__PURE__ */ new Set();
4367
5033
  const walk = (n) => {
4368
- var _a;
5034
+ var _a2;
4369
5035
  if (!n) return;
4370
5036
  if (n !== site && readCloneRetime(n)) count++;
4371
5037
  if (n.type === "use" && n.href) {
@@ -4375,7 +5041,7 @@ function applyAllRetimeEffects(root, ctx) {
4375
5041
  walk(ctx.idMap.get(id));
4376
5042
  }
4377
5043
  }
4378
- (_a = n.children) == null ? void 0 : _a.forEach(walk);
5044
+ (_a2 = n.children) == null ? void 0 : _a2.forEach(walk);
4379
5045
  };
4380
5046
  const rootId = stripHash2(site.href);
4381
5047
  if (rootId) {
@@ -4385,19 +5051,19 @@ function applyAllRetimeEffects(root, ctx) {
4385
5051
  reachCount.set(site, count);
4386
5052
  }
4387
5053
  sites.sort((a, b) => {
4388
- var _a, _b;
4389
- return ((_a = reachCount.get(b)) != null ? _a : 0) - ((_b = reachCount.get(a)) != null ? _b : 0);
5054
+ var _a2, _b;
5055
+ return ((_a2 = reachCount.get(b)) != null ? _a2 : 0) - ((_b = reachCount.get(a)) != null ? _b : 0);
4390
5056
  });
4391
5057
  for (const useNode of sites) {
4392
5058
  const retime = readCloneRetime(useNode);
4393
5059
  if (!retime) continue;
4394
5060
  const crop = retime.timeCrop;
4395
5061
  clearCloneRetime(useNode);
4396
- materialiseRetime(useNode, asRetime(retime), ctx);
5062
+ materializeRetime(useNode, asRetime(retime), ctx);
4397
5063
  if (crop) applyTimeCrop(useNode, crop, ctx);
4398
5064
  }
4399
5065
  }
4400
- function materialiseRetime(useNode, retime, ctx) {
5066
+ function materializeRetime(useNode, retime, ctx) {
4401
5067
  const targetId = stripHash2(useNode.href);
4402
5068
  if (!targetId) {
4403
5069
  ctx.errors.push("retime: <use> has no href to follow");
@@ -4405,7 +5071,7 @@ function materialiseRetime(useNode, retime, ctx) {
4405
5071
  }
4406
5072
  const chainRootId = buildChainClone(targetId, retime, ctx, /* @__PURE__ */ new Set());
4407
5073
  if (!chainRootId) return;
4408
- if (RETIME_MATERIALISATION_MODE_INLINE_G) {
5074
+ if (RETIME_MATERIALIZATION_MODE_INLINE_G) {
4409
5075
  const cloneNode = ctx.idMap.get(chainRootId);
4410
5076
  useNode.type = "g";
4411
5077
  delete useNode.href;
@@ -4445,15 +5111,15 @@ function buildChainClone(targetId, accum, ctx, chain) {
4445
5111
  if (subId2) cloneNode.href = "#" + subId2;
4446
5112
  }
4447
5113
  } else {
4448
- materialiseNestedRetimeUses(cloneNode, accum, ctx, chain, targetId);
5114
+ materializeNestedRetimeUses(cloneNode, accum, ctx, chain, targetId);
4449
5115
  }
4450
5116
  ctx.defs.push(cloneNode);
4451
5117
  if (typeof cloneNode.id === "string") ctx.idMap.set(cloneNode.id, cloneNode);
4452
5118
  return typeof cloneNode.id === "string" ? cloneNode.id : void 0;
4453
5119
  }
4454
- function materialiseNestedRetimeUses(node, accum, ctx, chain, parentTargetId) {
5120
+ function materializeNestedRetimeUses(node, accum, ctx, chain, parentTargetId) {
4455
5121
  const visit = (n) => {
4456
- var _a;
5122
+ var _a2;
4457
5123
  const retime = readCloneRetime(n);
4458
5124
  if (n.type === "use" && retime && n.href) {
4459
5125
  const subId = stripHash2(n.href);
@@ -4466,14 +5132,14 @@ function materialiseNestedRetimeUses(node, accum, ctx, chain, parentTargetId) {
4466
5132
  }
4467
5133
  clearCloneRetime(n);
4468
5134
  }
4469
- (_a = n.children) == null ? void 0 : _a.forEach(visit);
5135
+ (_a2 = n.children) == null ? void 0 : _a2.forEach(visit);
4470
5136
  };
4471
5137
  visit(node);
4472
5138
  }
4473
5139
  function remapKeyframeTimes(node, start, stretch) {
4474
- var _a;
5140
+ var _a2;
4475
5141
  remapKeyframeTimesOnly(node, start, stretch);
4476
- (_a = node.children) == null ? void 0 : _a.forEach((c) => remapKeyframeTimes(c, start, stretch));
5142
+ (_a2 = node.children) == null ? void 0 : _a2.forEach((c) => remapKeyframeTimes(c, start, stretch));
4477
5143
  }
4478
5144
  function remapKeyframeTimesOnly(node, start, stretch) {
4479
5145
  const remap2 = (kfs) => {
@@ -4490,7 +5156,7 @@ function remapKeyframeTimesOnly(node, start, stretch) {
4490
5156
  }
4491
5157
  }
4492
5158
 
4493
- // src/effects/pathSampler.ts
5159
+ // src/effects/text/pathSampler.ts
4494
5160
  var LUT_STEPS = 48;
4495
5161
  var CMD_RE = /[MmLlHhVvCcSsQqTtAaZz]/;
4496
5162
  function tokenize(d) {
@@ -4638,7 +5304,7 @@ function createPathSampler(d) {
4638
5304
  };
4639
5305
  }
4640
5306
 
4641
- // src/effects/textPathEffect.ts
5307
+ // src/effects/text/textPathEffect.ts
4642
5308
  var EXTEND_MARGIN_FRAC = 0.15;
4643
5309
  function numRange(v) {
4644
5310
  const read = readAnimatable(v);
@@ -4652,10 +5318,10 @@ function numRange(v) {
4652
5318
  function estimateTextAdvance(node) {
4653
5319
  let chars = 0, maxFont = 16;
4654
5320
  const walk = (el) => {
4655
- var _a, _b;
4656
- const fs = parseFloat(String((_a = el.fontSize) != null ? _a : "")) || 0;
5321
+ var _a2;
5322
+ const fs = parseFloat(String((_a2 = el.fontSize) != null ? _a2 : "")) || 0;
4657
5323
  if (fs) maxFont = Math.max(maxFont, fs);
4658
- const t = (_b = el.text) != null ? _b : el.textContent;
5324
+ const t = el.textContent;
4659
5325
  if (typeof t === "string") chars += t.length;
4660
5326
  if (el.children) for (const c of el.children) walk(c);
4661
5327
  };
@@ -4677,14 +5343,14 @@ function shiftAnimatable(v, by) {
4677
5343
  return out;
4678
5344
  }
4679
5345
  function extendedPathForBrowser(pathD, opts) {
4680
- var _a;
5346
+ var _a2;
4681
5347
  if (opts.pathOverflow === "clip") return { d: pathD, startShift: 0 };
4682
5348
  const sampler = createPathSampler(pathD);
4683
5349
  if (!sampler || sampler.closed || sampler.totalLength <= 0) return { d: pathD, startShift: 0 };
4684
5350
  const L = sampler.totalLength;
4685
5351
  const margin = EXTEND_MARGIN_FRAC * L;
4686
5352
  const so = numRange(opts.startOffset);
4687
- const runWidth = numRange(opts.textLength).max || ((_a = opts.advance) != null ? _a : 0);
5353
+ const runWidth = numRange(opts.textLength).max || ((_a2 = opts.advance) != null ? _a2 : 0);
4688
5354
  const startOverflow = Math.max(0, -so.min);
4689
5355
  const endOverflow = Math.max(0, so.max + runWidth - L);
4690
5356
  const startExt = startOverflow > 0 ? startOverflow + margin : 0;
@@ -4705,10 +5371,10 @@ function extendedPathForBrowser(pathD, opts) {
4705
5371
  return { d, startShift: startExt };
4706
5372
  }
4707
5373
  function applyTextPathEffect(node, fx, ctx) {
4708
- var _a;
4709
- if (!fx || typeof fx.path !== "string" || !fx.path) return node;
5374
+ var _a2;
5375
+ if (!fx || typeof fx.pathData !== "string" || !fx.pathData) return node;
4710
5376
  const pathId = genId(ctx, "tpath");
4711
- const { d, startShift } = extendedPathForBrowser(fx.path, {
5377
+ const { d, startShift } = extendedPathForBrowser(fx.pathData, {
4712
5378
  pathOverflow: fx.pathOverflow,
4713
5379
  startOffset: fx.startOffset,
4714
5380
  textLength: fx.textLength,
@@ -4718,7 +5384,7 @@ function applyTextPathEffect(node, fx, ctx) {
4718
5384
  const textPath = {
4719
5385
  type: "textPath",
4720
5386
  href: "#" + pathId,
4721
- children: (_a = node.children) != null ? _a : []
5387
+ children: (_a2 = node.children) != null ? _a2 : []
4722
5388
  };
4723
5389
  if (fx.lengthAdjust !== void 0) textPath.lengthAdjust = fx.lengthAdjust;
4724
5390
  if (fx.method !== void 0) textPath.method = fx.method;
@@ -4733,7 +5399,7 @@ function applyAnimatableNumber(node, attrName, raw) {
4733
5399
  writeAnimatableChannel(node, attrName, readAnimatable(raw), { asString: true });
4734
5400
  }
4735
5401
 
4736
- // src/effects/elementFactory.ts
5402
+ // src/effects/text/elementFactory.ts
4737
5403
  var jsonElementFactory = (type, props, children) => {
4738
5404
  const node = { type };
4739
5405
  for (const k in props) if (props[k] !== void 0) node[k] = props[k];
@@ -4742,7 +5408,7 @@ var jsonElementFactory = (type, props, children) => {
4742
5408
  return node;
4743
5409
  };
4744
5410
 
4745
- // src/effects/glyphPathBake.ts
5411
+ // src/effects/text/glyphPathBake.ts
4746
5412
  function fmt(v, decimals) {
4747
5413
  return Math.round(v) === v ? "" + Math.round(v) : v.toFixed(decimals);
4748
5414
  }
@@ -4788,7 +5454,7 @@ function transformPathData(d, m, decimals = 2) {
4788
5454
  return out;
4789
5455
  }
4790
5456
 
4791
- // src/effects/textGlyphsEffect.ts
5457
+ // src/effects/text/textGlyphsEffect.ts
4792
5458
  var DEFAULT_FONT_SIZE = 16;
4793
5459
  var TEXT_ATTR_KEYS = [
4794
5460
  "fontFamily",
@@ -4810,7 +5476,6 @@ var TEXT_ATTR_KEYS = [
4810
5476
  "stroke",
4811
5477
  "strokeWidth",
4812
5478
  "effects",
4813
- TEXT_ATTR,
4814
5479
  TEXT_CONTENT_ATTR,
4815
5480
  "xml:space"
4816
5481
  ];
@@ -4848,15 +5513,15 @@ function paintAnimateOf(node) {
4848
5513
  return out;
4849
5514
  }
4850
5515
  function resolveStyle2(node, parent) {
4851
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
5516
+ var _a2, _b, _c, _d, _e, _f, _g, _h, _i, _j;
4852
5517
  const isTextRoot = node.type === "text";
4853
5518
  const nodeStyle = node.style;
4854
5519
  const own = (key) => {
4855
- var _a2;
4856
- return isTextRoot ? void 0 : (_a2 = node[key]) != null ? _a2 : nodeStyle == null ? void 0 : nodeStyle[key];
5520
+ var _a3;
5521
+ return isTextRoot ? void 0 : (_a3 = node[key]) != null ? _a3 : nodeStyle == null ? void 0 : nodeStyle[key];
4857
5522
  };
4858
5523
  const res = {
4859
- fontFamily: (_a = str(node.fontFamily)) != null ? _a : parent.fontFamily,
5524
+ fontFamily: (_a2 = str(node.fontFamily)) != null ? _a2 : parent.fontFamily,
4860
5525
  fontSize: (_b = parseLen(node.fontSize)) != null ? _b : parent.fontSize,
4861
5526
  fill: (_c = node.fill) != null ? _c : parent.fill,
4862
5527
  stroke: (_d = node.stroke) != null ? _d : parent.stroke,
@@ -4873,10 +5538,10 @@ function resolveStyle2(node, parent) {
4873
5538
  return res;
4874
5539
  }
4875
5540
  function rootStyleOf(node) {
4876
- var _a, _b, _c;
5541
+ var _a2, _b, _c;
4877
5542
  return {
4878
5543
  fontFamily: str(node.fontFamily),
4879
- fontSize: (_a = parseLen(node.fontSize)) != null ? _a : DEFAULT_FONT_SIZE,
5544
+ fontSize: (_a2 = parseLen(node.fontSize)) != null ? _a2 : DEFAULT_FONT_SIZE,
4880
5545
  fill: node.fill,
4881
5546
  stroke: node.stroke,
4882
5547
  strokeWidth: node.strokeWidth,
@@ -4897,9 +5562,9 @@ function paintOf(s) {
4897
5562
  return p;
4898
5563
  }
4899
5564
  function glyphFontFor(s, glyphs, soleFont, warnings) {
4900
- var _a;
5565
+ var _a2;
4901
5566
  const gf = s.fontFamily ? glyphs[s.fontFamily] : soleFont;
4902
- if (!gf) warnings == null ? void 0 : warnings.push('textGlyphs: no glyphs for font "' + ((_a = s.fontFamily) != null ? _a : "") + '"');
5567
+ if (!gf) warnings == null ? void 0 : warnings.push('textGlyphs: no glyphs for font "' + ((_a2 = s.fontFamily) != null ? _a2 : "") + '"');
4903
5568
  return gf;
4904
5569
  }
4905
5570
  function soleFontOf(glyphs) {
@@ -4920,26 +5585,26 @@ function missingGlyphBoxEm(advanceEm, ascentEm) {
4920
5585
  const ix0 = x0 + t, ix1 = x1 - t, iyb = -t, iyt = y1 + t;
4921
5586
  return outer + "M" + ix0 + " " + iyb + "L" + ix0 + " " + iyt + "L" + ix1 + " " + iyt + "L" + ix1 + " " + iyb + "Z";
4922
5587
  }
4923
- function materialiseGlyphTextHorizontal(node, opts) {
4924
- var _a, _b, _c, _d;
5588
+ function materializeGlyphTextHorizontal(node, opts) {
5589
+ var _a2, _b, _c;
4925
5590
  const { glyphs, create = jsonElementFactory, warnings } = opts;
4926
5591
  const soleFont = soleFontOf(glyphs);
4927
- const pen = { x: (_a = parseLen(node.x)) != null ? _a : 0, y: (_b = parseLen(node.y)) != null ? _b : 0 };
5592
+ const pen = { x: (_a2 = parseLen(node.x)) != null ? _a2 : 0, y: (_b = parseLen(node.y)) != null ? _b : 0 };
4928
5593
  const placements = [];
4929
5594
  const lines = [{ start: pen.x, end: pen.x }];
4930
5595
  let line = 0;
4931
5596
  const renderChars = (content, s) => {
4932
- var _a2;
5597
+ var _a3;
4933
5598
  const gf = glyphFontFor(s, glyphs, soleFont, warnings);
4934
5599
  const upm = (gf == null ? void 0 : gf.unitsPerEm) || 1e3;
4935
5600
  const scale = s.fontSize / upm;
4936
- const ascentEm = (_a2 = gf == null ? void 0 : gf.ascent) != null ? _a2 : 0.9 * upm;
5601
+ const ascentEm = (_a3 = gf == null ? void 0 : gf.ascent) != null ? _a3 : 0.9 * upm;
4937
5602
  const paint = paintOf(s);
4938
5603
  for (let i = 0; i < content.length; i++) {
4939
5604
  const ch = content.charAt(i);
4940
5605
  const g = gf == null ? void 0 : gf.glyphs[ch];
4941
- if (g && g.d) {
4942
- placements.push({ glyphD: g.d, m: [scale, 0, 0, scale, pen.x, pen.y], paint, line, x: pen.x, y: pen.y, scale });
5606
+ if (g && g.pathData) {
5607
+ placements.push({ glyphD: g.pathData, m: [scale, 0, 0, scale, pen.x, pen.y], paint, line, x: pen.x, y: pen.y, scale });
4943
5608
  pen.x += g.width * scale;
4944
5609
  } else if (/\S/.test(ch)) {
4945
5610
  const advEm = g && g.width > 0 ? g.width : MISSING_GLYPH_ADVANCE_EM * upm;
@@ -4953,7 +5618,7 @@ function materialiseGlyphTextHorizontal(node, opts) {
4953
5618
  }
4954
5619
  };
4955
5620
  const walk = (el, parentStyle) => {
4956
- var _a2, _b2, _c2, _d2;
5621
+ var _a3, _b2, _c2;
4957
5622
  const s = resolveStyle2(el, parentStyle);
4958
5623
  const x = parseLen(el.x);
4959
5624
  const y = parseLen(el.y);
@@ -4963,16 +5628,16 @@ function materialiseGlyphTextHorizontal(node, opts) {
4963
5628
  lines.push({ start: pen.x, end: pen.x });
4964
5629
  }
4965
5630
  if (y !== void 0) pen.y = y;
4966
- pen.x += (_a2 = parseLen(el.dx)) != null ? _a2 : 0;
5631
+ pen.x += (_a3 = parseLen(el.dx)) != null ? _a3 : 0;
4967
5632
  pen.y += (_b2 = parseLen(el.dy)) != null ? _b2 : 0;
4968
- const content = (_c2 = str(el[TEXT_CONTENT_ATTR])) != null ? _c2 : str(el[TEXT_ATTR]);
4969
- if (content && !((_d2 = el.children) == null ? void 0 : _d2.length)) renderChars(content, s);
5633
+ const content = str(el[TEXT_CONTENT_ATTR]);
5634
+ if (content && !((_c2 = el.children) == null ? void 0 : _c2.length)) renderChars(content, s);
4970
5635
  if (el.children) for (const ch of el.children) walk(ch, s);
4971
5636
  };
4972
5637
  const rootStyle = rootStyleOf(node);
4973
5638
  if (node.children) for (const ch of node.children) walk(ch, rootStyle);
4974
- const rootContent = (_c = str(node[TEXT_CONTENT_ATTR])) != null ? _c : str(node[TEXT_ATTR]);
4975
- if (rootContent && !((_d = node.children) == null ? void 0 : _d.length)) renderChars(rootContent, rootStyle);
5639
+ const rootContent = str(node[TEXT_CONTENT_ATTR]);
5640
+ if (rootContent && !((_c = node.children) == null ? void 0 : _c.length)) renderChars(rootContent, rootStyle);
4976
5641
  const anchor = str(node.textAnchor);
4977
5642
  if (anchor === "middle" || anchor === "end") {
4978
5643
  for (const p of placements) {
@@ -4984,8 +5649,8 @@ function materialiseGlyphTextHorizontal(node, opts) {
4984
5649
  return toGroup(node, buildPaths(placements, create, warnings), create);
4985
5650
  }
4986
5651
  function layoutGlyphTextChars(node, opts) {
4987
- var _a, _b, _c, _d, _e, _f;
4988
- if ((_a = opts.alongPath) == null ? void 0 : _a.pathD) return layoutGlyphTextCharsAlongPath(node, opts.alongPath.pathD, opts);
5652
+ var _a2, _b, _c, _d, _e;
5653
+ if ((_a2 = opts.alongPath) == null ? void 0 : _a2.pathD) return layoutGlyphTextCharsAlongPath(node, opts.alongPath.pathD, opts);
4989
5654
  const { glyphs, warnings } = opts;
4990
5655
  const soleFont = soleFontOf(glyphs);
4991
5656
  const pen = { x: (_b = parseLen(node.x)) != null ? _b : 0, y: (_c = parseLen(node.y)) != null ? _c : 0 };
@@ -4993,11 +5658,11 @@ function layoutGlyphTextChars(node, opts) {
4993
5658
  const lines = [{ start: pen.x, end: pen.x }];
4994
5659
  let line = 0;
4995
5660
  const renderChars = (content, s) => {
4996
- var _a2;
5661
+ var _a3;
4997
5662
  const gf = glyphFontFor(s, glyphs, soleFont, warnings);
4998
5663
  const upm = (gf == null ? void 0 : gf.unitsPerEm) || 1e3;
4999
5664
  const scale = s.fontSize / upm;
5000
- const ascent = ((_a2 = gf == null ? void 0 : gf.ascent) != null ? _a2 : 0.9 * upm) * scale;
5665
+ const ascent = ((_a3 = gf == null ? void 0 : gf.ascent) != null ? _a3 : 0.9 * upm) * scale;
5001
5666
  for (let i = 0; i < content.length; i++) {
5002
5667
  const ch = content.charAt(i);
5003
5668
  const g = gf == null ? void 0 : gf.glyphs[ch];
@@ -5008,7 +5673,7 @@ function layoutGlyphTextChars(node, opts) {
5008
5673
  }
5009
5674
  };
5010
5675
  const walk = (el, parentStyle) => {
5011
- var _a2, _b2, _c2, _d2;
5676
+ var _a3, _b2, _c2;
5012
5677
  const s = resolveStyle2(el, parentStyle);
5013
5678
  const x = parseLen(el.x);
5014
5679
  const y = parseLen(el.y);
@@ -5018,10 +5683,10 @@ function layoutGlyphTextChars(node, opts) {
5018
5683
  lines.push({ start: pen.x, end: pen.x });
5019
5684
  }
5020
5685
  if (y !== void 0) pen.y = y;
5021
- pen.x += (_a2 = parseLen(el.dx)) != null ? _a2 : 0;
5686
+ pen.x += (_a3 = parseLen(el.dx)) != null ? _a3 : 0;
5022
5687
  pen.y += (_b2 = parseLen(el.dy)) != null ? _b2 : 0;
5023
- const content = (_c2 = str(el[TEXT_CONTENT_ATTR])) != null ? _c2 : str(el[TEXT_ATTR]);
5024
- if (content && !((_d2 = el.children) == null ? void 0 : _d2.length)) renderChars(content, s);
5688
+ const content = str(el[TEXT_CONTENT_ATTR]);
5689
+ if (content && !((_c2 = el.children) == null ? void 0 : _c2.length)) renderChars(content, s);
5025
5690
  if (el.children) for (const ch of el.children) walk(ch, s);
5026
5691
  };
5027
5692
  const rootStyle = rootStyleOf(node);
@@ -5035,8 +5700,8 @@ function layoutGlyphTextChars(node, opts) {
5035
5700
  boxes.push({ x: pen.x, y: pen.y, width: 0, ascent: ((_d = gf == null ? void 0 : gf.ascent) != null ? _d : 0.9 * upm) * (s.fontSize / upm), fontSize: s.fontSize, line });
5036
5701
  }
5037
5702
  }
5038
- const rootContent = (_e = str(node[TEXT_CONTENT_ATTR])) != null ? _e : str(node[TEXT_ATTR]);
5039
- if (rootContent && !((_f = node.children) == null ? void 0 : _f.length)) renderChars(rootContent, rootStyle);
5703
+ const rootContent = str(node[TEXT_CONTENT_ATTR]);
5704
+ if (rootContent && !((_e = node.children) == null ? void 0 : _e.length)) renderChars(rootContent, rootStyle);
5040
5705
  const anchor = str(node.textAnchor);
5041
5706
  if (anchor === "middle" || anchor === "end") {
5042
5707
  for (const b of boxes) {
@@ -5044,13 +5709,13 @@ function layoutGlyphTextChars(node, opts) {
5044
5709
  b.x += anchor === "middle" ? -w / 2 : -w;
5045
5710
  }
5046
5711
  }
5047
- return boxes.map((_g) => {
5048
- var _h = _g, { line: _l } = _h, b = __objRest(_h, ["line"]);
5712
+ return boxes.map((_f) => {
5713
+ var _g = _f, { line: _l } = _g, b = __objRest(_g, ["line"]);
5049
5714
  return b;
5050
5715
  });
5051
5716
  }
5052
5717
  function layoutGlyphTextCharsAlongPath(node, pathD, opts) {
5053
- var _a, _b;
5718
+ var _a2, _b;
5054
5719
  const { glyphs, warnings, alongPath } = opts;
5055
5720
  const sampler = createPathSampler(pathD);
5056
5721
  if (!sampler) {
@@ -5061,14 +5726,14 @@ function layoutGlyphTextCharsAlongPath(node, pathD, opts) {
5061
5726
  const chars = [];
5062
5727
  let adv = 0;
5063
5728
  const walk = (el, parentStyle) => {
5064
- var _a2, _b2, _c;
5729
+ var _a3, _b2;
5065
5730
  const s = resolveStyle2(el, parentStyle);
5066
- const content = (_a2 = str(el[TEXT_CONTENT_ATTR])) != null ? _a2 : str(el[TEXT_ATTR]);
5067
- if (content && !((_b2 = el.children) == null ? void 0 : _b2.length)) {
5731
+ const content = str(el[TEXT_CONTENT_ATTR]);
5732
+ if (content && !((_a3 = el.children) == null ? void 0 : _a3.length)) {
5068
5733
  const gf = glyphFontFor(s, glyphs, soleFont, warnings);
5069
5734
  const upm = (gf == null ? void 0 : gf.unitsPerEm) || 1e3;
5070
5735
  const scale = s.fontSize / upm;
5071
- const ascent = ((_c = gf == null ? void 0 : gf.ascent) != null ? _c : 0.9 * upm) * scale;
5736
+ const ascent = ((_b2 = gf == null ? void 0 : gf.ascent) != null ? _b2 : 0.9 * upm) * scale;
5072
5737
  for (let i = 0; i < content.length; i++) {
5073
5738
  const ch = content.charAt(i);
5074
5739
  const g = gf == null ? void 0 : gf.glyphs[ch];
@@ -5083,7 +5748,7 @@ function layoutGlyphTextCharsAlongPath(node, pathD, opts) {
5083
5748
  walk(node, rootStyleOf(node));
5084
5749
  const width = adv;
5085
5750
  const tlr = readAnimatable(alongPath == null ? void 0 : alongPath.textLength);
5086
- const tlv = tlr.kind === "animated" /* Animated */ ? Number((_a = tlr.keyframes[0]) == null ? void 0 : _a.value) || 0 : tlr.kind === "static" /* Static */ ? Number(tlr.value) || 0 : 0;
5751
+ const tlv = tlr.kind === "animated" /* Animated */ ? Number((_a2 = tlr.keyframes[0]) == null ? void 0 : _a2.value) || 0 : tlr.kind === "static" /* Static */ ? Number(tlr.value) || 0 : 0;
5087
5752
  const k = tlv > 0 && width > 0 ? tlv / width : 1;
5088
5753
  const so = readAnimatable(alongPath == null ? void 0 : alongPath.startOffset);
5089
5754
  const { along: alongOffset, perp } = alongPathNodeOffsets(node);
@@ -5115,21 +5780,21 @@ function collectAlongPathCells(node, glyphs, soleFont, warnings) {
5115
5780
  const cells = [];
5116
5781
  let adv = 0;
5117
5782
  const walk = (el, parentStyle) => {
5118
- var _a, _b, _c;
5783
+ var _a2, _b;
5119
5784
  const s = resolveStyle2(el, parentStyle);
5120
- const content = (_a = str(el[TEXT_CONTENT_ATTR])) != null ? _a : str(el[TEXT_ATTR]);
5121
- if (content && !((_b = el.children) == null ? void 0 : _b.length)) {
5785
+ const content = str(el[TEXT_CONTENT_ATTR]);
5786
+ if (content && !((_a2 = el.children) == null ? void 0 : _a2.length)) {
5122
5787
  const gf = glyphFontFor(s, glyphs, soleFont, warnings);
5123
5788
  if (gf) {
5124
5789
  const scale = s.fontSize / gf.unitsPerEm;
5125
- const ascentEm = (_c = gf.ascent) != null ? _c : 0.9 * gf.unitsPerEm;
5790
+ const ascentEm = (_b = gf.ascent) != null ? _b : 0.9 * gf.unitsPerEm;
5126
5791
  const paint = paintOf(s);
5127
5792
  for (let i = 0; i < content.length; i++) {
5128
5793
  const ch = content.charAt(i);
5129
5794
  const g = gf.glyphs[ch];
5130
- if (g && g.d) {
5795
+ if (g && g.pathData) {
5131
5796
  const glyphAdv = g.width * scale;
5132
- cells.push({ glyphD: g.d, widthEm: g.width, scale, paint, midBase: adv + glyphAdv / 2 });
5797
+ cells.push({ glyphD: g.pathData, widthEm: g.width, scale, paint, midBase: adv + glyphAdv / 2 });
5133
5798
  adv += glyphAdv;
5134
5799
  } else if (/\S/.test(ch)) {
5135
5800
  const wEm = g && g.width > 0 ? g.width : MISSING_GLYPH_ADVANCE_EM * gf.unitsPerEm;
@@ -5154,13 +5819,13 @@ function alongAffine(sampler, dist, scale, widthEm, perp = 0) {
5154
5819
  return [scale * cos, scale * sin, -scale * sin, scale * cos, x - scale * cos * hw - perp * sin, y - scale * sin * hw + perp * cos];
5155
5820
  }
5156
5821
  function alongPathNodeOffsets(node) {
5157
- var _a, _b, _c;
5822
+ var _a2, _b, _c;
5158
5823
  return {
5159
- along: ((_a = parseLen(node.x)) != null ? _a : 0) + ((_b = parseLen(node.dx)) != null ? _b : 0),
5824
+ along: ((_a2 = parseLen(node.x)) != null ? _a2 : 0) + ((_b = parseLen(node.dx)) != null ? _b : 0),
5160
5825
  perp: (_c = parseLen(node.dy)) != null ? _c : 0
5161
5826
  };
5162
5827
  }
5163
- function materialiseGlyphTextAlongPath(node, pathD, startOffset, opts, textLength, pathOverflow) {
5828
+ function materializeGlyphTextAlongPath(node, pathD, startOffset, opts, textLength, pathOverflow) {
5164
5829
  const { glyphs, create = jsonElementFactory, warnings } = opts;
5165
5830
  const sampler = pathD ? createPathSampler(pathD) : null;
5166
5831
  if (!sampler) {
@@ -5196,7 +5861,7 @@ function materialiseGlyphTextAlongPath(node, pathD, startOffset, opts, textLengt
5196
5861
  return toGroup(node, buildPaths(placements, create, warnings), create);
5197
5862
  }
5198
5863
  function numTrackOf(raw) {
5199
- var _a;
5864
+ var _a2;
5200
5865
  const r = readAnimatable(raw);
5201
5866
  if (r.kind === "animated" /* Animated */ && r.keyframes.length >= 2) {
5202
5867
  const kfs = [...r.keyframes].sort((k1, k2) => (Number(k1.time) || 0) - (Number(k2.time) || 0));
@@ -5219,7 +5884,7 @@ function numTrackOf(raw) {
5219
5884
  }
5220
5885
  };
5221
5886
  }
5222
- const v = r.kind === "animated" /* Animated */ ? Number((_a = r.keyframes[0]) == null ? void 0 : _a.value) || 0 : r.kind === "static" /* Static */ ? Number(r.value) || 0 : 0;
5887
+ const v = r.kind === "animated" /* Animated */ ? Number((_a2 = r.keyframes[0]) == null ? void 0 : _a2.value) || 0 : r.kind === "static" /* Static */ ? Number(r.value) || 0 : 0;
5223
5888
  return { animated: false, times: [], at: () => v };
5224
5889
  }
5225
5890
  function mergeTrackTimes(a, b) {
@@ -5239,8 +5904,8 @@ function buildAnimatedAlongPath(cells, sampler, distOf, times, loop, create, isC
5239
5904
  const onPath = (dist) => dist >= 0 && dist <= sampler.totalLength;
5240
5905
  const out = [];
5241
5906
  for (const c of cells) {
5242
- const centred = [c.scale, 0, 0, c.scale, -c.scale * (c.widthEm / 2), 0];
5243
- const d = transformPathData(c.glyphD, centred);
5907
+ const centered = [c.scale, 0, 0, c.scale, -c.scale * (c.widthEm / 2), 0];
5908
+ const d = transformPathData(c.glyphD, centered);
5244
5909
  const sampleKf = (dist, time) => {
5245
5910
  const { x, y, angle } = sampler.sampleAtDistance(dist);
5246
5911
  const cos = Math.cos(angle), sin = Math.sin(angle);
@@ -5295,7 +5960,7 @@ function paintProps(paint) {
5295
5960
  return p;
5296
5961
  }
5297
5962
  function missingGlyphProps(isMissing) {
5298
- return isMissing ? { class: MISSING_GLYPH_CLASS_NAME } : {};
5963
+ return isMissing ? { [CLASS_ATTR]: MISSING_GLYPH_CLASS_NAME } : {};
5299
5964
  }
5300
5965
  function buildPaths(placements, create, warnings) {
5301
5966
  if (!placements.length) {
@@ -5332,27 +5997,27 @@ function toGroup(node, children, create) {
5332
5997
  }
5333
5998
  return create("g", gProps, children);
5334
5999
  }
5335
- function materialiseGlyphText(node, opts) {
5336
- if (opts.alongPath) return materialiseGlyphTextAlongPath(node, opts.alongPath.pathD, opts.alongPath.startOffset, opts, opts.alongPath.textLength, opts.alongPath.pathOverflow);
5337
- return materialiseGlyphTextHorizontal(node, opts);
6000
+ function materializeGlyphText(node, opts) {
6001
+ if (opts.alongPath) return materializeGlyphTextAlongPath(node, opts.alongPath.pathD, opts.alongPath.startOffset, opts, opts.alongPath.textLength, opts.alongPath.pathOverflow);
6002
+ return materializeGlyphTextHorizontal(node, opts);
5338
6003
  }
5339
6004
  function applyTextGlyphsEffect(node, fx, ctx) {
5340
6005
  if (!(fx == null ? void 0 : fx.useGlyphs)) return node;
5341
6006
  if (!ctx.glyphs) {
5342
- ctx.warnings.push("textGlyphs: no definitions.glyphs \u2014 left as native <text>");
6007
+ ctx.warnings.push("textGlyphs: no definitions.fonts \u2014 left as native <text>");
5343
6008
  return node;
5344
6009
  }
5345
- return materialiseGlyphTextHorizontal(node, { glyphs: ctx.glyphs, warnings: ctx.warnings });
6010
+ return materializeGlyphTextHorizontal(node, { glyphs: ctx.glyphs, warnings: ctx.warnings });
5346
6011
  }
5347
6012
  function applyTextGlyphsAlongPath(node, ctx, pathD, startOffset, textLength, pathOverflow) {
5348
6013
  if (!ctx.glyphs) {
5349
- ctx.warnings.push("textGlyphs: no definitions.glyphs");
6014
+ ctx.warnings.push("textGlyphs: no definitions.fonts");
5350
6015
  return null;
5351
6016
  }
5352
- return materialiseGlyphTextAlongPath(node, pathD, startOffset, { glyphs: ctx.glyphs, warnings: ctx.warnings }, textLength, pathOverflow);
6017
+ return materializeGlyphTextAlongPath(node, pathD, startOffset, { glyphs: ctx.glyphs, warnings: ctx.warnings }, textLength, pathOverflow);
5353
6018
  }
5354
6019
 
5355
- // src/effects/strokeTrimEffect.ts
6020
+ // src/effects/stroke/strokeTrimEffect.ts
5356
6021
  function applyStrokeTrimEffect(node, strokeTrim, ctx) {
5357
6022
  if (!strokeTrim) return node;
5358
6023
  const combined = strokeTrim.subPaths === PxStrokeTrimSubPaths.combined;
@@ -5488,12 +6153,11 @@ function getOffsetIndexRange(minMaxOffset) {
5488
6153
  ];
5489
6154
  }
5490
6155
  function readScalarValues(r) {
5491
- var _a;
5492
6156
  if (r.kind === "absent" /* Absent */) return [];
5493
6157
  if (r.kind === "static" /* Static */) return [r.value];
5494
6158
  const out = [];
5495
6159
  for (const kf of r.keyframes) {
5496
- const v = (_a = kf.value) != null ? _a : kf.v;
6160
+ const v = kfValue(kf);
5497
6161
  if (typeof v === "number") out.push(v);
5498
6162
  }
5499
6163
  return out;
@@ -5503,14 +6167,11 @@ function computeAnimAttr(read, map) {
5503
6167
  if (read.kind === "static" /* Static */) return { kind: "static" /* Static */, value: map(read.value) };
5504
6168
  return {
5505
6169
  kind: "animated" /* Animated */,
5506
- keyframes: read.keyframes.map((kf) => {
5507
- var _a, _b, _c, _d;
5508
- return {
5509
- time: (_b = (_a = kf.time) != null ? _a : kf.t) != null ? _b : 0,
5510
- value: map((_c = kf.value) != null ? _c : kf.v),
5511
- easing: (_d = kf.easing) != null ? _d : kf.e
5512
- };
5513
- }),
6170
+ keyframes: read.keyframes.map((kf) => ({
6171
+ time: kfTime(kf),
6172
+ value: map(kfValue(kf)),
6173
+ easing: kfEasing(kf)
6174
+ })),
5514
6175
  loop: read.loop
5515
6176
  };
5516
6177
  }
@@ -5520,7 +6181,6 @@ function applyAttr(node, attrName, attr) {
5520
6181
  }
5521
6182
  var OPACITY_STEP_MS = 10;
5522
6183
  function computeOpacityFromRange(rangeRead) {
5523
- var _a, _b, _c, _d, _e, _f;
5524
6184
  const hide = (v) => v[0] === v[1];
5525
6185
  if (rangeRead.kind === "absent" /* Absent */) return void 0;
5526
6186
  if (rangeRead.kind === "static" /* Static */) return hide(rangeRead.value) ? { kind: "static" /* Static */, value: 0 } : void 0;
@@ -5528,7 +6188,7 @@ function computeOpacityFromRange(rangeRead) {
5528
6188
  let anyHide = false;
5529
6189
  let allHide = true;
5530
6190
  for (const kf of kfs) {
5531
- if (hide((_a = kf.value) != null ? _a : kf.v)) anyHide = true;
6191
+ if (hide(kfValue(kf))) anyHide = true;
5532
6192
  else allHide = false;
5533
6193
  }
5534
6194
  if (!anyHide) return void 0;
@@ -5538,10 +6198,10 @@ function computeOpacityFromRange(rangeRead) {
5538
6198
  const kf = kfs[i];
5539
6199
  const prevKf = i > 0 ? kfs[i - 1] : void 0;
5540
6200
  const nextKf = i < kfs.length - 1 ? kfs[i + 1] : void 0;
5541
- const t = (_c = (_b = kf.time) != null ? _b : kf.t) != null ? _c : 0;
5542
- const thisHide = hide((_d = kf.value) != null ? _d : kf.v);
5543
- const prevHide = prevKf ? thisHide && hide((_e = prevKf.value) != null ? _e : prevKf.v) : thisHide;
5544
- const nextHide = nextKf ? thisHide && hide((_f = nextKf.value) != null ? _f : nextKf.v) : thisHide;
6201
+ const t = kfTime(kf);
6202
+ const thisHide = hide(kfValue(kf));
6203
+ const prevHide = prevKf ? thisHide && hide(kfValue(prevKf)) : thisHide;
6204
+ const nextHide = nextKf ? thisHide && hide(kfValue(nextKf)) : thisHide;
5545
6205
  if (prevHide && !nextHide) {
5546
6206
  out.push({ time: t, value: 0 });
5547
6207
  out.push({ time: t + OPACITY_STEP_MS, value: 1 });
@@ -5556,14 +6216,11 @@ function computeOpacityFromRange(rangeRead) {
5556
6216
  function readRangeWithCrossings(raw) {
5557
6217
  const r = readAnimatable(raw);
5558
6218
  if (r.kind !== "animated" /* Animated */) return r;
5559
- const kfs = r.keyframes.map((kf) => {
5560
- var _a, _b, _c, _d;
5561
- return {
5562
- time: (_b = (_a = kf.time) != null ? _a : kf.t) != null ? _b : 0,
5563
- value: (_c = kf.value) != null ? _c : kf.v,
5564
- easing: (_d = kf.easing) != null ? _d : kf.e
5565
- };
5566
- });
6219
+ const kfs = r.keyframes.map((kf) => ({
6220
+ time: kfTime(kf),
6221
+ value: kfValue(kf),
6222
+ easing: kfEasing(kf)
6223
+ }));
5567
6224
  const hasReverse = kfs.some((kf) => kf.value[0] > kf.value[1]);
5568
6225
  if (!hasReverse) {
5569
6226
  return {
@@ -5660,20 +6317,20 @@ function pxBezierPathLength(path) {
5660
6317
  return total;
5661
6318
  }
5662
6319
  function segmentLength(path, from, to) {
5663
- var _a, _b, _c, _d;
6320
+ var _a2, _b, _c, _d;
5664
6321
  const v = path.v;
5665
6322
  const p0 = v[from];
5666
6323
  const p3 = v[to];
5667
- const p1 = (_b = (_a = path.o) == null ? void 0 : _a[from]) != null ? _b : p0;
6324
+ const p1 = (_b = (_a2 = path.o) == null ? void 0 : _a2[from]) != null ? _b : p0;
5668
6325
  const p2 = (_d = (_c = path.i) == null ? void 0 : _c[to]) != null ? _d : p3;
5669
6326
  const lut = bezier2D_arcLengthLUT(p0, p1, p2, p3);
5670
6327
  return lut.ds[lut.ds.length - 1];
5671
6328
  }
5672
6329
  var ARC_KAPPA = 0.5522847498307936;
5673
6330
  function shapeToPathD(node) {
5674
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
6331
+ var _a2, _b, _c, _d, _e, _f, _g, _h, _i, _j;
5675
6332
  if (node.type === "rect") {
5676
- const x = Number((_a = node.x) != null ? _a : 0), y = Number((_b = node.y) != null ? _b : 0);
6333
+ const x = Number((_a2 = node.x) != null ? _a2 : 0), y = Number((_b = node.y) != null ? _b : 0);
5677
6334
  const w = Number((_c = node.width) != null ? _c : 0), h = Number((_d = node.height) != null ? _d : 0);
5678
6335
  return "M" + (x + w) + "," + y + "L" + (x + w) + "," + (y + h) + "L" + x + "," + (y + h) + "L" + x + "," + y + "L" + (x + w) + "," + y + "z";
5679
6336
  }
@@ -5691,7 +6348,7 @@ function shapeToPathD(node) {
5691
6348
 
5692
6349
  // src/effects/PlayerEffectsUtil.ts
5693
6350
  function applyPlayerEffects(root) {
5694
- var _a, _b;
6351
+ var _a2, _b;
5695
6352
  const ctx = {
5696
6353
  defs: [],
5697
6354
  warnings: [],
@@ -5702,8 +6359,8 @@ function applyPlayerEffects(root) {
5702
6359
  maskAncestorChains: /* @__PURE__ */ new Map(),
5703
6360
  // Resolved engine: `frames` ONLY when explicitly set; auto/waapi/unset →
5704
6361
  // waapi (we're not 100% sure it's frames, and CSS/WAAPI need the inline form).
5705
- engine: ((_a = getAnimatorConfig(root)) == null ? void 0 : _a.mode) === PxAnimatorMode.frames ? PxAnimatorEngine.frames : PxAnimatorEngine.waapi,
5706
- glyphs: (_b = getDefs(root)) == null ? void 0 : _b.glyphs
6362
+ engine: resolveTimelineEngine((_a2 = getAnimatorConfig(root)) == null ? void 0 : _a2.engine),
6363
+ glyphs: (_b = getDefs(root)) == null ? void 0 : _b.fonts
5707
6364
  };
5708
6365
  const working = clone(root);
5709
6366
  indexById(working, ctx.idMap);
@@ -5726,7 +6383,7 @@ function applyPlayerEffects_exceptRetime(node, ctx) {
5726
6383
  let consumedByGlyphs = false;
5727
6384
  if (text == null ? void 0 : text.useGlyphs) {
5728
6385
  if (textPath) {
5729
- const pathD = typeof textPath.path === "string" ? textPath.path : void 0;
6386
+ const pathD = typeof textPath.pathData === "string" ? textPath.pathData : void 0;
5730
6387
  const glyphed = applyTextGlyphsAlongPath(n, ctx, pathD, textPath.startOffset, textPath.textLength, textPath.pathOverflow);
5731
6388
  if (glyphed) {
5732
6389
  n = glyphed;
@@ -5759,27 +6416,7 @@ function applyPlayerEffects_retime(node, ctx) {
5759
6416
  return node;
5760
6417
  }
5761
6418
 
5762
- // src/PxOffsetPathMaterialiser.ts
5763
- var kfTime = (kf) => {
5764
- var _a, _b;
5765
- return (_b = (_a = kf.t) != null ? _a : kf.time) != null ? _b : 0;
5766
- };
5767
- var kfValue = (kf) => {
5768
- var _a;
5769
- return (_a = kf.v) != null ? _a : kf.value;
5770
- };
5771
- var kfEasing = (kf) => {
5772
- var _a;
5773
- return (_a = kf.e) != null ? _a : kf.easing;
5774
- };
5775
- var kfTangentIn = (kf) => {
5776
- var _a;
5777
- return (_a = kf.tangentIn) != null ? _a : kf.ti;
5778
- };
5779
- var kfTangentOut = (kf) => {
5780
- var _a;
5781
- return (_a = kf.tangentOut) != null ? _a : kf.to;
5782
- };
6419
+ // src/materialize/PxOffsetPathMaterializer.ts
5783
6420
  function cubicAt(p0, c1, c2, p1, t) {
5784
6421
  const u = 1 - t;
5785
6422
  const a = u * u * u, b = 3 * u * u * t, c = 3 * u * t * t, d = t * t * t;
@@ -5803,7 +6440,7 @@ var fmt2 = (n) => {
5803
6440
  return Object.is(r, -0) ? "0" : String(r);
5804
6441
  };
5805
6442
  function buildOffsetPath(propAnim) {
5806
- var _a, _b, _c;
6443
+ var _a2, _b, _c;
5807
6444
  if (propAnim.alongPathMode !== "offsetPath") return void 0;
5808
6445
  const kfs = propAnim.keyframes;
5809
6446
  if (!kfs || kfs.length < 2) return void 0;
@@ -5816,7 +6453,7 @@ function buildOffsetPath(propAnim) {
5816
6453
  if (!tr || tr.length < 2) return void 0;
5817
6454
  const parts = Object.keys(v);
5818
6455
  if (parts.some((p) => p !== "translate" && p !== "origin")) return void 0;
5819
- const o = (_a = v == null ? void 0 : v.origin) != null ? _a : [0, 0];
6456
+ const o = (_a2 = v == null ? void 0 : v.origin) != null ? _a2 : [0, 0];
5820
6457
  if (o[0] !== anchor[0] || o[1] !== anchor[1]) return void 0;
5821
6458
  points.push([tr[0] + anchor[0], tr[1] + anchor[1]]);
5822
6459
  }
@@ -5845,9 +6482,9 @@ function buildOffsetPath(propAnim) {
5845
6482
  }
5846
6483
  return { pathStr: d, distanceKfs, autoOrient: !!propAnim.autoOrient, anchor };
5847
6484
  }
5848
- function materialiseOffsetPathsInTree(root) {
6485
+ function materializeOffsetPathsInTree(root) {
5849
6486
  const walk = (node) => {
5850
- var _a;
6487
+ var _a2;
5851
6488
  let out = node;
5852
6489
  const anim = node.animate;
5853
6490
  const transform = anim == null ? void 0 : anim["transform"];
@@ -5855,16 +6492,16 @@ function materialiseOffsetPathsInTree(root) {
5855
6492
  const built = buildOffsetPath(transform);
5856
6493
  if (built) {
5857
6494
  const newAnimate = __spreadValues({}, anim);
5858
- delete newAnimate["transform"];
6495
+ delete newAnimate[TRANSFORM_ATTR];
5859
6496
  const distance = { keyframes: built.distanceKfs };
5860
6497
  if (transform.loop !== void 0) distance.loop = transform.loop;
5861
- newAnimate["offsetDistance"] = distance;
6498
+ newAnimate[OFFSET_DISTANCE_ATTR] = distance;
5862
6499
  const staticTr = node.transform;
5863
6500
  let newTransform = staticTr;
5864
6501
  if (staticTr && typeof staticTr === "object") {
5865
6502
  const t = __spreadValues({}, staticTr);
5866
- delete t["translate"];
5867
- delete t["origin"];
6503
+ delete t[TRANSFORM_PART.translate];
6504
+ delete t[TRANSFORM_PART.origin];
5868
6505
  newTransform = Object.keys(t).length ? t : void 0;
5869
6506
  }
5870
6507
  out = __spreadProps(__spreadValues({}, node), {
@@ -5880,7 +6517,7 @@ function materialiseOffsetPathsInTree(root) {
5880
6517
  else delete out.transform;
5881
6518
  }
5882
6519
  }
5883
- if ((_a = out.children) == null ? void 0 : _a.length) {
6520
+ if ((_a2 = out.children) == null ? void 0 : _a2.length) {
5884
6521
  const children = out.children.map(walk);
5885
6522
  if (children.some((c, i) => c !== out.children[i])) out = __spreadProps(__spreadValues({}, out), { children });
5886
6523
  }
@@ -5889,16 +6526,16 @@ function materialiseOffsetPathsInTree(root) {
5889
6526
  return walk(root);
5890
6527
  }
5891
6528
 
5892
- // src/PxAnimatorMaterialiseAll.ts
5893
- function materialiseAllInTree(doc, engine, opts) {
5894
- var _a, _b;
6529
+ // src/materialize/PxAnimatorMaterializeAll.ts
6530
+ function materializeAllInTree(doc, engine, opts) {
6531
+ var _a2, _b;
5895
6532
  let root = applyPlayerEffects(doc).root;
5896
- root = materialiseOffsetPathsInTree(root);
5897
- const duration = (_b = (_a = getAnimatorConfig(root)) == null ? void 0 : _a.duration) != null ? _b : DEFAULT_DURATION_MS;
5898
- root = materialiseInternalLoopsInTree(root, duration);
5899
- if (engine === PxAnimatorEngine.waapi) {
5900
- root = materialiseMotionPathsInTree(root, opts == null ? void 0 : opts.motionPath);
5901
- root = materialiseAnimatedUseInstances(root);
6533
+ root = materializeOffsetPathsInTree(root);
6534
+ const duration = (_b = (_a2 = getAnimatorConfig(root)) == null ? void 0 : _a2.duration) != null ? _b : DEFAULT_DURATION_MS;
6535
+ root = materializeInternalLoopsInTree(root, duration);
6536
+ if (engine === PxTimelineEngine.native) {
6537
+ root = materializeMotionPathsInTree(root, opts == null ? void 0 : opts.motionPath);
6538
+ root = materializeAnimatedUseInstances(root);
5902
6539
  root = pruneUnreferencedDefs(root);
5903
6540
  }
5904
6541
  return root;
@@ -5906,9 +6543,9 @@ function materialiseAllInTree(doc, engine, opts) {
5906
6543
  function pruneUnreferencedDefs(root) {
5907
6544
  const stripHash3 = (h) => h.startsWith("#") ? h.slice(1) : h;
5908
6545
  const walk = (n, fn) => {
5909
- var _a;
6546
+ var _a2;
5910
6547
  fn(n);
5911
- (_a = n.children) == null ? void 0 : _a.forEach((c) => walk(c, fn));
6548
+ (_a2 = n.children) == null ? void 0 : _a2.forEach((c) => walk(c, fn));
5912
6549
  };
5913
6550
  let changed = true;
5914
6551
  while (changed) {
@@ -5933,7 +6570,67 @@ function pruneUnreferencedDefs(root) {
5933
6570
  return root;
5934
6571
  }
5935
6572
 
5936
- // src/PxFrameLoop.ts
6573
+ // src/playback/PxPlaybackTime.ts
6574
+ var PX_RATE_REJECTED = "setPlaybackRate: rate must be finite and non-zero";
6575
+ function isValidPlaybackRate(rate) {
6576
+ return Number.isFinite(rate) && rate !== 0;
6577
+ }
6578
+ function seekCeilingMs(durationMs, iterations) {
6579
+ if (!(durationMs > 0)) return 0;
6580
+ if (iterations === Infinity) return Infinity;
6581
+ return durationMs * (iterations > 0 ? iterations : 1);
6582
+ }
6583
+ function progressSpanMs(durationMs, iterations) {
6584
+ if (!(durationMs > 0)) return 0;
6585
+ if (iterations === Infinity) return durationMs;
6586
+ return durationMs * (iterations > 0 ? iterations : 1);
6587
+ }
6588
+ function clampSeekMs(timeMs, ceilingMs) {
6589
+ if (Number.isNaN(timeMs) || timeMs < 0) return 0;
6590
+ if (Number.isFinite(ceilingMs)) return timeMs > ceilingMs ? ceilingMs : timeMs;
6591
+ return Number.isFinite(timeMs) ? timeMs : 0;
6592
+ }
6593
+ function timeToProgress(timeMs, durationMs, iterations) {
6594
+ const span = progressSpanMs(durationMs, iterations);
6595
+ if (!(span > 0) || !Number.isFinite(timeMs)) return 0;
6596
+ if (timeMs <= 0) return 0;
6597
+ if (iterations === Infinity) return timeMs % span / span;
6598
+ return timeMs >= span ? 1 : timeMs / span;
6599
+ }
6600
+ function progressToTimeMs(progress, durationMs, iterations) {
6601
+ const span = progressSpanMs(durationMs, iterations);
6602
+ if (!(span > 0) || !Number.isFinite(progress)) return 0;
6603
+ if (progress <= 0) return 0;
6604
+ return progress >= 1 ? span : progress * span;
6605
+ }
6606
+ function createRunClock(ceilingMs, nowFn = Date.now) {
6607
+ let baseMs = 0;
6608
+ let startedAt = 0;
6609
+ let running = false;
6610
+ let rate = 1;
6611
+ const value = () => running ? clampSeekMs(baseMs + (nowFn() - startedAt) * rate, ceilingMs) : clampSeekMs(baseMs, ceilingMs);
6612
+ return {
6613
+ now: value,
6614
+ isRunning: () => running,
6615
+ start: (r, atMs) => {
6616
+ baseMs = clampSeekMs(atMs != null ? atMs : value(), ceilingMs);
6617
+ rate = isValidPlaybackRate(r) ? r : 1;
6618
+ startedAt = nowFn();
6619
+ running = true;
6620
+ },
6621
+ stop: () => {
6622
+ baseMs = value();
6623
+ startedAt = 0;
6624
+ running = false;
6625
+ },
6626
+ seek: (ms) => {
6627
+ baseMs = clampSeekMs(ms, ceilingMs);
6628
+ if (running) startedAt = nowFn();
6629
+ }
6630
+ };
6631
+ }
6632
+
6633
+ // src/playback/PxFrameLoop.ts
5937
6634
  function requestFrame(cb) {
5938
6635
  const g = globalThis;
5939
6636
  if (typeof g.requestAnimationFrame === "function") return g.requestAnimationFrame(cb);
@@ -5948,9 +6645,9 @@ function cancelFrame(handle) {
5948
6645
  g.clearTimeout(handle);
5949
6646
  }
5950
6647
  function createBasicFrameLoopAnimator(doc, adapter, callbacks) {
5951
- var _a;
6648
+ var _a2;
5952
6649
  const config = getAnimatorConfig(doc) || {};
5953
- const bindings = getNormalisedBindings(doc, PxAnimatorEngine.frames);
6650
+ const bindings = getNormalizedBindings(doc, PxTimelineEngine.js);
5954
6651
  const _iterations = config.iterations;
5955
6652
  let iterations = 1;
5956
6653
  if (typeof _iterations === "number") iterations = _iterations || 1;
@@ -5959,7 +6656,7 @@ function createBasicFrameLoopAnimator(doc, adapter, callbacks) {
5959
6656
  const duration = +(config.duration || DEFAULT_DURATION_MS);
5960
6657
  const totalDuration = duration && iterations ? duration * (iterations === Infinity ? Infinity : iterations) : duration ? (iterations != null ? iterations : 1) * duration : 0;
5961
6658
  const direction = config.direction || "normal";
5962
- const fill = (_a = config.fill) != null ? _a : "forwards";
6659
+ const fill = (_a2 = config.fill) != null ? _a2 : "forwards";
5963
6660
  const fillsForwards = fill === "forwards" || fill === "both";
5964
6661
  const fillsBackwards = fill === "backwards" || fill === "both";
5965
6662
  let timerId = null;
@@ -6021,7 +6718,7 @@ function createBasicFrameLoopAnimator(doc, adapter, callbacks) {
6021
6718
  }
6022
6719
  }
6023
6720
  const tick = () => {
6024
- var _a2, _b;
6721
+ var _a3, _b;
6025
6722
  if (!adapter.isConnected()) {
6026
6723
  pauseAnim();
6027
6724
  return;
@@ -6037,7 +6734,7 @@ function createBasicFrameLoopAnimator(doc, adapter, callbacks) {
6037
6734
  renderFrame(0);
6038
6735
  if (!finishCalled) {
6039
6736
  finishCalled = true;
6040
- (_a2 = callbacks == null ? void 0 : callbacks.onFinish) == null ? void 0 : _a2.call(callbacks);
6737
+ (_a3 = callbacks == null ? void 0 : callbacks.onFinish) == null ? void 0 : _a3.call(callbacks);
6041
6738
  }
6042
6739
  return;
6043
6740
  }
@@ -6129,17 +6826,17 @@ function createBasicFrameLoopAnimator(doc, adapter, callbacks) {
6129
6826
  }
6130
6827
  };
6131
6828
  const cancelAnim = () => {
6132
- var _a2;
6829
+ var _a3;
6133
6830
  pauseAnim();
6134
6831
  timeBeforeLastStartMs = 0;
6135
6832
  lastStartedTs = 0;
6136
6833
  playing = false;
6137
6834
  finishCalled = false;
6138
6835
  renderFrame(timeBeforeLastStartMs);
6139
- (_a2 = callbacks == null ? void 0 : callbacks.onCancel) == null ? void 0 : _a2.call(callbacks);
6836
+ (_a3 = callbacks == null ? void 0 : callbacks.onCancel) == null ? void 0 : _a3.call(callbacks);
6140
6837
  };
6141
6838
  const finishAnim = (callOnFinish = true) => {
6142
- var _a2;
6839
+ var _a3;
6143
6840
  if (Number.isFinite(totalDuration)) {
6144
6841
  timeBeforeLastStartMs = totalDuration;
6145
6842
  } else {
@@ -6154,7 +6851,7 @@ function createBasicFrameLoopAnimator(doc, adapter, callbacks) {
6154
6851
  renderFrame(fillsForwards ? timeBeforeLastStartMs : 0);
6155
6852
  if (callOnFinish && !finishCalled) {
6156
6853
  finishCalled = true;
6157
- (_a2 = callbacks == null ? void 0 : callbacks.onFinish) == null ? void 0 : _a2.call(callbacks);
6854
+ (_a3 = callbacks == null ? void 0 : callbacks.onFinish) == null ? void 0 : _a3.call(callbacks);
6158
6855
  }
6159
6856
  };
6160
6857
  const api = {
@@ -6164,14 +6861,14 @@ function createBasicFrameLoopAnimator(doc, adapter, callbacks) {
6164
6861
  return _isPlaying();
6165
6862
  },
6166
6863
  "play": () => {
6167
- var _a2;
6864
+ var _a3;
6168
6865
  startAnim();
6169
- (_a2 = callbacks == null ? void 0 : callbacks.onPlay) == null ? void 0 : _a2.call(callbacks);
6866
+ (_a3 = callbacks == null ? void 0 : callbacks.onPlay) == null ? void 0 : _a3.call(callbacks);
6170
6867
  },
6171
6868
  "pause": () => {
6172
- var _a2;
6869
+ var _a3;
6173
6870
  pauseAnim();
6174
- (_a2 = callbacks == null ? void 0 : callbacks.onPause) == null ? void 0 : _a2.call(callbacks);
6871
+ (_a3 = callbacks == null ? void 0 : callbacks.onPause) == null ? void 0 : _a3.call(callbacks);
6175
6872
  },
6176
6873
  "cancel": () => {
6177
6874
  cancelAnim();
@@ -6180,8 +6877,8 @@ function createBasicFrameLoopAnimator(doc, adapter, callbacks) {
6180
6877
  finishAnim(true);
6181
6878
  },
6182
6879
  "setPlaybackRate": (rate) => {
6183
- if (!isFinite(rate) || rate === 0) {
6184
- console.warn("setPlaybackRate: rate must be finite and non-zero");
6880
+ if (!isValidPlaybackRate(rate)) {
6881
+ console.warn(PX_RATE_REJECTED);
6185
6882
  return;
6186
6883
  }
6187
6884
  let current = getRawAnimTime();
@@ -6195,22 +6892,70 @@ function createBasicFrameLoopAnimator(doc, adapter, callbacks) {
6195
6892
  return getAnimCurrentTime();
6196
6893
  },
6197
6894
  "setCurrentTime": (newTime) => {
6198
- if (newTime < 0) newTime = 0;
6199
- if (Number.isFinite(totalDuration) && newTime > totalDuration) newTime = totalDuration;
6895
+ newTime = clampSeekMs(newTime, totalDuration);
6200
6896
  timeBeforeLastStartMs = newTime;
6201
6897
  if (playing) lastStartedTs = Date.now();
6202
6898
  if (!Number.isFinite(totalDuration) || newTime < totalDuration) finishCalled = false;
6203
6899
  renderFrame(getAnimCurrentTime());
6204
6900
  },
6901
+ "getCurrentProgress": () => timeToProgress(getAnimCurrentTime(), duration, iterations),
6902
+ "setCurrentProgress": (progress) => {
6903
+ api.setCurrentTime(progressToTimeMs(progress, duration, iterations));
6904
+ },
6205
6905
  "destroy": () => {
6206
- var _a2;
6906
+ var _a3;
6207
6907
  api.cancel();
6208
- (_a2 = callbacks == null ? void 0 : callbacks.onRemove) == null ? void 0 : _a2.call(callbacks);
6908
+ (_a3 = callbacks == null ? void 0 : callbacks.onRemove) == null ? void 0 : _a3.call(callbacks);
6209
6909
  }
6210
6910
  };
6211
6911
  return api;
6212
6912
  }
6213
6913
 
6914
+ // src/playback/PxDiagnostics.ts
6915
+ var PxDiagnosticKind = {
6916
+ /** The document is wrong — regenerate or repair the file. */
6917
+ document: "document",
6918
+ /** The page or app cannot provide what the document asks for — fix the mount. */
6919
+ host: "host",
6920
+ /** The platform cannot do it and the player degraded — usually nothing to fix. */
6921
+ platform: "platform",
6922
+ /** The call is wrong or self-contradictory — fix the options or props you passed. */
6923
+ usage: "usage",
6924
+ /** The player failed where it did not expect to — report it to us. */
6925
+ internal: "internal"
6926
+ };
6927
+ function asError(error) {
6928
+ return typeof error === "string" ? new Error(error) : error;
6929
+ }
6930
+ function isSilenced(silent, kind) {
6931
+ if (!silent) return false;
6932
+ return silent === true || silent.includes(kind);
6933
+ }
6934
+ function createDiagnostics(config, prefix) {
6935
+ const tag = prefix ? prefix + " " : "";
6936
+ return {
6937
+ warn: (kind, message, detail) => {
6938
+ if (config == null ? void 0 : config.onWarn) {
6939
+ config.onWarn({ kind, message, detail });
6940
+ return;
6941
+ }
6942
+ if (isSilenced(config == null ? void 0 : config.silent, kind)) return;
6943
+ const line = tag + kind + ": " + message;
6944
+ if (detail === void 0) console.warn(line);
6945
+ else console.warn(line, detail);
6946
+ },
6947
+ error: (kind, error) => {
6948
+ const err = asError(error);
6949
+ if (config == null ? void 0 : config.onError) {
6950
+ config.onError({ kind, message: err.message, error: err });
6951
+ return;
6952
+ }
6953
+ if (isSilenced(config == null ? void 0 : config.silent, kind)) return;
6954
+ console.error(tag + kind + ": " + err.message);
6955
+ }
6956
+ };
6957
+ }
6958
+
6214
6959
  // src/effects/PlayerEffectsUtil.visualModel.ts
6215
6960
  var IDENTITY = [1, 0, 0, 1, 0, 0];
6216
6961
  function mul(m, n) {
@@ -6261,9 +7006,9 @@ function lerp(a, b, f) {
6261
7006
  return a + (b - a) * f;
6262
7007
  }
6263
7008
  function interpParts(kfs, t) {
6264
- var _a, _b, _c, _d, _e, _f, _g;
7009
+ var _a2, _b, _c, _d, _e, _f, _g;
6265
7010
  if (!kfs.length) return {};
6266
- if (t <= ((_a = kfs[0].time) != null ? _a : 0)) return kfs[0].value || {};
7011
+ if (t <= ((_a2 = kfs[0].time) != null ? _a2 : 0)) return kfs[0].value || {};
6267
7012
  if (t >= ((_b = kfs[kfs.length - 1].time) != null ? _b : 0)) return kfs[kfs.length - 1].value || {};
6268
7013
  let i = 0;
6269
7014
  while (i < kfs.length - 1 && ((_c = kfs[i + 1].time) != null ? _c : 0) < t) i++;
@@ -6294,10 +7039,10 @@ function nodeMatrix(node, t) {
6294
7039
  return IDENTITY;
6295
7040
  }
6296
7041
  function evalScalar(animated, staticVal, fallback, t) {
6297
- var _a, _b, _c, _d, _e, _f;
7042
+ var _a2, _b, _c, _d, _e, _f;
6298
7043
  if (animated && animated.keyframes && animated.keyframes.length) {
6299
7044
  const kfs = animated.keyframes;
6300
- if (t <= ((_a = kfs[0].time) != null ? _a : 0)) return kfs[0].value;
7045
+ if (t <= ((_a2 = kfs[0].time) != null ? _a2 : 0)) return kfs[0].value;
6301
7046
  if (t >= ((_b = kfs[kfs.length - 1].time) != null ? _b : 0)) return kfs[kfs.length - 1].value;
6302
7047
  let i = 0;
6303
7048
  while (i < kfs.length - 1 && ((_c = kfs[i + 1].time) != null ? _c : 0) < t) i++;
@@ -6310,9 +7055,9 @@ function evalScalar(animated, staticVal, fallback, t) {
6310
7055
  var CONTAINER_TYPES = /* @__PURE__ */ new Set(["svg", "g", "symbol"]);
6311
7056
  var SKIP_TYPES = /* @__PURE__ */ new Set(["defs", "mask", "clipPath", "title"]);
6312
7057
  function buildIdMap2(node, map) {
6313
- var _a;
7058
+ var _a2;
6314
7059
  if (typeof node.id === "string") map.set(node.id, node);
6315
- (_a = node.children) == null ? void 0 : _a.forEach((c) => buildIdMap2(c, map));
7060
+ (_a2 = node.children) == null ? void 0 : _a2.forEach((c) => buildIdMap2(c, map));
6316
7061
  }
6317
7062
  function num(v) {
6318
7063
  return v === void 0 || v === null ? 0 : Number(v);
@@ -6321,7 +7066,7 @@ function round(n) {
6321
7066
  return Math.round(n * 100) / 100 + 0;
6322
7067
  }
6323
7068
  function geomKey(node) {
6324
- var _a;
7069
+ var _a2;
6325
7070
  switch (node.type) {
6326
7071
  case "rect":
6327
7072
  return num(node.width) + "," + num(node.height) + "," + num(node.x) + "," + num(node.y);
@@ -6330,14 +7075,14 @@ function geomKey(node) {
6330
7075
  case "circle":
6331
7076
  return num(node.r) + "," + num(node.cx) + "," + num(node.cy);
6332
7077
  case "path":
6333
- return String((_a = node.d) != null ? _a : "");
7078
+ return String((_a2 = node.d) != null ? _a2 : "");
6334
7079
  default:
6335
7080
  return "";
6336
7081
  }
6337
7082
  }
6338
7083
  function describePrimitive(node, m, t) {
6339
- var _a, _b, _c, _d, _e;
6340
- const fill = (_a = node.fill) != null ? _a : "";
7084
+ var _a2, _b, _c, _d, _e;
7085
+ const fill = (_a2 = node.fill) != null ? _a2 : "";
6341
7086
  const stroke = (_b = node.stroke) != null ? _b : "";
6342
7087
  const sw = (_d = (_c = node["stroke-width"]) != null ? _c : node.strokeWidth) != null ? _d : "";
6343
7088
  const opacity = round(evalScalar((_e = node.animate) == null ? void 0 : _e.opacity, node.opacity, 1, t));
@@ -6346,7 +7091,7 @@ function describePrimitive(node, m, t) {
6346
7091
  return node.type + "|" + geomKey(node) + "|[" + mat + "]|f:" + fill + "|s:" + stroke + "|sw:" + (num(sw) || "") + "|o:" + opacity + "|m:" + masked;
6347
7092
  }
6348
7093
  function flatten(node, parent, t, idMap, out) {
6349
- var _a;
7094
+ var _a2;
6350
7095
  const type = node.type || "";
6351
7096
  if (SKIP_TYPES.has(type)) return;
6352
7097
  const m = mul(parent, nodeMatrix(node, t));
@@ -6359,33 +7104,33 @@ function flatten(node, parent, t, idMap, out) {
6359
7104
  return;
6360
7105
  }
6361
7106
  if (CONTAINER_TYPES.has(type)) {
6362
- (_a = node.children) == null ? void 0 : _a.forEach((c) => flatten(c, m, t, idMap, out));
7107
+ (_a2 = node.children) == null ? void 0 : _a2.forEach((c) => flatten(c, m, t, idMap, out));
6363
7108
  return;
6364
7109
  }
6365
7110
  out.push(describePrimitive(node, m, t));
6366
7111
  }
6367
7112
  function collectSampleTimes(node, into) {
6368
- var _a;
7113
+ var _a2;
6369
7114
  into.add(0);
6370
7115
  const scanAnim = (anim) => {
6371
- var _a2;
7116
+ var _a3;
6372
7117
  if (!anim || typeof anim !== "object") return;
6373
7118
  for (const key of Object.keys(anim)) {
6374
- const kfs = (_a2 = anim[key]) == null ? void 0 : _a2.keyframes;
7119
+ const kfs = (_a3 = anim[key]) == null ? void 0 : _a3.keyframes;
6375
7120
  if (Array.isArray(kfs)) kfs.forEach((kf) => {
6376
- var _a3;
6377
- return into.add((_a3 = kf.time) != null ? _a3 : 0);
7121
+ var _a4;
7122
+ return into.add((_a4 = kf.time) != null ? _a4 : 0);
6378
7123
  });
6379
7124
  }
6380
7125
  };
6381
7126
  scanAnim(node.animate);
6382
7127
  if (node.transform && typeof node.transform === "object" && node.transform.keyframes) {
6383
7128
  node.transform.keyframes.forEach((kf) => {
6384
- var _a2;
6385
- return into.add((_a2 = kf.time) != null ? _a2 : 0);
7129
+ var _a3;
7130
+ return into.add((_a3 = kf.time) != null ? _a3 : 0);
6386
7131
  });
6387
7132
  }
6388
- (_a = node.children) == null ? void 0 : _a.forEach((c) => collectSampleTimes(c, into));
7133
+ (_a2 = node.children) == null ? void 0 : _a2.forEach((c) => collectSampleTimes(c, into));
6389
7134
  }
6390
7135
  function visualModelAt(root, t) {
6391
7136
  const idMap = /* @__PURE__ */ new Map();
@@ -6419,9 +7164,181 @@ function subtractMultiset(a, b) {
6419
7164
  }
6420
7165
  return extra;
6421
7166
  }
7167
+
7168
+ // src/playback/PxAnimatorConfigPatch.ts
7169
+ var FLAT_ONLY_KEYS = [
7170
+ "timelineSource",
7171
+ "scroll",
7172
+ "trigger",
7173
+ "delay",
7174
+ "iterations",
7175
+ "direction",
7176
+ "fill",
7177
+ "resetOnFinish",
7178
+ "duration",
7179
+ "mode",
7180
+ "frameRate"
7181
+ ];
7182
+ var CONTENT_KEYS = ["definitions", "animateById"];
7183
+ var isPlainObject = (v) => !!v && typeof v === "object" && !Array.isArray(v);
7184
+ var timelineTypeOf = (t) => isPlainObject(t) && typeof t.type === "string" ? t.type : "time";
7185
+ var isScrollish = (type) => type === "scroll" || type === "view";
7186
+ function mergePlain(base, patch) {
7187
+ const out = isPlainObject(base) ? __spreadValues({}, base) : {};
7188
+ for (const key of Object.keys(patch)) {
7189
+ const value = patch[key];
7190
+ if (value === null) {
7191
+ delete out[key];
7192
+ continue;
7193
+ }
7194
+ if (isPlainObject(value)) {
7195
+ out[key] = mergePlain(out[key], value);
7196
+ continue;
7197
+ }
7198
+ out[key] = value;
7199
+ }
7200
+ return out;
7201
+ }
7202
+ function mergeTimeline(base, patch, warn) {
7203
+ const baseType = timelineTypeOf(base);
7204
+ const patchNamesType = isPlainObject(patch) && typeof patch.type === "string";
7205
+ const patchType = patchNamesType ? String(patch.type) : baseType;
7206
+ let merged;
7207
+ if (patchType !== baseType) {
7208
+ const carried = {};
7209
+ if (isPlainObject(base)) {
7210
+ for (const k of PX_TIMELINE_SHARED_KEYS) {
7211
+ if (base[k] !== void 0) carried[k] = base[k];
7212
+ }
7213
+ }
7214
+ merged = mergePlain(carried, patch);
7215
+ } else {
7216
+ merged = mergePlain(base, patch);
7217
+ }
7218
+ if (isScrollish(patchType)) {
7219
+ for (const k of PX_TIME_ONLY_TIMELINE_KEYS) {
7220
+ if (merged[k] === void 0) continue;
7221
+ warn("animator.timeline." + k + ": no slot on a '" + patchType + "' timeline \u2014 dropped");
7222
+ delete merged[k];
7223
+ }
7224
+ if (merged.iterations === "infinite") {
7225
+ warn("animator.timeline.iterations: 'infinite' cannot map onto a scroll range \u2014 dropped");
7226
+ delete merged.iterations;
7227
+ }
7228
+ }
7229
+ return merged;
7230
+ }
7231
+ function foldTimelineOverride(timeline, shortcuts) {
7232
+ let base;
7233
+ if (typeof timeline === "string") {
7234
+ try {
7235
+ base = JSON.parse(timeline);
7236
+ } catch (e) {
7237
+ console.warn("timeline override: not valid JSON \u2014 ignored", e);
7238
+ base = void 0;
7239
+ }
7240
+ } else {
7241
+ base = timeline != null ? timeline : void 0;
7242
+ }
7243
+ const { duration, delay, iterations, startOn } = shortcuts;
7244
+ if (duration === void 0 && delay === void 0 && iterations === void 0 && startOn === void 0) {
7245
+ return base === void 0 ? void 0 : { timeline: base };
7246
+ }
7247
+ const out = isPlainObject(base) ? __spreadValues({}, base) : {};
7248
+ if (duration !== void 0) out.duration = duration;
7249
+ if (delay !== void 0) out.delay = delay;
7250
+ if (iterations !== void 0) out.iterations = iterations;
7251
+ if (startOn !== void 0) {
7252
+ out.trigger = __spreadProps(__spreadValues({}, out.trigger), { startOn });
7253
+ }
7254
+ return { timeline: out };
7255
+ }
7256
+ function mergeAnimatorConfig(base, patch) {
7257
+ const warnings = [];
7258
+ const warn = (m) => warnings.push(m);
7259
+ if (patch === null) return { config: void 0, warnings };
7260
+ if (!isPlainObject(patch) || Object.keys(patch).length === 0) {
7261
+ return { config: base, warnings };
7262
+ }
7263
+ const flatInBase = isPlainObject(base) ? FLAT_ONLY_KEYS.filter((k) => base[k] !== void 0) : [];
7264
+ if (flatInBase.length) {
7265
+ warn("animator: the base carries the flat runtime spelling (" + flatInBase.join(", ") + "); the patch merges the wire spelling only");
7266
+ }
7267
+ const out = isPlainObject(base) ? __spreadValues({}, base) : {};
7268
+ for (const key of Object.keys(patch)) {
7269
+ const value = patch[key];
7270
+ if (value === null) {
7271
+ delete out[key];
7272
+ continue;
7273
+ }
7274
+ if (key === "timeline") {
7275
+ out.timeline = isPlainObject(value) ? mergeTimeline(out.timeline, value, warn) : value;
7276
+ continue;
7277
+ }
7278
+ if (isPlainObject(value)) {
7279
+ out[key] = mergePlain(out[key], value);
7280
+ continue;
7281
+ }
7282
+ out[key] = value;
7283
+ }
7284
+ return { config: out, warnings };
7285
+ }
7286
+ function applyAnimatorConfig(doc, patch, opts) {
7287
+ var _a2, _b;
7288
+ const reset = !!(opts == null ? void 0 : opts.resetDefaults);
7289
+ if (!doc || (patch === void 0 || !reset && (patch === null || !isPlainObject(patch) || !Object.keys(patch).length))) {
7290
+ return { doc, warnings: [] };
7291
+ }
7292
+ const anyDoc = doc;
7293
+ const atRoot = isPlainObject(anyDoc.animator);
7294
+ const atMeta = !atRoot && isPlainObject((_a2 = anyDoc.meta) == null ? void 0 : _a2.animator);
7295
+ const current = atRoot ? anyDoc.animator : atMeta ? anyDoc.meta.animator : void 0;
7296
+ const warnings = [];
7297
+ if (atRoot && isPlainObject((_b = anyDoc.meta) == null ? void 0 : _b.animator)) {
7298
+ warnings.push("animator: doc.meta.animator is shadowed by doc.animator and was not patched");
7299
+ }
7300
+ let base = current;
7301
+ if (reset) {
7302
+ const kept = {};
7303
+ for (const k of CONTENT_KEYS) {
7304
+ if (isPlainObject(current) && current[k] !== void 0) kept[k] = current[k];
7305
+ }
7306
+ base = kept;
7307
+ }
7308
+ const merged = mergeAnimatorConfig(base, patch != null ? patch : {});
7309
+ warnings.push(...merged.warnings);
7310
+ if (merged.config === current) return { doc, warnings };
7311
+ if (atMeta) {
7312
+ return {
7313
+ doc: __spreadProps(__spreadValues({}, anyDoc), { meta: __spreadProps(__spreadValues({}, anyDoc.meta), { animator: merged.config }) }),
7314
+ warnings
7315
+ };
7316
+ }
7317
+ return { doc: __spreadProps(__spreadValues({}, anyDoc), { animator: merged.config }), warnings };
7318
+ }
7319
+
7320
+ // src/format/PxDocumentDiagnostic.ts
7321
+ var MAX_REPORTED = 6;
7322
+ function diagnoseDocument(doc) {
7323
+ try {
7324
+ return { problems: validateDocument(doc) };
7325
+ } catch (e) {
7326
+ return { problems: [] };
7327
+ }
7328
+ }
7329
+ function reportDocumentDiagnostics(doc, where) {
7330
+ const { problems } = diagnoseDocument(doc);
7331
+ if (!problems.length) return;
7332
+ const shown = problems.slice(0, MAX_REPORTED);
7333
+ const more = problems.length - shown.length;
7334
+ console.warn(
7335
+ 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."
7336
+ );
7337
+ }
6422
7338
  // Annotate the CommonJS export names for ESM import in node:
6423
7339
  0 && (module.exports = {
6424
- COLOUR_ATTR_NAMES,
7340
+ BASELINE_PLAYER_VERSION,
7341
+ COLOR_ATTR_NAMES,
6425
7342
  CSS_ONLY_STYLE_PROPS,
6426
7343
  DEFAULT_DURATION_MS,
6427
7344
  DISALLOWED_SVG_TAGS_LOWER,
@@ -6429,116 +7346,183 @@ function subtractMultiset(a, b) {
6429
7346
  LOOP_JUMP_SHIFT_MS,
6430
7347
  MISSING_GLYPH_CLASS_NAME,
6431
7348
  PCT_BASED_ATTR_NAMES,
7349
+ PLAYER_WIRE_STEPS,
7350
+ PLAYER_WIRE_VERSION,
6432
7351
  PX_ANIM_ATTR_NAME,
6433
7352
  PX_ANIM_SRC_ATTR_NAME,
7353
+ PX_PLAYER_SCHEMA_VERSION,
7354
+ PX_RATE_REJECTED,
6434
7355
  PX_TRANSFORM_PART_KEYS,
7356
+ PX_TRIGGER_DEFAULTS,
7357
+ PX_UNKNOWN_KEY_ERROR,
7358
+ PxAlongPathMode,
6435
7359
  PxAnimatedSvgDocumentSchema,
6436
7360
  PxAnimationDefinitionSchema,
6437
7361
  PxAnimatorConfigSchema,
6438
- PxAnimatorEngine,
6439
- PxAnimatorMode,
6440
7362
  PxAttrValueSchema,
6441
7363
  PxBezierPathSchema,
6442
7364
  PxBindingSchema,
7365
+ PxClipPathEffectSchema,
6443
7366
  PxCloneEffectSchema,
7367
+ PxCloneWithout,
7368
+ PxControlMode,
6444
7369
  PxDefsSchema,
7370
+ PxDiagnosticKind,
6445
7371
  PxEasingOrRefSchema,
6446
7372
  PxEffectsSchema,
6447
7373
  PxElementAnimationSchema,
6448
7374
  PxFillGradientEffectSchema,
7375
+ PxFillMode,
7376
+ PxFinishAction,
6449
7377
  PxGradientSpreadMethod,
6450
7378
  PxGradientStopSchema,
6451
7379
  PxGradientType,
6452
- PxGradientUnits,
6453
7380
  PxKeyframeSchema,
6454
7381
  PxKeyframeValueSchema,
6455
- PxLoopExtend,
7382
+ PxLengthAdjust,
7383
+ PxLoopDirection,
7384
+ PxLoopRepeatAt,
6456
7385
  PxLoopSchema,
7386
+ PxMaskType,
6457
7387
  PxMaskedByEffectSchema,
6458
7388
  PxNodeBase,
6459
7389
  PxNodeSchema,
7390
+ PxOutAction,
7391
+ PxPathOverflow,
7392
+ PxPinAlign,
7393
+ PxPlaybackDirection,
6460
7394
  PxPropertyAnimationSchema,
6461
7395
  PxRepeaterEffectSchema,
6462
7396
  PxRetimeEffectSchema,
7397
+ PxScrollAxis,
7398
+ PxScrollKind,
7399
+ PxScrollPhase,
6463
7400
  PxScrollRangePointSchema,
6464
7401
  PxScrollRangeSchema,
6465
7402
  PxScrollSchema,
7403
+ PxScrollSource,
7404
+ PxStartOn,
6466
7405
  PxStrokeGradientEffectSchema,
6467
7406
  PxStrokeTrimEffectSchema,
6468
7407
  PxStrokeTrimSubPaths,
6469
7408
  PxSvgNodeExtra,
6470
7409
  PxTextEffectSchema,
6471
7410
  PxTextPathEffectSchema,
7411
+ PxTextPathMethod,
7412
+ PxTextPathSpacing,
7413
+ PxTimelineEngine,
7414
+ PxTimelineEngineExtra,
6472
7415
  PxTimelinePinSchema,
6473
7416
  PxTimelineSchema,
6474
7417
  PxTransformByEffectSchema,
6475
7418
  PxTransformPartsSchema,
6476
7419
  PxTransformValueSchema,
6477
7420
  PxTriggerSchema,
7421
+ PxUnits,
6478
7422
  STYLE_ATTR_NAMES,
6479
- TEXT_ATTR,
6480
7423
  TEXT_CONTENT_ATTR,
6481
7424
  TRANSFORM_FN_NAMES,
7425
+ WIRE_VERSION_KEY,
7426
+ WireStepKind,
7427
+ WireVersionRelation,
7428
+ applyAnimatorConfig,
6482
7429
  applyPlayerEffects,
7430
+ applyWireSteps,
7431
+ applyWireStepsDown,
6483
7432
  bezierToSvgPath,
6484
7433
  calcAnimationValues,
6485
7434
  camelCaseToKebabWordIfNeeded,
6486
7435
  clamp,
7436
+ clampSeekMs,
6487
7437
  collectSampleTimes,
7438
+ compareWireVersion,
6488
7439
  composeTransformParts,
7440
+ controlModeTakesOverTrigger,
7441
+ convertPlayerDocument,
6489
7442
  createBasicFrameLoopAnimator,
7443
+ createDiagnostics,
6490
7444
  createPathSampler,
7445
+ createRunClock,
6491
7446
  cubicBezier,
6492
7447
  deepClone,
6493
7448
  describeSchema,
7449
+ diagnoseDocument,
7450
+ diffFieldUniverse,
6494
7451
  diffInEffect,
7452
+ downgradePlayerDocument,
6495
7453
  evaluateMotionPathSegment,
6496
7454
  extendedPathForBrowser,
6497
7455
  flattenAnimatorTimeline,
7456
+ foldTimelineOverride,
7457
+ formatWireVersion,
6498
7458
  generateNewIds,
6499
7459
  generateUniqueId,
6500
7460
  getAnimatorConfig,
6501
7461
  getBindings,
6502
7462
  getChildren,
6503
7463
  getDefs,
6504
- getNormalisedBindings,
7464
+ getNormalizedBindings,
6505
7465
  getNormalizedProps,
6506
7466
  interpolateBeziers,
6507
7467
  interpolateValue,
7468
+ isNativeForced,
6508
7469
  isPxElementFileFormat,
6509
7470
  isPxElementFileFormatDeep,
6510
7471
  isScrollTimeline,
7472
+ isValidPlaybackRate,
6511
7473
  jsonElementFactory,
6512
7474
  kebabToCamelCaseWord,
7475
+ kfEasing,
7476
+ kfTangentIn,
7477
+ kfTangentOut,
7478
+ kfTime,
7479
+ kfValue,
6513
7480
  layoutGlyphTextChars,
6514
- materialiseAllInTree,
6515
- materialiseAnimatedUseInstances,
6516
- materialiseGlyphText,
6517
- materialiseGlyphTextAlongPath,
6518
- materialiseGlyphTextHorizontal,
6519
- materialiseInternalLoopsInPropAnim,
6520
- materialiseInternalLoopsInTree,
6521
- materialiseMotionPathInPropAnim,
6522
- materialiseMotionPathsInTree,
7481
+ materializeAllInTree,
7482
+ materializeAnimatedUseInstances,
7483
+ materializeGlyphText,
7484
+ materializeGlyphTextAlongPath,
7485
+ materializeGlyphTextHorizontal,
7486
+ materializeInternalLoopsInPropAnim,
7487
+ materializeInternalLoopsInTree,
7488
+ materializeMotionPathInPropAnim,
7489
+ materializeMotionPathsInTree,
7490
+ mayUseNativeScrollTimeline,
7491
+ mergeAnimatorConfig,
6523
7492
  mergeStaticTransformIntoAnimDef,
6524
7493
  nestAnimatorTimeline,
6525
7494
  parseTransformParts,
7495
+ parseWireVersion,
7496
+ planSchemaRelease,
7497
+ progressSpanMs,
7498
+ progressToTimeMs,
6526
7499
  propAnimIsMotionPath,
6527
7500
  px,
7501
+ readWireVersion,
7502
+ releaseLogProblems,
7503
+ reportDocumentDiagnostics,
7504
+ resolveControlMode,
6528
7505
  resolveStyle,
7506
+ resolveTimelineEngine,
7507
+ resolveTrigger,
6529
7508
  reverseEasing,
6530
- sanitiseAttributeValue,
7509
+ sanitizeAttributeValue,
7510
+ schemaFieldUniverse,
6531
7511
  schemaKeys,
6532
7512
  scrollOffsetProgress,
6533
7513
  scrollPhaseInterval,
6534
7514
  scrollResolveAxis,
6535
7515
  scrollTotalDurationMs,
6536
7516
  scrollViewProgress,
7517
+ seekCeilingMs,
6537
7518
  shiftAnimatable,
6538
7519
  splitEasing,
6539
7520
  subdivideCubicBezier,
7521
+ timeToProgress,
6540
7522
  toRGBA,
7523
+ validateDocument,
6541
7524
  validateNodeEffects,
7525
+ versionAdvice,
6542
7526
  visualModelAt
6543
7527
  });
6544
7528
  //# sourceMappingURL=index.cjs.map