@pixodesk/svg-animator-web 1.0.21 → 1.0.24

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.umd.js CHANGED
@@ -8,6 +8,7 @@ var PixodeskAnimator = (() => {
8
8
  var __getOwnPropSymbols = Object.getOwnPropertySymbols;
9
9
  var __hasOwnProp = Object.prototype.hasOwnProperty;
10
10
  var __propIsEnum = Object.prototype.propertyIsEnumerable;
11
+ var __pow = Math.pow;
11
12
  var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
12
13
  var __spreadValues = (a, b) => {
13
14
  for (var prop in b || (b = {}))
@@ -47,130 +48,22 @@ var PixodeskAnimator = (() => {
47
48
  };
48
49
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
49
50
 
50
- // src/index.ts
51
- var index_exports = {};
52
- __export(index_exports, {
53
- COLOUR_ATTR_NAMES: () => COLOUR_ATTR_NAMES,
51
+ // src/index.player.ts
52
+ var index_player_exports = {};
53
+ __export(index_player_exports, {
54
54
  PX_ANIMATOR_DATA_KEY: () => PX_ANIMATOR_DATA_KEY,
55
55
  PX_ANIM_ATTR_NAME: () => PX_ANIM_ATTR_NAME,
56
56
  PX_ANIM_SRC_ATTR_NAME: () => PX_ANIM_SRC_ATTR_NAME,
57
- PX_TRANSFORM_PART_KEYS: () => PX_TRANSFORM_PART_KEYS,
58
- PxAnimatedSvgDocumentSchema: () => PxAnimatedSvgDocumentSchema,
59
- PxAnimationDefinitionSchema: () => PxAnimationDefinitionSchema,
60
- PxAnimatorConfigSchema: () => PxAnimatorConfigSchema,
61
57
  PxAnimatorEngine: () => PxAnimatorEngine,
62
58
  PxAnimatorMode: () => PxAnimatorMode,
63
- PxAttrValueSchema: () => PxAttrValueSchema,
64
- PxBezierPathSchema: () => PxBezierPathSchema,
65
- PxBindingSchema: () => PxBindingSchema,
66
- PxCloneEffectSchema: () => PxCloneEffectSchema,
67
- PxDefsSchema: () => PxDefsSchema,
68
- PxEasingOrRefSchema: () => PxEasingOrRefSchema,
69
- PxEffectsSchema: () => PxEffectsSchema,
70
- PxElementAnimationSchema: () => PxElementAnimationSchema,
71
- PxFillGradientEffectSchema: () => PxFillGradientEffectSchema,
72
- PxGradientSpreadMethod: () => PxGradientSpreadMethod,
73
- PxGradientStopSchema: () => PxGradientStopSchema,
74
- PxGradientType: () => PxGradientType,
75
- PxGradientUnits: () => PxGradientUnits,
76
- PxKeyframeSchema: () => PxKeyframeSchema,
77
- PxLoopSchema: () => PxLoopSchema,
78
- PxMaskedByEffectSchema: () => PxMaskedByEffectSchema,
79
- PxNodeBase: () => PxNodeBase,
80
- PxNodeSchema: () => PxNodeSchema,
81
- PxPropertyAnimationSchema: () => PxPropertyAnimationSchema,
82
- PxRepeaterEffectSchema: () => PxRepeaterEffectSchema,
83
- PxRetimeEffectSchema: () => PxRetimeEffectSchema,
84
- PxStrokeGradientEffectSchema: () => PxStrokeGradientEffectSchema,
85
- PxSvgNodeExtra: () => PxSvgNodeExtra,
86
- PxTextEffectSchema: () => PxTextEffectSchema,
87
- PxTextPathEffectSchema: () => PxTextPathEffectSchema,
88
- PxTransformPartsSchema: () => PxTransformPartsSchema,
89
- PxTransformValueSchema: () => PxTransformValueSchema,
90
- PxTransformationEffectSchema: () => PxTransformationEffectSchema,
91
- PxTriggerSchema: () => PxTriggerSchema,
92
- PxTrimPathEffectSchema: () => PxTrimPathEffectSchema,
93
- STYLE_ATTR_NAMES: () => STYLE_ATTR_NAMES,
94
- TRANSFORM_FN_NAMES: () => TRANSFORM_FN_NAMES,
95
- applyPlayerEffects: () => applyPlayerEffects,
96
- calcAnimationValues: () => calcAnimationValues,
97
- camelCaseToKebabWordIfNeeded: () => camelCaseToKebabWordIfNeeded,
98
- collectSampleTimes: () => collectSampleTimes,
99
59
  createAnimator: () => createAnimator,
100
60
  createAnimatorImpl: () => createAnimatorImpl,
101
- createBasicFrameLoopAnimator: () => createBasicFrameLoopAnimator,
102
- createFrameLoopAnimator: () => createFrameLoopAnimator,
103
- createPathSampler: () => createPathSampler,
104
- createWebApiAnimator: () => createWebApiAnimator,
105
- describeSchema: () => describeSchema,
106
- diffInEffect: () => diffInEffect,
107
- evaluateMotionPathSegment: () => evaluateMotionPathSegment,
108
- extendedPathForBrowser: () => extendedPathForBrowser,
109
61
  generateNewIds: () => generateNewIds,
110
- getAnimatorConfig: () => getAnimatorConfig,
111
- getBindings: () => getBindings,
112
- getChildren: () => getChildren,
113
- getDefs: () => getDefs,
114
- getNormalizedProps: () => getNormalizedProps,
115
- isPxElementFileFormat: () => isPxElementFileFormat,
116
- isPxElementFileFormatDeep: () => isPxElementFileFormatDeep,
117
- jsonElementFactory: () => jsonElementFactory,
118
- layoutGlyphTextChars: () => layoutGlyphTextChars,
119
62
  loadTagAnimators: () => loadTagAnimators,
120
- materialiseAllInTree: () => materialiseAllInTree,
121
- materialiseAnimatedUseInstances: () => materialiseAnimatedUseInstances,
122
- materialiseGlyphText: () => materialiseGlyphText,
123
- materialiseGlyphTextAlongPath: () => materialiseGlyphTextAlongPath,
124
- materialiseGlyphTextHorizontal: () => materialiseGlyphTextHorizontal,
125
- materialiseInternalLoopsInPropAnim: () => materialiseInternalLoopsInPropAnim,
126
- materialiseInternalLoopsInTree: () => materialiseInternalLoopsInTree,
127
- materialiseMotionPathInPropAnim: () => materialiseMotionPathInPropAnim,
128
- materialiseMotionPathsInTree: () => materialiseMotionPathsInTree,
129
- normalizeDocument: () => getNormalisedBindings,
130
- propAnimIsMotionPath: () => propAnimIsMotionPath,
131
- px: () => px,
132
- renderNode: () => renderNode,
133
- schemaKeys: () => schemaKeys,
134
- setupAnimationTriggers: () => setupAnimationTriggers,
135
- shiftAnimatable: () => shiftAnimatable,
136
- toRGBA: () => toRGBA,
137
- validateNodeEffects: () => validateNodeEffects,
138
- visualModelAt: () => visualModelAt
63
+ setupAnimationTriggers: () => setupAnimationTriggers
139
64
  });
140
65
 
141
- // ../svg-animator-core/dist/index.js
142
- var __defProp2 = Object.defineProperty;
143
- var __defProps2 = Object.defineProperties;
144
- var __getOwnPropDescs2 = Object.getOwnPropertyDescriptors;
145
- var __getOwnPropSymbols2 = Object.getOwnPropertySymbols;
146
- var __hasOwnProp2 = Object.prototype.hasOwnProperty;
147
- var __propIsEnum2 = Object.prototype.propertyIsEnumerable;
148
- var __pow = Math.pow;
149
- var __defNormalProp2 = (obj, key, value) => key in obj ? __defProp2(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
150
- var __spreadValues2 = (a, b) => {
151
- for (var prop in b || (b = {}))
152
- if (__hasOwnProp2.call(b, prop))
153
- __defNormalProp2(a, prop, b[prop]);
154
- if (__getOwnPropSymbols2)
155
- for (var prop of __getOwnPropSymbols2(b)) {
156
- if (__propIsEnum2.call(b, prop))
157
- __defNormalProp2(a, prop, b[prop]);
158
- }
159
- return a;
160
- };
161
- var __spreadProps2 = (a, b) => __defProps2(a, __getOwnPropDescs2(b));
162
- var __objRest2 = (source, exclude) => {
163
- var target = {};
164
- for (var prop in source)
165
- if (__hasOwnProp2.call(source, prop) && exclude.indexOf(prop) < 0)
166
- target[prop] = source[prop];
167
- if (source != null && __getOwnPropSymbols2)
168
- for (var prop of __getOwnPropSymbols2(source)) {
169
- if (exclude.indexOf(prop) < 0 && __propIsEnum2.call(source, prop))
170
- target[prop] = source[prop];
171
- }
172
- return target;
173
- };
66
+ // ../svg-animator-core/src/PxSchema.ts
174
67
  function pathStr(path) {
175
68
  if (!path.length) return ".";
176
69
  let result = "";
@@ -292,8 +185,9 @@ var PixodeskAnimator = (() => {
292
185
  }
293
186
  isValid(raw, ctx, path) {
294
187
  var _a;
295
- if (this.schemas.some((s) => s.isValid(raw))) return true;
296
- 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, 60));
188
+ const probe = ctx && { errors: [], warnings: [], strict: ctx.strict };
189
+ if (this.schemas.some((s) => s.isValid(raw, probe, path ? [...path] : void 0))) return true;
190
+ 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));
297
191
  return false;
298
192
  }
299
193
  _canSanitize(raw) {
@@ -369,6 +263,7 @@ var PixodeskAnimator = (() => {
369
263
  if (ctx == null ? void 0 : ctx.strict) {
370
264
  for (const key of Object.keys(obj)) {
371
265
  if (key in this._shape) continue;
266
+ if (obj[key] === void 0) continue;
372
267
  p.push(key);
373
268
  ctx.errors.push(pathStr(p) + ": unexpected extra key");
374
269
  p.pop();
@@ -392,7 +287,7 @@ var PixodeskAnimator = (() => {
392
287
  }
393
288
  sanitize(raw) {
394
289
  const src = raw && typeof raw === "object" && !Array.isArray(raw) ? raw : {};
395
- const out = __spreadValues2({}, src);
290
+ const out = __spreadValues({}, src);
396
291
  for (const key of Object.keys(this._shape)) {
397
292
  out[key] = this._shape[key].sanitize(src[key]);
398
293
  }
@@ -509,6 +404,23 @@ var PixodeskAnimator = (() => {
509
404
  return true;
510
405
  }
511
406
  };
407
+ var Defined = class extends Base {
408
+ constructor() {
409
+ super(...arguments);
410
+ this._default = void 0;
411
+ }
412
+ sanitize(raw) {
413
+ return raw;
414
+ }
415
+ isValid(raw, ctx, path) {
416
+ if (raw !== void 0) return true;
417
+ ctx == null ? void 0 : ctx.errors.push(pathStr(path != null ? path : []) + ": required value is missing");
418
+ return false;
419
+ }
420
+ _canSanitize(raw) {
421
+ return raw !== void 0;
422
+ }
423
+ };
512
424
  var Lazy = class extends Base {
513
425
  constructor(fn, _default) {
514
426
  super();
@@ -562,20 +474,6 @@ var PixodeskAnimator = (() => {
562
474
  function implementsInterface() {
563
475
  return (schema) => schema;
564
476
  }
565
- function schemaKeys(schema) {
566
- return Object.fromEntries(
567
- Object.keys(schema["_shape"]).map((k) => [k, k])
568
- );
569
- }
570
- function describeSchema(schema) {
571
- var _a;
572
- const s = schema;
573
- if ("_shape" in s) return { kind: "shape", shape: s._shape };
574
- if ("item" in s) return { kind: "array", item: s.item };
575
- if ("inner" in s) return { kind: "optional", inner: s.inner };
576
- if ("fn" in s) return { kind: "lazy", resolved: (_a = s.resolved) != null ? _a : s.fn() };
577
- return { kind: "leaf" };
578
- }
579
477
  var px = {
580
478
  /** Matches a string. Default: '' or provided value. */
581
479
  string: (defaultVal = "") => new Str(defaultVal),
@@ -613,29 +511,72 @@ var PixodeskAnimator = (() => {
613
511
  * @example
614
512
  * const PxSvgNodeSchema = px.extendedObject(PxNodeBase, { width: px.number().optional() });
615
513
  */
616
- extendedObject: (base, extra) => new Obj(__spreadValues2(__spreadValues2({}, base._shape), extra)),
514
+ extendedObject: (base, extra) => new Obj(__spreadValues(__spreadValues({}, base._shape), extra)),
617
515
  /** Array whose unrecoverable items are filtered out. Default: []. */
618
516
  array: (item) => new Arr(item),
619
517
  /** String-keyed record whose unrecoverable values are dropped. Default: {}. */
620
518
  record: (value) => new Rec(value),
621
519
  /** Passes anything through unchanged — always valid. */
622
520
  any: () => new Any(),
521
+ /** Anything EXCEPT `undefined` — an open type whose presence is required (V6). */
522
+ defined: () => new Defined(),
623
523
  /** Fixed-length tuple — validates element count and each position individually. */
624
524
  tuple: (schemas) => new Tuple(schemas),
625
525
  /** Defers schema creation — required for recursive types. Must supply a default value. */
626
526
  lazy: (fn, defaultVal) => new Lazy(fn, defaultVal)
627
527
  };
528
+
529
+ // ../svg-animator-core/src/PxAnimatorConstants.ts
628
530
  var PX_ANIM_SRC_ATTR_NAME = "data-px-animation-src";
629
531
  var PX_ANIM_ATTR_NAME = "_px_animator";
630
532
  var PxAnimatorMode = {
631
533
  auto: "auto",
632
- webapi: "webapi",
534
+ waapi: "waapi",
633
535
  frames: "frames"
634
536
  };
635
537
  var PxAnimatorEngine = {
636
- webapi: PxAnimatorMode.webapi,
538
+ waapi: PxAnimatorMode.waapi,
637
539
  frames: PxAnimatorMode.frames
638
540
  };
541
+ var PxLoopExtend = {
542
+ /** Segment from the START; the animation is extended BEFORE the first keyframe
543
+ * (intro loops that run before the main timeline begins). */
544
+ before: "before",
545
+ /** DEFAULT — segment from the END; extended AFTER the last keyframe (idle/outro
546
+ * loops that continue once the main timeline has finished). */
547
+ after: "after"
548
+ };
549
+ var PxMaskType = {
550
+ luminance: "luminance",
551
+ alpha: "alpha"
552
+ };
553
+ var PxUnits = {
554
+ userSpaceOnUse: "userSpaceOnUse",
555
+ objectBoundingBox: "objectBoundingBox"
556
+ };
557
+ var PxCloneType = {
558
+ content: "content"
559
+ };
560
+ var PxPathOverflow = {
561
+ clip: "clip",
562
+ extend: "extend"
563
+ };
564
+ var PxLengthAdjust = {
565
+ spacing: "spacing",
566
+ spacingAndGlyphs: "spacingAndGlyphs"
567
+ };
568
+ var PxTextPathMethod = {
569
+ align: "align",
570
+ stretch: "stretch"
571
+ };
572
+ var PxTextPathSpacing = {
573
+ auto: "auto",
574
+ exact: "exact"
575
+ };
576
+ var PxTrimSubPaths = {
577
+ separate: "separate",
578
+ combined: "combined"
579
+ };
639
580
  var TEXT_ATTR = "text";
640
581
  var TEXT_CONTENT_ATTR = "textContent";
641
582
  var INTERNAL_ATTRS = /* @__PURE__ */ new Set([
@@ -644,9 +585,47 @@ var PixodeskAnimator = (() => {
644
585
  "animator",
645
586
  "meta",
646
587
  "animate",
588
+ "effects",
647
589
  TEXT_ATTR,
648
590
  TEXT_CONTENT_ATTR
649
591
  ]);
592
+ var PxGradientUnits = {
593
+ userSpaceOnUse: "userSpaceOnUse",
594
+ objectBoundingBox: "objectBoundingBox"
595
+ };
596
+ var PxGradientSpreadMethod = {
597
+ pad: "pad",
598
+ reflect: "reflect",
599
+ repeat: "repeat"
600
+ };
601
+ var PxGradientType = {
602
+ linear: "linear",
603
+ radial: "radial"
604
+ };
605
+ function isPxElementFileFormat(fileJson) {
606
+ if (!(fileJson && typeof fileJson === "object" && !Array.isArray(fileJson))) {
607
+ return false;
608
+ }
609
+ return fileJson["type"] === "svg";
610
+ }
611
+ function getAnimatorConfig(doc) {
612
+ var _a;
613
+ return (doc == null ? void 0 : doc.animator) || ((_a = doc == null ? void 0 : doc.meta) == null ? void 0 : _a.animator);
614
+ }
615
+ function getDefs(doc) {
616
+ var _a;
617
+ if (!doc) return void 0;
618
+ return (_a = getAnimatorConfig(doc)) == null ? void 0 : _a.definitions;
619
+ }
620
+ function getBindings(doc) {
621
+ var _a;
622
+ if (!doc) return void 0;
623
+ const animateById = (_a = getAnimatorConfig(doc)) == null ? void 0 : _a.animateById;
624
+ if (!animateById) return void 0;
625
+ return Object.entries(animateById).map(([id, anim]) => ({ id, animate: anim }));
626
+ }
627
+
628
+ // ../svg-animator-core/src/PxAnimatorTypes.ts
650
629
  var PxEasingOrRefSchema = px.union([
651
630
  px.string(),
652
631
  px.tuple([px.number(), px.number(), px.number(), px.number()])
@@ -658,13 +637,15 @@ var PixodeskAnimator = (() => {
658
637
  px.array(px.number()),
659
638
  px.lazy(() => PxTransformPartsSchema, {}),
660
639
  px.object({ path: px.string() }),
661
- px.lazy(() => px.object({ paths: px.array(PxBezierPathSchema) }), { paths: [] })
640
+ px.lazy(() => px.object({ paths: px.array(PxBezierPathSchema) }), { paths: [] }),
641
+ // Gradient `stops` timeline — each kf value is the full stops-array snapshot.
642
+ px.lazy(() => px.array(PxGradientStopSchema), [])
662
643
  ]));
663
644
  var PxKeyframeSchema = implementsInterface()(px.object({
664
645
  time: px.number().optional(),
665
646
  t: px.number().optional(),
666
- value: px.any().optional(),
667
- v: px.any().optional(),
647
+ value: PxKeyframeValueSchema.optional(),
648
+ v: PxKeyframeValueSchema.optional(),
668
649
  easing: PxEasingOrRefSchema.optional(),
669
650
  e: PxEasingOrRefSchema.optional(),
670
651
  tangentOut: px.tuple([px.number(), px.number()]).optional(),
@@ -678,16 +659,16 @@ var PixodeskAnimator = (() => {
678
659
  }));
679
660
  var PxLoopSchema = implementsInterface()(px.object({
680
661
  segmentCount: px.number().optional(),
681
- before: px.boolean().optional(),
662
+ extend: px.enum([PxLoopExtend.before, PxLoopExtend.after]).optional(),
682
663
  alternate: px.boolean().optional()
683
664
  }));
684
665
  var PxPropertyAnimationSchema = implementsInterface()(px.object({
666
+ value: PxKeyframeValueSchema.optional(),
685
667
  keyframes: px.array(PxKeyframeSchema).optional(),
686
668
  kfs: px.array(PxKeyframeSchema).optional(),
687
669
  loop: px.union([PxLoopSchema, px.boolean()]).optional(),
688
670
  autoOrient: px.boolean().optional()
689
671
  }));
690
- var PX_TRANSFORM_PART_KEYS = ["translate", "rotate", "scale", "origin"];
691
672
  var PxTransformPartsSchema = implementsInterface()(px.object({
692
673
  translate: px.tuple([px.number(), px.number()]).optional(),
693
674
  rotate: px.number().optional(),
@@ -697,6 +678,7 @@ var PixodeskAnimator = (() => {
697
678
  }));
698
679
  var PxTransformValueSchema = px.union([
699
680
  px.string(),
681
+ PxTransformPartsSchema,
700
682
  px.object({ value: PxTransformPartsSchema }),
701
683
  PxPropertyAnimationSchema
702
684
  ]);
@@ -731,9 +713,11 @@ var PixodeskAnimator = (() => {
731
713
  glyphs: px.record(PxGlyphFontSchema).optional()
732
714
  }));
733
715
  var PxAnimatorConfigSchema = implementsInterface()(px.object({
734
- mode: px.enum([PxAnimatorMode.auto, PxAnimatorMode.webapi, PxAnimatorMode.frames]).optional(),
716
+ mode: px.enum([PxAnimatorMode.auto, PxAnimatorMode.waapi, PxAnimatorMode.frames]).optional(),
735
717
  duration: px.number().optional(),
736
718
  delay: px.number().optional(),
719
+ // LAW (SCHEMA-DESIGN R3, S10): the ONE sanctioned string-in-number union
720
+ // (CSS animation-iteration-count familiarity) — do not add more mixed unions.
737
721
  iterations: px.union([px.number(), px.literal("infinite")]).optional(),
738
722
  fill: px.enum(["forwards", "backwards", "both", "none"]).optional(),
739
723
  direction: px.enum(["normal", "reverse", "alternate", "alternate-reverse"]).optional(),
@@ -741,8 +725,8 @@ var PixodeskAnimator = (() => {
741
725
  trigger: PxTriggerSchema.optional(),
742
726
  resetOnFinish: px.boolean().optional(),
743
727
  definitions: PxDefsSchema.optional(),
744
- animate: px.record(PxElementAnimationSchema).optional(),
745
- debug: px.boolean().optional(),
728
+ animateById: px.record(PxElementAnimationSchema).optional(),
729
+ timelineSource: px.string().optional(),
746
730
  debugInstName: px.string().optional()
747
731
  }));
748
732
  var PxBindingSchema = implementsInterface()(px.object({
@@ -752,26 +736,29 @@ var PixodeskAnimator = (() => {
752
736
  var PxAttrValueSchema = px.union([
753
737
  px.string(),
754
738
  px.number(),
755
- px.object({ value: px.any() }),
756
- PxPropertyAnimationSchema
739
+ px.array(px.number()),
740
+ // Structured static — `{value: …}` (read-accepted transitional spelling, S1).
741
+ // `defined`, not `any`: the KEY's presence is what identifies this branch (V6).
742
+ px.object({ value: px.defined() }),
743
+ // Bare transform parts record — the canonical static `transform` on the wire (T2).
744
+ PxTransformPartsSchema
757
745
  ]);
758
746
  var PxAnimatableNumberSchema = px.union([
759
747
  px.number(),
760
748
  px.object({ value: px.number() }),
761
- px.object({
762
- keyframes: px.array(PxKeyframeSchema),
763
- autoOrient: px.boolean().optional()
764
- })
749
+ PxPropertyAnimationSchema
765
750
  ]);
766
751
  var PxAnimatableVec2Schema = px.union([
767
752
  px.tuple([px.number(), px.number()]),
768
753
  px.object({ value: px.tuple([px.number(), px.number()]) }),
769
- px.object({
770
- keyframes: px.array(PxKeyframeSchema),
771
- autoOrient: px.boolean().optional()
772
- })
754
+ PxPropertyAnimationSchema
755
+ ]);
756
+ var PxAnimatableStringSchema = px.union([
757
+ px.string(),
758
+ px.object({ value: px.string() }),
759
+ PxPropertyAnimationSchema
773
760
  ]);
774
- var PxTransformationEffectSchema = implementsInterface()(px.object({
761
+ var PxTransformByEffectSchema = implementsInterface()(px.object({
775
762
  translate: PxAnimatableVec2Schema.optional(),
776
763
  rotate: PxAnimatableNumberSchema.optional(),
777
764
  scale: PxAnimatableVec2Schema.optional(),
@@ -779,51 +766,46 @@ var PixodeskAnimator = (() => {
779
766
  origin: PxAnimatableVec2Schema.optional()
780
767
  }));
781
768
  var PxRepeaterEffectSchema = implementsInterface()(px.object({
769
+ // STATIC config, not a channel (V2/SCHEMA-DESIGN R5): the copy COUNT is read
770
+ // once at expansion time and never sampled — plain number, no `keyframes`.
782
771
  copies: px.number().optional(),
783
772
  translate: PxAnimatableVec2Schema.optional(),
784
773
  rotate: PxAnimatableNumberSchema.optional(),
774
+ skew: PxAnimatableNumberSchema.optional(),
785
775
  scale: PxAnimatableVec2Schema.optional(),
786
776
  origin: PxAnimatableVec2Schema.optional()
787
777
  }));
788
778
  var PxMaskedByEffectSchema = implementsInterface()(px.object({
789
- href: px.string().optional(),
790
- maskType: px.string().optional(),
791
- maskUnits: px.string().optional(),
792
- maskContentUnits: px.string().optional()
779
+ sourceId: px.string().optional(),
780
+ maskType: px.enum([PxMaskType.luminance, PxMaskType.alpha]).optional(),
781
+ maskUnits: px.enum([PxUnits.userSpaceOnUse, PxUnits.objectBoundingBox]).optional(),
782
+ maskContentUnits: px.enum([PxUnits.userSpaceOnUse, PxUnits.objectBoundingBox]).optional(),
783
+ x: px.number().optional(),
784
+ y: px.number().optional(),
785
+ width: px.number().optional(),
786
+ height: px.number().optional()
793
787
  }));
794
788
  var PxClipPathEffectSchema = implementsInterface()(px.object({
795
- d: px.string().optional(),
789
+ d: PxAnimatableStringSchema.optional(),
796
790
  animate: PxPropertyAnimationSchema.optional()
797
791
  }));
798
792
  var PxTrimPathEffectSchema = implementsInterface()(px.object({
799
793
  offset: PxAnimatableNumberSchema.optional(),
800
794
  range: PxAnimatableVec2Schema.optional(),
801
- trimAllAsOne: px.boolean().optional()
795
+ subPaths: px.enum([PxTrimSubPaths.separate, PxTrimSubPaths.combined]).optional()
802
796
  }));
803
797
  var PxRetimeEffectSchema = implementsInterface()(px.object({
804
- baseId: px.string().optional(),
798
+ sourceId: px.string().optional(),
805
799
  start: px.number().optional(),
806
800
  stretch: px.number().optional(),
807
801
  timeCrop: px.tuple([px.number(), px.number()]).optional()
808
802
  }));
809
803
  var PxCloneEffectSchema = implementsInterface()(px.object({
810
- type: px.string().optional(),
811
- baseId: px.string().optional(),
804
+ // Contextual kind — the `type` convention, see `PxNodeBase.type`.
805
+ type: px.enum([PxCloneType.content]).optional(),
806
+ sourceId: px.string().optional(),
812
807
  retime: PxRetimeEffectSchema.optional()
813
808
  }));
814
- var PxGradientUnits = {
815
- userSpaceOnUse: "userSpaceOnUse",
816
- objectBoundingBox: "objectBoundingBox"
817
- };
818
- var PxGradientSpreadMethod = {
819
- pad: "pad",
820
- reflect: "reflect",
821
- repeat: "repeat"
822
- };
823
- var PxGradientType = {
824
- linear: "linear",
825
- radial: "radial"
826
- };
827
809
  var PxGradientStopSchema = implementsInterface()(px.object({
828
810
  offset: px.number(),
829
811
  color: px.string()
@@ -831,27 +813,28 @@ var PixodeskAnimator = (() => {
831
813
  var PxAnimatableGradientStopsSchema = px.union([
832
814
  px.array(PxGradientStopSchema),
833
815
  px.object({ value: px.array(PxGradientStopSchema) }),
834
- px.object({ keyframes: px.array(PxKeyframeSchema) })
816
+ PxPropertyAnimationSchema
835
817
  ]);
836
818
  var PxFillGradientEffectSchema = implementsInterface()(px.object({
819
+ // Contextual kind — the `type` convention, see `PxNodeBase.type`.
837
820
  type: px.enum([PxGradientType.linear, PxGradientType.radial]),
838
- p1: px.tuple([px.number(), px.number()]).optional(),
839
- p2: px.tuple([px.number(), px.number()]).optional(),
840
- c: px.tuple([px.number(), px.number()]).optional(),
841
- r: px.number().optional(),
842
- fp: px.tuple([px.number(), px.number()]).optional(),
821
+ p1: PxAnimatableVec2Schema.optional(),
822
+ p2: PxAnimatableVec2Schema.optional(),
823
+ c: PxAnimatableVec2Schema.optional(),
824
+ r: PxAnimatableNumberSchema.optional(),
825
+ fp: PxAnimatableVec2Schema.optional(),
843
826
  stops: PxAnimatableGradientStopsSchema.optional(),
844
- gradientUnits: px.string().optional(),
845
- spreadMethod: px.string().optional(),
827
+ gradientUnits: px.enum([PxGradientUnits.userSpaceOnUse, PxGradientUnits.objectBoundingBox]).optional(),
828
+ spreadMethod: px.enum([PxGradientSpreadMethod.pad, PxGradientSpreadMethod.reflect, PxGradientSpreadMethod.repeat]).optional(),
846
829
  gradientTransform: px.string().optional()
847
830
  }));
848
831
  var PxStrokeGradientEffectSchema = PxFillGradientEffectSchema;
849
832
  var PxTextPathEffectSchema = implementsInterface()(px.object({
850
833
  path: px.string(),
851
- pathOverflow: px.string().optional(),
852
- lengthAdjust: px.string().optional(),
853
- method: px.string().optional(),
854
- spacing: px.string().optional(),
834
+ pathOverflow: px.enum([PxPathOverflow.clip, PxPathOverflow.extend]).optional(),
835
+ lengthAdjust: px.enum([PxLengthAdjust.spacing, PxLengthAdjust.spacingAndGlyphs]).optional(),
836
+ method: px.enum([PxTextPathMethod.align, PxTextPathMethod.stretch]).optional(),
837
+ spacing: px.enum([PxTextPathSpacing.auto, PxTextPathSpacing.exact]).optional(),
855
838
  startOffset: PxAnimatableNumberSchema.optional(),
856
839
  textLength: PxAnimatableNumberSchema.optional()
857
840
  }));
@@ -859,13 +842,12 @@ var PixodeskAnimator = (() => {
859
842
  useGlyphs: px.boolean().optional()
860
843
  }));
861
844
  var PxEffectsSchema = implementsInterface()(px.object({
862
- transformation: PxTransformationEffectSchema.optional(),
845
+ transformBy: PxTransformByEffectSchema.optional(),
863
846
  repeater: PxRepeaterEffectSchema.optional(),
864
847
  maskedBy: PxMaskedByEffectSchema.optional(),
865
848
  clipPath: PxClipPathEffectSchema.optional(),
866
849
  trimPath: PxTrimPathEffectSchema.optional(),
867
850
  clone: PxCloneEffectSchema.optional(),
868
- isCombinedShape: px.boolean().optional(),
869
851
  fillGradient: PxFillGradientEffectSchema.optional(),
870
852
  strokeGradient: PxStrokeGradientEffectSchema.optional(),
871
853
  textPath: PxTextPathEffectSchema.optional(),
@@ -889,6 +871,14 @@ var PixodeskAnimator = (() => {
889
871
  return warnings;
890
872
  }
891
873
  var PxNodeBase = px.openObject({
874
+ // CONVENTION (SCHEMA-DESIGN R1 / issues N4): `type` is the ONE word for "what
875
+ // kind of thing is this", discriminated by its CARRIER — here the node TAG
876
+ // (`rect`, `text`), and inside a sub-object that object's kind (`clone.type`,
877
+ // `fillGradient.type`, editor `preset.type`). Each sits in its own object, so
878
+ // the carrier disambiguates completely; synonyms (`cloneKind`, `presetShape`)
879
+ // would add words that all mean "type" and still need the carrier to read.
880
+ // Guarding a `type` SLOT against a wrong VALUE is the job of strict enums
881
+ // (issues V3), never of distinct key names.
892
882
  type: px.string(),
893
883
  id: px.string().optional(),
894
884
  meta: px.any().optional(),
@@ -898,11 +888,11 @@ var PixodeskAnimator = (() => {
898
888
  effects: PxEffectsSchema.optional(),
899
889
  // `PxElementAnimation` (not just `PxAnimationDefinition`) — accepts
900
890
  // string ref / array of refs / inline definition / mixed array; mirrors
901
- // `animator.animate` map values and what `processNode` resolves at runtime.
891
+ // `animator.animateById` map values and what `processNode` resolves at runtime.
902
892
  animate: PxElementAnimationSchema.optional(),
903
893
  style: px.union([px.string(), px.record(px.union([px.string(), px.number()]))]).optional()
904
894
  }, PxAttrValueSchema);
905
- var PxNodeSchema = px.openObject(__spreadProps2(__spreadValues2({}, PxNodeBase._shape), {
895
+ var PxNodeSchema = px.openObject(__spreadProps(__spreadValues({}, PxNodeBase._shape), {
906
896
  children: px.lazy(() => px.array(PxNodeSchema), []).optional()
907
897
  }), PxAttrValueSchema);
908
898
  var PxSvgNodeExtra = px.object({
@@ -911,7 +901,7 @@ var PixodeskAnimator = (() => {
911
901
  viewBox: px.string().optional(),
912
902
  animator: PxAnimatorConfigSchema.optional()
913
903
  });
914
- var PxAnimatedSvgDocumentSchema = px.openObject(__spreadProps2(__spreadValues2(__spreadValues2({}, PxNodeBase._shape), PxSvgNodeExtra._shape), {
904
+ var PxAnimatedSvgDocumentSchema = px.openObject(__spreadProps(__spreadValues(__spreadValues({}, PxNodeBase._shape), PxSvgNodeExtra._shape), {
915
905
  type: px.literal("svg"),
916
906
  // override string → literal to require 'svg'
917
907
  children: px.array(PxNodeSchema).optional()
@@ -922,35 +912,8 @@ var PixodeskAnimator = (() => {
922
912
  o: px.array(px.array(px.number())).optional(),
923
913
  c: px.boolean().optional()
924
914
  }));
925
- function isPxElementFileFormat(fileJson) {
926
- if (!(fileJson && typeof fileJson === "object" && !Array.isArray(fileJson))) {
927
- return false;
928
- }
929
- return fileJson["type"] === "svg" || fileJson["tagName"] === "svg";
930
- }
931
- function isPxElementFileFormatDeep(fileJson) {
932
- const valid = PxAnimatedSvgDocumentSchema.isValid(fileJson);
933
- return { valid, errors: valid ? [] : ["Document failed schema validation"] };
934
- }
935
- function getAnimatorConfig(doc) {
936
- var _a, _b;
937
- return (doc == null ? void 0 : doc.animator) || ((_a = doc == null ? void 0 : doc.meta) == null ? void 0 : _a.animator) || (doc == null ? void 0 : doc.animation) || ((_b = doc == null ? void 0 : doc.meta) == null ? void 0 : _b.animation);
938
- }
939
- function getDefs(doc) {
940
- var _a;
941
- if (!doc) return void 0;
942
- return (_a = getAnimatorConfig(doc)) == null ? void 0 : _a.definitions;
943
- }
944
- function getBindings(doc) {
945
- var _a;
946
- if (!doc) return void 0;
947
- const animate = (_a = getAnimatorConfig(doc)) == null ? void 0 : _a.animate;
948
- if (!animate) return void 0;
949
- return Object.entries(animate).map(([id, anim]) => ({ id, animate: anim }));
950
- }
951
- function getChildren(doc) {
952
- return doc == null ? void 0 : doc.children;
953
- }
915
+
916
+ // ../svg-animator-core/src/PxAnimatorUtil.ts
954
917
  function bezierToSvgPath(path, forceCurves = false) {
955
918
  var _a, _b, _c, _d;
956
919
  const v = path.v;
@@ -1365,6 +1328,8 @@ var PixodeskAnimator = (() => {
1365
1328
  const flipped = [easing[1], easing[0], easing[3], easing[2]];
1366
1329
  return cubicBezier(flipped);
1367
1330
  }
1331
+
1332
+ // ../svg-animator-core/src/PxIdUtil.ts
1368
1333
  var _idCounter = 0;
1369
1334
  function generateUniqueId() {
1370
1335
  const timestamp = Date.now().toString(36);
@@ -1401,7 +1366,7 @@ var PixodeskAnimator = (() => {
1401
1366
  "flood-color",
1402
1367
  "lighting-color"
1403
1368
  ]);
1404
- const directIdRefAttrs = /* @__PURE__ */ new Set(["baseId", "targetId", "boundElementId"]);
1369
+ const directIdRefAttrs = /* @__PURE__ */ new Set(["sourceId", "targetId", "boundElementId"]);
1405
1370
  function collectIds(node) {
1406
1371
  if (!node || typeof node !== "object") return;
1407
1372
  if (node.id && typeof node.id === "string") {
@@ -1439,9 +1404,10 @@ var PixodeskAnimator = (() => {
1439
1404
  } else if (urlRefAttrs.has(key)) {
1440
1405
  node[key] = replaceUrlRefs(value, idMap);
1441
1406
  } else if (directIdRefAttrs.has(key)) {
1442
- const newId = idMap.get(value);
1407
+ const hasHash = value.startsWith("#");
1408
+ const newId = idMap.get(hasHash ? value.slice(1) : value);
1443
1409
  if (newId) {
1444
- node[key] = newId;
1410
+ node[key] = hasHash ? "#" + newId : newId;
1445
1411
  }
1446
1412
  } else if (value.includes("url(#")) {
1447
1413
  node[key] = replaceUrlRefs(value, idMap);
@@ -1459,14 +1425,14 @@ var PixodeskAnimator = (() => {
1459
1425
  }
1460
1426
  collectIds(cloned);
1461
1427
  updateRefs(cloned);
1462
- const docAnimate = (_a = cloned.animator) == null ? void 0 : _a.animate;
1428
+ const docAnimate = (_a = cloned.animator) == null ? void 0 : _a.animateById;
1463
1429
  if (docAnimate && typeof docAnimate === "object") {
1464
1430
  const updatedAnimate = {};
1465
1431
  for (const [id, anim] of Object.entries(docAnimate)) {
1466
1432
  const newId = (_b = idMap.get(id)) != null ? _b : id;
1467
1433
  updatedAnimate[newId] = anim;
1468
1434
  }
1469
- cloned.animator = __spreadProps2(__spreadValues2({}, cloned.animator), { animate: updatedAnimate });
1435
+ cloned.animator = __spreadProps(__spreadValues({}, cloned.animator), { animateById: updatedAnimate });
1470
1436
  }
1471
1437
  return cloned;
1472
1438
  }
@@ -1476,6 +1442,8 @@ var PixodeskAnimator = (() => {
1476
1442
  return newId ? "url(#" + newId + ")" : match;
1477
1443
  });
1478
1444
  }
1445
+
1446
+ // ../svg-animator-core/src/PxNodeProps.ts
1479
1447
  var DISALLOWED_SVG_TAGS_LOWER = /* @__PURE__ */ new Set([
1480
1448
  "script",
1481
1449
  "foreignobject"
@@ -1555,8 +1523,9 @@ var PixodeskAnimator = (() => {
1555
1523
  let value = props[rawKey];
1556
1524
  if (COLOUR_ATTR_NAMES.has(key) && Array.isArray(value)) {
1557
1525
  propsCopy[key] = toRGBA(value);
1558
- } else if (key === "transform" && value !== null && typeof value === "object" && !Array.isArray(value) && value.value && typeof value.value === "object") {
1559
- propsCopy["transform"] = composeTransformParts(value.value, { withUnits: false });
1526
+ } else if (key === "transform" && value !== null && typeof value === "object" && !Array.isArray(value) && !value.keyframes && !value.kfs) {
1527
+ const parts = value.value && typeof value.value === "object" ? value.value : value;
1528
+ propsCopy["transform"] = composeTransformParts(parts, { withUnits: false });
1560
1529
  } else if (TRANSFORM_FN_NAMES.has(key)) {
1561
1530
  if (Array.isArray(value)) {
1562
1531
  if (key === "translate") value = value.map((v) => v + "px");
@@ -1564,12 +1533,16 @@ var PixodeskAnimator = (() => {
1564
1533
  }
1565
1534
  if (key === "rotate") value = value + "deg";
1566
1535
  propsCopy["transform"] = key + "(" + value + ")";
1536
+ } else if (Array.isArray(value)) {
1537
+ propsCopy[key] = value.join(",");
1567
1538
  } else if (value !== void 0 && value !== null) {
1568
1539
  propsCopy[key] = String(value);
1569
1540
  }
1570
1541
  }
1571
1542
  return propsCopy;
1572
1543
  }
1544
+
1545
+ // ../svg-animator-core/src/PxMotionPath.ts
1573
1546
  function getKfTranslate(kf) {
1574
1547
  var _a;
1575
1548
  const v = (_a = kf.value) != null ? _a : kf.v;
@@ -1951,16 +1924,28 @@ var PixodeskAnimator = (() => {
1951
1924
  if (transformAnim && typeof transformAnim === "object" && propAnimIsMotionPath(transformAnim)) {
1952
1925
  const materialised = materialiseMotionPathInPropAnim(transformAnim, opts);
1953
1926
  if (materialised !== transformAnim) {
1954
- newAnimate = __spreadProps2(__spreadValues2({}, animDef), { transform: materialised });
1927
+ newAnimate = __spreadProps(__spreadValues({}, animDef), { transform: materialised });
1955
1928
  }
1956
1929
  }
1957
1930
  }
1958
1931
  if (!newChildren && !newAnimate) return null;
1959
- const cloned = __spreadValues2({}, node);
1932
+ const cloned = __spreadValues({}, node);
1960
1933
  if (newChildren) cloned.children = newChildren;
1961
1934
  if (newAnimate) cloned.animate = newAnimate;
1962
1935
  return cloned;
1963
1936
  }
1937
+
1938
+ // ../svg-animator-core/src/PxDefinitions.ts
1939
+ var LOOP_JUMP_SHIFT_MS = 10;
1940
+ function deepEqualValue(a, b) {
1941
+ if (a === b) return true;
1942
+ if (typeof a !== typeof b || a === null || b === null || typeof a !== "object") return false;
1943
+ if (Array.isArray(a) !== Array.isArray(b)) return false;
1944
+ const ka = Object.keys(a);
1945
+ const kb = Object.keys(b);
1946
+ if (ka.length !== kb.length) return false;
1947
+ return ka.every((k) => deepEqualValue(a[k], b[k]));
1948
+ }
1964
1949
  function parsePathCommands(d) {
1965
1950
  const tokens = d.split(/([MLCZmlcz]|[\s,]+)/).map((t) => t.trim()).filter((t) => t && t !== ",");
1966
1951
  const commands = [];
@@ -2163,7 +2148,7 @@ var PixodeskAnimator = (() => {
2163
2148
  const totalIntervals = keyframes.length - 1;
2164
2149
  const segCount = clamp((_a = loop.segmentCount) != null ? _a : totalIntervals, 1, totalIntervals);
2165
2150
  let segKfs;
2166
- if (loop.before) {
2151
+ if (loop.extend === PxLoopExtend.before) {
2167
2152
  segKfs = keyframes.slice(0, segCount + 1);
2168
2153
  } else {
2169
2154
  segKfs = keyframes.slice(totalIntervals - segCount);
@@ -2171,7 +2156,7 @@ var PixodeskAnimator = (() => {
2171
2156
  const firstT = (_b = keyframes[0].t) != null ? _b : 0;
2172
2157
  const lastT = (_c = keyframes[keyframes.length - 1].t) != null ? _c : 0;
2173
2158
  let fillStart, fillEnd;
2174
- if (loop.before) {
2159
+ if (loop.extend === PxLoopExtend.before) {
2175
2160
  fillStart = 0;
2176
2161
  fillEnd = firstT;
2177
2162
  } else {
@@ -2198,7 +2183,10 @@ var PixodeskAnimator = (() => {
2198
2183
  const remainder = fillDuration - fullReps * segDuration;
2199
2184
  const partialFraction = remainder / segDuration;
2200
2185
  const looped = [];
2186
+ const separateBoundary = loop.extend !== PxLoopExtend.before;
2187
+ const originalTerminalKf = keyframes[keyframes.length - 1];
2201
2188
  function appendRep(repStart, isReversed, partial) {
2189
+ var _a2;
2202
2190
  let entries;
2203
2191
  if (isReversed) {
2204
2192
  entries = [];
@@ -2234,8 +2222,17 @@ var PixodeskAnimator = (() => {
2234
2222
  looped.push({ t: repStart + cutRelT * segDuration, v: cutValue, e: void 0 });
2235
2223
  return;
2236
2224
  }
2225
+ const prevKf = looped.length > 0 ? looped[looped.length - 1] : originalTerminalKf;
2226
+ const isBoundary = separateBoundary && i === 0 && prevKf !== void 0 && Math.abs(((_a2 = prevKf.t) != null ? _a2 : 0) - (repStart + entry.relT * segDuration)) < 1e-9;
2227
+ if (isBoundary) {
2228
+ if (deepEqualValue(prevKf.v, entry.v)) continue;
2229
+ if (looped.length > 0) {
2230
+ delete prevKf.tangentIn;
2231
+ delete prevKf.tangentOut;
2232
+ }
2233
+ }
2237
2234
  const pushed = {
2238
- t: repStart + entry.relT * segDuration,
2235
+ t: repStart + entry.relT * segDuration + (isBoundary ? LOOP_JUMP_SHIFT_MS : 0),
2239
2236
  v: entry.v,
2240
2237
  e: i < entries.length - 1 ? entry.e : void 0
2241
2238
  };
@@ -2283,7 +2280,7 @@ var PixodeskAnimator = (() => {
2283
2280
  looped.push(pushed);
2284
2281
  }
2285
2282
  }
2286
- if (loop.before) {
2283
+ if (loop.extend === PxLoopExtend.before) {
2287
2284
  if (partialFraction > 1e-9) {
2288
2285
  const isReversed = !!loop.alternate && fullReps % 2 === 0;
2289
2286
  appendRepTail(fillStart, isReversed, partialFraction);
@@ -2306,7 +2303,7 @@ var PixodeskAnimator = (() => {
2306
2303
  appendRep(repStart, isReversed, partialFraction);
2307
2304
  }
2308
2305
  }
2309
- if (loop.before) {
2306
+ if (loop.extend === PxLoopExtend.before) {
2310
2307
  return [...looped, ...keyframes];
2311
2308
  } else {
2312
2309
  return [...keyframes, ...looped];
@@ -2407,13 +2404,13 @@ var PixodeskAnimator = (() => {
2407
2404
  const propAnim = animDef[propName];
2408
2405
  const materialised = materialiseInternalLoopsInPropAnim(propName, propAnim, duration);
2409
2406
  if (materialised !== propAnim) {
2410
- if (!newAnimate) newAnimate = __spreadValues2({}, animDef);
2407
+ if (!newAnimate) newAnimate = __spreadValues({}, animDef);
2411
2408
  newAnimate[propName] = materialised;
2412
2409
  }
2413
2410
  }
2414
2411
  }
2415
2412
  if (!newChildren && !newAnimate) return null;
2416
- const cloned = __spreadValues2({}, node);
2413
+ const cloned = __spreadValues({}, node);
2417
2414
  if (newChildren) cloned.children = newChildren;
2418
2415
  if (newAnimate) cloned.animate = newAnimate;
2419
2416
  return cloned;
@@ -2422,7 +2419,7 @@ var PixodeskAnimator = (() => {
2422
2419
  function generateElementId() {
2423
2420
  return "_px_el_" + ++_elementIdCounter;
2424
2421
  }
2425
- function normalizeAnimationDefinition(animDef, duration, defs, engine = PxAnimatorEngine.webapi) {
2422
+ function normalizeAnimationDefinition(animDef, duration, defs, engine = PxAnimatorEngine.waapi) {
2426
2423
  const normalized = {};
2427
2424
  for (const [propName, propAnim] of Object.entries(animDef)) {
2428
2425
  const normalizedKfs = normalizeKeyframes(propName, propAnim, duration, defs);
@@ -2430,12 +2427,12 @@ var PixodeskAnimator = (() => {
2430
2427
  const out = { kfs: normalizedKfs };
2431
2428
  if (propAnim.autoOrient !== void 0) out.autoOrient = propAnim.autoOrient;
2432
2429
  if (propAnim.loop !== void 0) out.loop = propAnim.loop;
2433
- normalized[propName] = engine === PxAnimatorEngine.webapi && propName === "transform" ? materialiseMotionPathInPropAnim(out) : out;
2430
+ normalized[propName] = engine === PxAnimatorEngine.waapi && propName === "transform" ? materialiseMotionPathInPropAnim(out) : out;
2434
2431
  }
2435
2432
  }
2436
2433
  return normalized;
2437
2434
  }
2438
- function getNormalisedBindings(doc, engine = PxAnimatorEngine.webapi) {
2435
+ function getNormalisedBindings(doc, engine = PxAnimatorEngine.waapi) {
2439
2436
  const animatorConfig = getAnimatorConfig(doc) || {};
2440
2437
  const defs = getDefs(doc);
2441
2438
  const duration = animatorConfig.duration || 1e3;
@@ -2600,12 +2597,12 @@ var PixodeskAnimator = (() => {
2600
2597
  cssValue = "scale(" + v.join(",") + ")";
2601
2598
  cssAttrName = "transform";
2602
2599
  } else {
2603
- const num2 = interpolateNum(
2600
+ const num = interpolateNum(
2604
2601
  +(prevV || 0),
2605
2602
  +(nextV || 0),
2606
2603
  localProgress
2607
2604
  );
2608
- cssValue = num2;
2605
+ cssValue = num;
2609
2606
  }
2610
2607
  if (PCT_BASED_ATTR_NAMES.has(cssAttrName) && typeof cssValue === "number") {
2611
2608
  cssValue = cssValue * 100 + "%";
@@ -2622,6 +2619,8 @@ var PixodeskAnimator = (() => {
2622
2619
  }
2623
2620
  return result;
2624
2621
  }
2622
+
2623
+ // ../svg-animator-core/src/PxNodeCloneUtil.ts
2625
2624
  function deepClonePxNode(value) {
2626
2625
  if (value === null || typeof value !== "object") return value;
2627
2626
  if (Array.isArray(value)) return value.map(deepClonePxNode);
@@ -2684,6 +2683,8 @@ var PixodeskAnimator = (() => {
2684
2683
  }
2685
2684
  return gNode;
2686
2685
  }
2686
+
2687
+ // ../svg-animator-core/src/PxAnimatorUseMaterialiser.ts
2687
2688
  function materialiseAnimatedUseInstances(root) {
2688
2689
  var _a;
2689
2690
  const idMap = buildIdMap(root);
@@ -2697,7 +2698,7 @@ var PixodeskAnimator = (() => {
2697
2698
  if (defsCollector.length === 0) return walked;
2698
2699
  const defsNode = { type: "defs", children: defsCollector };
2699
2700
  const newChildren = [...(_a = walked.children) != null ? _a : [], defsNode];
2700
- return __spreadProps2(__spreadValues2({}, walked), { children: newChildren });
2701
+ return __spreadProps(__spreadValues({}, walked), { children: newChildren });
2701
2702
  }
2702
2703
  function readRootViewport(root) {
2703
2704
  const vb = parseViewBox(root.viewBox);
@@ -2775,7 +2776,7 @@ var PixodeskAnimator = (() => {
2775
2776
  const useH = (_d = (_c = numericAttr(useNode.height)) != null ? _c : symbolViewBox == null ? void 0 : symbolViewBox[3]) != null ? _d : rootViewport[1];
2776
2777
  const rewrittenClone = clone2.type === "symbol" ? rewriteSymbolRootToGroup(clone2, genId3, defsCollector, useW, useH) : clone2;
2777
2778
  const materialisedClone = walkAndMaterialise2(rewrittenClone, idMap, animatedIds, genId3, defsCollector, rootViewport);
2778
- const newNode = __spreadProps2(__spreadValues2({}, useNode), { type: "g", children: [materialisedClone] });
2779
+ const newNode = __spreadProps(__spreadValues({}, useNode), { type: "g", children: [materialisedClone] });
2779
2780
  delete newNode.href;
2780
2781
  delete newNode.width;
2781
2782
  delete newNode.height;
@@ -2783,7 +2784,7 @@ var PixodeskAnimator = (() => {
2783
2784
  }
2784
2785
  function rewriteSymbolRootToGroup(symbolNode, genId3, defsCollector, useW, useH) {
2785
2786
  const viewBox = parseViewBox(symbolNode.viewBox);
2786
- const g = __spreadProps2(__spreadValues2({}, symbolNode), { type: "g" });
2787
+ const g = __spreadProps(__spreadValues({}, symbolNode), { type: "g" });
2787
2788
  delete g.viewBox;
2788
2789
  delete g.preserveAspectRatio;
2789
2790
  delete g.width;
@@ -2828,38 +2829,75 @@ var PixodeskAnimator = (() => {
2828
2829
  if (m !== ch) changed = true;
2829
2830
  return m;
2830
2831
  });
2831
- return changed ? __spreadProps2(__spreadValues2({}, node), { children: newChildren }) : node;
2832
+ return changed ? __spreadProps(__spreadValues({}, node), { children: newChildren }) : node;
2832
2833
  }
2834
+
2835
+ // ../svg-animator-core/src/effects/transformParts.ts
2833
2836
  function partsRecord(part, value, origin) {
2834
2837
  const rec = {};
2835
- if (part === "translate") rec.translate = value;
2836
- else if (part === "rotate") rec.rotate = value;
2837
- else if (part === "skew") rec.skew = value;
2838
+ if (part === "translate" /* Translate */) rec.translate = value;
2839
+ else if (part === "rotate" /* Rotate */) rec.rotate = value;
2840
+ else if (part === "skew" /* Skew */) rec.skew = value;
2838
2841
  else rec.scale = value;
2839
- if (origin && part !== "translate") rec.origin = origin;
2842
+ if (origin && part !== "translate" /* Translate */) rec.origin = origin;
2840
2843
  return rec;
2841
2844
  }
2842
2845
  function readAnimatable(raw) {
2843
- if (raw === void 0) return {
2844
- kind: "absent"
2845
- /* Absent */
2846
- };
2847
- if (Array.isArray(raw)) return { kind: "static", value: raw };
2846
+ var _a, _b, _c;
2847
+ if (raw === void 0) return { kind: "absent" /* Absent */ };
2848
+ if (Array.isArray(raw)) return { kind: "static" /* Static */, value: raw };
2848
2849
  if (typeof raw === "object") {
2849
2850
  const obj = raw;
2850
- if (obj.keyframes) {
2851
- return { kind: "animated", keyframes: obj.keyframes, autoOrient: obj.autoOrient, loop: obj.loop };
2851
+ const kfs = (_a = obj.keyframes) != null ? _a : obj.kfs;
2852
+ if (kfs) {
2853
+ const out = { kind: "animated" /* Animated */, keyframes: kfs.map(normaliseKeyframe), autoOrient: obj.autoOrient, loop: obj.loop };
2854
+ const base = (_b = obj.value) != null ? _b : obj.v;
2855
+ if (base !== void 0 && out.kind === "animated" /* Animated */) out.base = base;
2856
+ return out;
2852
2857
  }
2853
- if (obj.value !== void 0) return { kind: "static", value: obj.value };
2858
+ const staticValue = (_c = obj.value) != null ? _c : obj.v;
2859
+ if (staticValue !== void 0) return { kind: "static" /* Static */, value: staticValue };
2860
+ }
2861
+ return { kind: "static" /* Static */, value: raw };
2862
+ }
2863
+ function writeAnimatableChannel(node, attrName, read, opts) {
2864
+ var _a, _b, _c, _d;
2865
+ const toOut = (v) => (opts == null ? void 0 : opts.asString) && v !== void 0 && v !== null ? String(v) : v;
2866
+ if (read.kind === "absent" /* Absent */) return;
2867
+ if (read.kind === "static" /* Static */) {
2868
+ node[attrName] = toOut(read.value);
2869
+ return;
2854
2870
  }
2855
- return { kind: "static", value: raw };
2871
+ const prevAnimate = node.animate && typeof node.animate === "object" && !Array.isArray(node.animate) ? node.animate : void 0;
2872
+ const animate = __spreadValues({}, prevAnimate || {});
2873
+ const block = { keyframes: read.keyframes };
2874
+ if (read.loop !== void 0) block.loop = read.loop;
2875
+ if (read.autoOrient !== void 0) block.autoOrient = read.autoOrient;
2876
+ animate[attrName] = block;
2877
+ node.animate = animate;
2878
+ 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;
2879
+ if (baseline !== void 0) node[attrName] = toOut(baseline);
2880
+ }
2881
+ function normaliseKeyframe(kf) {
2882
+ if (!kf || typeof kf !== "object") return kf;
2883
+ const k = kf;
2884
+ if (k.t === void 0 && k.v === void 0 && k.e === void 0 && k.to === void 0 && k.ti === void 0) {
2885
+ return kf;
2886
+ }
2887
+ const out = __spreadValues({}, k);
2888
+ if (out.time === void 0 && k.t !== void 0) out.time = k.t;
2889
+ if (out.value === void 0 && k.v !== void 0) out.value = k.v;
2890
+ if (out.easing === void 0 && k.e !== void 0) out.easing = k.e;
2891
+ if (out.tangentOut === void 0 && k.to !== void 0) out.tangentOut = k.to;
2892
+ if (out.tangentIn === void 0 && k.ti !== void 0) out.tangentIn = k.ti;
2893
+ return out;
2856
2894
  }
2857
2895
  function readStaticOrigin(raw, ctx) {
2858
2896
  var _a;
2859
2897
  const o = readAnimatable(raw);
2860
- if (o.kind === "absent") return void 0;
2861
- if (o.kind === "static") return o.value;
2862
- ctx.warnings.push("transformation.origin: animated origin approximated by its first keyframe");
2898
+ if (o.kind === "absent" /* Absent */) return void 0;
2899
+ if (o.kind === "static" /* Static */) return o.value;
2900
+ ctx.warnings.push("transformBy.origin: animated origin approximated by its first keyframe");
2863
2901
  return (_a = o.keyframes[0]) == null ? void 0 : _a.value;
2864
2902
  }
2865
2903
  function keyframeWith(kf, value) {
@@ -2870,7 +2908,9 @@ var PixodeskAnimator = (() => {
2870
2908
  if (kf.tangentIn !== void 0) out.tangentIn = kf.tangentIn;
2871
2909
  return out;
2872
2910
  }
2873
- function applyTransformationEffect(node, fx, ctx) {
2911
+
2912
+ // ../svg-animator-core/src/effects/transformationEffect.ts
2913
+ function applyTransformByEffect(node, fx, ctx) {
2874
2914
  if (!fx) return node;
2875
2915
  delete node.transform;
2876
2916
  let n = node;
@@ -2880,9 +2920,9 @@ var PixodeskAnimator = (() => {
2880
2920
  /*invert=*/
2881
2921
  true
2882
2922
  );
2883
- n = wrapTransformPart(n, "scale", normalizeScale(fx.scale), ctx);
2884
- n = wrapTransformPart(n, "skew", fx.skew, ctx);
2885
- n = wrapTransformPart(n, "rotate", fx.rotate, ctx);
2923
+ n = wrapTransformPart(n, "scale" /* Scale */, normalizeScale(fx.scale), ctx);
2924
+ n = wrapTransformPart(n, "skew" /* Skew */, fx.skew, ctx);
2925
+ n = wrapTransformPart(n, "rotate" /* Rotate */, fx.rotate, ctx);
2886
2926
  n = wrapOrigin(
2887
2927
  n,
2888
2928
  fx.origin,
@@ -2896,7 +2936,7 @@ var PixodeskAnimator = (() => {
2896
2936
  /*invert=*/
2897
2937
  true
2898
2938
  );
2899
- n = wrapTransformPart(n, "translate", fx.translate, ctx);
2939
+ n = wrapTransformPart(n, "translate" /* Translate */, fx.translate, ctx);
2900
2940
  n = wrapOrigin(
2901
2941
  n,
2902
2942
  fx.origin,
@@ -2904,7 +2944,11 @@ var PixodeskAnimator = (() => {
2904
2944
  false
2905
2945
  );
2906
2946
  } else {
2907
- n = wrapTransformPart(n, "translate", fx.translate, ctx);
2947
+ n = wrapTransformPart(n, "translate" /* Translate */, fx.translate, ctx);
2948
+ }
2949
+ if (n !== node && node.id) {
2950
+ n.id = node.id;
2951
+ delete node.id;
2908
2952
  }
2909
2953
  return n;
2910
2954
  }
@@ -2915,17 +2959,15 @@ var PixodeskAnimator = (() => {
2915
2959
  return Array.isArray(obj.keyframes) && obj.keyframes.some((kf) => kf.tangentOut || kf.tangentIn);
2916
2960
  }
2917
2961
  function normalizeScale(raw) {
2918
- if (raw === void 0) return void 0;
2919
- if (Array.isArray(raw)) return [raw[0] / 100, raw[1] / 100];
2920
2962
  return raw;
2921
2963
  }
2922
2964
  function wrapTransformPart(inner, part, raw, ctx) {
2923
2965
  if (raw === void 0) return inner;
2924
2966
  const v = readAnimatable(raw);
2925
- if (v.kind === "static") {
2967
+ if (v.kind === "static" /* Static */) {
2926
2968
  return { type: "g", transform: { value: partsRecord(part, v.value, void 0) }, children: [inner] };
2927
2969
  }
2928
- if (v.kind === "animated") {
2970
+ if (v.kind === "animated" /* Animated */) {
2929
2971
  const animTr = { keyframes: v.keyframes.map((kf) => keyframeWith(kf, partsRecord(part, kf.value, void 0))) };
2930
2972
  if (v.autoOrient) animTr.autoOrient = true;
2931
2973
  if (v.loop !== void 0) animTr.loop = v.loop;
@@ -2941,12 +2983,12 @@ var PixodeskAnimator = (() => {
2941
2983
  if (raw === void 0) return inner;
2942
2984
  const v = readAnimatable(raw);
2943
2985
  const sign = (value) => invert ? [-value[0], -value[1]] : value;
2944
- if (v.kind === "absent") return inner;
2945
- if (v.kind === "static") {
2986
+ if (v.kind === "absent" /* Absent */) return inner;
2987
+ if (v.kind === "static" /* Static */) {
2946
2988
  if (v.value[0] === 0 && v.value[1] === 0) return inner;
2947
2989
  return { type: "g", transform: { value: { translate: sign(v.value) } }, children: [inner] };
2948
2990
  }
2949
- if (v.kind === "animated") {
2991
+ if (v.kind === "animated" /* Animated */) {
2950
2992
  const animTr = { keyframes: v.keyframes.map((kf) => keyframeWith(kf, { translate: sign(kf.value) })) };
2951
2993
  if (v.loop !== void 0) animTr.loop = v.loop;
2952
2994
  return {
@@ -2957,34 +2999,58 @@ var PixodeskAnimator = (() => {
2957
2999
  }
2958
3000
  return inner;
2959
3001
  }
3002
+
3003
+ // ../svg-animator-core/src/effects/util.ts
3004
+ function genId(ctx, prefix) {
3005
+ return "_lw_" + prefix + "_" + ctx.nextId++;
3006
+ }
3007
+ function stripHash2(href) {
3008
+ return typeof href === "string" ? href.replace(/^#/, "") : void 0;
3009
+ }
3010
+ function indexById(node, map) {
3011
+ var _a;
3012
+ if (typeof node.id === "string") map.set(node.id, node);
3013
+ (_a = node.children) == null ? void 0 : _a.forEach((child) => indexById(child, map));
3014
+ }
3015
+ function spliceDefs(root, defs) {
3016
+ if (!defs.length) return;
3017
+ const existing = root.children || (root.children = []);
3018
+ existing.unshift({ type: "defs", children: defs });
3019
+ }
3020
+ var clone = deepClonePxNode;
3021
+ function regenerateIdsInClone(root, ctx) {
3022
+ return regenerateIdsAndRewriteRefs(root, () => genId(ctx, "retimed"));
3023
+ }
3024
+
3025
+ // ../svg-animator-core/src/effects/contentRefSplit.ts
2960
3026
  function identifyContentRefTargets(node, ctx, allocator) {
2961
3027
  var _a, _b, _c;
2962
3028
  if (node.type === "use" && ((_b = (_a = node.effects) == null ? void 0 : _a.clone) == null ? void 0 : _b.type) === "content") {
2963
- const baseId = node.effects.clone.baseId;
2964
- if (typeof baseId === "string" && baseId && !ctx.contentRefInnerIds.has(baseId)) {
2965
- ctx.contentRefInnerIds.set(baseId, allocator(baseId));
3029
+ const sourceId = stripHash2(node.effects.clone.sourceId);
3030
+ if (typeof sourceId === "string" && sourceId && !ctx.contentRefInnerIds.has(sourceId)) {
3031
+ ctx.contentRefInnerIds.set(sourceId, allocator(sourceId));
2966
3032
  }
2967
3033
  }
2968
3034
  (_c = node.children) == null ? void 0 : _c.forEach((c) => identifyContentRefTargets(c, ctx, allocator));
2969
3035
  }
2970
- function splitForContentRef(node, transformation, originalId, innerId, ctx) {
2971
- const outerBody = liftBodyTranslate(node, transformation);
3036
+ function splitForContentRef(node, transformBy, originalId, innerId, ctx) {
3037
+ const outerBody = liftBodyTranslate(node, transformBy);
2972
3038
  if (typeof node.id === "string") delete node.id;
2973
- const { outer: outerTr, inner: innerTr } = splitTransformationEffect(transformation);
3039
+ const { outer: outerTr, inner: innerTr } = splitTransformByEffect(transformBy);
2974
3040
  let innerNode = node;
2975
- innerNode = applyTransformationEffect(innerNode, innerTr, ctx);
3041
+ innerNode = applyTransformByEffect(innerNode, innerTr, ctx);
2976
3042
  const innerWrapper = { type: "g", id: innerId, children: [innerNode] };
2977
3043
  let outerWrapper = { type: "g", id: originalId, children: [innerWrapper] };
2978
3044
  if (outerBody.transform !== void 0) outerWrapper.transform = outerBody.transform;
2979
3045
  if (outerBody.animate !== void 0) outerWrapper.animate = outerBody.animate;
2980
3046
  if (outerTr) {
2981
3047
  delete outerWrapper.id;
2982
- outerWrapper = applyTransformationEffect(outerWrapper, outerTr, ctx);
3048
+ outerWrapper = applyTransformByEffect(outerWrapper, outerTr, ctx);
2983
3049
  outerWrapper.id = originalId;
2984
3050
  }
2985
3051
  return outerWrapper;
2986
3052
  }
2987
- function liftBodyTranslate(node, transformation) {
3053
+ function liftBodyTranslate(node, transformBy) {
2988
3054
  var _a, _b, _c;
2989
3055
  const out = {};
2990
3056
  let didLiftAnimate = false;
@@ -3038,7 +3104,7 @@ var PixodeskAnimator = (() => {
3038
3104
  didLiftAnimate = true;
3039
3105
  }
3040
3106
  }
3041
- const transformationHasTranslate = (transformation == null ? void 0 : transformation.translate) !== void 0;
3107
+ const transformationHasTranslate = (transformBy == null ? void 0 : transformBy.translate) !== void 0;
3042
3108
  const stripBodyTranslateOnly = didLiftAnimate || transformationHasTranslate;
3043
3109
  const liftedAnimateIsAutoOriented = didLiftAnimate && needsOriginOnOuter(((_b = node.animate) == null ? void 0 : _b.transform) || void 0) || didLiftAnimate && needsOriginOnOuter(((_c = out.animate) == null ? void 0 : _c.transform) || void 0);
3044
3110
  if (typeof node.transform === "string") {
@@ -3057,6 +3123,24 @@ var PixodeskAnimator = (() => {
3057
3123
  if (split.rest) node.transform = split.rest;
3058
3124
  else delete node.transform;
3059
3125
  }
3126
+ } else if (node.transform && typeof node.transform === "object" && !Array.isArray(node.transform) && !node.transform.keyframes && !node.transform.kfs) {
3127
+ const wrapped = node.transform.value;
3128
+ const isWrapped = !!(wrapped && typeof wrapped === "object");
3129
+ const value = isWrapped ? wrapped : node.transform;
3130
+ const rewrap = (rec) => isWrapped ? { value: rec } : rec;
3131
+ if (Array.isArray(value.translate)) {
3132
+ const rest = __spreadValues({}, value);
3133
+ delete rest.translate;
3134
+ const hasRest = Object.keys(rest).length > 0;
3135
+ if (stripBodyTranslateOnly) {
3136
+ if (hasRest) node.transform = rewrap(rest);
3137
+ else delete node.transform;
3138
+ } else {
3139
+ out.transform = rewrap({ translate: value.translate });
3140
+ if (hasRest) node.transform = rewrap(rest);
3141
+ else delete node.transform;
3142
+ }
3143
+ }
3060
3144
  }
3061
3145
  return out;
3062
3146
  }
@@ -3126,7 +3210,7 @@ var PixodeskAnimator = (() => {
3126
3210
  const nums = m[1].split(/[\s,]+/).filter(Boolean).map(Number);
3127
3211
  return [nums[0] || 0, nums[1] || 0];
3128
3212
  }
3129
- function splitTransformationEffect(fx) {
3213
+ function splitTransformByEffect(fx) {
3130
3214
  if (!fx) return {};
3131
3215
  const originOnOuter = needsOriginOnOuter(fx.translate);
3132
3216
  const innerHasPivotedPart = fx.rotate !== void 0 || fx.scale !== void 0;
@@ -3152,26 +3236,8 @@ var PixodeskAnimator = (() => {
3152
3236
  }
3153
3237
  return false;
3154
3238
  }
3155
- function genId(ctx, prefix) {
3156
- return "_lw_" + prefix + "_" + ctx.nextId++;
3157
- }
3158
- function stripHash2(href) {
3159
- return typeof href === "string" ? href.replace(/^#/, "") : void 0;
3160
- }
3161
- function indexById(node, map) {
3162
- var _a;
3163
- if (typeof node.id === "string") map.set(node.id, node);
3164
- (_a = node.children) == null ? void 0 : _a.forEach((child) => indexById(child, map));
3165
- }
3166
- function spliceDefs(root, defs) {
3167
- if (!defs.length) return;
3168
- const existing = root.children || (root.children = []);
3169
- existing.unshift({ type: "defs", children: defs });
3170
- }
3171
- var clone = deepClonePxNode;
3172
- function regenerateIdsInClone(root, ctx) {
3173
- return regenerateIdsAndRewriteRefs(root, () => genId(ctx, "retimed"));
3174
- }
3239
+
3240
+ // ../svg-animator-core/src/effects/gradientEffect.ts
3175
3241
  function applyFillGradientEffect(node, fx, ctx) {
3176
3242
  return applyGradient(node, fx, ctx, "fill");
3177
3243
  }
@@ -3192,62 +3258,63 @@ var PixodeskAnimator = (() => {
3192
3258
  id
3193
3259
  };
3194
3260
  if (fx.type === PxGradientType.linear) {
3195
- if (fx.p1) {
3196
- out.x1 = String(fx.p1[0]);
3197
- out.y1 = String(fx.p1[1]);
3198
- }
3199
- if (fx.p2) {
3200
- out.x2 = String(fx.p2[0]);
3201
- out.y2 = String(fx.p2[1]);
3202
- }
3261
+ applyGeomVec(out, "x1", "y1", fx.p1);
3262
+ applyGeomVec(out, "x2", "y2", fx.p2);
3203
3263
  } else {
3204
- if (fx.c) {
3205
- out.cx = String(fx.c[0]);
3206
- out.cy = String(fx.c[1]);
3207
- }
3208
- if (fx.r !== void 0) out.r = String(fx.r);
3209
- if (fx.fp) {
3210
- out.fx = String(fx.fp[0]);
3211
- out.fy = String(fx.fp[1]);
3212
- }
3264
+ applyGeomVec(out, "cx", "cy", fx.c);
3265
+ applyGeomNumber(out, "r", fx.r);
3266
+ applyGeomVec(out, "fx", "fy", fx.fp);
3213
3267
  }
3214
3268
  if (fx.gradientUnits) out.gradientUnits = fx.gradientUnits;
3215
3269
  if (fx.spreadMethod) out.spreadMethod = fx.spreadMethod;
3216
3270
  if (fx.gradientTransform) out.gradientTransform = fx.gradientTransform;
3217
- const animate = fx.animate;
3218
- if (animate) {
3219
- const mapped = {};
3220
- for (const wireKey of Object.keys(animate)) {
3221
- const attr = GRADIENT_ANIM_CHANNEL_TO_ATTR[wireKey];
3222
- if (attr) mapped[attr] = animate[wireKey];
3223
- }
3224
- if (Object.keys(mapped).length) out.animate = mapped;
3225
- }
3226
3271
  out.children = buildStopChildren(fx.stops, ctx);
3227
3272
  return out;
3228
3273
  }
3229
- var GRADIENT_ANIM_CHANNEL_TO_ATTR = {
3230
- gradientX1: "x1",
3231
- gradientY1: "y1",
3232
- gradientX2: "x2",
3233
- gradientY2: "y2",
3234
- gradientCx: "cx",
3235
- gradientCy: "cy",
3236
- gradientFx: "fx",
3237
- gradientFy: "fy",
3238
- gradientR: "r"
3239
- };
3274
+ function applyGeomVec(out, xAttr, yAttr, raw) {
3275
+ var _a, _b, _c;
3276
+ const read = readAnimatable(raw);
3277
+ if (read.kind === "absent" /* Absent */) return;
3278
+ if (read.kind === "static" /* Static */) {
3279
+ out[xAttr] = String(read.value[0]);
3280
+ out[yAttr] = String(read.value[1]);
3281
+ return;
3282
+ }
3283
+ const axisChannel = (idx) => {
3284
+ const block = {
3285
+ keyframes: read.keyframes.map((kf) => {
3286
+ const axisKf = { time: kf.time, value: Array.isArray(kf.value) ? kf.value[idx] : void 0 };
3287
+ if (kf.easing !== void 0) axisKf.easing = kf.easing;
3288
+ return axisKf;
3289
+ })
3290
+ };
3291
+ if (read.loop !== void 0) block.loop = read.loop;
3292
+ return block;
3293
+ };
3294
+ const animate = (_a = out.animate) != null ? _a : {};
3295
+ animate[xAttr] = axisChannel(0);
3296
+ animate[yAttr] = axisChannel(1);
3297
+ out.animate = animate;
3298
+ const baseline = (_c = read.base) != null ? _c : (_b = read.keyframes[0]) == null ? void 0 : _b.value;
3299
+ if (Array.isArray(baseline)) {
3300
+ out[xAttr] = String(baseline[0]);
3301
+ out[yAttr] = String(baseline[1]);
3302
+ }
3303
+ }
3304
+ function applyGeomNumber(out, attrName, raw) {
3305
+ const read = readAnimatable(raw);
3306
+ if (read.kind === "absent" /* Absent */) return;
3307
+ writeAnimatableChannel(out, attrName, read, { asString: true });
3308
+ }
3240
3309
  function buildStopChildren(stops, ctx) {
3241
3310
  var _a, _b, _c, _d;
3242
3311
  if (!stops) return [];
3243
- if (Array.isArray(stops)) return stops.map(staticStopNode);
3244
- if (typeof stops === "object" && Array.isArray(stops.value)) {
3245
- return stops.value.map(staticStopNode);
3246
- }
3247
- const animBlock = stops;
3248
- const kfs = animBlock.keyframes;
3249
- if (!Array.isArray(kfs) || !kfs.length) return [];
3250
- const loopFromSource = animBlock.loop;
3312
+ const read = readAnimatable(stops);
3313
+ if (read.kind === "absent" /* Absent */) return [];
3314
+ if (read.kind === "static" /* Static */) return Array.isArray(read.value) ? read.value.map(staticStopNode) : [];
3315
+ const kfs = read.keyframes;
3316
+ if (!kfs.length) return [];
3317
+ const loopFromSource = read.loop;
3251
3318
  let stopCount = 0;
3252
3319
  for (const kf of kfs) {
3253
3320
  const v = (_a = kf.value) != null ? _a : kf.v;
@@ -3321,37 +3388,65 @@ var PixodeskAnimator = (() => {
3321
3388
  const pct = Math.round(o * 1e3) / 10;
3322
3389
  return pct + "%";
3323
3390
  }
3391
+
3392
+ // ../svg-animator-core/src/effects/clipPathEffect.ts
3324
3393
  function applyClipPathEffect(node, fx, ctx) {
3394
+ var _a, _b;
3325
3395
  if (!fx || !fx.d && !fx.animate) return node;
3326
3396
  const clipId = genId(ctx, "clip");
3327
- const pathChild = { type: "path", d: fx.d };
3328
- if (fx.animate) pathChild.animate = { d: fx.animate };
3397
+ const pathChild = { type: "path" };
3398
+ const read = readAnimatable(fx.d);
3399
+ if (read.kind !== "absent" /* Absent */) {
3400
+ if (read.kind === "static" /* Static */) {
3401
+ pathChild.d = pathString(read.value);
3402
+ } else {
3403
+ writeAnimatableChannel(pathChild, "d", read);
3404
+ if (pathChild.d !== void 0) pathChild.d = pathString(pathChild.d);
3405
+ }
3406
+ }
3407
+ if (fx.animate && !((_a = pathChild.animate) == null ? void 0 : _a.d)) {
3408
+ const animate = (_b = pathChild.animate) != null ? _b : {};
3409
+ animate.d = fx.animate;
3410
+ pathChild.animate = animate;
3411
+ }
3329
3412
  ctx.defs.push({ type: "clipPath", id: clipId, children: [pathChild] });
3330
3413
  node.clipPath = "url(#" + clipId + ")";
3331
3414
  return node;
3332
3415
  }
3333
- function applyMaskedByEffect(node, fx, transformation, ctx) {
3416
+ function pathString(v) {
3417
+ if (typeof v === "string") return v;
3418
+ if (v && typeof v === "object" && typeof v.path === "string") return v.path;
3419
+ return void 0;
3420
+ }
3421
+
3422
+ // ../svg-animator-core/src/effects/maskedByEffect.ts
3423
+ function applyMaskedByEffect(node, fx, transformBy, ctx) {
3334
3424
  if (!fx) return node;
3335
- if (!fx.href) {
3336
- ctx.errors.push("maskedBy.href missing \u2014 cannot build mask");
3425
+ const sourceId = stripHash2(fx.sourceId);
3426
+ if (!sourceId) {
3427
+ ctx.errors.push("maskedBy.sourceId missing \u2014 cannot build mask");
3337
3428
  return node;
3338
3429
  }
3339
3430
  const maskId = genId(ctx, "mask");
3340
- let content = { type: "use", href: "#" + fx.href };
3341
- if (transformation) {
3342
- content = wrapInverseTransform(content, transformation, ctx);
3431
+ let content = { type: "use", href: "#" + sourceId };
3432
+ if (transformBy) {
3433
+ content = wrapInverseTransform(content, transformBy, ctx);
3343
3434
  } else if (hasAnimateTransform(node)) {
3344
3435
  content = wrapInverseAnimatedBodyTransform(content, node, ctx);
3345
3436
  } else {
3346
3437
  const bodyStatic = readTransformationFromBody(node);
3347
3438
  if (bodyStatic) content = wrapInverseTransform(content, bodyStatic, ctx);
3348
3439
  }
3349
- const includeTargetOwn = transformation === void 0 && !nodeHasBodyTransform(node);
3350
- content = wrapAncestorChainCompensation(content, node, fx.href, ctx, includeTargetOwn);
3440
+ const includeTargetOwn = transformBy === void 0 && !nodeHasBodyTransform(node);
3441
+ content = wrapAncestorChainCompensation(content, node, sourceId, ctx, includeTargetOwn);
3351
3442
  const mask = { type: "mask", id: maskId, children: [content] };
3352
3443
  if (fx.maskType) mask.maskType = fx.maskType;
3353
3444
  if (fx.maskUnits) mask.maskUnits = fx.maskUnits;
3354
3445
  if (fx.maskContentUnits) mask.maskContentUnits = fx.maskContentUnits;
3446
+ if (fx.x !== void 0) mask.x = String(fx.x);
3447
+ if (fx.y !== void 0) mask.y = String(fx.y);
3448
+ if (fx.width !== void 0) mask.width = String(fx.width);
3449
+ if (fx.height !== void 0) mask.height = String(fx.height);
3355
3450
  ctx.defs.push(mask);
3356
3451
  node.mask = "url(#" + maskId + ")";
3357
3452
  return node;
@@ -3360,22 +3455,22 @@ var PixodeskAnimator = (() => {
3360
3455
  if (!fx) return inner;
3361
3456
  const origin = readStaticOrigin(fx.origin, ctx);
3362
3457
  let n = inner;
3363
- n = wrapInversePart(n, "translate", fx.translate, void 0, ctx);
3364
- n = wrapInversePart(n, "rotate", fx.rotate, origin, ctx);
3365
- n = wrapInversePart(n, "scale", fx.scale, origin, ctx);
3458
+ n = wrapInversePart(n, "translate" /* Translate */, fx.translate, void 0, ctx);
3459
+ n = wrapInversePart(n, "rotate" /* Rotate */, fx.rotate, origin, ctx);
3460
+ n = wrapInversePart(n, "scale" /* Scale */, fx.scale, origin, ctx);
3366
3461
  return n;
3367
3462
  }
3368
3463
  function wrapInversePart(inner, part, raw, origin, ctx) {
3369
3464
  if (raw === void 0) return inner;
3370
- const normalisedRaw = part === "scale" && Array.isArray(raw) ? [raw[0] / 100, raw[1] / 100] : raw;
3465
+ const normalisedRaw = part === "scale" /* Scale */ && Array.isArray(raw) ? [raw[0] / 100, raw[1] / 100] : raw;
3371
3466
  const v = readAnimatable(normalisedRaw);
3372
- if (v.kind === "static") {
3467
+ if (v.kind === "static" /* Static */) {
3373
3468
  return { type: "g", transform: { value: partsRecord(part, invertPartValue(part, v.value), origin) }, children: [inner] };
3374
3469
  }
3375
- if (v.kind === "animated") {
3470
+ if (v.kind === "animated" /* Animated */) {
3376
3471
  const animTr = { keyframes: v.keyframes.map((kf) => {
3377
3472
  const out = keyframeWith(kf, partsRecord(part, invertPartValue(part, kf.value), origin));
3378
- return part === "translate" ? __spreadValues2(__spreadValues2({}, out), negatedSpatialTangents(kf)) : out;
3473
+ return part === "translate" /* Translate */ ? __spreadValues(__spreadValues({}, out), negatedSpatialTangents(kf)) : out;
3379
3474
  }) };
3380
3475
  if (v.loop !== void 0) animTr.loop = v.loop;
3381
3476
  return {
@@ -3387,8 +3482,8 @@ var PixodeskAnimator = (() => {
3387
3482
  return inner;
3388
3483
  }
3389
3484
  function invertPartValue(part, value) {
3390
- if (part === "translate") return [-value[0], -value[1]];
3391
- if (part === "rotate") return -value;
3485
+ if (part === "translate" /* Translate */) return [-value[0], -value[1]];
3486
+ if (part === "rotate" /* Rotate */) return -value;
3392
3487
  return [1 / value[0], 1 / value[1]];
3393
3488
  }
3394
3489
  function negatedSpatialTangents(kf) {
@@ -3413,17 +3508,17 @@ var PixodeskAnimator = (() => {
3413
3508
  const v = ((_a = kf.value) != null ? _a : kf.v) || {};
3414
3509
  const baseKf = keyframeWith(kf, void 0);
3415
3510
  if (Array.isArray(v.translate)) {
3416
- translateKfs.push(__spreadProps2(__spreadValues2(__spreadValues2({}, baseKf), negatedSpatialTangents(kf)), { value: { translate: [-v.translate[0], -v.translate[1]] } }));
3511
+ translateKfs.push(__spreadProps(__spreadValues(__spreadValues({}, baseKf), negatedSpatialTangents(kf)), { value: { translate: [-v.translate[0], -v.translate[1]] } }));
3417
3512
  }
3418
3513
  if (typeof v.rotate === "number") {
3419
3514
  const rec = { rotate: -v.rotate };
3420
3515
  if (Array.isArray(v.origin)) rec.origin = [v.origin[0], v.origin[1]];
3421
- rotateKfs.push(__spreadProps2(__spreadValues2({}, baseKf), { value: rec }));
3516
+ rotateKfs.push(__spreadProps(__spreadValues({}, baseKf), { value: rec }));
3422
3517
  }
3423
3518
  if (Array.isArray(v.scale)) {
3424
3519
  const rec = { scale: [1 / v.scale[0], 1 / v.scale[1]] };
3425
3520
  if (Array.isArray(v.origin)) rec.origin = [v.origin[0], v.origin[1]];
3426
- scaleKfs.push(__spreadProps2(__spreadValues2({}, baseKf), { value: rec }));
3521
+ scaleKfs.push(__spreadProps(__spreadValues({}, baseKf), { value: rec }));
3427
3522
  }
3428
3523
  }
3429
3524
  const srcLoop = animTr == null ? void 0 : animTr.loop;
@@ -3458,6 +3553,19 @@ var PixodeskAnimator = (() => {
3458
3553
  if (parts.origin) out.origin = parts.origin;
3459
3554
  return Object.keys(out).length ? out : void 0;
3460
3555
  }
3556
+ if (node.transform && typeof node.transform === "object" && !node.transform.keyframes && !node.transform.kfs) {
3557
+ const wrapped = node.transform.value;
3558
+ const value = wrapped && typeof wrapped === "object" ? wrapped : node.transform;
3559
+ if (value && typeof value === "object") {
3560
+ const out = {};
3561
+ if (Array.isArray(value.translate)) out.translate = value.translate;
3562
+ if (typeof value.rotate === "number") out.rotate = value.rotate;
3563
+ if (typeof value.skew === "number") out.skew = value.skew;
3564
+ if (Array.isArray(value.scale)) out.scale = { value: value.scale };
3565
+ if (Array.isArray(value.origin)) out.origin = value.origin;
3566
+ return Object.keys(out).length ? out : void 0;
3567
+ }
3568
+ }
3461
3569
  return void 0;
3462
3570
  }
3463
3571
  function parseTransformStringToParts(s) {
@@ -3591,10 +3699,10 @@ var PixodeskAnimator = (() => {
3591
3699
  const interestingNodes = /* @__PURE__ */ new Set();
3592
3700
  const collectInterestingNodes = (n) => {
3593
3701
  var _a, _b;
3594
- const href = (_b = (_a = n.effects) == null ? void 0 : _a.maskedBy) == null ? void 0 : _b.href;
3595
- if (typeof href === "string") {
3702
+ const maskSourceId = stripHash2((_b = (_a = n.effects) == null ? void 0 : _a.maskedBy) == null ? void 0 : _b.sourceId);
3703
+ if (typeof maskSourceId === "string") {
3596
3704
  interestingNodes.add(n);
3597
- const sourceNode = ctx.idMap.get(href);
3705
+ const sourceNode = ctx.idMap.get(maskSourceId);
3598
3706
  if (sourceNode) interestingNodes.add(sourceNode);
3599
3707
  }
3600
3708
  if (Array.isArray(n.children)) for (const ch of n.children) collectInterestingNodes(ch);
@@ -3620,8 +3728,9 @@ var PixodeskAnimator = (() => {
3620
3728
  if (typeof tr === "string") {
3621
3729
  const parts = parseTranslateOnlyFromString(tr, ctx);
3622
3730
  if (parts) out.translate = parts;
3623
- } else if (tr && typeof tr === "object") {
3624
- const value = tr.value;
3731
+ } else if (tr && typeof tr === "object" && !tr.keyframes && !tr.kfs) {
3732
+ const wrapped = tr.value;
3733
+ const value = wrapped && typeof wrapped === "object" ? wrapped : tr;
3625
3734
  if (value && typeof value === "object" && Array.isArray(value.translate)) {
3626
3735
  out.translate = [value.translate[0] || 0, value.translate[1] || 0];
3627
3736
  }
@@ -3666,21 +3775,25 @@ var PixodeskAnimator = (() => {
3666
3775
  if (droppedNonTranslate) ctx.warnings.push("maskedBy ancestor: non-translate transform in string ignored: " + s);
3667
3776
  return seen ? [x, y] : void 0;
3668
3777
  }
3778
+
3779
+ // ../svg-animator-core/src/effects/refEffect.ts
3669
3780
  var CONTENT_SUBREF = "content";
3670
3781
  function applyRefHref(node, clone2, ctx) {
3671
3782
  if (!clone2) return;
3672
- const baseId = clone2.baseId;
3673
- if (!baseId) {
3674
- if (clone2.type === CONTENT_SUBREF) ctx.errors.push("clone: content ref missing baseId");
3783
+ const sourceId = stripHash2(clone2.sourceId);
3784
+ if (!sourceId) {
3785
+ if (clone2.type === CONTENT_SUBREF) ctx.errors.push("clone: content ref missing sourceId");
3675
3786
  return;
3676
3787
  }
3677
- const targetId = clone2.type === CONTENT_SUBREF ? ctx.contentRefInnerIds.get(baseId) || baseId : baseId;
3788
+ const targetId = clone2.type === CONTENT_SUBREF ? ctx.contentRefInnerIds.get(sourceId) || sourceId : sourceId;
3678
3789
  node.href = "#" + targetId;
3679
3790
  }
3680
- function applyRefAndTransformationEffect(node, clone2, transformation, ctx) {
3791
+ function applyRefAndTransformationEffect(node, clone2, transformBy, ctx) {
3681
3792
  applyRefHref(node, clone2, ctx);
3682
- return applyTransformationEffect(node, transformation, ctx);
3793
+ return applyTransformByEffect(node, transformBy, ctx);
3683
3794
  }
3795
+
3796
+ // ../svg-animator-core/src/effects/repeaterEffect.ts
3684
3797
  function applyRepeaterEffect(node, fx, ctx) {
3685
3798
  var _a, _b;
3686
3799
  if (!fx) return node;
@@ -3702,7 +3815,7 @@ var PixodeskAnimator = (() => {
3702
3815
  for (let i = 1; i < copies; i++) {
3703
3816
  const baseClone = clone(base);
3704
3817
  const synthFx = synthesisePerCopyFx(fx, i);
3705
- const wrapped = synthFx ? applyTransformationEffect(baseClone, synthFx, ctx) : baseClone;
3818
+ const wrapped = synthFx ? applyTransformByEffect(baseClone, synthFx, ctx) : baseClone;
3706
3819
  children.push(wrapped);
3707
3820
  }
3708
3821
  const wrapper = { type: "g", children };
@@ -3714,10 +3827,13 @@ var PixodeskAnimator = (() => {
3714
3827
  function synthesisePerCopyFx(fx, i) {
3715
3828
  const out = {};
3716
3829
  if (fx.translate !== void 0) {
3717
- out.translate = mapAnimatableVec2(fx.translate, (v) => [v[0] * i, v[1] * i]);
3830
+ out.translate = mapAnimatable(fx.translate, (v) => [v[0] * i, v[1] * i]);
3718
3831
  }
3719
3832
  if (fx.rotate !== void 0) {
3720
- out.rotate = mapAnimatableNumber(fx.rotate, (v) => v * i);
3833
+ out.rotate = mapAnimatable(fx.rotate, (v) => v * i);
3834
+ }
3835
+ if (fx.skew !== void 0) {
3836
+ out.skew = mapAnimatable(fx.skew, (v) => v * i);
3721
3837
  }
3722
3838
  if (fx.scale !== void 0) {
3723
3839
  out.scale = synthesiseScale(fx.scale, i);
@@ -3727,63 +3843,52 @@ var PixodeskAnimator = (() => {
3727
3843
  }
3728
3844
  return Object.keys(out).length ? out : void 0;
3729
3845
  }
3730
- function mapAnimatableVec2(raw, fn) {
3731
- if (Array.isArray(raw)) return fn(raw);
3732
- if (raw && typeof raw === "object") {
3733
- const obj = raw;
3734
- if (Array.isArray(obj.keyframes)) {
3735
- return __spreadProps2(__spreadValues2({}, obj), {
3736
- keyframes: obj.keyframes.map((kf) => kf && kf.value !== void 0 ? __spreadProps2(__spreadValues2({}, kf), { value: fn(kf.value) }) : kf)
3737
- });
3738
- }
3739
- if (obj.value !== void 0) {
3740
- return __spreadProps2(__spreadValues2({}, obj), { value: fn(obj.value) });
3741
- }
3846
+ function mapAnimatable(raw, fn, wrapStatic = false) {
3847
+ const read = readAnimatable(raw);
3848
+ if (read.kind === "absent" /* Absent */) return raw;
3849
+ if (read.kind === "static" /* Static */) {
3850
+ const mapped = fn(read.value);
3851
+ const wasRawStatic = typeof raw === "number" || Array.isArray(raw);
3852
+ return wasRawStatic && !wrapStatic ? mapped : { value: mapped };
3742
3853
  }
3743
- return raw;
3744
- }
3745
- function mapAnimatableNumber(raw, fn) {
3746
- if (typeof raw === "number") return fn(raw);
3747
- if (raw && typeof raw === "object") {
3748
- const obj = raw;
3749
- if (Array.isArray(obj.keyframes)) {
3750
- return __spreadProps2(__spreadValues2({}, obj), {
3751
- keyframes: obj.keyframes.map((kf) => kf && kf.value !== void 0 ? __spreadProps2(__spreadValues2({}, kf), { value: fn(kf.value) }) : kf)
3752
- });
3753
- }
3754
- if (obj.value !== void 0) {
3755
- return __spreadProps2(__spreadValues2({}, obj), { value: fn(obj.value) });
3756
- }
3757
- }
3758
- return raw;
3854
+ const out = {
3855
+ keyframes: read.keyframes.map((kf) => kf && kf.value !== void 0 ? __spreadProps(__spreadValues({}, kf), { value: fn(kf.value) }) : kf)
3856
+ };
3857
+ if (read.loop !== void 0) out.loop = read.loop;
3858
+ if (read.autoOrient !== void 0) out.autoOrient = read.autoOrient;
3859
+ if (read.base !== void 0) out.value = fn(read.base);
3860
+ return out;
3759
3861
  }
3760
3862
  function synthesiseScale(raw, i) {
3761
- const scalePowerFromPercent = (v) => [Math.pow(v[0] / 100, i), Math.pow(v[1] / 100, i)];
3762
- const scalePowerFromUnits = (v) => [Math.pow(v[0], i), Math.pow(v[1], i)];
3763
- if (Array.isArray(raw)) {
3764
- return { value: scalePowerFromPercent(raw) };
3765
- }
3766
- if (raw && typeof raw === "object") {
3767
- const obj = raw;
3768
- if (Array.isArray(obj.keyframes)) {
3769
- return __spreadProps2(__spreadValues2({}, obj), {
3770
- keyframes: obj.keyframes.map((kf) => kf && kf.value !== void 0 ? __spreadProps2(__spreadValues2({}, kf), { value: scalePowerFromUnits(kf.value) }) : kf)
3771
- });
3772
- }
3773
- if (obj.value !== void 0) {
3774
- return __spreadProps2(__spreadValues2({}, obj), { value: scalePowerFromPercent(obj.value) });
3775
- }
3776
- }
3777
- return raw;
3863
+ const scalePower = (v) => [Math.pow(v[0], i), Math.pow(v[1], i)];
3864
+ return mapAnimatable(raw, scalePower, true);
3778
3865
  }
3866
+
3867
+ // ../svg-animator-core/src/effects/retimeEffect.ts
3779
3868
  var RETIME_MATERIALISATION_MODE_INLINE_G = false;
3780
3869
  function asRetime(r) {
3781
3870
  var _a, _b;
3782
- if (r.timeCrop) {
3783
- console.warn("retime: `timeCrop` is not supported yet and will be ignored");
3784
- }
3785
3871
  return { start: (_a = r.start) != null ? _a : 0, stretch: (_b = r.stretch) != null ? _b : 1 };
3786
3872
  }
3873
+ var CROP_EDGE_MS = 1;
3874
+ function applyTimeCrop(useNode, crop, ctx) {
3875
+ const [start, end] = crop;
3876
+ if (!Number.isFinite(start) || !Number.isFinite(end)) {
3877
+ ctx.warnings.push("retime: timeCrop is not a pair of finite numbers \u2014 ignored");
3878
+ return;
3879
+ }
3880
+ const keyframes = end <= start ? [{ time: 0, value: 0 }] : [
3881
+ ...start > 0 ? [{ time: Math.max(0, start - CROP_EDGE_MS), value: 0 }] : [],
3882
+ { time: Math.max(0, start), value: 1 },
3883
+ { time: end, value: 1 },
3884
+ { time: end + CROP_EDGE_MS, value: 0 }
3885
+ ];
3886
+ const inner = __spreadValues({}, useNode);
3887
+ for (const k of Object.keys(useNode)) delete useNode[k];
3888
+ useNode.type = "g";
3889
+ useNode.children = [inner];
3890
+ useNode.animate = { opacity: { keyframes } };
3891
+ }
3787
3892
  function concatRetime(child, parent) {
3788
3893
  return {
3789
3894
  start: parent.start + parent.stretch * child.start,
@@ -3843,8 +3948,10 @@ var PixodeskAnimator = (() => {
3843
3948
  for (const useNode of sites) {
3844
3949
  const retime = readCloneRetime(useNode);
3845
3950
  if (!retime) continue;
3951
+ const crop = retime.timeCrop;
3846
3952
  clearCloneRetime(useNode);
3847
3953
  materialiseRetime(useNode, asRetime(retime), ctx);
3954
+ if (crop) applyTimeCrop(useNode, crop, ctx);
3848
3955
  }
3849
3956
  }
3850
3957
  function materialiseRetime(useNode, retime, ctx) {
@@ -3939,6 +4046,8 @@ var PixodeskAnimator = (() => {
3939
4046
  }
3940
4047
  }
3941
4048
  }
4049
+
4050
+ // ../svg-animator-core/src/effects/pathSampler.ts
3942
4051
  var LUT_STEPS = 48;
3943
4052
  var CMD_RE = /[MmLlHhVvCcSsQqTtAaZz]/;
3944
4053
  function tokenize(d) {
@@ -3963,7 +4072,7 @@ var PixodeskAnimator = (() => {
3963
4072
  let pcx = 0, pcy = 0;
3964
4073
  let pqx = 0, pqy = 0;
3965
4074
  let prevCmd = "";
3966
- const num2 = () => parseFloat(tokens[i++]);
4075
+ const num = () => parseFloat(tokens[i++]);
3967
4076
  const push = (P1, P2, P3) => {
3968
4077
  const P0 = [cx, cy];
3969
4078
  const lut = bezier2D_arcLengthLUT(P0, P1, P2, P3, LUT_STEPS);
@@ -3992,7 +4101,7 @@ var PixodeskAnimator = (() => {
3992
4101
  continue;
3993
4102
  }
3994
4103
  if (U === "M") {
3995
- const x = num2() + (rel ? cx : 0), y = num2() + (rel ? cy : 0);
4104
+ const x = num() + (rel ? cx : 0), y = num() + (rel ? cy : 0);
3996
4105
  cx = x;
3997
4106
  cy = y;
3998
4107
  sx = x;
@@ -4001,29 +4110,29 @@ var PixodeskAnimator = (() => {
4001
4110
  continue;
4002
4111
  }
4003
4112
  if (U === "L") {
4004
- pushLine(num2() + (rel ? cx : 0), num2() + (rel ? cy : 0));
4113
+ pushLine(num() + (rel ? cx : 0), num() + (rel ? cy : 0));
4005
4114
  } else if (U === "H") {
4006
- pushLine(num2() + (rel ? cx : 0), cy);
4115
+ pushLine(num() + (rel ? cx : 0), cy);
4007
4116
  } else if (U === "V") {
4008
- pushLine(cx, num2() + (rel ? cy : 0));
4117
+ pushLine(cx, num() + (rel ? cy : 0));
4009
4118
  } else if (U === "C") {
4010
- const p1 = [num2() + (rel ? cx : 0), num2() + (rel ? cy : 0)];
4011
- const p2 = [num2() + (rel ? cx : 0), num2() + (rel ? cy : 0)];
4012
- const p3 = [num2() + (rel ? cx : 0), num2() + (rel ? cy : 0)];
4119
+ const p1 = [num() + (rel ? cx : 0), num() + (rel ? cy : 0)];
4120
+ const p2 = [num() + (rel ? cx : 0), num() + (rel ? cy : 0)];
4121
+ const p3 = [num() + (rel ? cx : 0), num() + (rel ? cy : 0)];
4013
4122
  pcx = p2[0];
4014
4123
  pcy = p2[1];
4015
4124
  push(p1, p2, p3);
4016
4125
  } else if (U === "S") {
4017
4126
  const smooth = prevCmd.toUpperCase() === "C" || prevCmd.toUpperCase() === "S";
4018
4127
  const p1 = smooth ? [2 * cx - pcx, 2 * cy - pcy] : [cx, cy];
4019
- const p2 = [num2() + (rel ? cx : 0), num2() + (rel ? cy : 0)];
4020
- const p3 = [num2() + (rel ? cx : 0), num2() + (rel ? cy : 0)];
4128
+ const p2 = [num() + (rel ? cx : 0), num() + (rel ? cy : 0)];
4129
+ const p3 = [num() + (rel ? cx : 0), num() + (rel ? cy : 0)];
4021
4130
  pcx = p2[0];
4022
4131
  pcy = p2[1];
4023
4132
  push(p1, p2, p3);
4024
4133
  } else if (U === "Q") {
4025
- const qc = [num2() + (rel ? cx : 0), num2() + (rel ? cy : 0)];
4026
- const p3 = [num2() + (rel ? cx : 0), num2() + (rel ? cy : 0)];
4134
+ const qc = [num() + (rel ? cx : 0), num() + (rel ? cy : 0)];
4135
+ const p3 = [num() + (rel ? cx : 0), num() + (rel ? cy : 0)];
4027
4136
  pqx = qc[0];
4028
4137
  pqy = qc[1];
4029
4138
  const { P1, P2 } = quadToCubic([cx, cy], qc, p3);
@@ -4031,14 +4140,14 @@ var PixodeskAnimator = (() => {
4031
4140
  } else if (U === "T") {
4032
4141
  const smooth = prevCmd.toUpperCase() === "Q" || prevCmd.toUpperCase() === "T";
4033
4142
  const qc = smooth ? [2 * cx - pqx, 2 * cy - pqy] : [cx, cy];
4034
- const p3 = [num2() + (rel ? cx : 0), num2() + (rel ? cy : 0)];
4143
+ const p3 = [num() + (rel ? cx : 0), num() + (rel ? cy : 0)];
4035
4144
  pqx = qc[0];
4036
4145
  pqy = qc[1];
4037
4146
  const { P1, P2 } = quadToCubic([cx, cy], qc, p3);
4038
4147
  push(P1, P2, p3);
4039
4148
  } else if (U === "A") {
4040
4149
  i += 5;
4041
- pushLine(num2() + (rel ? cx : 0), num2() + (rel ? cy : 0));
4150
+ pushLine(num() + (rel ? cx : 0), num() + (rel ? cy : 0));
4042
4151
  } else {
4043
4152
  i++;
4044
4153
  continue;
@@ -4085,16 +4194,15 @@ var PixodeskAnimator = (() => {
4085
4194
  }
4086
4195
  };
4087
4196
  }
4197
+
4198
+ // ../svg-animator-core/src/effects/textPathEffect.ts
4088
4199
  var EXTEND_MARGIN_FRAC = 0.15;
4089
4200
  function numRange(v) {
4090
- if (typeof v === "number") return { min: v, max: v };
4091
- if (v && typeof v === "object") {
4092
- const o = v;
4093
- if (typeof o.value === "number") return { min: o.value, max: o.value };
4094
- if (Array.isArray(o.keyframes) && o.keyframes.length) {
4095
- const vals = o.keyframes.map((k) => Number(k.value) || 0);
4096
- return { min: Math.min(...vals), max: Math.max(...vals) };
4097
- }
4201
+ const read = readAnimatable(v);
4202
+ if (read.kind === "static" /* Static */ && typeof read.value === "number") return { min: read.value, max: read.value };
4203
+ if (read.kind === "animated" /* Animated */ && read.keyframes.length) {
4204
+ const vals = read.keyframes.map((k) => Number(k.value) || 0);
4205
+ return { min: Math.min(...vals), max: Math.max(...vals) };
4098
4206
  }
4099
4207
  return { min: 0, max: 0 };
4100
4208
  }
@@ -4114,11 +4222,16 @@ var PixodeskAnimator = (() => {
4114
4222
  var r3 = (n) => Math.round(n * 1e3) / 1e3;
4115
4223
  function shiftAnimatable(v, by) {
4116
4224
  if (!by || v === void 0 || v === null) return v;
4117
- if (typeof v === "number") return v + by;
4118
- const o = v;
4119
- if (typeof o.value === "number") return __spreadProps2(__spreadValues2({}, o), { value: o.value + by });
4120
- if (Array.isArray(o.keyframes)) return __spreadProps2(__spreadValues2({}, o), { keyframes: o.keyframes.map((k) => __spreadProps2(__spreadValues2({}, k), { value: (Number(k.value) || 0) + by })) });
4121
- return v;
4225
+ const read = readAnimatable(v);
4226
+ if (read.kind === "absent" /* Absent */) return v;
4227
+ if (read.kind === "static" /* Static */) return typeof v === "number" ? read.value + by : { value: read.value + by };
4228
+ const out = {
4229
+ keyframes: read.keyframes.map((k) => __spreadProps(__spreadValues({}, k), { value: (Number(k.value) || 0) + by }))
4230
+ };
4231
+ if (read.loop !== void 0) out.loop = read.loop;
4232
+ if (read.autoOrient !== void 0) out.autoOrient = read.autoOrient;
4233
+ if (read.base !== void 0) out.value = read.base + by;
4234
+ return out;
4122
4235
  }
4123
4236
  function extendedPathForBrowser(pathD, opts) {
4124
4237
  var _a;
@@ -4174,27 +4287,10 @@ var PixodeskAnimator = (() => {
4174
4287
  }
4175
4288
  function applyAnimatableNumber(node, attrName, raw) {
4176
4289
  if (raw === void 0 || raw === null) return;
4177
- if (typeof raw === "number") {
4178
- node[attrName] = String(raw);
4179
- return;
4180
- }
4181
- if (typeof raw === "object" && raw !== null) {
4182
- const obj = raw;
4183
- if (Array.isArray(obj.keyframes)) {
4184
- const prevAnimate = node.animate && typeof node.animate === "object" && !Array.isArray(node.animate) ? node.animate : void 0;
4185
- const animate = __spreadValues2({}, prevAnimate || {});
4186
- const block = { keyframes: obj.keyframes };
4187
- if (obj.loop !== void 0) block.loop = obj.loop;
4188
- animate[attrName] = block;
4189
- node.animate = animate;
4190
- return;
4191
- }
4192
- if (typeof obj.value === "number") {
4193
- node[attrName] = String(obj.value);
4194
- return;
4195
- }
4196
- }
4290
+ writeAnimatableChannel(node, attrName, readAnimatable(raw), { asString: true });
4197
4291
  }
4292
+
4293
+ // ../svg-animator-core/src/effects/elementFactory.ts
4198
4294
  var jsonElementFactory = (type, props, children) => {
4199
4295
  const node = { type };
4200
4296
  for (const k in props) if (props[k] !== void 0) node[k] = props[k];
@@ -4202,6 +4298,8 @@ var PixodeskAnimator = (() => {
4202
4298
  if (arr.length) node.children = arr;
4203
4299
  return node;
4204
4300
  };
4301
+
4302
+ // ../svg-animator-core/src/effects/glyphPathBake.ts
4205
4303
  function fmt(v, decimals) {
4206
4304
  return Math.round(v) === v ? "" + Math.round(v) : v.toFixed(decimals);
4207
4305
  }
@@ -4225,20 +4323,20 @@ var PixodeskAnimator = (() => {
4225
4323
  while ((match = TOKEN_RE.exec(d)) !== null) tokens.push(match[0]);
4226
4324
  let out = "";
4227
4325
  let i = 0;
4228
- const num2 = () => parseFloat(tokens[i++]);
4326
+ const num = () => parseFloat(tokens[i++]);
4229
4327
  while (i < tokens.length) {
4230
4328
  const cmd = tokens[i++];
4231
4329
  if (cmd === "M" || cmd === "L") {
4232
- const [x, y] = apply(m, num2(), num2());
4330
+ const [x, y] = apply(m, num(), num());
4233
4331
  out += cmd + pack([x, y], decimals);
4234
4332
  } else if (cmd === "C") {
4235
- const [x1, y1] = apply(m, num2(), num2());
4236
- const [x2, y2] = apply(m, num2(), num2());
4237
- const [x, y] = apply(m, num2(), num2());
4333
+ const [x1, y1] = apply(m, num(), num());
4334
+ const [x2, y2] = apply(m, num(), num());
4335
+ const [x, y] = apply(m, num(), num());
4238
4336
  out += "C" + pack([x1, y1, x2, y2, x, y], decimals);
4239
4337
  } else if (cmd === "Q") {
4240
- const [x1, y1] = apply(m, num2(), num2());
4241
- const [x, y] = apply(m, num2(), num2());
4338
+ const [x1, y1] = apply(m, num(), num());
4339
+ const [x, y] = apply(m, num(), num());
4242
4340
  out += "Q" + pack([x1, y1, x, y], decimals);
4243
4341
  } else if (cmd === "Z" || cmd === "z") {
4244
4342
  out += "Z";
@@ -4246,6 +4344,8 @@ var PixodeskAnimator = (() => {
4246
4344
  }
4247
4345
  return out;
4248
4346
  }
4347
+
4348
+ // ../svg-animator-core/src/effects/textGlyphsEffect.ts
4249
4349
  var DEFAULT_FONT_SIZE = 16;
4250
4350
  var TEXT_ATTR_KEYS = [
4251
4351
  "fontFamily",
@@ -4381,13 +4481,13 @@ var PixodeskAnimator = (() => {
4381
4481
  if (y !== void 0) pen.y = y;
4382
4482
  pen.x += (_a2 = parseLen(el.dx)) != null ? _a2 : 0;
4383
4483
  pen.y += (_b2 = parseLen(el.dy)) != null ? _b2 : 0;
4384
- const content = (_c2 = str(el[TEXT_ATTR])) != null ? _c2 : str(el[TEXT_CONTENT_ATTR]);
4484
+ const content = (_c2 = str(el[TEXT_CONTENT_ATTR])) != null ? _c2 : str(el[TEXT_ATTR]);
4385
4485
  if (content && !((_d2 = el.children) == null ? void 0 : _d2.length)) renderChars(content, s);
4386
4486
  if (el.children) for (const ch of el.children) walk(ch, s);
4387
4487
  };
4388
4488
  const rootStyle = rootStyleOf(node);
4389
4489
  if (node.children) for (const ch of node.children) walk(ch, rootStyle);
4390
- const rootContent = (_c = str(node[TEXT_ATTR])) != null ? _c : str(node[TEXT_CONTENT_ATTR]);
4490
+ const rootContent = (_c = str(node[TEXT_CONTENT_ATTR])) != null ? _c : str(node[TEXT_ATTR]);
4391
4491
  if (rootContent && !((_d = node.children) == null ? void 0 : _d.length)) renderChars(rootContent, rootStyle);
4392
4492
  const anchor = str(node.textAnchor);
4393
4493
  if (anchor === "middle" || anchor === "end") {
@@ -4399,141 +4499,13 @@ var PixodeskAnimator = (() => {
4399
4499
  }
4400
4500
  return toGroup(node, buildPaths(placements, create, warnings), create);
4401
4501
  }
4402
- function layoutGlyphTextChars(node, opts) {
4403
- var _a, _b, _c, _d, _e, _f;
4404
- if ((_a = opts.alongPath) == null ? void 0 : _a.pathD) return layoutGlyphTextCharsAlongPath(node, opts.alongPath.pathD, opts);
4405
- const { glyphs, warnings } = opts;
4406
- const soleFont = soleFontOf(glyphs);
4407
- const pen = { x: (_b = parseLen(node.x)) != null ? _b : 0, y: (_c = parseLen(node.y)) != null ? _c : 0 };
4408
- const boxes = [];
4409
- const lines = [{ start: pen.x, end: pen.x }];
4410
- let line = 0;
4411
- const renderChars = (content, s) => {
4412
- var _a2;
4413
- const gf = glyphFontFor(s, glyphs, soleFont, warnings);
4414
- const upm = (gf == null ? void 0 : gf.unitsPerEm) || 1e3;
4415
- const scale = s.fontSize / upm;
4416
- const ascent = ((_a2 = gf == null ? void 0 : gf.ascent) != null ? _a2 : 0.9 * upm) * scale;
4417
- for (let i = 0; i < content.length; i++) {
4418
- const ch = content.charAt(i);
4419
- const g = gf == null ? void 0 : gf.glyphs[ch];
4420
- const advance = (g ? g.width : 0) * scale + s.letterSpacing + (ch === " " ? s.wordSpacing : 0);
4421
- boxes.push({ x: pen.x, y: pen.y, width: advance, ascent, fontSize: s.fontSize, line });
4422
- pen.x += advance;
4423
- lines[line].end = pen.x;
4424
- }
4425
- };
4426
- const walk = (el, parentStyle) => {
4427
- var _a2, _b2, _c2, _d2;
4428
- const s = resolveStyle2(el, parentStyle);
4429
- const x = parseLen(el.x);
4430
- const y = parseLen(el.y);
4431
- if (x !== void 0) {
4432
- pen.x = x;
4433
- line = lines.length;
4434
- lines.push({ start: pen.x, end: pen.x });
4435
- }
4436
- if (y !== void 0) pen.y = y;
4437
- pen.x += (_a2 = parseLen(el.dx)) != null ? _a2 : 0;
4438
- pen.y += (_b2 = parseLen(el.dy)) != null ? _b2 : 0;
4439
- const content = (_c2 = str(el[TEXT_ATTR])) != null ? _c2 : str(el[TEXT_CONTENT_ATTR]);
4440
- if (content && !((_d2 = el.children) == null ? void 0 : _d2.length)) renderChars(content, s);
4441
- if (el.children) for (const ch of el.children) walk(ch, s);
4442
- };
4443
- const rootStyle = rootStyleOf(node);
4444
- if (node.children) for (const ch of node.children) {
4445
- const before = boxes.length;
4446
- walk(ch, rootStyle);
4447
- if (boxes.length === before) {
4448
- const s = resolveStyle2(ch, rootStyle);
4449
- const gf = glyphFontFor(s, glyphs, soleFont);
4450
- const upm = (gf == null ? void 0 : gf.unitsPerEm) || 1e3;
4451
- 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 });
4452
- }
4453
- }
4454
- const rootContent = (_e = str(node[TEXT_ATTR])) != null ? _e : str(node[TEXT_CONTENT_ATTR]);
4455
- if (rootContent && !((_f = node.children) == null ? void 0 : _f.length)) renderChars(rootContent, rootStyle);
4456
- const anchor = str(node.textAnchor);
4457
- if (anchor === "middle" || anchor === "end") {
4458
- for (const b of boxes) {
4459
- const w = lines[b.line].end - lines[b.line].start;
4460
- b.x += anchor === "middle" ? -w / 2 : -w;
4461
- }
4462
- }
4463
- return boxes.map((_g) => {
4464
- var _h = _g, { line: _l } = _h, b = __objRest2(_h, ["line"]);
4465
- return b;
4466
- });
4467
- }
4468
- function layoutGlyphTextCharsAlongPath(node, pathD, opts) {
4469
- var _a, _b;
4470
- const { glyphs, warnings, alongPath } = opts;
4471
- const sampler = createPathSampler(pathD);
4472
- if (!sampler) {
4473
- warnings == null ? void 0 : warnings.push("textGlyphs: unparsable along-path geometry (caret)");
4474
- return [];
4475
- }
4476
- const soleFont = soleFontOf(glyphs);
4477
- const chars = [];
4478
- let adv = 0;
4479
- const walk = (el, parentStyle) => {
4480
- var _a2, _b2, _c;
4481
- const s = resolveStyle2(el, parentStyle);
4482
- const content = (_a2 = str(el[TEXT_ATTR])) != null ? _a2 : str(el[TEXT_CONTENT_ATTR]);
4483
- if (content && !((_b2 = el.children) == null ? void 0 : _b2.length)) {
4484
- const gf = glyphFontFor(s, glyphs, soleFont, warnings);
4485
- const upm = (gf == null ? void 0 : gf.unitsPerEm) || 1e3;
4486
- const scale = s.fontSize / upm;
4487
- const ascent = ((_c = gf == null ? void 0 : gf.ascent) != null ? _c : 0.9 * upm) * scale;
4488
- for (let i = 0; i < content.length; i++) {
4489
- const ch = content.charAt(i);
4490
- const g = gf == null ? void 0 : gf.glyphs[ch];
4491
- const glyphW = (g ? g.width : 0) * scale;
4492
- const advance = glyphW + s.letterSpacing + (ch === " " ? s.wordSpacing : 0);
4493
- chars.push({ advStart: adv, advEnd: adv + advance, glyphW, ascent, fontSize: s.fontSize });
4494
- adv += advance;
4495
- }
4496
- }
4497
- if (el.children) for (const ch of el.children) walk(ch, s);
4498
- };
4499
- walk(node, rootStyleOf(node));
4500
- const width = adv;
4501
- const tlr = readAnimatable(alongPath == null ? void 0 : alongPath.textLength);
4502
- const tlv = tlr.kind === "animated" ? Number((_a = tlr.keyframes[0]) == null ? void 0 : _a.value) || 0 : tlr.kind === "static" ? Number(tlr.value) || 0 : 0;
4503
- const k = tlv > 0 && width > 0 ? tlv / width : 1;
4504
- const so = readAnimatable(alongPath == null ? void 0 : alongPath.startOffset);
4505
- const { along: alongOffset, perp } = alongPathNodeOffsets(node);
4506
- const base = alongOffset + (so.kind === "animated" ? Number((_b = so.keyframes[0]) == null ? void 0 : _b.value) || 0 : so.kind === "static" ? Number(so.value) || 0 : 0);
4507
- const withPerp = (p) => ({
4508
- x: p.x - perp * Math.sin(p.angle),
4509
- y: p.y + perp * Math.cos(p.angle),
4510
- angle: p.angle
4511
- });
4512
- return chars.map((c) => {
4513
- const dStart = base + c.advStart * k;
4514
- const dEnd = base + c.advEnd * k;
4515
- const p0 = withPerp(sampler.sampleAtDistance(dStart));
4516
- const p1 = withPerp(sampler.sampleAtDistance(dEnd));
4517
- const glyphMid = sampler.sampleAtDistance(base + (c.advStart + c.glyphW / 2) * k);
4518
- return {
4519
- x: p0.x,
4520
- y: p0.y,
4521
- width: c.advEnd - c.advStart,
4522
- ascent: c.ascent,
4523
- fontSize: c.fontSize,
4524
- endX: p1.x,
4525
- endY: p1.y,
4526
- rotation: glyphMid.angle * 180 / Math.PI
4527
- };
4528
- });
4529
- }
4530
4502
  function collectAlongPathCells(node, glyphs, soleFont, warnings) {
4531
4503
  const cells = [];
4532
4504
  let adv = 0;
4533
4505
  const walk = (el, parentStyle) => {
4534
4506
  var _a, _b, _c;
4535
4507
  const s = resolveStyle2(el, parentStyle);
4536
- const content = (_a = str(el[TEXT_ATTR])) != null ? _a : str(el[TEXT_CONTENT_ATTR]);
4508
+ const content = (_a = str(el[TEXT_CONTENT_ATTR])) != null ? _a : str(el[TEXT_ATTR]);
4537
4509
  if (content && !((_b = el.children) == null ? void 0 : _b.length)) {
4538
4510
  const gf = glyphFontFor(s, glyphs, soleFont, warnings);
4539
4511
  if (gf) {
@@ -4613,7 +4585,7 @@ var PixodeskAnimator = (() => {
4613
4585
  function numTrackOf(raw) {
4614
4586
  var _a;
4615
4587
  const r = readAnimatable(raw);
4616
- if (r.kind === "animated" && r.keyframes.length >= 2) {
4588
+ if (r.kind === "animated" /* Animated */ && r.keyframes.length >= 2) {
4617
4589
  const kfs = [...r.keyframes].sort((k1, k2) => (Number(k1.time) || 0) - (Number(k2.time) || 0));
4618
4590
  const times = kfs.map((kf) => Number(kf.time) || 0);
4619
4591
  const vals = kfs.map((kf) => Number(kf.value) || 0);
@@ -4634,7 +4606,7 @@ var PixodeskAnimator = (() => {
4634
4606
  }
4635
4607
  };
4636
4608
  }
4637
- const v = r.kind === "animated" ? Number((_a = r.keyframes[0]) == null ? void 0 : _a.value) || 0 : r.kind === "static" ? Number(r.value) || 0 : 0;
4609
+ 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;
4638
4610
  return { animated: false, times: [], at: () => v };
4639
4611
  }
4640
4612
  function mergeTrackTimes(a, b) {
@@ -4662,14 +4634,8 @@ var PixodeskAnimator = (() => {
4662
4634
  return {
4663
4635
  time,
4664
4636
  value: {
4665
- [
4666
- "translate"
4667
- /* Translate */
4668
- ]: [roundN(x - perp * sin, 3), roundN(y + perp * cos, 3)],
4669
- [
4670
- "rotate"
4671
- /* Rotate */
4672
- ]: roundN(angle * 180 / Math.PI, 3)
4637
+ ["translate" /* Translate */]: [roundN(x - perp * sin, 3), roundN(y + perp * cos, 3)],
4638
+ ["rotate" /* Rotate */]: roundN(angle * 180 / Math.PI, 3)
4673
4639
  }
4674
4640
  };
4675
4641
  };
@@ -4699,7 +4665,7 @@ var PixodeskAnimator = (() => {
4699
4665
  if (loop !== void 0) op.loop = loop;
4700
4666
  animate.opacity = op;
4701
4667
  }
4702
- out.push(create("path", __spreadProps2(__spreadValues2({ d }, paintProps(c.paint)), { animate }), []));
4668
+ out.push(create("path", __spreadProps(__spreadValues({ d }, paintProps(c.paint)), { animate }), []));
4703
4669
  }
4704
4670
  return out;
4705
4671
  }
@@ -4725,7 +4691,7 @@ var PixodeskAnimator = (() => {
4725
4691
  else byPaint.set(key, { paint: p.paint, d: baked });
4726
4692
  }
4727
4693
  const out = [];
4728
- for (const { paint, d } of byPaint.values()) out.push(create("path", __spreadValues2({ d }, paintProps(paint)), []));
4694
+ for (const { paint, d } of byPaint.values()) out.push(create("path", __spreadValues({ d }, paintProps(paint)), []));
4729
4695
  return out;
4730
4696
  }
4731
4697
  function toGroup(node, children, create) {
@@ -4735,17 +4701,13 @@ var PixodeskAnimator = (() => {
4735
4701
  gProps[k] = node[k];
4736
4702
  }
4737
4703
  if (gProps.style && typeof gProps.style === "object") {
4738
- const style = __spreadValues2({}, gProps.style);
4704
+ const style = __spreadValues({}, gProps.style);
4739
4705
  delete style["white-space"];
4740
4706
  if (Object.keys(style).length) gProps.style = style;
4741
4707
  else delete gProps.style;
4742
4708
  }
4743
4709
  return create("g", gProps, children);
4744
4710
  }
4745
- function materialiseGlyphText(node, opts) {
4746
- if (opts.alongPath) return materialiseGlyphTextAlongPath(node, opts.alongPath.pathD, opts.alongPath.startOffset, opts, opts.alongPath.textLength, opts.alongPath.pathOverflow);
4747
- return materialiseGlyphTextHorizontal(node, opts);
4748
- }
4749
4711
  function applyTextGlyphsEffect(node, fx, ctx) {
4750
4712
  if (!(fx == null ? void 0 : fx.useGlyphs)) return node;
4751
4713
  if (!ctx.glyphs) {
@@ -4761,9 +4723,11 @@ var PixodeskAnimator = (() => {
4761
4723
  }
4762
4724
  return materialiseGlyphTextAlongPath(node, pathD, startOffset, { glyphs: ctx.glyphs, warnings: ctx.warnings }, textLength, pathOverflow);
4763
4725
  }
4764
- function applyTrimPathEffect(node, trimPath, isCombinedShape, ctx) {
4726
+
4727
+ // ../svg-animator-core/src/effects/trimPathEffect.ts
4728
+ function applyTrimPathEffect(node, trimPath, ctx) {
4765
4729
  if (!trimPath) return node;
4766
- const trimAllAsOne = !!trimPath.trimAllAsOne;
4730
+ const combined = trimPath.subPaths === PxTrimSubPaths.combined;
4767
4731
  const leafEntries = [];
4768
4732
  const measure = (n) => {
4769
4733
  if (Array.isArray(n.children) && n.children.length > 0) {
@@ -4784,20 +4748,20 @@ var PixodeskAnimator = (() => {
4784
4748
  measure(node);
4785
4749
  if (!leafEntries.length) return node;
4786
4750
  let acc = 0;
4787
- const iterOrder = trimAllAsOne ? [...leafEntries].reverse() : leafEntries;
4751
+ const iterOrder = combined ? [...leafEntries].reverse() : leafEntries;
4788
4752
  for (const entry of iterOrder) {
4789
4753
  for (const sp of entry.subpaths) {
4790
- if (!trimAllAsOne) acc = 0;
4754
+ if (!combined) acc = 0;
4791
4755
  sp.startOffsetPx = acc;
4792
4756
  acc += sp.lengthPx;
4793
4757
  }
4794
4758
  }
4795
4759
  const chainLengthPx = acc;
4796
- if (trimAllAsOne && chainLengthPx < 1e-3) return node;
4760
+ if (combined && chainLengthPx < 1e-3) return node;
4797
4761
  const offsetReadRaw = readAnimatable(trimPath.offset);
4798
- const offsetRead = offsetReadRaw.kind === "absent" ? { kind: "static", value: 0 } : offsetReadRaw;
4762
+ const offsetRead = offsetReadRaw.kind === "absent" /* Absent */ ? { kind: "static" /* Static */, value: 0 } : offsetReadRaw;
4799
4763
  const rangeReadRaw = readRangeWithCrossings(trimPath.range);
4800
- const rangeRead = rangeReadRaw.kind === "absent" ? { kind: "static", value: [0, 1] } : rangeReadRaw;
4764
+ const rangeRead = rangeReadRaw.kind === "absent" /* Absent */ ? { kind: "static" /* Static */, value: [0, 1] } : rangeReadRaw;
4801
4765
  const offsetValues = readScalarValues(offsetRead);
4802
4766
  const minOffset = offsetValues.length ? Math.min(...offsetValues) : 0;
4803
4767
  const maxOffset = offsetValues.length ? Math.max(...offsetValues) : 0;
@@ -4805,18 +4769,18 @@ var PixodeskAnimator = (() => {
4805
4769
  if (leafEntries.length === 1 && leafEntries[0].leaf === node && leafEntries[0].subpaths.length === 1) {
4806
4770
  const entry = leafEntries[0];
4807
4771
  const sp = entry.subpaths[0];
4808
- const pathLengthPx = trimAllAsOne ? chainLengthPx : sp.lengthPx;
4772
+ const pathLengthPx = combined ? chainLengthPx : sp.lengthPx;
4809
4773
  if (pathLengthPx < 1e-3) return node;
4810
- const startOffsetPct = trimAllAsOne ? sp.startOffsetPx / pathLengthPx : 0;
4774
+ const startOffsetPct = combined ? sp.startOffsetPx / pathLengthPx : 0;
4811
4775
  return collapseLeafWithTrim(entry.leaf, pathLengthPx, startOffsetPct, minMaxOffset, offsetRead, rangeRead);
4812
4776
  }
4813
4777
  const replacements = /* @__PURE__ */ new Map();
4814
4778
  for (const entry of leafEntries) {
4815
4779
  const newChildren = [];
4816
4780
  for (const sp of entry.subpaths) {
4817
- const pathLengthPx = trimAllAsOne ? chainLengthPx : sp.lengthPx;
4781
+ const pathLengthPx = combined ? chainLengthPx : sp.lengthPx;
4818
4782
  if (pathLengthPx < 1e-3) continue;
4819
- const startOffsetPct = trimAllAsOne ? sp.startOffsetPx / pathLengthPx : 0;
4783
+ const startOffsetPct = combined ? sp.startOffsetPx / pathLengthPx : 0;
4820
4784
  newChildren.push(...buildSubpathNodes(entry.leaf, sp.subpath, pathLengthPx, startOffsetPct, minMaxOffset, offsetRead, rangeRead, ctx));
4821
4785
  }
4822
4786
  replacements.set(entry.leaf, wrapLeafAsGroup(entry.leaf, newChildren));
@@ -4825,14 +4789,14 @@ var PixodeskAnimator = (() => {
4825
4789
  const r = replacements.get(n);
4826
4790
  if (r) return r;
4827
4791
  if (Array.isArray(n.children) && n.children.length > 0) {
4828
- return __spreadProps2(__spreadValues2({}, n), { children: n.children.map(swap) });
4792
+ return __spreadProps(__spreadValues({}, n), { children: n.children.map(swap) });
4829
4793
  }
4830
4794
  return n;
4831
4795
  };
4832
4796
  return swap(node);
4833
4797
  }
4834
4798
  function wrapLeafAsGroup(leaf, children) {
4835
- const wrapper = __spreadProps2(__spreadValues2({}, leaf), { type: "g", children });
4799
+ const wrapper = __spreadProps(__spreadValues({}, leaf), { type: "g", children });
4836
4800
  delete wrapper.d;
4837
4801
  delete wrapper.strokeDasharray;
4838
4802
  delete wrapper.strokeDashoffset;
@@ -4855,7 +4819,7 @@ var PixodeskAnimator = (() => {
4855
4819
  function collapseLeafWithTrim(leaf, pathLengthPx, startOffsetPct, minMaxOffset, offsetRead, rangeRead) {
4856
4820
  const offsetToDashOffset = makeOffsetToDashOffset(startOffsetPct, pathLengthPx, minMaxOffset);
4857
4821
  const rangeToDasharray = makeRangeToDasharray(pathLengthPx, minMaxOffset);
4858
- const node = __spreadValues2({}, leaf);
4822
+ const node = __spreadValues({}, leaf);
4859
4823
  delete node.effects;
4860
4824
  applyAttr(node, "strokeDasharray", computeAnimAttr(rangeRead, rangeToDasharray));
4861
4825
  applyAttr(node, "strokeDashoffset", computeAnimAttr(offsetRead, offsetToDashOffset));
@@ -4897,8 +4861,8 @@ var PixodeskAnimator = (() => {
4897
4861
  }
4898
4862
  function readScalarValues(r) {
4899
4863
  var _a;
4900
- if (r.kind === "absent") return [];
4901
- if (r.kind === "static") return [r.value];
4864
+ if (r.kind === "absent" /* Absent */) return [];
4865
+ if (r.kind === "static" /* Static */) return [r.value];
4902
4866
  const out = [];
4903
4867
  for (const kf of r.keyframes) {
4904
4868
  const v = (_a = kf.value) != null ? _a : kf.v;
@@ -4907,10 +4871,10 @@ var PixodeskAnimator = (() => {
4907
4871
  return out;
4908
4872
  }
4909
4873
  function computeAnimAttr(read, map) {
4910
- if (read.kind === "absent") return void 0;
4911
- if (read.kind === "static") return { kind: "static", value: map(read.value) };
4874
+ if (read.kind === "absent" /* Absent */) return void 0;
4875
+ if (read.kind === "static" /* Static */) return { kind: "static" /* Static */, value: map(read.value) };
4912
4876
  return {
4913
- kind: "animated",
4877
+ kind: "animated" /* Animated */,
4914
4878
  keyframes: read.keyframes.map((kf) => {
4915
4879
  var _a, _b, _c, _d;
4916
4880
  return {
@@ -4923,29 +4887,15 @@ var PixodeskAnimator = (() => {
4923
4887
  };
4924
4888
  }
4925
4889
  function applyAttr(node, attrName, attr) {
4926
- var _a, _b;
4927
4890
  if (!attr) return;
4928
- if (attr.kind === "static") {
4929
- node[attrName] = attr.value;
4930
- return;
4931
- }
4932
- const prevAnimate = node.animate && typeof node.animate === "object" && !Array.isArray(node.animate) ? node.animate : void 0;
4933
- const animate = __spreadValues2({}, prevAnimate || {});
4934
- const block = { keyframes: attr.keyframes };
4935
- if (attr.loop !== void 0) block.loop = attr.loop;
4936
- animate[attrName] = block;
4937
- node.animate = animate;
4938
- const firstKf = attr.keyframes[0];
4939
- if (firstKf && ((_a = firstKf.value) != null ? _a : firstKf.v) !== void 0) {
4940
- node[attrName] = (_b = firstKf.value) != null ? _b : firstKf.v;
4941
- }
4891
+ writeAnimatableChannel(node, attrName, attr);
4942
4892
  }
4943
4893
  var OPACITY_STEP_MS = 10;
4944
4894
  function computeOpacityFromRange(rangeRead) {
4945
4895
  var _a, _b, _c, _d, _e, _f;
4946
4896
  const hide = (v) => v[0] === v[1];
4947
- if (rangeRead.kind === "absent") return void 0;
4948
- if (rangeRead.kind === "static") return hide(rangeRead.value) ? { kind: "static", value: 0 } : void 0;
4897
+ if (rangeRead.kind === "absent" /* Absent */) return void 0;
4898
+ if (rangeRead.kind === "static" /* Static */) return hide(rangeRead.value) ? { kind: "static" /* Static */, value: 0 } : void 0;
4949
4899
  const kfs = rangeRead.keyframes;
4950
4900
  let anyHide = false;
4951
4901
  let allHide = true;
@@ -4954,7 +4904,7 @@ var PixodeskAnimator = (() => {
4954
4904
  else allHide = false;
4955
4905
  }
4956
4906
  if (!anyHide) return void 0;
4957
- if (allHide) return { kind: "static", value: 0 };
4907
+ if (allHide) return { kind: "static" /* Static */, value: 0 };
4958
4908
  const out = [];
4959
4909
  for (let i = 0; i < kfs.length; i++) {
4960
4910
  const kf = kfs[i];
@@ -4973,11 +4923,11 @@ var PixodeskAnimator = (() => {
4973
4923
  }
4974
4924
  }
4975
4925
  if (out.length <= 1) return void 0;
4976
- return { kind: "animated", keyframes: out };
4926
+ return { kind: "animated" /* Animated */, keyframes: out };
4977
4927
  }
4978
4928
  function readRangeWithCrossings(raw) {
4979
4929
  const r = readAnimatable(raw);
4980
- if (r.kind !== "animated") return r;
4930
+ if (r.kind !== "animated" /* Animated */) return r;
4981
4931
  const kfs = r.keyframes.map((kf) => {
4982
4932
  var _a, _b, _c, _d;
4983
4933
  return {
@@ -4989,7 +4939,7 @@ var PixodeskAnimator = (() => {
4989
4939
  const hasReverse = kfs.some((kf) => kf.value[0] > kf.value[1]);
4990
4940
  if (!hasReverse) {
4991
4941
  return {
4992
- kind: "animated",
4942
+ kind: "animated" /* Animated */,
4993
4943
  keyframes: kfs.map((kf) => ({ time: kf.time, value: kf.value, easing: kf.easing }))
4994
4944
  };
4995
4945
  }
@@ -5025,7 +4975,7 @@ var PixodeskAnimator = (() => {
5025
4975
  const m = (v[0] + v[1]) / 2;
5026
4976
  out.push({ time: t, value: [m, m] });
5027
4977
  }
5028
- return { kind: "animated", keyframes: out };
4978
+ return { kind: "animated" /* Animated */, keyframes: out };
5029
4979
  }
5030
4980
  function bisectionForRangeCrossing(prev, cur) {
5031
4981
  const f = (t) => {
@@ -5110,6 +5060,8 @@ var PixodeskAnimator = (() => {
5110
5060
  }
5111
5061
  return void 0;
5112
5062
  }
5063
+
5064
+ // ../svg-animator-core/src/effects/PlayerEffectsUtil.ts
5113
5065
  function applyPlayerEffects(root) {
5114
5066
  var _a, _b;
5115
5067
  const ctx = {
@@ -5120,9 +5072,9 @@ var PixodeskAnimator = (() => {
5120
5072
  nextId: 0,
5121
5073
  contentRefInnerIds: /* @__PURE__ */ new Map(),
5122
5074
  maskAncestorChains: /* @__PURE__ */ new Map(),
5123
- // Resolved engine: `frames` ONLY when explicitly set; auto/webapi/unset →
5124
- // webapi (we're not 100% sure it's frames, and CSS/WAAPI need the inline form).
5125
- engine: ((_a = getAnimatorConfig(root)) == null ? void 0 : _a.mode) === PxAnimatorMode.frames ? PxAnimatorEngine.frames : PxAnimatorEngine.webapi,
5075
+ // Resolved engine: `frames` ONLY when explicitly set; auto/waapi/unset →
5076
+ // waapi (we're not 100% sure it's frames, and CSS/WAAPI need the inline form).
5077
+ engine: ((_a = getAnimatorConfig(root)) == null ? void 0 : _a.mode) === PxAnimatorMode.frames ? PxAnimatorEngine.frames : PxAnimatorEngine.waapi,
5126
5078
  glyphs: (_b = getDefs(root)) == null ? void 0 : _b.glyphs
5127
5079
  };
5128
5080
  const working = clone(root);
@@ -5140,8 +5092,7 @@ var PixodeskAnimator = (() => {
5140
5092
  const originalId = typeof node.id === "string" ? node.id : void 0;
5141
5093
  const innerIdForContentRef = originalId ? ctx.contentRefInnerIds.get(originalId) : void 0;
5142
5094
  if (!fx && !innerIdForContentRef) return node;
5143
- const { transformation, repeater, maskedBy, clipPath, trimPath, clone: cloneFx, fillGradient, strokeGradient, textPath, text } = fx != null ? fx : {};
5144
- const isCombinedShape = fx == null ? void 0 : fx.isCombinedShape;
5095
+ const { transformBy, repeater, maskedBy, clipPath, trimPath, clone: cloneFx, fillGradient, strokeGradient, textPath, text } = fx != null ? fx : {};
5145
5096
  if (fx) delete node.effects;
5146
5097
  let n = node;
5147
5098
  let consumedByGlyphs = false;
@@ -5161,15 +5112,15 @@ var PixodeskAnimator = (() => {
5161
5112
  if (!consumedByGlyphs) n = applyTextPathEffect(n, textPath, ctx);
5162
5113
  n = applyFillGradientEffect(n, fillGradient, ctx);
5163
5114
  n = applyStrokeGradientEffect(n, strokeGradient, ctx);
5164
- n = applyTrimPathEffect(n, trimPath, isCombinedShape, ctx);
5115
+ n = applyTrimPathEffect(n, trimPath, ctx);
5165
5116
  n = applyRepeaterEffect(n, repeater, ctx);
5166
- n = applyMaskedByEffect(n, maskedBy, transformation, ctx);
5117
+ n = applyMaskedByEffect(n, maskedBy, transformBy, ctx);
5167
5118
  n = applyClipPathEffect(n, clipPath, ctx);
5168
5119
  if (innerIdForContentRef) {
5169
5120
  applyRefHref(n, cloneFx, ctx);
5170
- n = splitForContentRef(n, transformation, originalId, innerIdForContentRef, ctx);
5121
+ n = splitForContentRef(n, transformBy, originalId, innerIdForContentRef, ctx);
5171
5122
  } else {
5172
- n = applyRefAndTransformationEffect(n, cloneFx, transformation, ctx);
5123
+ n = applyRefAndTransformationEffect(n, cloneFx, transformBy, ctx);
5173
5124
  }
5174
5125
  if (cloneFx == null ? void 0 : cloneFx.retime) node.effects = { clone: { retime: cloneFx.retime } };
5175
5126
  if (originalId) ctx.idMap.set(originalId, n);
@@ -5179,12 +5130,14 @@ var PixodeskAnimator = (() => {
5179
5130
  applyAllRetimeEffects(node, ctx);
5180
5131
  return node;
5181
5132
  }
5133
+
5134
+ // ../svg-animator-core/src/PxAnimatorMaterialiseAll.ts
5182
5135
  function materialiseAllInTree(doc, engine, opts) {
5183
5136
  var _a, _b;
5184
5137
  let root = applyPlayerEffects(doc).root;
5185
5138
  const duration = (_b = (_a = getAnimatorConfig(root)) == null ? void 0 : _a.duration) != null ? _b : DEFAULT_DURATION_MS;
5186
5139
  root = materialiseInternalLoopsInTree(root, duration);
5187
- if (engine === PxAnimatorEngine.webapi) {
5140
+ if (engine === PxAnimatorEngine.waapi) {
5188
5141
  root = materialiseMotionPathsInTree(root, opts == null ? void 0 : opts.motionPath);
5189
5142
  root = materialiseAnimatedUseInstances(root);
5190
5143
  root = pruneUnreferencedDefs(root);
@@ -5220,6 +5173,8 @@ var PixodeskAnimator = (() => {
5220
5173
  }
5221
5174
  return root;
5222
5175
  }
5176
+
5177
+ // ../svg-animator-core/src/PxFrameLoop.ts
5223
5178
  function requestFrame(cb) {
5224
5179
  const g = globalThis;
5225
5180
  if (typeof g.requestAnimationFrame === "function") return g.requestAnimationFrame(cb);
@@ -5496,270 +5451,6 @@ var PixodeskAnimator = (() => {
5496
5451
  };
5497
5452
  return api;
5498
5453
  }
5499
- var IDENTITY = [1, 0, 0, 1, 0, 0];
5500
- function mul(m, n) {
5501
- return [
5502
- m[0] * n[0] + m[2] * n[1],
5503
- m[1] * n[0] + m[3] * n[1],
5504
- m[0] * n[2] + m[2] * n[3],
5505
- m[1] * n[2] + m[3] * n[3],
5506
- m[0] * n[4] + m[2] * n[5] + m[4],
5507
- m[1] * n[4] + m[3] * n[5] + m[5]
5508
- ];
5509
- }
5510
- var translateM = (x, y) => [1, 0, 0, 1, x, y];
5511
- var scaleM = (sx, sy) => [sx, 0, 0, sy, 0, 0];
5512
- function rotateM(deg) {
5513
- const r = deg * Math.PI / 180;
5514
- return [Math.cos(r), Math.sin(r), -Math.sin(r), Math.cos(r), 0, 0];
5515
- }
5516
- var skewXM = (deg) => [1, 0, Math.tan(deg * Math.PI / 180), 1, 0, 0];
5517
- var skewYM = (deg) => [1, Math.tan(deg * Math.PI / 180), 0, 1, 0, 0];
5518
- function parseTransformString(s) {
5519
- let m = IDENTITY;
5520
- const re = /(translate|rotate|scale|matrix|skewX|skewY)\(([^)]*)\)/g;
5521
- let hit;
5522
- while (hit = re.exec(s)) {
5523
- const fn = hit[1];
5524
- const a = hit[2].split(/[\s,]+/).filter(Boolean).map(Number);
5525
- if (fn === "translate") m = mul(m, translateM(a[0] || 0, a[1] || 0));
5526
- else if (fn === "scale") m = mul(m, scaleM(a[0], a.length > 1 ? a[1] : a[0]));
5527
- else if (fn === "rotate") m = mul(m, rotateM(a[0]));
5528
- else if (fn === "skewX") m = mul(m, skewXM(a[0]));
5529
- else if (fn === "skewY") m = mul(m, skewYM(a[0]));
5530
- else if (fn === "matrix") m = mul(m, [a[0], a[1], a[2], a[3], a[4], a[5]]);
5531
- }
5532
- return m;
5533
- }
5534
- function partsToMatrix(p) {
5535
- let m = IDENTITY;
5536
- if (p.translate) m = mul(m, translateM(p.translate[0], p.translate[1]));
5537
- const pivot = p.origin && (p.rotate !== void 0 || p.scale);
5538
- if (pivot) m = mul(m, translateM(p.origin[0], p.origin[1]));
5539
- if (p.rotate !== void 0) m = mul(m, rotateM(p.rotate));
5540
- if (p.scale) m = mul(m, scaleM(p.scale[0], p.scale[1]));
5541
- if (pivot) m = mul(m, translateM(-p.origin[0], -p.origin[1]));
5542
- return m;
5543
- }
5544
- function lerp(a, b, f) {
5545
- return a + (b - a) * f;
5546
- }
5547
- function interpParts(kfs, t) {
5548
- var _a, _b, _c, _d, _e, _f, _g;
5549
- if (!kfs.length) return {};
5550
- if (t <= ((_a = kfs[0].time) != null ? _a : 0)) return kfs[0].value || {};
5551
- if (t >= ((_b = kfs[kfs.length - 1].time) != null ? _b : 0)) return kfs[kfs.length - 1].value || {};
5552
- let i = 0;
5553
- while (i < kfs.length - 1 && ((_c = kfs[i + 1].time) != null ? _c : 0) < t) i++;
5554
- const a = kfs[i], b = kfs[i + 1];
5555
- const f = (t - ((_d = a.time) != null ? _d : 0)) / (((_e = b.time) != null ? _e : 0) - ((_f = a.time) != null ? _f : 0) || 1);
5556
- const va = a.value || {}, vb = b.value || {};
5557
- const out = {};
5558
- if (va.translate && vb.translate) out.translate = [lerp(va.translate[0], vb.translate[0], f), lerp(va.translate[1], vb.translate[1], f)];
5559
- else out.translate = va.translate || vb.translate;
5560
- if (va.rotate !== void 0 && vb.rotate !== void 0) out.rotate = lerp(va.rotate, vb.rotate, f);
5561
- else out.rotate = (_g = va.rotate) != null ? _g : vb.rotate;
5562
- if (va.scale && vb.scale) out.scale = [lerp(va.scale[0], vb.scale[0], f), lerp(va.scale[1], vb.scale[1], f)];
5563
- else out.scale = va.scale || vb.scale;
5564
- out.origin = va.origin || vb.origin;
5565
- return out;
5566
- }
5567
- function evalTransformValue(v, t) {
5568
- if (v === void 0 || v === null) return IDENTITY;
5569
- if (typeof v === "string") return parseTransformString(v);
5570
- if (v.keyframes) return partsToMatrix(interpParts(v.keyframes, t));
5571
- if (v.value) return partsToMatrix(v.value);
5572
- return IDENTITY;
5573
- }
5574
- function nodeMatrix(node, t) {
5575
- if (node.animate && node.animate.transform) return evalTransformValue(node.animate.transform, t);
5576
- if (node.transform !== void 0) return evalTransformValue(node.transform, t);
5577
- return IDENTITY;
5578
- }
5579
- function evalScalar(animated, staticVal, fallback, t) {
5580
- var _a, _b, _c, _d, _e, _f;
5581
- if (animated && animated.keyframes && animated.keyframes.length) {
5582
- const kfs = animated.keyframes;
5583
- if (t <= ((_a = kfs[0].time) != null ? _a : 0)) return kfs[0].value;
5584
- if (t >= ((_b = kfs[kfs.length - 1].time) != null ? _b : 0)) return kfs[kfs.length - 1].value;
5585
- let i = 0;
5586
- while (i < kfs.length - 1 && ((_c = kfs[i + 1].time) != null ? _c : 0) < t) i++;
5587
- const a = kfs[i], b = kfs[i + 1];
5588
- const f = (t - ((_d = a.time) != null ? _d : 0)) / (((_e = b.time) != null ? _e : 0) - ((_f = a.time) != null ? _f : 0) || 1);
5589
- return lerp(a.value, b.value, f);
5590
- }
5591
- return staticVal !== void 0 ? Number(staticVal) : fallback;
5592
- }
5593
- var CONTAINER_TYPES = /* @__PURE__ */ new Set(["svg", "g", "symbol"]);
5594
- var SKIP_TYPES = /* @__PURE__ */ new Set(["defs", "mask", "clipPath", "title"]);
5595
- function buildIdMap2(node, map) {
5596
- var _a;
5597
- if (typeof node.id === "string") map.set(node.id, node);
5598
- (_a = node.children) == null ? void 0 : _a.forEach((c) => buildIdMap2(c, map));
5599
- }
5600
- function num(v) {
5601
- return v === void 0 || v === null ? 0 : Number(v);
5602
- }
5603
- function round(n) {
5604
- return Math.round(n * 100) / 100 + 0;
5605
- }
5606
- function geomKey(node) {
5607
- var _a;
5608
- switch (node.type) {
5609
- case "rect":
5610
- return num(node.width) + "," + num(node.height) + "," + num(node.x) + "," + num(node.y);
5611
- case "ellipse":
5612
- return num(node.rx) + "," + num(node.ry) + "," + num(node.cx) + "," + num(node.cy);
5613
- case "circle":
5614
- return num(node.r) + "," + num(node.cx) + "," + num(node.cy);
5615
- case "path":
5616
- return String((_a = node.d) != null ? _a : "");
5617
- default:
5618
- return "";
5619
- }
5620
- }
5621
- function describePrimitive(node, m, t) {
5622
- var _a, _b, _c, _d, _e;
5623
- const fill = (_a = node.fill) != null ? _a : "";
5624
- const stroke = (_b = node.stroke) != null ? _b : "";
5625
- const sw = (_d = (_c = node["stroke-width"]) != null ? _c : node.strokeWidth) != null ? _d : "";
5626
- const opacity = round(evalScalar((_e = node.animate) == null ? void 0 : _e.opacity, node.opacity, 1, t));
5627
- const masked = node.mask ? 1 : 0;
5628
- const mat = m.map(round).join(",");
5629
- return node.type + "|" + geomKey(node) + "|[" + mat + "]|f:" + fill + "|s:" + stroke + "|sw:" + (num(sw) || "") + "|o:" + opacity + "|m:" + masked;
5630
- }
5631
- function flatten(node, parent, t, idMap, out) {
5632
- var _a;
5633
- const type = node.type || "";
5634
- if (SKIP_TYPES.has(type)) return;
5635
- const m = mul(parent, nodeMatrix(node, t));
5636
- if (type === "use") {
5637
- const targetId = typeof node.href === "string" ? node.href.replace(/^#/, "") : "";
5638
- const target = idMap.get(targetId);
5639
- const useM = mul(m, translateM(num(node.x), num(node.y)));
5640
- if (target) flatten(target, useM, t, idMap, out);
5641
- else out.push("UNRESOLVED_USE:#" + targetId);
5642
- return;
5643
- }
5644
- if (CONTAINER_TYPES.has(type)) {
5645
- (_a = node.children) == null ? void 0 : _a.forEach((c) => flatten(c, m, t, idMap, out));
5646
- return;
5647
- }
5648
- out.push(describePrimitive(node, m, t));
5649
- }
5650
- function collectSampleTimes(node, into) {
5651
- var _a;
5652
- into.add(0);
5653
- const scanAnim = (anim) => {
5654
- var _a2;
5655
- if (!anim || typeof anim !== "object") return;
5656
- for (const key of Object.keys(anim)) {
5657
- const kfs = (_a2 = anim[key]) == null ? void 0 : _a2.keyframes;
5658
- if (Array.isArray(kfs)) kfs.forEach((kf) => {
5659
- var _a3;
5660
- return into.add((_a3 = kf.time) != null ? _a3 : 0);
5661
- });
5662
- }
5663
- };
5664
- scanAnim(node.animate);
5665
- if (node.transform && typeof node.transform === "object" && node.transform.keyframes) {
5666
- node.transform.keyframes.forEach((kf) => {
5667
- var _a2;
5668
- return into.add((_a2 = kf.time) != null ? _a2 : 0);
5669
- });
5670
- }
5671
- (_a = node.children) == null ? void 0 : _a.forEach((c) => collectSampleTimes(c, into));
5672
- }
5673
- function visualModelAt(root, t) {
5674
- const idMap = /* @__PURE__ */ new Map();
5675
- buildIdMap2(root, idMap);
5676
- const out = [];
5677
- flatten(root, IDENTITY, t, idMap, out);
5678
- return out.sort();
5679
- }
5680
- function diffInEffect(a, b) {
5681
- const times = /* @__PURE__ */ new Set();
5682
- collectSampleTimes(a, times);
5683
- collectSampleTimes(b, times);
5684
- const diffs = [];
5685
- for (const t of Array.from(times).sort((x, y) => x - y)) {
5686
- const ma = visualModelAt(a, t);
5687
- const mb = visualModelAt(b, t);
5688
- const onlyInA = subtractMultiset(ma, mb);
5689
- const onlyInB = subtractMultiset(mb, ma);
5690
- if (onlyInA.length || onlyInB.length) diffs.push({ time: t, onlyInA, onlyInB });
5691
- }
5692
- return diffs;
5693
- }
5694
- function subtractMultiset(a, b) {
5695
- const counts = /* @__PURE__ */ new Map();
5696
- for (const x of b) counts.set(x, (counts.get(x) || 0) + 1);
5697
- const extra = [];
5698
- for (const x of a) {
5699
- const c = counts.get(x) || 0;
5700
- if (c > 0) counts.set(x, c - 1);
5701
- else extra.push(x);
5702
- }
5703
- return extra;
5704
- }
5705
-
5706
- // src/PxAnimatorDOM.ts
5707
- var SVG_NS = "http://www.w3.org/2000/svg";
5708
- function createElement(tagName, normalisedProps, style, children, textContent) {
5709
- if (DISALLOWED_SVG_TAGS_LOWER.has(tagName.toLowerCase())) {
5710
- console.warn("SVG tag blocked (dangerous): ", tagName);
5711
- return null;
5712
- }
5713
- const element = document.createElementNS(SVG_NS, tagName);
5714
- for (const propName in normalisedProps) {
5715
- const sanitised = sanitiseAttributeValue(propName, normalisedProps[propName]);
5716
- if (sanitised === void 0) continue;
5717
- if (CSS_ONLY_STYLE_PROPS.has(propName)) {
5718
- element.style[propName] = String(sanitised);
5719
- continue;
5720
- }
5721
- element.setAttribute(camelCaseToKebabWordIfNeeded(propName), sanitised);
5722
- }
5723
- if (style) {
5724
- for (const styleProp in style) {
5725
- element.style[styleProp] = String(style[styleProp]);
5726
- }
5727
- }
5728
- if (children) {
5729
- for (const child of children) {
5730
- element.appendChild(child);
5731
- }
5732
- }
5733
- if (textContent) element.textContent = textContent;
5734
- return element;
5735
- }
5736
- function renderNode(node, defs) {
5737
- if (!node) return null;
5738
- const _a = node, { type, children, style } = _a, props = __objRest(_a, ["type", "children", "style"]);
5739
- const feFuncType = props.funcType;
5740
- if (feFuncType !== void 0) delete props.funcType;
5741
- const nodeDefs = getDefs(node) || defs;
5742
- const resolvedStyle = resolveStyle(style, nodeDefs);
5743
- let childElements;
5744
- if (children) {
5745
- for (const ch of children) {
5746
- const child = renderNode(ch, nodeDefs);
5747
- if (child) {
5748
- if (!childElements) childElements = [];
5749
- childElements.push(child);
5750
- }
5751
- }
5752
- }
5753
- const element = createElement(
5754
- type || "g",
5755
- getNormalizedProps(props),
5756
- resolvedStyle,
5757
- childElements,
5758
- props[TEXT_ATTR] || props[TEXT_CONTENT_ATTR]
5759
- );
5760
- if (element && feFuncType !== void 0) element.setAttribute("type", feFuncType);
5761
- return element;
5762
- }
5763
5454
 
5764
5455
  // src/PxAnimatorTriggers.ts
5765
5456
  function setupAnimationTriggers(api, config) {
@@ -5806,8 +5497,14 @@ var PixodeskAnimator = (() => {
5806
5497
  break;
5807
5498
  }
5808
5499
  case "mouseOver": {
5809
- const mouseOverHandler = () => start();
5810
- const mouseOutHandler = () => handleEndAction();
5500
+ let enteredOnce = false;
5501
+ const mouseOverHandler = () => {
5502
+ enteredOnce = true;
5503
+ start();
5504
+ };
5505
+ const mouseOutHandler = () => {
5506
+ if (enteredOnce) handleEndAction();
5507
+ };
5811
5508
  root.addEventListener("mouseenter", mouseOverHandler);
5812
5509
  root.addEventListener("mouseleave", mouseOutHandler);
5813
5510
  break;
@@ -5824,17 +5521,32 @@ var PixodeskAnimator = (() => {
5824
5521
  break;
5825
5522
  }
5826
5523
  case "scrollIntoView": {
5524
+ const effectiveRatio = (entry) => {
5525
+ var _a, _b;
5526
+ const target = entry.boundingClientRect;
5527
+ const visible = entry.intersectionRect;
5528
+ if (!(target == null ? void 0 : target.height) || !visible) return entry.intersectionRatio;
5529
+ const live = typeof window !== "undefined" && window.innerHeight ? window.innerHeight : Infinity;
5530
+ const declared = (_b = (_a = entry.rootBounds) == null ? void 0 : _a.height) != null ? _b : Infinity;
5531
+ const viewport = Math.min(live, declared);
5532
+ const denom = Math.min(target.height, Number.isFinite(viewport) ? viewport : target.height);
5533
+ return denom > 0 ? visible.height / denom : entry.intersectionRatio;
5534
+ };
5535
+ const thresholdSteps = Array.from({ length: 21 }, (_, i) => i / 20);
5536
+ let wasIntersecting = false;
5827
5537
  const observer = new IntersectionObserver(
5828
5538
  (entries) => {
5829
5539
  entries.forEach((entry) => {
5830
- if (entry.isIntersecting && entry.intersectionRatio >= scrollIntoViewThreshold) {
5540
+ if (entry.isIntersecting && effectiveRatio(entry) >= scrollIntoViewThreshold) {
5541
+ wasIntersecting = true;
5831
5542
  start();
5832
- } else {
5543
+ } else if (wasIntersecting) {
5544
+ wasIntersecting = false;
5833
5545
  handleEndAction();
5834
5546
  }
5835
5547
  });
5836
5548
  },
5837
- { threshold: scrollIntoViewThreshold }
5549
+ { threshold: thresholdSteps }
5838
5550
  );
5839
5551
  observer.observe(root);
5840
5552
  break;
@@ -5929,7 +5641,7 @@ var PixodeskAnimator = (() => {
5929
5641
  } else {
5930
5642
  cssValue = "" + value;
5931
5643
  }
5932
- if (!CSS.supports(cssKey, cssValue)) unsupportedSet.add(cssKey);
5644
+ if (!CSS.supports(camelCaseToKebabWordIfNeeded(cssKey), cssValue)) unsupportedSet.add(cssKey);
5933
5645
  cssKey = kebabToCamelCaseWord(cssKey);
5934
5646
  cssKf[cssKey] = cssValue;
5935
5647
  return cssKf;
@@ -6006,7 +5718,7 @@ var PixodeskAnimator = (() => {
6006
5718
  console.warn("createFrameLoopAnimator: No root element provided");
6007
5719
  }
6008
5720
  }
6009
- const bindings = getNormalisedBindings(doc, PxAnimatorEngine.webapi);
5721
+ const bindings = getNormalisedBindings(doc, PxAnimatorEngine.waapi);
6010
5722
  const animations = [];
6011
5723
  const _iterations = config.iterations;
6012
5724
  let iterations;
@@ -6152,9 +5864,8 @@ var PixodeskAnimator = (() => {
6152
5864
  return api;
6153
5865
  }
6154
5866
 
6155
- // src/PxAnimator.ts
6156
- function createAnimatorFromConfig(doc, adapter, callbacks, rootElement) {
6157
- const animatorConfig = getAnimatorConfig(doc) || {};
5867
+ // src/PxAnimatorBind.ts
5868
+ function finaliseAnimator(animatorConfig, callbacks, make) {
6158
5869
  let apiRef;
6159
5870
  let effectiveCallbacks = callbacks;
6160
5871
  if (animatorConfig.resetOnFinish) {
@@ -6166,29 +5877,99 @@ var PixodeskAnimator = (() => {
6166
5877
  }
6167
5878
  });
6168
5879
  }
6169
- let res;
6170
- if (animatorConfig.mode === PxAnimatorMode.frames) {
6171
- res = createFrameLoopAnimator(doc, adapter, effectiveCallbacks, rootElement);
6172
- } else {
6173
- res = createWebApiAnimator(
6174
- doc,
6175
- effectiveCallbacks,
6176
- rootElement,
6177
- animatorConfig.mode === PxAnimatorMode.webapi
6178
- // forcing webapi
6179
- ) || createFrameLoopAnimator(doc, adapter, effectiveCallbacks, rootElement);
6180
- }
5880
+ const res = make(effectiveCallbacks);
6181
5881
  apiRef = res;
6182
5882
  if (animatorConfig.debugInstName) {
6183
5883
  window[animatorConfig.debugInstName] = res;
6184
5884
  }
6185
5885
  return res;
6186
5886
  }
5887
+ function bindWithEngineChoice(doc, adapter, callbacks, rootElement) {
5888
+ const animatorConfig = getAnimatorConfig(doc) || {};
5889
+ return finaliseAnimator(animatorConfig, callbacks, (cb) => {
5890
+ if (animatorConfig.mode === PxAnimatorMode.frames) {
5891
+ return createFrameLoopAnimator(doc, adapter, cb, rootElement);
5892
+ }
5893
+ return createWebApiAnimator(
5894
+ doc,
5895
+ cb,
5896
+ rootElement,
5897
+ animatorConfig.mode === PxAnimatorMode.waapi
5898
+ // forcing waapi
5899
+ ) || createFrameLoopAnimator(doc, adapter, cb, rootElement);
5900
+ });
5901
+ }
5902
+
5903
+ // src/PxAnimatorDOM.ts
5904
+ var SVG_NS = "http://www.w3.org/2000/svg";
5905
+ function createElement(tagName, normalisedProps, style, children, textContent) {
5906
+ if (DISALLOWED_SVG_TAGS_LOWER.has(tagName.toLowerCase())) {
5907
+ console.warn("SVG tag blocked (dangerous): ", tagName);
5908
+ return null;
5909
+ }
5910
+ const element = document.createElementNS(SVG_NS, tagName);
5911
+ for (const propName in normalisedProps) {
5912
+ const sanitised = sanitiseAttributeValue(propName, normalisedProps[propName]);
5913
+ if (sanitised === void 0) continue;
5914
+ if (CSS_ONLY_STYLE_PROPS.has(propName)) {
5915
+ element.style[propName] = String(sanitised);
5916
+ continue;
5917
+ }
5918
+ element.setAttribute(camelCaseToKebabWordIfNeeded(propName), sanitised);
5919
+ }
5920
+ if (style) {
5921
+ for (const styleProp in style) {
5922
+ element.style[styleProp] = String(style[styleProp]);
5923
+ }
5924
+ }
5925
+ if (children) {
5926
+ for (const child of children) {
5927
+ element.appendChild(child);
5928
+ }
5929
+ }
5930
+ if (textContent) element.textContent = textContent;
5931
+ return element;
5932
+ }
5933
+ function renderNode(node, defs) {
5934
+ if (!node) return null;
5935
+ const _a = node, { type, children, style } = _a, props = __objRest(_a, ["type", "children", "style"]);
5936
+ const domType = props.domType;
5937
+ if (domType !== void 0) delete props.domType;
5938
+ const nodeDefs = getDefs(node) || defs;
5939
+ const resolvedStyle = resolveStyle(style, nodeDefs);
5940
+ let childElements;
5941
+ if (children) {
5942
+ for (const ch of children) {
5943
+ const child = renderNode(ch, nodeDefs);
5944
+ if (child) {
5945
+ if (!childElements) childElements = [];
5946
+ childElements.push(child);
5947
+ }
5948
+ }
5949
+ }
5950
+ const element = createElement(
5951
+ type || "g",
5952
+ getNormalizedProps(props),
5953
+ resolvedStyle,
5954
+ childElements,
5955
+ props[TEXT_CONTENT_ATTR] || props[TEXT_ATTR]
5956
+ );
5957
+ if (element && domType !== void 0) element.setAttribute("type", domType);
5958
+ return element;
5959
+ }
5960
+
5961
+ // src/PxAnimatorKeys.ts
5962
+ var PX_ANIMATOR_DATA_KEY = "data";
5963
+
5964
+ // src/PxAnimator.ts
5965
+ function createAnimatorFromConfig(doc, adapter, callbacks, rootElement) {
5966
+ return bindWithEngineChoice(doc, adapter, callbacks, rootElement);
5967
+ }
6187
5968
  function createAnimatorImpl(doc, adapter, callbacks, containerElement) {
6188
5969
  const effectsWarnings = validateNodeEffects(doc);
6189
5970
  for (const w of effectsWarnings) console.warn("[PxAnimator] effects shape warning:", w);
6190
5971
  const animatorConfig = getAnimatorConfig(doc) || {};
6191
- const engine = animatorConfig.mode === PxAnimatorMode.frames ? PxAnimatorEngine.frames : PxAnimatorEngine.webapi;
5972
+ const engine = animatorConfig.mode === PxAnimatorMode.frames ? PxAnimatorEngine.frames : PxAnimatorEngine.waapi;
6192
5973
  doc = materialiseAllInTree(doc, engine);
6193
5974
  let rootElement = null;
6194
5975
  if (containerElement) {
@@ -6203,7 +5984,6 @@ var PixodeskAnimator = (() => {
6203
5984
  }
6204
5985
  return createAnimatorFromConfig(doc, adapter, callbacks, rootElement);
6205
5986
  }
6206
- var PX_ANIMATOR_DATA_KEY = "data";
6207
5987
  function createAnimator(options) {
6208
5988
  const { src, data, adapter, callbacks, container } = options;
6209
5989
  if (data !== void 0 && src !== void 0) {
@@ -6286,6 +6066,6 @@ var PixodeskAnimator = (() => {
6286
6066
  window["createAnimator"] = createAnimator;
6287
6067
  window["setupAnimationTriggers"] = setupAnimationTriggers;
6288
6068
  }
6289
- return __toCommonJS(index_exports);
6069
+ return __toCommonJS(index_player_exports);
6290
6070
  })();
6291
6071
  //# sourceMappingURL=index.umd.js.map