@pixodesk/svg-animator-web 1.0.22 → 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.cjs CHANGED
@@ -73,6 +73,7 @@ __export(index_exports, {
73
73
  PxGradientType: () => PxGradientType,
74
74
  PxGradientUnits: () => PxGradientUnits,
75
75
  PxKeyframeSchema: () => PxKeyframeSchema,
76
+ PxKeyframeValueSchema: () => PxKeyframeValueSchema,
76
77
  PxLoopSchema: () => PxLoopSchema,
77
78
  PxMaskedByEffectSchema: () => PxMaskedByEffectSchema,
78
79
  PxNodeBase: () => PxNodeBase,
@@ -84,9 +85,9 @@ __export(index_exports, {
84
85
  PxSvgNodeExtra: () => PxSvgNodeExtra,
85
86
  PxTextEffectSchema: () => PxTextEffectSchema,
86
87
  PxTextPathEffectSchema: () => PxTextPathEffectSchema,
88
+ PxTransformByEffectSchema: () => PxTransformByEffectSchema,
87
89
  PxTransformPartsSchema: () => PxTransformPartsSchema,
88
90
  PxTransformValueSchema: () => PxTransformValueSchema,
89
- PxTransformationEffectSchema: () => PxTransformationEffectSchema,
90
91
  PxTriggerSchema: () => PxTriggerSchema,
91
92
  PxTrimPathEffectSchema: () => PxTrimPathEffectSchema,
92
93
  STYLE_ATTR_NAMES: () => STYLE_ATTR_NAMES,
@@ -292,8 +293,9 @@ var Union = class extends Base {
292
293
  }
293
294
  isValid(raw, ctx, path) {
294
295
  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));
296
+ const probe = ctx && { errors: [], warnings: [], strict: ctx.strict };
297
+ if (this.schemas.some((s) => s.isValid(raw, probe, path ? [...path] : void 0))) return true;
298
+ 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
299
  return false;
298
300
  }
299
301
  _canSanitize(raw) {
@@ -369,6 +371,7 @@ var Obj = class extends Base {
369
371
  if (ctx == null ? void 0 : ctx.strict) {
370
372
  for (const key of Object.keys(obj)) {
371
373
  if (key in this._shape) continue;
374
+ if (obj[key] === void 0) continue;
372
375
  p.push(key);
373
376
  ctx.errors.push(pathStr(p) + ": unexpected extra key");
374
377
  p.pop();
@@ -509,6 +512,23 @@ var Any = class extends Base {
509
512
  return true;
510
513
  }
511
514
  };
515
+ var Defined = class extends Base {
516
+ constructor() {
517
+ super(...arguments);
518
+ this._default = void 0;
519
+ }
520
+ sanitize(raw) {
521
+ return raw;
522
+ }
523
+ isValid(raw, ctx, path) {
524
+ if (raw !== void 0) return true;
525
+ ctx == null ? void 0 : ctx.errors.push(pathStr(path != null ? path : []) + ": required value is missing");
526
+ return false;
527
+ }
528
+ _canSanitize(raw) {
529
+ return raw !== void 0;
530
+ }
531
+ };
512
532
  var Lazy = class extends Base {
513
533
  constructor(fn, _default) {
514
534
  super();
@@ -620,6 +640,8 @@ var px = {
620
640
  record: (value) => new Rec(value),
621
641
  /** Passes anything through unchanged — always valid. */
622
642
  any: () => new Any(),
643
+ /** Anything EXCEPT `undefined` — an open type whose presence is required (V6). */
644
+ defined: () => new Defined(),
623
645
  /** Fixed-length tuple — validates element count and each position individually. */
624
646
  tuple: (schemas) => new Tuple(schemas),
625
647
  /** Defers schema creation — required for recursive types. Must supply a default value. */
@@ -629,13 +651,52 @@ var PX_ANIM_SRC_ATTR_NAME = "data-px-animation-src";
629
651
  var PX_ANIM_ATTR_NAME = "_px_animator";
630
652
  var PxAnimatorMode = {
631
653
  auto: "auto",
632
- webapi: "webapi",
654
+ waapi: "waapi",
633
655
  frames: "frames"
634
656
  };
635
657
  var PxAnimatorEngine = {
636
- webapi: PxAnimatorMode.webapi,
658
+ waapi: PxAnimatorMode.waapi,
637
659
  frames: PxAnimatorMode.frames
638
660
  };
661
+ var PxLoopExtend = {
662
+ /** Segment from the START; the animation is extended BEFORE the first keyframe
663
+ * (intro loops that run before the main timeline begins). */
664
+ before: "before",
665
+ /** DEFAULT — segment from the END; extended AFTER the last keyframe (idle/outro
666
+ * loops that continue once the main timeline has finished). */
667
+ after: "after"
668
+ };
669
+ var PxMaskType = {
670
+ luminance: "luminance",
671
+ alpha: "alpha"
672
+ };
673
+ var PxUnits = {
674
+ userSpaceOnUse: "userSpaceOnUse",
675
+ objectBoundingBox: "objectBoundingBox"
676
+ };
677
+ var PxCloneType = {
678
+ content: "content"
679
+ };
680
+ var PxPathOverflow = {
681
+ clip: "clip",
682
+ extend: "extend"
683
+ };
684
+ var PxLengthAdjust = {
685
+ spacing: "spacing",
686
+ spacingAndGlyphs: "spacingAndGlyphs"
687
+ };
688
+ var PxTextPathMethod = {
689
+ align: "align",
690
+ stretch: "stretch"
691
+ };
692
+ var PxTextPathSpacing = {
693
+ auto: "auto",
694
+ exact: "exact"
695
+ };
696
+ var PxTrimSubPaths = {
697
+ separate: "separate",
698
+ combined: "combined"
699
+ };
639
700
  var TEXT_ATTR = "text";
640
701
  var TEXT_CONTENT_ATTR = "textContent";
641
702
  var INTERNAL_ATTRS = /* @__PURE__ */ new Set([
@@ -644,9 +705,49 @@ var INTERNAL_ATTRS = /* @__PURE__ */ new Set([
644
705
  "animator",
645
706
  "meta",
646
707
  "animate",
708
+ "effects",
647
709
  TEXT_ATTR,
648
710
  TEXT_CONTENT_ATTR
649
711
  ]);
712
+ var PX_TRANSFORM_PART_KEYS = ["translate", "rotate", "scale", "origin"];
713
+ var PxGradientUnits = {
714
+ userSpaceOnUse: "userSpaceOnUse",
715
+ objectBoundingBox: "objectBoundingBox"
716
+ };
717
+ var PxGradientSpreadMethod = {
718
+ pad: "pad",
719
+ reflect: "reflect",
720
+ repeat: "repeat"
721
+ };
722
+ var PxGradientType = {
723
+ linear: "linear",
724
+ radial: "radial"
725
+ };
726
+ function isPxElementFileFormat(fileJson) {
727
+ if (!(fileJson && typeof fileJson === "object" && !Array.isArray(fileJson))) {
728
+ return false;
729
+ }
730
+ return fileJson["type"] === "svg";
731
+ }
732
+ function getAnimatorConfig(doc) {
733
+ var _a;
734
+ return (doc == null ? void 0 : doc.animator) || ((_a = doc == null ? void 0 : doc.meta) == null ? void 0 : _a.animator);
735
+ }
736
+ function getDefs(doc) {
737
+ var _a;
738
+ if (!doc) return void 0;
739
+ return (_a = getAnimatorConfig(doc)) == null ? void 0 : _a.definitions;
740
+ }
741
+ function getBindings(doc) {
742
+ var _a;
743
+ if (!doc) return void 0;
744
+ const animateById = (_a = getAnimatorConfig(doc)) == null ? void 0 : _a.animateById;
745
+ if (!animateById) return void 0;
746
+ return Object.entries(animateById).map(([id, anim]) => ({ id, animate: anim }));
747
+ }
748
+ function getChildren(doc) {
749
+ return doc == null ? void 0 : doc.children;
750
+ }
650
751
  var PxEasingOrRefSchema = px.union([
651
752
  px.string(),
652
753
  px.tuple([px.number(), px.number(), px.number(), px.number()])
@@ -658,13 +759,15 @@ var PxKeyframeValueSchema = implementsInterface()(px.union([
658
759
  px.array(px.number()),
659
760
  px.lazy(() => PxTransformPartsSchema, {}),
660
761
  px.object({ path: px.string() }),
661
- px.lazy(() => px.object({ paths: px.array(PxBezierPathSchema) }), { paths: [] })
762
+ px.lazy(() => px.object({ paths: px.array(PxBezierPathSchema) }), { paths: [] }),
763
+ // Gradient `stops` timeline — each kf value is the full stops-array snapshot.
764
+ px.lazy(() => px.array(PxGradientStopSchema), [])
662
765
  ]));
663
766
  var PxKeyframeSchema = implementsInterface()(px.object({
664
767
  time: px.number().optional(),
665
768
  t: px.number().optional(),
666
- value: px.any().optional(),
667
- v: px.any().optional(),
769
+ value: PxKeyframeValueSchema.optional(),
770
+ v: PxKeyframeValueSchema.optional(),
668
771
  easing: PxEasingOrRefSchema.optional(),
669
772
  e: PxEasingOrRefSchema.optional(),
670
773
  tangentOut: px.tuple([px.number(), px.number()]).optional(),
@@ -678,16 +781,16 @@ var PxKeyframeSchema = implementsInterface()(px.object({
678
781
  }));
679
782
  var PxLoopSchema = implementsInterface()(px.object({
680
783
  segmentCount: px.number().optional(),
681
- before: px.boolean().optional(),
784
+ extend: px.enum([PxLoopExtend.before, PxLoopExtend.after]).optional(),
682
785
  alternate: px.boolean().optional()
683
786
  }));
684
787
  var PxPropertyAnimationSchema = implementsInterface()(px.object({
788
+ value: PxKeyframeValueSchema.optional(),
685
789
  keyframes: px.array(PxKeyframeSchema).optional(),
686
790
  kfs: px.array(PxKeyframeSchema).optional(),
687
791
  loop: px.union([PxLoopSchema, px.boolean()]).optional(),
688
792
  autoOrient: px.boolean().optional()
689
793
  }));
690
- var PX_TRANSFORM_PART_KEYS = ["translate", "rotate", "scale", "origin"];
691
794
  var PxTransformPartsSchema = implementsInterface()(px.object({
692
795
  translate: px.tuple([px.number(), px.number()]).optional(),
693
796
  rotate: px.number().optional(),
@@ -697,6 +800,7 @@ var PxTransformPartsSchema = implementsInterface()(px.object({
697
800
  }));
698
801
  var PxTransformValueSchema = px.union([
699
802
  px.string(),
803
+ PxTransformPartsSchema,
700
804
  px.object({ value: PxTransformPartsSchema }),
701
805
  PxPropertyAnimationSchema
702
806
  ]);
@@ -731,9 +835,11 @@ var PxDefsSchema = implementsInterface()(px.object({
731
835
  glyphs: px.record(PxGlyphFontSchema).optional()
732
836
  }));
733
837
  var PxAnimatorConfigSchema = implementsInterface()(px.object({
734
- mode: px.enum([PxAnimatorMode.auto, PxAnimatorMode.webapi, PxAnimatorMode.frames]).optional(),
838
+ mode: px.enum([PxAnimatorMode.auto, PxAnimatorMode.waapi, PxAnimatorMode.frames]).optional(),
735
839
  duration: px.number().optional(),
736
840
  delay: px.number().optional(),
841
+ // LAW (SCHEMA-DESIGN R3, S10): the ONE sanctioned string-in-number union
842
+ // (CSS animation-iteration-count familiarity) — do not add more mixed unions.
737
843
  iterations: px.union([px.number(), px.literal("infinite")]).optional(),
738
844
  fill: px.enum(["forwards", "backwards", "both", "none"]).optional(),
739
845
  direction: px.enum(["normal", "reverse", "alternate", "alternate-reverse"]).optional(),
@@ -741,9 +847,8 @@ var PxAnimatorConfigSchema = implementsInterface()(px.object({
741
847
  trigger: PxTriggerSchema.optional(),
742
848
  resetOnFinish: px.boolean().optional(),
743
849
  definitions: PxDefsSchema.optional(),
744
- animate: px.record(PxElementAnimationSchema).optional(),
745
- timeline: px.string().optional(),
746
- debug: px.boolean().optional(),
850
+ animateById: px.record(PxElementAnimationSchema).optional(),
851
+ timelineSource: px.string().optional(),
747
852
  debugInstName: px.string().optional()
748
853
  }));
749
854
  var PxBindingSchema = implementsInterface()(px.object({
@@ -753,26 +858,29 @@ var PxBindingSchema = implementsInterface()(px.object({
753
858
  var PxAttrValueSchema = px.union([
754
859
  px.string(),
755
860
  px.number(),
756
- px.object({ value: px.any() }),
757
- PxPropertyAnimationSchema
861
+ px.array(px.number()),
862
+ // Structured static — `{value: …}` (read-accepted transitional spelling, S1).
863
+ // `defined`, not `any`: the KEY's presence is what identifies this branch (V6).
864
+ px.object({ value: px.defined() }),
865
+ // Bare transform parts record — the canonical static `transform` on the wire (T2).
866
+ PxTransformPartsSchema
758
867
  ]);
759
868
  var PxAnimatableNumberSchema = px.union([
760
869
  px.number(),
761
870
  px.object({ value: px.number() }),
762
- px.object({
763
- keyframes: px.array(PxKeyframeSchema),
764
- autoOrient: px.boolean().optional()
765
- })
871
+ PxPropertyAnimationSchema
766
872
  ]);
767
873
  var PxAnimatableVec2Schema = px.union([
768
874
  px.tuple([px.number(), px.number()]),
769
875
  px.object({ value: px.tuple([px.number(), px.number()]) }),
770
- px.object({
771
- keyframes: px.array(PxKeyframeSchema),
772
- autoOrient: px.boolean().optional()
773
- })
876
+ PxPropertyAnimationSchema
877
+ ]);
878
+ var PxAnimatableStringSchema = px.union([
879
+ px.string(),
880
+ px.object({ value: px.string() }),
881
+ PxPropertyAnimationSchema
774
882
  ]);
775
- var PxTransformationEffectSchema = implementsInterface()(px.object({
883
+ var PxTransformByEffectSchema = implementsInterface()(px.object({
776
884
  translate: PxAnimatableVec2Schema.optional(),
777
885
  rotate: PxAnimatableNumberSchema.optional(),
778
886
  scale: PxAnimatableVec2Schema.optional(),
@@ -780,51 +888,46 @@ var PxTransformationEffectSchema = implementsInterface()(px.object({
780
888
  origin: PxAnimatableVec2Schema.optional()
781
889
  }));
782
890
  var PxRepeaterEffectSchema = implementsInterface()(px.object({
891
+ // STATIC config, not a channel (V2/SCHEMA-DESIGN R5): the copy COUNT is read
892
+ // once at expansion time and never sampled — plain number, no `keyframes`.
783
893
  copies: px.number().optional(),
784
894
  translate: PxAnimatableVec2Schema.optional(),
785
895
  rotate: PxAnimatableNumberSchema.optional(),
896
+ skew: PxAnimatableNumberSchema.optional(),
786
897
  scale: PxAnimatableVec2Schema.optional(),
787
898
  origin: PxAnimatableVec2Schema.optional()
788
899
  }));
789
900
  var PxMaskedByEffectSchema = implementsInterface()(px.object({
790
- href: px.string().optional(),
791
- maskType: px.string().optional(),
792
- maskUnits: px.string().optional(),
793
- maskContentUnits: px.string().optional()
901
+ sourceId: px.string().optional(),
902
+ maskType: px.enum([PxMaskType.luminance, PxMaskType.alpha]).optional(),
903
+ maskUnits: px.enum([PxUnits.userSpaceOnUse, PxUnits.objectBoundingBox]).optional(),
904
+ maskContentUnits: px.enum([PxUnits.userSpaceOnUse, PxUnits.objectBoundingBox]).optional(),
905
+ x: px.number().optional(),
906
+ y: px.number().optional(),
907
+ width: px.number().optional(),
908
+ height: px.number().optional()
794
909
  }));
795
910
  var PxClipPathEffectSchema = implementsInterface()(px.object({
796
- d: px.string().optional(),
911
+ d: PxAnimatableStringSchema.optional(),
797
912
  animate: PxPropertyAnimationSchema.optional()
798
913
  }));
799
914
  var PxTrimPathEffectSchema = implementsInterface()(px.object({
800
915
  offset: PxAnimatableNumberSchema.optional(),
801
916
  range: PxAnimatableVec2Schema.optional(),
802
- trimAllAsOne: px.boolean().optional()
917
+ subPaths: px.enum([PxTrimSubPaths.separate, PxTrimSubPaths.combined]).optional()
803
918
  }));
804
919
  var PxRetimeEffectSchema = implementsInterface()(px.object({
805
- baseId: px.string().optional(),
920
+ sourceId: px.string().optional(),
806
921
  start: px.number().optional(),
807
922
  stretch: px.number().optional(),
808
923
  timeCrop: px.tuple([px.number(), px.number()]).optional()
809
924
  }));
810
925
  var PxCloneEffectSchema = implementsInterface()(px.object({
811
- type: px.string().optional(),
812
- baseId: px.string().optional(),
926
+ // Contextual kind — the `type` convention, see `PxNodeBase.type`.
927
+ type: px.enum([PxCloneType.content]).optional(),
928
+ sourceId: px.string().optional(),
813
929
  retime: PxRetimeEffectSchema.optional()
814
930
  }));
815
- var PxGradientUnits = {
816
- userSpaceOnUse: "userSpaceOnUse",
817
- objectBoundingBox: "objectBoundingBox"
818
- };
819
- var PxGradientSpreadMethod = {
820
- pad: "pad",
821
- reflect: "reflect",
822
- repeat: "repeat"
823
- };
824
- var PxGradientType = {
825
- linear: "linear",
826
- radial: "radial"
827
- };
828
931
  var PxGradientStopSchema = implementsInterface()(px.object({
829
932
  offset: px.number(),
830
933
  color: px.string()
@@ -832,39 +935,28 @@ var PxGradientStopSchema = implementsInterface()(px.object({
832
935
  var PxAnimatableGradientStopsSchema = px.union([
833
936
  px.array(PxGradientStopSchema),
834
937
  px.object({ value: px.array(PxGradientStopSchema) }),
835
- px.object({ keyframes: px.array(PxKeyframeSchema) })
938
+ PxPropertyAnimationSchema
836
939
  ]);
837
- var PxGradientGeometryAnimationSchema = implementsInterface()(px.object({
838
- gradientX1: PxPropertyAnimationSchema.optional(),
839
- gradientY1: PxPropertyAnimationSchema.optional(),
840
- gradientX2: PxPropertyAnimationSchema.optional(),
841
- gradientY2: PxPropertyAnimationSchema.optional(),
842
- gradientCx: PxPropertyAnimationSchema.optional(),
843
- gradientCy: PxPropertyAnimationSchema.optional(),
844
- gradientFx: PxPropertyAnimationSchema.optional(),
845
- gradientFy: PxPropertyAnimationSchema.optional(),
846
- gradientR: PxPropertyAnimationSchema.optional()
847
- }));
848
940
  var PxFillGradientEffectSchema = implementsInterface()(px.object({
941
+ // Contextual kind — the `type` convention, see `PxNodeBase.type`.
849
942
  type: px.enum([PxGradientType.linear, PxGradientType.radial]),
850
- p1: px.tuple([px.number(), px.number()]).optional(),
851
- p2: px.tuple([px.number(), px.number()]).optional(),
852
- c: px.tuple([px.number(), px.number()]).optional(),
853
- r: px.number().optional(),
854
- fp: px.tuple([px.number(), px.number()]).optional(),
943
+ p1: PxAnimatableVec2Schema.optional(),
944
+ p2: PxAnimatableVec2Schema.optional(),
945
+ c: PxAnimatableVec2Schema.optional(),
946
+ r: PxAnimatableNumberSchema.optional(),
947
+ fp: PxAnimatableVec2Schema.optional(),
855
948
  stops: PxAnimatableGradientStopsSchema.optional(),
856
- gradientUnits: px.string().optional(),
857
- spreadMethod: px.string().optional(),
858
- gradientTransform: px.string().optional(),
859
- animate: PxGradientGeometryAnimationSchema.optional()
949
+ gradientUnits: px.enum([PxGradientUnits.userSpaceOnUse, PxGradientUnits.objectBoundingBox]).optional(),
950
+ spreadMethod: px.enum([PxGradientSpreadMethod.pad, PxGradientSpreadMethod.reflect, PxGradientSpreadMethod.repeat]).optional(),
951
+ gradientTransform: px.string().optional()
860
952
  }));
861
953
  var PxStrokeGradientEffectSchema = PxFillGradientEffectSchema;
862
954
  var PxTextPathEffectSchema = implementsInterface()(px.object({
863
955
  path: px.string(),
864
- pathOverflow: px.string().optional(),
865
- lengthAdjust: px.string().optional(),
866
- method: px.string().optional(),
867
- spacing: px.string().optional(),
956
+ pathOverflow: px.enum([PxPathOverflow.clip, PxPathOverflow.extend]).optional(),
957
+ lengthAdjust: px.enum([PxLengthAdjust.spacing, PxLengthAdjust.spacingAndGlyphs]).optional(),
958
+ method: px.enum([PxTextPathMethod.align, PxTextPathMethod.stretch]).optional(),
959
+ spacing: px.enum([PxTextPathSpacing.auto, PxTextPathSpacing.exact]).optional(),
868
960
  startOffset: PxAnimatableNumberSchema.optional(),
869
961
  textLength: PxAnimatableNumberSchema.optional()
870
962
  }));
@@ -872,13 +964,12 @@ var PxTextEffectSchema = implementsInterface()(px.object({
872
964
  useGlyphs: px.boolean().optional()
873
965
  }));
874
966
  var PxEffectsSchema = implementsInterface()(px.object({
875
- transformation: PxTransformationEffectSchema.optional(),
967
+ transformBy: PxTransformByEffectSchema.optional(),
876
968
  repeater: PxRepeaterEffectSchema.optional(),
877
969
  maskedBy: PxMaskedByEffectSchema.optional(),
878
970
  clipPath: PxClipPathEffectSchema.optional(),
879
971
  trimPath: PxTrimPathEffectSchema.optional(),
880
972
  clone: PxCloneEffectSchema.optional(),
881
- isCombinedShape: px.boolean().optional(),
882
973
  fillGradient: PxFillGradientEffectSchema.optional(),
883
974
  strokeGradient: PxStrokeGradientEffectSchema.optional(),
884
975
  textPath: PxTextPathEffectSchema.optional(),
@@ -902,6 +993,14 @@ function validateNodeEffects(root, opts) {
902
993
  return warnings;
903
994
  }
904
995
  var PxNodeBase = px.openObject({
996
+ // CONVENTION (SCHEMA-DESIGN R1 / issues N4): `type` is the ONE word for "what
997
+ // kind of thing is this", discriminated by its CARRIER — here the node TAG
998
+ // (`rect`, `text`), and inside a sub-object that object's kind (`clone.type`,
999
+ // `fillGradient.type`, editor `preset.type`). Each sits in its own object, so
1000
+ // the carrier disambiguates completely; synonyms (`cloneKind`, `presetShape`)
1001
+ // would add words that all mean "type" and still need the carrier to read.
1002
+ // Guarding a `type` SLOT against a wrong VALUE is the job of strict enums
1003
+ // (issues V3), never of distinct key names.
905
1004
  type: px.string(),
906
1005
  id: px.string().optional(),
907
1006
  meta: px.any().optional(),
@@ -911,7 +1010,7 @@ var PxNodeBase = px.openObject({
911
1010
  effects: PxEffectsSchema.optional(),
912
1011
  // `PxElementAnimation` (not just `PxAnimationDefinition`) — accepts
913
1012
  // string ref / array of refs / inline definition / mixed array; mirrors
914
- // `animator.animate` map values and what `processNode` resolves at runtime.
1013
+ // `animator.animateById` map values and what `processNode` resolves at runtime.
915
1014
  animate: PxElementAnimationSchema.optional(),
916
1015
  style: px.union([px.string(), px.record(px.union([px.string(), px.number()]))]).optional()
917
1016
  }, PxAttrValueSchema);
@@ -935,35 +1034,10 @@ var PxBezierPathSchema = implementsInterface()(px.object({
935
1034
  o: px.array(px.array(px.number())).optional(),
936
1035
  c: px.boolean().optional()
937
1036
  }));
938
- function isPxElementFileFormat(fileJson) {
939
- if (!(fileJson && typeof fileJson === "object" && !Array.isArray(fileJson))) {
940
- return false;
941
- }
942
- return fileJson["type"] === "svg" || fileJson["tagName"] === "svg";
943
- }
944
1037
  function isPxElementFileFormatDeep(fileJson) {
945
1038
  const valid = PxAnimatedSvgDocumentSchema.isValid(fileJson);
946
1039
  return { valid, errors: valid ? [] : ["Document failed schema validation"] };
947
1040
  }
948
- function getAnimatorConfig(doc) {
949
- var _a, _b;
950
- 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);
951
- }
952
- function getDefs(doc) {
953
- var _a;
954
- if (!doc) return void 0;
955
- return (_a = getAnimatorConfig(doc)) == null ? void 0 : _a.definitions;
956
- }
957
- function getBindings(doc) {
958
- var _a;
959
- if (!doc) return void 0;
960
- const animate = (_a = getAnimatorConfig(doc)) == null ? void 0 : _a.animate;
961
- if (!animate) return void 0;
962
- return Object.entries(animate).map(([id, anim]) => ({ id, animate: anim }));
963
- }
964
- function getChildren(doc) {
965
- return doc == null ? void 0 : doc.children;
966
- }
967
1041
  function bezierToSvgPath(path, forceCurves = false) {
968
1042
  var _a, _b, _c, _d;
969
1043
  const v = path.v;
@@ -1414,7 +1488,7 @@ function generateNewIds(doc) {
1414
1488
  "flood-color",
1415
1489
  "lighting-color"
1416
1490
  ]);
1417
- const directIdRefAttrs = /* @__PURE__ */ new Set(["baseId", "targetId", "boundElementId"]);
1491
+ const directIdRefAttrs = /* @__PURE__ */ new Set(["sourceId", "targetId", "boundElementId"]);
1418
1492
  function collectIds(node) {
1419
1493
  if (!node || typeof node !== "object") return;
1420
1494
  if (node.id && typeof node.id === "string") {
@@ -1452,9 +1526,10 @@ function generateNewIds(doc) {
1452
1526
  } else if (urlRefAttrs.has(key)) {
1453
1527
  node[key] = replaceUrlRefs(value, idMap);
1454
1528
  } else if (directIdRefAttrs.has(key)) {
1455
- const newId = idMap.get(value);
1529
+ const hasHash = value.startsWith("#");
1530
+ const newId = idMap.get(hasHash ? value.slice(1) : value);
1456
1531
  if (newId) {
1457
- node[key] = newId;
1532
+ node[key] = hasHash ? "#" + newId : newId;
1458
1533
  }
1459
1534
  } else if (value.includes("url(#")) {
1460
1535
  node[key] = replaceUrlRefs(value, idMap);
@@ -1472,14 +1547,14 @@ function generateNewIds(doc) {
1472
1547
  }
1473
1548
  collectIds(cloned);
1474
1549
  updateRefs(cloned);
1475
- const docAnimate = (_a = cloned.animator) == null ? void 0 : _a.animate;
1550
+ const docAnimate = (_a = cloned.animator) == null ? void 0 : _a.animateById;
1476
1551
  if (docAnimate && typeof docAnimate === "object") {
1477
1552
  const updatedAnimate = {};
1478
1553
  for (const [id, anim] of Object.entries(docAnimate)) {
1479
1554
  const newId = (_b = idMap.get(id)) != null ? _b : id;
1480
1555
  updatedAnimate[newId] = anim;
1481
1556
  }
1482
- cloned.animator = __spreadProps2(__spreadValues2({}, cloned.animator), { animate: updatedAnimate });
1557
+ cloned.animator = __spreadProps2(__spreadValues2({}, cloned.animator), { animateById: updatedAnimate });
1483
1558
  }
1484
1559
  return cloned;
1485
1560
  }
@@ -1568,8 +1643,9 @@ function getNormalizedProps(props) {
1568
1643
  let value = props[rawKey];
1569
1644
  if (COLOUR_ATTR_NAMES.has(key) && Array.isArray(value)) {
1570
1645
  propsCopy[key] = toRGBA(value);
1571
- } else if (key === "transform" && value !== null && typeof value === "object" && !Array.isArray(value) && value.value && typeof value.value === "object") {
1572
- propsCopy["transform"] = composeTransformParts(value.value, { withUnits: false });
1646
+ } else if (key === "transform" && value !== null && typeof value === "object" && !Array.isArray(value) && !value.keyframes && !value.kfs) {
1647
+ const parts = value.value && typeof value.value === "object" ? value.value : value;
1648
+ propsCopy["transform"] = composeTransformParts(parts, { withUnits: false });
1573
1649
  } else if (TRANSFORM_FN_NAMES.has(key)) {
1574
1650
  if (Array.isArray(value)) {
1575
1651
  if (key === "translate") value = value.map((v) => v + "px");
@@ -1577,6 +1653,8 @@ function getNormalizedProps(props) {
1577
1653
  }
1578
1654
  if (key === "rotate") value = value + "deg";
1579
1655
  propsCopy["transform"] = key + "(" + value + ")";
1656
+ } else if (Array.isArray(value)) {
1657
+ propsCopy[key] = value.join(",");
1580
1658
  } else if (value !== void 0 && value !== null) {
1581
1659
  propsCopy[key] = String(value);
1582
1660
  }
@@ -1974,6 +2052,16 @@ function walkAndMaterialise(node, opts) {
1974
2052
  if (newAnimate) cloned.animate = newAnimate;
1975
2053
  return cloned;
1976
2054
  }
2055
+ var LOOP_JUMP_SHIFT_MS = 10;
2056
+ function deepEqualValue(a, b) {
2057
+ if (a === b) return true;
2058
+ if (typeof a !== typeof b || a === null || b === null || typeof a !== "object") return false;
2059
+ if (Array.isArray(a) !== Array.isArray(b)) return false;
2060
+ const ka = Object.keys(a);
2061
+ const kb = Object.keys(b);
2062
+ if (ka.length !== kb.length) return false;
2063
+ return ka.every((k) => deepEqualValue(a[k], b[k]));
2064
+ }
1977
2065
  function parsePathCommands(d) {
1978
2066
  const tokens = d.split(/([MLCZmlcz]|[\s,]+)/).map((t) => t.trim()).filter((t) => t && t !== ",");
1979
2067
  const commands = [];
@@ -2176,7 +2264,7 @@ function expandLoopKeyframes(propName, keyframes, loop, duration) {
2176
2264
  const totalIntervals = keyframes.length - 1;
2177
2265
  const segCount = clamp((_a = loop.segmentCount) != null ? _a : totalIntervals, 1, totalIntervals);
2178
2266
  let segKfs;
2179
- if (loop.before) {
2267
+ if (loop.extend === PxLoopExtend.before) {
2180
2268
  segKfs = keyframes.slice(0, segCount + 1);
2181
2269
  } else {
2182
2270
  segKfs = keyframes.slice(totalIntervals - segCount);
@@ -2184,7 +2272,7 @@ function expandLoopKeyframes(propName, keyframes, loop, duration) {
2184
2272
  const firstT = (_b = keyframes[0].t) != null ? _b : 0;
2185
2273
  const lastT = (_c = keyframes[keyframes.length - 1].t) != null ? _c : 0;
2186
2274
  let fillStart, fillEnd;
2187
- if (loop.before) {
2275
+ if (loop.extend === PxLoopExtend.before) {
2188
2276
  fillStart = 0;
2189
2277
  fillEnd = firstT;
2190
2278
  } else {
@@ -2211,7 +2299,10 @@ function expandLoopKeyframes(propName, keyframes, loop, duration) {
2211
2299
  const remainder = fillDuration - fullReps * segDuration;
2212
2300
  const partialFraction = remainder / segDuration;
2213
2301
  const looped = [];
2302
+ const separateBoundary = loop.extend !== PxLoopExtend.before;
2303
+ const originalTerminalKf = keyframes[keyframes.length - 1];
2214
2304
  function appendRep(repStart, isReversed, partial) {
2305
+ var _a2;
2215
2306
  let entries;
2216
2307
  if (isReversed) {
2217
2308
  entries = [];
@@ -2247,8 +2338,17 @@ function expandLoopKeyframes(propName, keyframes, loop, duration) {
2247
2338
  looped.push({ t: repStart + cutRelT * segDuration, v: cutValue, e: void 0 });
2248
2339
  return;
2249
2340
  }
2341
+ const prevKf = looped.length > 0 ? looped[looped.length - 1] : originalTerminalKf;
2342
+ const isBoundary = separateBoundary && i === 0 && prevKf !== void 0 && Math.abs(((_a2 = prevKf.t) != null ? _a2 : 0) - (repStart + entry.relT * segDuration)) < 1e-9;
2343
+ if (isBoundary) {
2344
+ if (deepEqualValue(prevKf.v, entry.v)) continue;
2345
+ if (looped.length > 0) {
2346
+ delete prevKf.tangentIn;
2347
+ delete prevKf.tangentOut;
2348
+ }
2349
+ }
2250
2350
  const pushed = {
2251
- t: repStart + entry.relT * segDuration,
2351
+ t: repStart + entry.relT * segDuration + (isBoundary ? LOOP_JUMP_SHIFT_MS : 0),
2252
2352
  v: entry.v,
2253
2353
  e: i < entries.length - 1 ? entry.e : void 0
2254
2354
  };
@@ -2296,7 +2396,7 @@ function expandLoopKeyframes(propName, keyframes, loop, duration) {
2296
2396
  looped.push(pushed);
2297
2397
  }
2298
2398
  }
2299
- if (loop.before) {
2399
+ if (loop.extend === PxLoopExtend.before) {
2300
2400
  if (partialFraction > 1e-9) {
2301
2401
  const isReversed = !!loop.alternate && fullReps % 2 === 0;
2302
2402
  appendRepTail(fillStart, isReversed, partialFraction);
@@ -2319,7 +2419,7 @@ function expandLoopKeyframes(propName, keyframes, loop, duration) {
2319
2419
  appendRep(repStart, isReversed, partialFraction);
2320
2420
  }
2321
2421
  }
2322
- if (loop.before) {
2422
+ if (loop.extend === PxLoopExtend.before) {
2323
2423
  return [...looped, ...keyframes];
2324
2424
  } else {
2325
2425
  return [...keyframes, ...looped];
@@ -2435,7 +2535,7 @@ var _elementIdCounter = 0;
2435
2535
  function generateElementId() {
2436
2536
  return "_px_el_" + ++_elementIdCounter;
2437
2537
  }
2438
- function normalizeAnimationDefinition(animDef, duration, defs, engine = PxAnimatorEngine.webapi) {
2538
+ function normalizeAnimationDefinition(animDef, duration, defs, engine = PxAnimatorEngine.waapi) {
2439
2539
  const normalized = {};
2440
2540
  for (const [propName, propAnim] of Object.entries(animDef)) {
2441
2541
  const normalizedKfs = normalizeKeyframes(propName, propAnim, duration, defs);
@@ -2443,12 +2543,12 @@ function normalizeAnimationDefinition(animDef, duration, defs, engine = PxAnimat
2443
2543
  const out = { kfs: normalizedKfs };
2444
2544
  if (propAnim.autoOrient !== void 0) out.autoOrient = propAnim.autoOrient;
2445
2545
  if (propAnim.loop !== void 0) out.loop = propAnim.loop;
2446
- normalized[propName] = engine === PxAnimatorEngine.webapi && propName === "transform" ? materialiseMotionPathInPropAnim(out) : out;
2546
+ normalized[propName] = engine === PxAnimatorEngine.waapi && propName === "transform" ? materialiseMotionPathInPropAnim(out) : out;
2447
2547
  }
2448
2548
  }
2449
2549
  return normalized;
2450
2550
  }
2451
- function getNormalisedBindings(doc, engine = PxAnimatorEngine.webapi) {
2551
+ function getNormalisedBindings(doc, engine = PxAnimatorEngine.waapi) {
2452
2552
  const animatorConfig = getAnimatorConfig(doc) || {};
2453
2553
  const defs = getDefs(doc);
2454
2554
  const duration = animatorConfig.duration || 1e3;
@@ -2853,7 +2953,7 @@ function partsRecord(part, value, origin) {
2853
2953
  return rec;
2854
2954
  }
2855
2955
  function readAnimatable(raw) {
2856
- var _a, _b;
2956
+ var _a, _b, _c;
2857
2957
  if (raw === void 0) return {
2858
2958
  kind: "absent"
2859
2959
  /* Absent */
@@ -2863,13 +2963,34 @@ function readAnimatable(raw) {
2863
2963
  const obj = raw;
2864
2964
  const kfs = (_a = obj.keyframes) != null ? _a : obj.kfs;
2865
2965
  if (kfs) {
2866
- return { kind: "animated", keyframes: kfs.map(normaliseKeyframe), autoOrient: obj.autoOrient, loop: obj.loop };
2966
+ const out = { kind: "animated", keyframes: kfs.map(normaliseKeyframe), autoOrient: obj.autoOrient, loop: obj.loop };
2967
+ const base = (_b = obj.value) != null ? _b : obj.v;
2968
+ if (base !== void 0 && out.kind === "animated") out.base = base;
2969
+ return out;
2867
2970
  }
2868
- const staticValue = (_b = obj.value) != null ? _b : obj.v;
2971
+ const staticValue = (_c = obj.value) != null ? _c : obj.v;
2869
2972
  if (staticValue !== void 0) return { kind: "static", value: staticValue };
2870
2973
  }
2871
2974
  return { kind: "static", value: raw };
2872
2975
  }
2976
+ function writeAnimatableChannel(node, attrName, read, opts) {
2977
+ var _a, _b, _c, _d;
2978
+ const toOut = (v) => (opts == null ? void 0 : opts.asString) && v !== void 0 && v !== null ? String(v) : v;
2979
+ if (read.kind === "absent") return;
2980
+ if (read.kind === "static") {
2981
+ node[attrName] = toOut(read.value);
2982
+ return;
2983
+ }
2984
+ const prevAnimate = node.animate && typeof node.animate === "object" && !Array.isArray(node.animate) ? node.animate : void 0;
2985
+ const animate = __spreadValues2({}, prevAnimate || {});
2986
+ const block = { keyframes: read.keyframes };
2987
+ if (read.loop !== void 0) block.loop = read.loop;
2988
+ if (read.autoOrient !== void 0) block.autoOrient = read.autoOrient;
2989
+ animate[attrName] = block;
2990
+ node.animate = animate;
2991
+ 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;
2992
+ if (baseline !== void 0) node[attrName] = toOut(baseline);
2993
+ }
2873
2994
  function normaliseKeyframe(kf) {
2874
2995
  if (!kf || typeof kf !== "object") return kf;
2875
2996
  const k = kf;
@@ -2889,7 +3010,7 @@ function readStaticOrigin(raw, ctx) {
2889
3010
  const o = readAnimatable(raw);
2890
3011
  if (o.kind === "absent") return void 0;
2891
3012
  if (o.kind === "static") return o.value;
2892
- ctx.warnings.push("transformation.origin: animated origin approximated by its first keyframe");
3013
+ ctx.warnings.push("transformBy.origin: animated origin approximated by its first keyframe");
2893
3014
  return (_a = o.keyframes[0]) == null ? void 0 : _a.value;
2894
3015
  }
2895
3016
  function keyframeWith(kf, value) {
@@ -2900,7 +3021,7 @@ function keyframeWith(kf, value) {
2900
3021
  if (kf.tangentIn !== void 0) out.tangentIn = kf.tangentIn;
2901
3022
  return out;
2902
3023
  }
2903
- function applyTransformationEffect(node, fx, ctx) {
3024
+ function applyTransformByEffect(node, fx, ctx) {
2904
3025
  if (!fx) return node;
2905
3026
  delete node.transform;
2906
3027
  let n = node;
@@ -2936,6 +3057,10 @@ function applyTransformationEffect(node, fx, ctx) {
2936
3057
  } else {
2937
3058
  n = wrapTransformPart(n, "translate", fx.translate, ctx);
2938
3059
  }
3060
+ if (n !== node && node.id) {
3061
+ n.id = node.id;
3062
+ delete node.id;
3063
+ }
2939
3064
  return n;
2940
3065
  }
2941
3066
  function translateHasAutoOrient(translate) {
@@ -2945,8 +3070,6 @@ function translateHasAutoOrient(translate) {
2945
3070
  return Array.isArray(obj.keyframes) && obj.keyframes.some((kf) => kf.tangentOut || kf.tangentIn);
2946
3071
  }
2947
3072
  function normalizeScale(raw) {
2948
- if (raw === void 0) return void 0;
2949
- if (Array.isArray(raw)) return [raw[0] / 100, raw[1] / 100];
2950
3073
  return raw;
2951
3074
  }
2952
3075
  function wrapTransformPart(inner, part, raw, ctx) {
@@ -2987,34 +3110,54 @@ function wrapOrigin(inner, raw, invert) {
2987
3110
  }
2988
3111
  return inner;
2989
3112
  }
3113
+ function genId(ctx, prefix) {
3114
+ return "_lw_" + prefix + "_" + ctx.nextId++;
3115
+ }
3116
+ function stripHash2(href) {
3117
+ return typeof href === "string" ? href.replace(/^#/, "") : void 0;
3118
+ }
3119
+ function indexById(node, map) {
3120
+ var _a;
3121
+ if (typeof node.id === "string") map.set(node.id, node);
3122
+ (_a = node.children) == null ? void 0 : _a.forEach((child) => indexById(child, map));
3123
+ }
3124
+ function spliceDefs(root, defs) {
3125
+ if (!defs.length) return;
3126
+ const existing = root.children || (root.children = []);
3127
+ existing.unshift({ type: "defs", children: defs });
3128
+ }
3129
+ var clone = deepClonePxNode;
3130
+ function regenerateIdsInClone(root, ctx) {
3131
+ return regenerateIdsAndRewriteRefs(root, () => genId(ctx, "retimed"));
3132
+ }
2990
3133
  function identifyContentRefTargets(node, ctx, allocator) {
2991
3134
  var _a, _b, _c;
2992
3135
  if (node.type === "use" && ((_b = (_a = node.effects) == null ? void 0 : _a.clone) == null ? void 0 : _b.type) === "content") {
2993
- const baseId = node.effects.clone.baseId;
2994
- if (typeof baseId === "string" && baseId && !ctx.contentRefInnerIds.has(baseId)) {
2995
- ctx.contentRefInnerIds.set(baseId, allocator(baseId));
3136
+ const sourceId = stripHash2(node.effects.clone.sourceId);
3137
+ if (typeof sourceId === "string" && sourceId && !ctx.contentRefInnerIds.has(sourceId)) {
3138
+ ctx.contentRefInnerIds.set(sourceId, allocator(sourceId));
2996
3139
  }
2997
3140
  }
2998
3141
  (_c = node.children) == null ? void 0 : _c.forEach((c) => identifyContentRefTargets(c, ctx, allocator));
2999
3142
  }
3000
- function splitForContentRef(node, transformation, originalId, innerId, ctx) {
3001
- const outerBody = liftBodyTranslate(node, transformation);
3143
+ function splitForContentRef(node, transformBy, originalId, innerId, ctx) {
3144
+ const outerBody = liftBodyTranslate(node, transformBy);
3002
3145
  if (typeof node.id === "string") delete node.id;
3003
- const { outer: outerTr, inner: innerTr } = splitTransformationEffect(transformation);
3146
+ const { outer: outerTr, inner: innerTr } = splitTransformByEffect(transformBy);
3004
3147
  let innerNode = node;
3005
- innerNode = applyTransformationEffect(innerNode, innerTr, ctx);
3148
+ innerNode = applyTransformByEffect(innerNode, innerTr, ctx);
3006
3149
  const innerWrapper = { type: "g", id: innerId, children: [innerNode] };
3007
3150
  let outerWrapper = { type: "g", id: originalId, children: [innerWrapper] };
3008
3151
  if (outerBody.transform !== void 0) outerWrapper.transform = outerBody.transform;
3009
3152
  if (outerBody.animate !== void 0) outerWrapper.animate = outerBody.animate;
3010
3153
  if (outerTr) {
3011
3154
  delete outerWrapper.id;
3012
- outerWrapper = applyTransformationEffect(outerWrapper, outerTr, ctx);
3155
+ outerWrapper = applyTransformByEffect(outerWrapper, outerTr, ctx);
3013
3156
  outerWrapper.id = originalId;
3014
3157
  }
3015
3158
  return outerWrapper;
3016
3159
  }
3017
- function liftBodyTranslate(node, transformation) {
3160
+ function liftBodyTranslate(node, transformBy) {
3018
3161
  var _a, _b, _c;
3019
3162
  const out = {};
3020
3163
  let didLiftAnimate = false;
@@ -3068,7 +3211,7 @@ function liftBodyTranslate(node, transformation) {
3068
3211
  didLiftAnimate = true;
3069
3212
  }
3070
3213
  }
3071
- const transformationHasTranslate = (transformation == null ? void 0 : transformation.translate) !== void 0;
3214
+ const transformationHasTranslate = (transformBy == null ? void 0 : transformBy.translate) !== void 0;
3072
3215
  const stripBodyTranslateOnly = didLiftAnimate || transformationHasTranslate;
3073
3216
  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);
3074
3217
  if (typeof node.transform === "string") {
@@ -3087,6 +3230,24 @@ function liftBodyTranslate(node, transformation) {
3087
3230
  if (split.rest) node.transform = split.rest;
3088
3231
  else delete node.transform;
3089
3232
  }
3233
+ } else if (node.transform && typeof node.transform === "object" && !Array.isArray(node.transform) && !node.transform.keyframes && !node.transform.kfs) {
3234
+ const wrapped = node.transform.value;
3235
+ const isWrapped = !!(wrapped && typeof wrapped === "object");
3236
+ const value = isWrapped ? wrapped : node.transform;
3237
+ const rewrap = (rec) => isWrapped ? { value: rec } : rec;
3238
+ if (Array.isArray(value.translate)) {
3239
+ const rest = __spreadValues2({}, value);
3240
+ delete rest.translate;
3241
+ const hasRest = Object.keys(rest).length > 0;
3242
+ if (stripBodyTranslateOnly) {
3243
+ if (hasRest) node.transform = rewrap(rest);
3244
+ else delete node.transform;
3245
+ } else {
3246
+ out.transform = rewrap({ translate: value.translate });
3247
+ if (hasRest) node.transform = rewrap(rest);
3248
+ else delete node.transform;
3249
+ }
3250
+ }
3090
3251
  }
3091
3252
  return out;
3092
3253
  }
@@ -3156,7 +3317,7 @@ function parseTranslateArgs(translateOp) {
3156
3317
  const nums = m[1].split(/[\s,]+/).filter(Boolean).map(Number);
3157
3318
  return [nums[0] || 0, nums[1] || 0];
3158
3319
  }
3159
- function splitTransformationEffect(fx) {
3320
+ function splitTransformByEffect(fx) {
3160
3321
  if (!fx) return {};
3161
3322
  const originOnOuter = needsOriginOnOuter(fx.translate);
3162
3323
  const innerHasPivotedPart = fx.rotate !== void 0 || fx.scale !== void 0;
@@ -3182,26 +3343,6 @@ function needsOriginOnOuter(translateAnim) {
3182
3343
  }
3183
3344
  return false;
3184
3345
  }
3185
- function genId(ctx, prefix) {
3186
- return "_lw_" + prefix + "_" + ctx.nextId++;
3187
- }
3188
- function stripHash2(href) {
3189
- return typeof href === "string" ? href.replace(/^#/, "") : void 0;
3190
- }
3191
- function indexById(node, map) {
3192
- var _a;
3193
- if (typeof node.id === "string") map.set(node.id, node);
3194
- (_a = node.children) == null ? void 0 : _a.forEach((child) => indexById(child, map));
3195
- }
3196
- function spliceDefs(root, defs) {
3197
- if (!defs.length) return;
3198
- const existing = root.children || (root.children = []);
3199
- existing.unshift({ type: "defs", children: defs });
3200
- }
3201
- var clone = deepClonePxNode;
3202
- function regenerateIdsInClone(root, ctx) {
3203
- return regenerateIdsAndRewriteRefs(root, () => genId(ctx, "retimed"));
3204
- }
3205
3346
  function applyFillGradientEffect(node, fx, ctx) {
3206
3347
  return applyGradient(node, fx, ctx, "fill");
3207
3348
  }
@@ -3222,62 +3363,63 @@ function synthesiseGradientDef(fx, id, ctx) {
3222
3363
  id
3223
3364
  };
3224
3365
  if (fx.type === PxGradientType.linear) {
3225
- if (fx.p1) {
3226
- out.x1 = String(fx.p1[0]);
3227
- out.y1 = String(fx.p1[1]);
3228
- }
3229
- if (fx.p2) {
3230
- out.x2 = String(fx.p2[0]);
3231
- out.y2 = String(fx.p2[1]);
3232
- }
3366
+ applyGeomVec(out, "x1", "y1", fx.p1);
3367
+ applyGeomVec(out, "x2", "y2", fx.p2);
3233
3368
  } else {
3234
- if (fx.c) {
3235
- out.cx = String(fx.c[0]);
3236
- out.cy = String(fx.c[1]);
3237
- }
3238
- if (fx.r !== void 0) out.r = String(fx.r);
3239
- if (fx.fp) {
3240
- out.fx = String(fx.fp[0]);
3241
- out.fy = String(fx.fp[1]);
3242
- }
3369
+ applyGeomVec(out, "cx", "cy", fx.c);
3370
+ applyGeomNumber(out, "r", fx.r);
3371
+ applyGeomVec(out, "fx", "fy", fx.fp);
3243
3372
  }
3244
3373
  if (fx.gradientUnits) out.gradientUnits = fx.gradientUnits;
3245
3374
  if (fx.spreadMethod) out.spreadMethod = fx.spreadMethod;
3246
3375
  if (fx.gradientTransform) out.gradientTransform = fx.gradientTransform;
3247
- const animate = fx.animate;
3248
- if (animate) {
3249
- const mapped = {};
3250
- for (const wireKey of Object.keys(animate)) {
3251
- const attr = GRADIENT_ANIM_CHANNEL_TO_ATTR[wireKey];
3252
- if (attr) mapped[attr] = animate[wireKey];
3253
- }
3254
- if (Object.keys(mapped).length) out.animate = mapped;
3255
- }
3256
3376
  out.children = buildStopChildren(fx.stops, ctx);
3257
3377
  return out;
3258
3378
  }
3259
- var GRADIENT_ANIM_CHANNEL_TO_ATTR = {
3260
- gradientX1: "x1",
3261
- gradientY1: "y1",
3262
- gradientX2: "x2",
3263
- gradientY2: "y2",
3264
- gradientCx: "cx",
3265
- gradientCy: "cy",
3266
- gradientFx: "fx",
3267
- gradientFy: "fy",
3268
- gradientR: "r"
3269
- };
3379
+ function applyGeomVec(out, xAttr, yAttr, raw) {
3380
+ var _a, _b, _c;
3381
+ const read = readAnimatable(raw);
3382
+ if (read.kind === "absent") return;
3383
+ if (read.kind === "static") {
3384
+ out[xAttr] = String(read.value[0]);
3385
+ out[yAttr] = String(read.value[1]);
3386
+ return;
3387
+ }
3388
+ const axisChannel = (idx) => {
3389
+ const block = {
3390
+ keyframes: read.keyframes.map((kf) => {
3391
+ const axisKf = { time: kf.time, value: Array.isArray(kf.value) ? kf.value[idx] : void 0 };
3392
+ if (kf.easing !== void 0) axisKf.easing = kf.easing;
3393
+ return axisKf;
3394
+ })
3395
+ };
3396
+ if (read.loop !== void 0) block.loop = read.loop;
3397
+ return block;
3398
+ };
3399
+ const animate = (_a = out.animate) != null ? _a : {};
3400
+ animate[xAttr] = axisChannel(0);
3401
+ animate[yAttr] = axisChannel(1);
3402
+ out.animate = animate;
3403
+ const baseline = (_c = read.base) != null ? _c : (_b = read.keyframes[0]) == null ? void 0 : _b.value;
3404
+ if (Array.isArray(baseline)) {
3405
+ out[xAttr] = String(baseline[0]);
3406
+ out[yAttr] = String(baseline[1]);
3407
+ }
3408
+ }
3409
+ function applyGeomNumber(out, attrName, raw) {
3410
+ const read = readAnimatable(raw);
3411
+ if (read.kind === "absent") return;
3412
+ writeAnimatableChannel(out, attrName, read, { asString: true });
3413
+ }
3270
3414
  function buildStopChildren(stops, ctx) {
3271
3415
  var _a, _b, _c, _d;
3272
3416
  if (!stops) return [];
3273
- if (Array.isArray(stops)) return stops.map(staticStopNode);
3274
- if (typeof stops === "object" && Array.isArray(stops.value)) {
3275
- return stops.value.map(staticStopNode);
3276
- }
3277
- const animBlock = stops;
3278
- const kfs = animBlock.keyframes;
3279
- if (!Array.isArray(kfs) || !kfs.length) return [];
3280
- const loopFromSource = animBlock.loop;
3417
+ const read = readAnimatable(stops);
3418
+ if (read.kind === "absent") return [];
3419
+ if (read.kind === "static") return Array.isArray(read.value) ? read.value.map(staticStopNode) : [];
3420
+ const kfs = read.keyframes;
3421
+ if (!kfs.length) return [];
3422
+ const loopFromSource = read.loop;
3281
3423
  let stopCount = 0;
3282
3424
  for (const kf of kfs) {
3283
3425
  const v = (_a = kf.value) != null ? _a : kf.v;
@@ -3352,36 +3494,60 @@ function formatOffset(o) {
3352
3494
  return pct + "%";
3353
3495
  }
3354
3496
  function applyClipPathEffect(node, fx, ctx) {
3497
+ var _a, _b;
3355
3498
  if (!fx || !fx.d && !fx.animate) return node;
3356
3499
  const clipId = genId(ctx, "clip");
3357
- const pathChild = { type: "path", d: fx.d };
3358
- if (fx.animate) pathChild.animate = { d: fx.animate };
3500
+ const pathChild = { type: "path" };
3501
+ const read = readAnimatable(fx.d);
3502
+ if (read.kind !== "absent") {
3503
+ if (read.kind === "static") {
3504
+ pathChild.d = pathString(read.value);
3505
+ } else {
3506
+ writeAnimatableChannel(pathChild, "d", read);
3507
+ if (pathChild.d !== void 0) pathChild.d = pathString(pathChild.d);
3508
+ }
3509
+ }
3510
+ if (fx.animate && !((_a = pathChild.animate) == null ? void 0 : _a.d)) {
3511
+ const animate = (_b = pathChild.animate) != null ? _b : {};
3512
+ animate.d = fx.animate;
3513
+ pathChild.animate = animate;
3514
+ }
3359
3515
  ctx.defs.push({ type: "clipPath", id: clipId, children: [pathChild] });
3360
3516
  node.clipPath = "url(#" + clipId + ")";
3361
3517
  return node;
3362
3518
  }
3363
- function applyMaskedByEffect(node, fx, transformation, ctx) {
3519
+ function pathString(v) {
3520
+ if (typeof v === "string") return v;
3521
+ if (v && typeof v === "object" && typeof v.path === "string") return v.path;
3522
+ return void 0;
3523
+ }
3524
+ function applyMaskedByEffect(node, fx, transformBy, ctx) {
3364
3525
  if (!fx) return node;
3365
- if (!fx.href) {
3366
- ctx.errors.push("maskedBy.href missing \u2014 cannot build mask");
3526
+ const sourceId = stripHash2(fx.sourceId);
3527
+ if (!sourceId) {
3528
+ ctx.errors.push("maskedBy.sourceId missing \u2014 cannot build mask");
3367
3529
  return node;
3368
3530
  }
3369
3531
  const maskId = genId(ctx, "mask");
3370
- let content = { type: "use", href: "#" + fx.href };
3371
- if (transformation) {
3372
- content = wrapInverseTransform(content, transformation, ctx);
3532
+ let content = { type: "use", href: "#" + sourceId };
3533
+ if (transformBy) {
3534
+ content = wrapInverseTransform(content, transformBy, ctx);
3373
3535
  } else if (hasAnimateTransform(node)) {
3374
3536
  content = wrapInverseAnimatedBodyTransform(content, node, ctx);
3375
3537
  } else {
3376
3538
  const bodyStatic = readTransformationFromBody(node);
3377
3539
  if (bodyStatic) content = wrapInverseTransform(content, bodyStatic, ctx);
3378
3540
  }
3379
- const includeTargetOwn = transformation === void 0 && !nodeHasBodyTransform(node);
3380
- content = wrapAncestorChainCompensation(content, node, fx.href, ctx, includeTargetOwn);
3541
+ const includeTargetOwn = transformBy === void 0 && !nodeHasBodyTransform(node);
3542
+ content = wrapAncestorChainCompensation(content, node, sourceId, ctx, includeTargetOwn);
3381
3543
  const mask = { type: "mask", id: maskId, children: [content] };
3382
3544
  if (fx.maskType) mask.maskType = fx.maskType;
3383
3545
  if (fx.maskUnits) mask.maskUnits = fx.maskUnits;
3384
3546
  if (fx.maskContentUnits) mask.maskContentUnits = fx.maskContentUnits;
3547
+ if (fx.x !== void 0) mask.x = String(fx.x);
3548
+ if (fx.y !== void 0) mask.y = String(fx.y);
3549
+ if (fx.width !== void 0) mask.width = String(fx.width);
3550
+ if (fx.height !== void 0) mask.height = String(fx.height);
3385
3551
  ctx.defs.push(mask);
3386
3552
  node.mask = "url(#" + maskId + ")";
3387
3553
  return node;
@@ -3488,6 +3654,19 @@ function readTransformationFromBody(node) {
3488
3654
  if (parts.origin) out.origin = parts.origin;
3489
3655
  return Object.keys(out).length ? out : void 0;
3490
3656
  }
3657
+ if (node.transform && typeof node.transform === "object" && !node.transform.keyframes && !node.transform.kfs) {
3658
+ const wrapped = node.transform.value;
3659
+ const value = wrapped && typeof wrapped === "object" ? wrapped : node.transform;
3660
+ if (value && typeof value === "object") {
3661
+ const out = {};
3662
+ if (Array.isArray(value.translate)) out.translate = value.translate;
3663
+ if (typeof value.rotate === "number") out.rotate = value.rotate;
3664
+ if (typeof value.skew === "number") out.skew = value.skew;
3665
+ if (Array.isArray(value.scale)) out.scale = { value: value.scale };
3666
+ if (Array.isArray(value.origin)) out.origin = value.origin;
3667
+ return Object.keys(out).length ? out : void 0;
3668
+ }
3669
+ }
3491
3670
  return void 0;
3492
3671
  }
3493
3672
  function parseTransformStringToParts(s) {
@@ -3621,10 +3800,10 @@ function collectMaskAncestorChains(root, ctx) {
3621
3800
  const interestingNodes = /* @__PURE__ */ new Set();
3622
3801
  const collectInterestingNodes = (n) => {
3623
3802
  var _a, _b;
3624
- const href = (_b = (_a = n.effects) == null ? void 0 : _a.maskedBy) == null ? void 0 : _b.href;
3625
- if (typeof href === "string") {
3803
+ const maskSourceId = stripHash2((_b = (_a = n.effects) == null ? void 0 : _a.maskedBy) == null ? void 0 : _b.sourceId);
3804
+ if (typeof maskSourceId === "string") {
3626
3805
  interestingNodes.add(n);
3627
- const sourceNode = ctx.idMap.get(href);
3806
+ const sourceNode = ctx.idMap.get(maskSourceId);
3628
3807
  if (sourceNode) interestingNodes.add(sourceNode);
3629
3808
  }
3630
3809
  if (Array.isArray(n.children)) for (const ch of n.children) collectInterestingNodes(ch);
@@ -3650,8 +3829,9 @@ function extractTranslateOnly(node, ctx) {
3650
3829
  if (typeof tr === "string") {
3651
3830
  const parts = parseTranslateOnlyFromString(tr, ctx);
3652
3831
  if (parts) out.translate = parts;
3653
- } else if (tr && typeof tr === "object") {
3654
- const value = tr.value;
3832
+ } else if (tr && typeof tr === "object" && !tr.keyframes && !tr.kfs) {
3833
+ const wrapped = tr.value;
3834
+ const value = wrapped && typeof wrapped === "object" ? wrapped : tr;
3655
3835
  if (value && typeof value === "object" && Array.isArray(value.translate)) {
3656
3836
  out.translate = [value.translate[0] || 0, value.translate[1] || 0];
3657
3837
  }
@@ -3699,17 +3879,17 @@ function parseTranslateOnlyFromString(s, ctx) {
3699
3879
  var CONTENT_SUBREF = "content";
3700
3880
  function applyRefHref(node, clone2, ctx) {
3701
3881
  if (!clone2) return;
3702
- const baseId = clone2.baseId;
3703
- if (!baseId) {
3704
- if (clone2.type === CONTENT_SUBREF) ctx.errors.push("clone: content ref missing baseId");
3882
+ const sourceId = stripHash2(clone2.sourceId);
3883
+ if (!sourceId) {
3884
+ if (clone2.type === CONTENT_SUBREF) ctx.errors.push("clone: content ref missing sourceId");
3705
3885
  return;
3706
3886
  }
3707
- const targetId = clone2.type === CONTENT_SUBREF ? ctx.contentRefInnerIds.get(baseId) || baseId : baseId;
3887
+ const targetId = clone2.type === CONTENT_SUBREF ? ctx.contentRefInnerIds.get(sourceId) || sourceId : sourceId;
3708
3888
  node.href = "#" + targetId;
3709
3889
  }
3710
- function applyRefAndTransformationEffect(node, clone2, transformation, ctx) {
3890
+ function applyRefAndTransformationEffect(node, clone2, transformBy, ctx) {
3711
3891
  applyRefHref(node, clone2, ctx);
3712
- return applyTransformationEffect(node, transformation, ctx);
3892
+ return applyTransformByEffect(node, transformBy, ctx);
3713
3893
  }
3714
3894
  function applyRepeaterEffect(node, fx, ctx) {
3715
3895
  var _a, _b;
@@ -3732,7 +3912,7 @@ function applyRepeaterEffect(node, fx, ctx) {
3732
3912
  for (let i = 1; i < copies; i++) {
3733
3913
  const baseClone = clone(base);
3734
3914
  const synthFx = synthesisePerCopyFx(fx, i);
3735
- const wrapped = synthFx ? applyTransformationEffect(baseClone, synthFx, ctx) : baseClone;
3915
+ const wrapped = synthFx ? applyTransformByEffect(baseClone, synthFx, ctx) : baseClone;
3736
3916
  children.push(wrapped);
3737
3917
  }
3738
3918
  const wrapper = { type: "g", children };
@@ -3744,10 +3924,13 @@ function applyRepeaterEffect(node, fx, ctx) {
3744
3924
  function synthesisePerCopyFx(fx, i) {
3745
3925
  const out = {};
3746
3926
  if (fx.translate !== void 0) {
3747
- out.translate = mapAnimatableVec2(fx.translate, (v) => [v[0] * i, v[1] * i]);
3927
+ out.translate = mapAnimatable(fx.translate, (v) => [v[0] * i, v[1] * i]);
3748
3928
  }
3749
3929
  if (fx.rotate !== void 0) {
3750
- out.rotate = mapAnimatableNumber(fx.rotate, (v) => v * i);
3930
+ out.rotate = mapAnimatable(fx.rotate, (v) => v * i);
3931
+ }
3932
+ if (fx.skew !== void 0) {
3933
+ out.skew = mapAnimatable(fx.skew, (v) => v * i);
3751
3934
  }
3752
3935
  if (fx.scale !== void 0) {
3753
3936
  out.scale = synthesiseScale(fx.scale, i);
@@ -3757,63 +3940,50 @@ function synthesisePerCopyFx(fx, i) {
3757
3940
  }
3758
3941
  return Object.keys(out).length ? out : void 0;
3759
3942
  }
3760
- function mapAnimatableVec2(raw, fn) {
3761
- if (Array.isArray(raw)) return fn(raw);
3762
- if (raw && typeof raw === "object") {
3763
- const obj = raw;
3764
- if (Array.isArray(obj.keyframes)) {
3765
- return __spreadProps2(__spreadValues2({}, obj), {
3766
- keyframes: obj.keyframes.map((kf) => kf && kf.value !== void 0 ? __spreadProps2(__spreadValues2({}, kf), { value: fn(kf.value) }) : kf)
3767
- });
3768
- }
3769
- if (obj.value !== void 0) {
3770
- return __spreadProps2(__spreadValues2({}, obj), { value: fn(obj.value) });
3771
- }
3943
+ function mapAnimatable(raw, fn, wrapStatic = false) {
3944
+ const read = readAnimatable(raw);
3945
+ if (read.kind === "absent") return raw;
3946
+ if (read.kind === "static") {
3947
+ const mapped = fn(read.value);
3948
+ const wasRawStatic = typeof raw === "number" || Array.isArray(raw);
3949
+ return wasRawStatic && !wrapStatic ? mapped : { value: mapped };
3772
3950
  }
3773
- return raw;
3774
- }
3775
- function mapAnimatableNumber(raw, fn) {
3776
- if (typeof raw === "number") return fn(raw);
3777
- if (raw && typeof raw === "object") {
3778
- const obj = raw;
3779
- if (Array.isArray(obj.keyframes)) {
3780
- return __spreadProps2(__spreadValues2({}, obj), {
3781
- keyframes: obj.keyframes.map((kf) => kf && kf.value !== void 0 ? __spreadProps2(__spreadValues2({}, kf), { value: fn(kf.value) }) : kf)
3782
- });
3783
- }
3784
- if (obj.value !== void 0) {
3785
- return __spreadProps2(__spreadValues2({}, obj), { value: fn(obj.value) });
3786
- }
3787
- }
3788
- return raw;
3951
+ const out = {
3952
+ keyframes: read.keyframes.map((kf) => kf && kf.value !== void 0 ? __spreadProps2(__spreadValues2({}, kf), { value: fn(kf.value) }) : kf)
3953
+ };
3954
+ if (read.loop !== void 0) out.loop = read.loop;
3955
+ if (read.autoOrient !== void 0) out.autoOrient = read.autoOrient;
3956
+ if (read.base !== void 0) out.value = fn(read.base);
3957
+ return out;
3789
3958
  }
3790
3959
  function synthesiseScale(raw, i) {
3791
- const scalePowerFromPercent = (v) => [Math.pow(v[0] / 100, i), Math.pow(v[1] / 100, i)];
3792
- const scalePowerFromUnits = (v) => [Math.pow(v[0], i), Math.pow(v[1], i)];
3793
- if (Array.isArray(raw)) {
3794
- return { value: scalePowerFromPercent(raw) };
3795
- }
3796
- if (raw && typeof raw === "object") {
3797
- const obj = raw;
3798
- if (Array.isArray(obj.keyframes)) {
3799
- return __spreadProps2(__spreadValues2({}, obj), {
3800
- keyframes: obj.keyframes.map((kf) => kf && kf.value !== void 0 ? __spreadProps2(__spreadValues2({}, kf), { value: scalePowerFromUnits(kf.value) }) : kf)
3801
- });
3802
- }
3803
- if (obj.value !== void 0) {
3804
- return __spreadProps2(__spreadValues2({}, obj), { value: scalePowerFromPercent(obj.value) });
3805
- }
3806
- }
3807
- return raw;
3960
+ const scalePower = (v) => [Math.pow(v[0], i), Math.pow(v[1], i)];
3961
+ return mapAnimatable(raw, scalePower, true);
3808
3962
  }
3809
3963
  var RETIME_MATERIALISATION_MODE_INLINE_G = false;
3810
3964
  function asRetime(r) {
3811
3965
  var _a, _b;
3812
- if (r.timeCrop) {
3813
- console.warn("retime: `timeCrop` is not supported yet and will be ignored");
3814
- }
3815
3966
  return { start: (_a = r.start) != null ? _a : 0, stretch: (_b = r.stretch) != null ? _b : 1 };
3816
3967
  }
3968
+ var CROP_EDGE_MS = 1;
3969
+ function applyTimeCrop(useNode, crop, ctx) {
3970
+ const [start, end] = crop;
3971
+ if (!Number.isFinite(start) || !Number.isFinite(end)) {
3972
+ ctx.warnings.push("retime: timeCrop is not a pair of finite numbers \u2014 ignored");
3973
+ return;
3974
+ }
3975
+ const keyframes = end <= start ? [{ time: 0, value: 0 }] : [
3976
+ ...start > 0 ? [{ time: Math.max(0, start - CROP_EDGE_MS), value: 0 }] : [],
3977
+ { time: Math.max(0, start), value: 1 },
3978
+ { time: end, value: 1 },
3979
+ { time: end + CROP_EDGE_MS, value: 0 }
3980
+ ];
3981
+ const inner = __spreadValues2({}, useNode);
3982
+ for (const k of Object.keys(useNode)) delete useNode[k];
3983
+ useNode.type = "g";
3984
+ useNode.children = [inner];
3985
+ useNode.animate = { opacity: { keyframes } };
3986
+ }
3817
3987
  function concatRetime(child, parent) {
3818
3988
  return {
3819
3989
  start: parent.start + parent.stretch * child.start,
@@ -3873,8 +4043,10 @@ function applyAllRetimeEffects(root, ctx) {
3873
4043
  for (const useNode of sites) {
3874
4044
  const retime = readCloneRetime(useNode);
3875
4045
  if (!retime) continue;
4046
+ const crop = retime.timeCrop;
3876
4047
  clearCloneRetime(useNode);
3877
4048
  materialiseRetime(useNode, asRetime(retime), ctx);
4049
+ if (crop) applyTimeCrop(useNode, crop, ctx);
3878
4050
  }
3879
4051
  }
3880
4052
  function materialiseRetime(useNode, retime, ctx) {
@@ -4117,14 +4289,11 @@ function createPathSampler(d) {
4117
4289
  }
4118
4290
  var EXTEND_MARGIN_FRAC = 0.15;
4119
4291
  function numRange(v) {
4120
- if (typeof v === "number") return { min: v, max: v };
4121
- if (v && typeof v === "object") {
4122
- const o = v;
4123
- if (typeof o.value === "number") return { min: o.value, max: o.value };
4124
- if (Array.isArray(o.keyframes) && o.keyframes.length) {
4125
- const vals = o.keyframes.map((k) => Number(k.value) || 0);
4126
- return { min: Math.min(...vals), max: Math.max(...vals) };
4127
- }
4292
+ const read = readAnimatable(v);
4293
+ if (read.kind === "static" && typeof read.value === "number") return { min: read.value, max: read.value };
4294
+ if (read.kind === "animated" && read.keyframes.length) {
4295
+ const vals = read.keyframes.map((k) => Number(k.value) || 0);
4296
+ return { min: Math.min(...vals), max: Math.max(...vals) };
4128
4297
  }
4129
4298
  return { min: 0, max: 0 };
4130
4299
  }
@@ -4144,11 +4313,16 @@ function estimateTextAdvance(node) {
4144
4313
  var r3 = (n) => Math.round(n * 1e3) / 1e3;
4145
4314
  function shiftAnimatable(v, by) {
4146
4315
  if (!by || v === void 0 || v === null) return v;
4147
- if (typeof v === "number") return v + by;
4148
- const o = v;
4149
- if (typeof o.value === "number") return __spreadProps2(__spreadValues2({}, o), { value: o.value + by });
4150
- if (Array.isArray(o.keyframes)) return __spreadProps2(__spreadValues2({}, o), { keyframes: o.keyframes.map((k) => __spreadProps2(__spreadValues2({}, k), { value: (Number(k.value) || 0) + by })) });
4151
- return v;
4316
+ const read = readAnimatable(v);
4317
+ if (read.kind === "absent") return v;
4318
+ if (read.kind === "static") return typeof v === "number" ? read.value + by : { value: read.value + by };
4319
+ const out = {
4320
+ keyframes: read.keyframes.map((k) => __spreadProps2(__spreadValues2({}, k), { value: (Number(k.value) || 0) + by }))
4321
+ };
4322
+ if (read.loop !== void 0) out.loop = read.loop;
4323
+ if (read.autoOrient !== void 0) out.autoOrient = read.autoOrient;
4324
+ if (read.base !== void 0) out.value = read.base + by;
4325
+ return out;
4152
4326
  }
4153
4327
  function extendedPathForBrowser(pathD, opts) {
4154
4328
  var _a;
@@ -4204,26 +4378,7 @@ function applyTextPathEffect(node, fx, ctx) {
4204
4378
  }
4205
4379
  function applyAnimatableNumber(node, attrName, raw) {
4206
4380
  if (raw === void 0 || raw === null) return;
4207
- if (typeof raw === "number") {
4208
- node[attrName] = String(raw);
4209
- return;
4210
- }
4211
- if (typeof raw === "object" && raw !== null) {
4212
- const obj = raw;
4213
- if (Array.isArray(obj.keyframes)) {
4214
- const prevAnimate = node.animate && typeof node.animate === "object" && !Array.isArray(node.animate) ? node.animate : void 0;
4215
- const animate = __spreadValues2({}, prevAnimate || {});
4216
- const block = { keyframes: obj.keyframes };
4217
- if (obj.loop !== void 0) block.loop = obj.loop;
4218
- animate[attrName] = block;
4219
- node.animate = animate;
4220
- return;
4221
- }
4222
- if (typeof obj.value === "number") {
4223
- node[attrName] = String(obj.value);
4224
- return;
4225
- }
4226
- }
4381
+ writeAnimatableChannel(node, attrName, readAnimatable(raw), { asString: true });
4227
4382
  }
4228
4383
  var jsonElementFactory = (type, props, children) => {
4229
4384
  const node = { type };
@@ -4411,13 +4566,13 @@ function materialiseGlyphTextHorizontal(node, opts) {
4411
4566
  if (y !== void 0) pen.y = y;
4412
4567
  pen.x += (_a2 = parseLen(el.dx)) != null ? _a2 : 0;
4413
4568
  pen.y += (_b2 = parseLen(el.dy)) != null ? _b2 : 0;
4414
- const content = (_c2 = str(el[TEXT_ATTR])) != null ? _c2 : str(el[TEXT_CONTENT_ATTR]);
4569
+ const content = (_c2 = str(el[TEXT_CONTENT_ATTR])) != null ? _c2 : str(el[TEXT_ATTR]);
4415
4570
  if (content && !((_d2 = el.children) == null ? void 0 : _d2.length)) renderChars(content, s);
4416
4571
  if (el.children) for (const ch of el.children) walk(ch, s);
4417
4572
  };
4418
4573
  const rootStyle = rootStyleOf(node);
4419
4574
  if (node.children) for (const ch of node.children) walk(ch, rootStyle);
4420
- const rootContent = (_c = str(node[TEXT_ATTR])) != null ? _c : str(node[TEXT_CONTENT_ATTR]);
4575
+ const rootContent = (_c = str(node[TEXT_CONTENT_ATTR])) != null ? _c : str(node[TEXT_ATTR]);
4421
4576
  if (rootContent && !((_d = node.children) == null ? void 0 : _d.length)) renderChars(rootContent, rootStyle);
4422
4577
  const anchor = str(node.textAnchor);
4423
4578
  if (anchor === "middle" || anchor === "end") {
@@ -4466,7 +4621,7 @@ function layoutGlyphTextChars(node, opts) {
4466
4621
  if (y !== void 0) pen.y = y;
4467
4622
  pen.x += (_a2 = parseLen(el.dx)) != null ? _a2 : 0;
4468
4623
  pen.y += (_b2 = parseLen(el.dy)) != null ? _b2 : 0;
4469
- const content = (_c2 = str(el[TEXT_ATTR])) != null ? _c2 : str(el[TEXT_CONTENT_ATTR]);
4624
+ const content = (_c2 = str(el[TEXT_CONTENT_ATTR])) != null ? _c2 : str(el[TEXT_ATTR]);
4470
4625
  if (content && !((_d2 = el.children) == null ? void 0 : _d2.length)) renderChars(content, s);
4471
4626
  if (el.children) for (const ch of el.children) walk(ch, s);
4472
4627
  };
@@ -4481,7 +4636,7 @@ function layoutGlyphTextChars(node, opts) {
4481
4636
  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 });
4482
4637
  }
4483
4638
  }
4484
- const rootContent = (_e = str(node[TEXT_ATTR])) != null ? _e : str(node[TEXT_CONTENT_ATTR]);
4639
+ const rootContent = (_e = str(node[TEXT_CONTENT_ATTR])) != null ? _e : str(node[TEXT_ATTR]);
4485
4640
  if (rootContent && !((_f = node.children) == null ? void 0 : _f.length)) renderChars(rootContent, rootStyle);
4486
4641
  const anchor = str(node.textAnchor);
4487
4642
  if (anchor === "middle" || anchor === "end") {
@@ -4509,7 +4664,7 @@ function layoutGlyphTextCharsAlongPath(node, pathD, opts) {
4509
4664
  const walk = (el, parentStyle) => {
4510
4665
  var _a2, _b2, _c;
4511
4666
  const s = resolveStyle2(el, parentStyle);
4512
- const content = (_a2 = str(el[TEXT_ATTR])) != null ? _a2 : str(el[TEXT_CONTENT_ATTR]);
4667
+ const content = (_a2 = str(el[TEXT_CONTENT_ATTR])) != null ? _a2 : str(el[TEXT_ATTR]);
4513
4668
  if (content && !((_b2 = el.children) == null ? void 0 : _b2.length)) {
4514
4669
  const gf = glyphFontFor(s, glyphs, soleFont, warnings);
4515
4670
  const upm = (gf == null ? void 0 : gf.unitsPerEm) || 1e3;
@@ -4563,7 +4718,7 @@ function collectAlongPathCells(node, glyphs, soleFont, warnings) {
4563
4718
  const walk = (el, parentStyle) => {
4564
4719
  var _a, _b, _c;
4565
4720
  const s = resolveStyle2(el, parentStyle);
4566
- const content = (_a = str(el[TEXT_ATTR])) != null ? _a : str(el[TEXT_CONTENT_ATTR]);
4721
+ const content = (_a = str(el[TEXT_CONTENT_ATTR])) != null ? _a : str(el[TEXT_ATTR]);
4567
4722
  if (content && !((_b = el.children) == null ? void 0 : _b.length)) {
4568
4723
  const gf = glyphFontFor(s, glyphs, soleFont, warnings);
4569
4724
  if (gf) {
@@ -4791,9 +4946,9 @@ function applyTextGlyphsAlongPath(node, ctx, pathD, startOffset, textLength, pat
4791
4946
  }
4792
4947
  return materialiseGlyphTextAlongPath(node, pathD, startOffset, { glyphs: ctx.glyphs, warnings: ctx.warnings }, textLength, pathOverflow);
4793
4948
  }
4794
- function applyTrimPathEffect(node, trimPath, isCombinedShape, ctx) {
4949
+ function applyTrimPathEffect(node, trimPath, ctx) {
4795
4950
  if (!trimPath) return node;
4796
- const trimAllAsOne = !!trimPath.trimAllAsOne;
4951
+ const combined = trimPath.subPaths === PxTrimSubPaths.combined;
4797
4952
  const leafEntries = [];
4798
4953
  const measure = (n) => {
4799
4954
  if (Array.isArray(n.children) && n.children.length > 0) {
@@ -4814,16 +4969,16 @@ function applyTrimPathEffect(node, trimPath, isCombinedShape, ctx) {
4814
4969
  measure(node);
4815
4970
  if (!leafEntries.length) return node;
4816
4971
  let acc = 0;
4817
- const iterOrder = trimAllAsOne ? [...leafEntries].reverse() : leafEntries;
4972
+ const iterOrder = combined ? [...leafEntries].reverse() : leafEntries;
4818
4973
  for (const entry of iterOrder) {
4819
4974
  for (const sp of entry.subpaths) {
4820
- if (!trimAllAsOne) acc = 0;
4975
+ if (!combined) acc = 0;
4821
4976
  sp.startOffsetPx = acc;
4822
4977
  acc += sp.lengthPx;
4823
4978
  }
4824
4979
  }
4825
4980
  const chainLengthPx = acc;
4826
- if (trimAllAsOne && chainLengthPx < 1e-3) return node;
4981
+ if (combined && chainLengthPx < 1e-3) return node;
4827
4982
  const offsetReadRaw = readAnimatable(trimPath.offset);
4828
4983
  const offsetRead = offsetReadRaw.kind === "absent" ? { kind: "static", value: 0 } : offsetReadRaw;
4829
4984
  const rangeReadRaw = readRangeWithCrossings(trimPath.range);
@@ -4835,18 +4990,18 @@ function applyTrimPathEffect(node, trimPath, isCombinedShape, ctx) {
4835
4990
  if (leafEntries.length === 1 && leafEntries[0].leaf === node && leafEntries[0].subpaths.length === 1) {
4836
4991
  const entry = leafEntries[0];
4837
4992
  const sp = entry.subpaths[0];
4838
- const pathLengthPx = trimAllAsOne ? chainLengthPx : sp.lengthPx;
4993
+ const pathLengthPx = combined ? chainLengthPx : sp.lengthPx;
4839
4994
  if (pathLengthPx < 1e-3) return node;
4840
- const startOffsetPct = trimAllAsOne ? sp.startOffsetPx / pathLengthPx : 0;
4995
+ const startOffsetPct = combined ? sp.startOffsetPx / pathLengthPx : 0;
4841
4996
  return collapseLeafWithTrim(entry.leaf, pathLengthPx, startOffsetPct, minMaxOffset, offsetRead, rangeRead);
4842
4997
  }
4843
4998
  const replacements = /* @__PURE__ */ new Map();
4844
4999
  for (const entry of leafEntries) {
4845
5000
  const newChildren = [];
4846
5001
  for (const sp of entry.subpaths) {
4847
- const pathLengthPx = trimAllAsOne ? chainLengthPx : sp.lengthPx;
5002
+ const pathLengthPx = combined ? chainLengthPx : sp.lengthPx;
4848
5003
  if (pathLengthPx < 1e-3) continue;
4849
- const startOffsetPct = trimAllAsOne ? sp.startOffsetPx / pathLengthPx : 0;
5004
+ const startOffsetPct = combined ? sp.startOffsetPx / pathLengthPx : 0;
4850
5005
  newChildren.push(...buildSubpathNodes(entry.leaf, sp.subpath, pathLengthPx, startOffsetPct, minMaxOffset, offsetRead, rangeRead, ctx));
4851
5006
  }
4852
5007
  replacements.set(entry.leaf, wrapLeafAsGroup(entry.leaf, newChildren));
@@ -4953,22 +5108,8 @@ function computeAnimAttr(read, map) {
4953
5108
  };
4954
5109
  }
4955
5110
  function applyAttr(node, attrName, attr) {
4956
- var _a, _b;
4957
5111
  if (!attr) return;
4958
- if (attr.kind === "static") {
4959
- node[attrName] = attr.value;
4960
- return;
4961
- }
4962
- const prevAnimate = node.animate && typeof node.animate === "object" && !Array.isArray(node.animate) ? node.animate : void 0;
4963
- const animate = __spreadValues2({}, prevAnimate || {});
4964
- const block = { keyframes: attr.keyframes };
4965
- if (attr.loop !== void 0) block.loop = attr.loop;
4966
- animate[attrName] = block;
4967
- node.animate = animate;
4968
- const firstKf = attr.keyframes[0];
4969
- if (firstKf && ((_a = firstKf.value) != null ? _a : firstKf.v) !== void 0) {
4970
- node[attrName] = (_b = firstKf.value) != null ? _b : firstKf.v;
4971
- }
5112
+ writeAnimatableChannel(node, attrName, attr);
4972
5113
  }
4973
5114
  var OPACITY_STEP_MS = 10;
4974
5115
  function computeOpacityFromRange(rangeRead) {
@@ -5150,9 +5291,9 @@ function applyPlayerEffects(root) {
5150
5291
  nextId: 0,
5151
5292
  contentRefInnerIds: /* @__PURE__ */ new Map(),
5152
5293
  maskAncestorChains: /* @__PURE__ */ new Map(),
5153
- // Resolved engine: `frames` ONLY when explicitly set; auto/webapi/unset →
5154
- // webapi (we're not 100% sure it's frames, and CSS/WAAPI need the inline form).
5155
- engine: ((_a = getAnimatorConfig(root)) == null ? void 0 : _a.mode) === PxAnimatorMode.frames ? PxAnimatorEngine.frames : PxAnimatorEngine.webapi,
5294
+ // Resolved engine: `frames` ONLY when explicitly set; auto/waapi/unset →
5295
+ // waapi (we're not 100% sure it's frames, and CSS/WAAPI need the inline form).
5296
+ engine: ((_a = getAnimatorConfig(root)) == null ? void 0 : _a.mode) === PxAnimatorMode.frames ? PxAnimatorEngine.frames : PxAnimatorEngine.waapi,
5156
5297
  glyphs: (_b = getDefs(root)) == null ? void 0 : _b.glyphs
5157
5298
  };
5158
5299
  const working = clone(root);
@@ -5170,8 +5311,7 @@ function applyPlayerEffects_exceptRetime(node, ctx) {
5170
5311
  const originalId = typeof node.id === "string" ? node.id : void 0;
5171
5312
  const innerIdForContentRef = originalId ? ctx.contentRefInnerIds.get(originalId) : void 0;
5172
5313
  if (!fx && !innerIdForContentRef) return node;
5173
- const { transformation, repeater, maskedBy, clipPath, trimPath, clone: cloneFx, fillGradient, strokeGradient, textPath, text } = fx != null ? fx : {};
5174
- const isCombinedShape = fx == null ? void 0 : fx.isCombinedShape;
5314
+ const { transformBy, repeater, maskedBy, clipPath, trimPath, clone: cloneFx, fillGradient, strokeGradient, textPath, text } = fx != null ? fx : {};
5175
5315
  if (fx) delete node.effects;
5176
5316
  let n = node;
5177
5317
  let consumedByGlyphs = false;
@@ -5191,15 +5331,15 @@ function applyPlayerEffects_exceptRetime(node, ctx) {
5191
5331
  if (!consumedByGlyphs) n = applyTextPathEffect(n, textPath, ctx);
5192
5332
  n = applyFillGradientEffect(n, fillGradient, ctx);
5193
5333
  n = applyStrokeGradientEffect(n, strokeGradient, ctx);
5194
- n = applyTrimPathEffect(n, trimPath, isCombinedShape, ctx);
5334
+ n = applyTrimPathEffect(n, trimPath, ctx);
5195
5335
  n = applyRepeaterEffect(n, repeater, ctx);
5196
- n = applyMaskedByEffect(n, maskedBy, transformation, ctx);
5336
+ n = applyMaskedByEffect(n, maskedBy, transformBy, ctx);
5197
5337
  n = applyClipPathEffect(n, clipPath, ctx);
5198
5338
  if (innerIdForContentRef) {
5199
5339
  applyRefHref(n, cloneFx, ctx);
5200
- n = splitForContentRef(n, transformation, originalId, innerIdForContentRef, ctx);
5340
+ n = splitForContentRef(n, transformBy, originalId, innerIdForContentRef, ctx);
5201
5341
  } else {
5202
- n = applyRefAndTransformationEffect(n, cloneFx, transformation, ctx);
5342
+ n = applyRefAndTransformationEffect(n, cloneFx, transformBy, ctx);
5203
5343
  }
5204
5344
  if (cloneFx == null ? void 0 : cloneFx.retime) node.effects = { clone: { retime: cloneFx.retime } };
5205
5345
  if (originalId) ctx.idMap.set(originalId, n);
@@ -5214,7 +5354,7 @@ function materialiseAllInTree(doc, engine, opts) {
5214
5354
  let root = applyPlayerEffects(doc).root;
5215
5355
  const duration = (_b = (_a = getAnimatorConfig(root)) == null ? void 0 : _a.duration) != null ? _b : DEFAULT_DURATION_MS;
5216
5356
  root = materialiseInternalLoopsInTree(root, duration);
5217
- if (engine === PxAnimatorEngine.webapi) {
5357
+ if (engine === PxAnimatorEngine.waapi) {
5218
5358
  root = materialiseMotionPathsInTree(root, opts == null ? void 0 : opts.motionPath);
5219
5359
  root = materialiseAnimatedUseInstances(root);
5220
5360
  root = pruneUnreferencedDefs(root);
@@ -5599,6 +5739,7 @@ function evalTransformValue(v, t) {
5599
5739
  if (typeof v === "string") return parseTransformString(v);
5600
5740
  if (v.keyframes) return partsToMatrix(interpParts(v.keyframes, t));
5601
5741
  if (v.value) return partsToMatrix(v.value);
5742
+ if (typeof v === "object" && !Array.isArray(v)) return partsToMatrix(v);
5602
5743
  return IDENTITY;
5603
5744
  }
5604
5745
  function nodeMatrix(node, t) {
@@ -5733,64 +5874,6 @@ function subtractMultiset(a, b) {
5733
5874
  return extra;
5734
5875
  }
5735
5876
 
5736
- // src/PxAnimatorDOM.ts
5737
- var SVG_NS = "http://www.w3.org/2000/svg";
5738
- function createElement(tagName, normalisedProps, style, children, textContent) {
5739
- if (DISALLOWED_SVG_TAGS_LOWER.has(tagName.toLowerCase())) {
5740
- console.warn("SVG tag blocked (dangerous): ", tagName);
5741
- return null;
5742
- }
5743
- const element = document.createElementNS(SVG_NS, tagName);
5744
- for (const propName in normalisedProps) {
5745
- const sanitised = sanitiseAttributeValue(propName, normalisedProps[propName]);
5746
- if (sanitised === void 0) continue;
5747
- if (CSS_ONLY_STYLE_PROPS.has(propName)) {
5748
- element.style[propName] = String(sanitised);
5749
- continue;
5750
- }
5751
- element.setAttribute(camelCaseToKebabWordIfNeeded(propName), sanitised);
5752
- }
5753
- if (style) {
5754
- for (const styleProp in style) {
5755
- element.style[styleProp] = String(style[styleProp]);
5756
- }
5757
- }
5758
- if (children) {
5759
- for (const child of children) {
5760
- element.appendChild(child);
5761
- }
5762
- }
5763
- if (textContent) element.textContent = textContent;
5764
- return element;
5765
- }
5766
- function renderNode(node, defs) {
5767
- if (!node) return null;
5768
- const _a = node, { type, children, style } = _a, props = __objRest(_a, ["type", "children", "style"]);
5769
- const feFuncType = props.funcType;
5770
- if (feFuncType !== void 0) delete props.funcType;
5771
- const nodeDefs = getDefs(node) || defs;
5772
- const resolvedStyle = resolveStyle(style, nodeDefs);
5773
- let childElements;
5774
- if (children) {
5775
- for (const ch of children) {
5776
- const child = renderNode(ch, nodeDefs);
5777
- if (child) {
5778
- if (!childElements) childElements = [];
5779
- childElements.push(child);
5780
- }
5781
- }
5782
- }
5783
- const element = createElement(
5784
- type || "g",
5785
- getNormalizedProps(props),
5786
- resolvedStyle,
5787
- childElements,
5788
- props[TEXT_ATTR] || props[TEXT_CONTENT_ATTR]
5789
- );
5790
- if (element && feFuncType !== void 0) element.setAttribute("type", feFuncType);
5791
- return element;
5792
- }
5793
-
5794
5877
  // src/PxAnimatorTriggers.ts
5795
5878
  function setupAnimationTriggers(api, config) {
5796
5879
  const { startOn, outAction = "continue", scrollIntoViewThreshold = 0 } = config;
@@ -5980,7 +6063,7 @@ function createCssKf(kf, t, propName, unsupportedSet) {
5980
6063
  } else {
5981
6064
  cssValue = "" + value;
5982
6065
  }
5983
- if (!CSS.supports(cssKey, cssValue)) unsupportedSet.add(cssKey);
6066
+ if (!CSS.supports(camelCaseToKebabWordIfNeeded(cssKey), cssValue)) unsupportedSet.add(cssKey);
5984
6067
  cssKey = kebabToCamelCaseWord(cssKey);
5985
6068
  cssKf[cssKey] = cssValue;
5986
6069
  return cssKf;
@@ -6057,7 +6140,7 @@ function createWebApiAnimator(doc, callbacks, rootElement, forceEvenIfHasUnsuppo
6057
6140
  console.warn("createFrameLoopAnimator: No root element provided");
6058
6141
  }
6059
6142
  }
6060
- const bindings = getNormalisedBindings(doc, PxAnimatorEngine.webapi);
6143
+ const bindings = getNormalisedBindings(doc, PxAnimatorEngine.waapi);
6061
6144
  const animations = [];
6062
6145
  const _iterations = config.iterations;
6063
6146
  let iterations;
@@ -6203,9 +6286,8 @@ function createWebApiAnimator(doc, callbacks, rootElement, forceEvenIfHasUnsuppo
6203
6286
  return api;
6204
6287
  }
6205
6288
 
6206
- // src/PxAnimator.ts
6207
- function createAnimatorFromConfig(doc, adapter, callbacks, rootElement) {
6208
- const animatorConfig = getAnimatorConfig(doc) || {};
6289
+ // src/PxAnimatorBind.ts
6290
+ function finaliseAnimator(animatorConfig, callbacks, make) {
6209
6291
  let apiRef;
6210
6292
  let effectiveCallbacks = callbacks;
6211
6293
  if (animatorConfig.resetOnFinish) {
@@ -6217,29 +6299,99 @@ function createAnimatorFromConfig(doc, adapter, callbacks, rootElement) {
6217
6299
  }
6218
6300
  });
6219
6301
  }
6220
- let res;
6221
- if (animatorConfig.mode === PxAnimatorMode.frames) {
6222
- res = createFrameLoopAnimator(doc, adapter, effectiveCallbacks, rootElement);
6223
- } else {
6224
- res = createWebApiAnimator(
6225
- doc,
6226
- effectiveCallbacks,
6227
- rootElement,
6228
- animatorConfig.mode === PxAnimatorMode.webapi
6229
- // forcing webapi
6230
- ) || createFrameLoopAnimator(doc, adapter, effectiveCallbacks, rootElement);
6231
- }
6302
+ const res = make(effectiveCallbacks);
6232
6303
  apiRef = res;
6233
6304
  if (animatorConfig.debugInstName) {
6234
6305
  window[animatorConfig.debugInstName] = res;
6235
6306
  }
6236
6307
  return res;
6237
6308
  }
6309
+ function bindWithEngineChoice(doc, adapter, callbacks, rootElement) {
6310
+ const animatorConfig = getAnimatorConfig(doc) || {};
6311
+ return finaliseAnimator(animatorConfig, callbacks, (cb) => {
6312
+ if (animatorConfig.mode === PxAnimatorMode.frames) {
6313
+ return createFrameLoopAnimator(doc, adapter, cb, rootElement);
6314
+ }
6315
+ return createWebApiAnimator(
6316
+ doc,
6317
+ cb,
6318
+ rootElement,
6319
+ animatorConfig.mode === PxAnimatorMode.waapi
6320
+ // forcing waapi
6321
+ ) || createFrameLoopAnimator(doc, adapter, cb, rootElement);
6322
+ });
6323
+ }
6324
+
6325
+ // src/PxAnimatorDOM.ts
6326
+ var SVG_NS = "http://www.w3.org/2000/svg";
6327
+ function createElement(tagName, normalisedProps, style, children, textContent) {
6328
+ if (DISALLOWED_SVG_TAGS_LOWER.has(tagName.toLowerCase())) {
6329
+ console.warn("SVG tag blocked (dangerous): ", tagName);
6330
+ return null;
6331
+ }
6332
+ const element = document.createElementNS(SVG_NS, tagName);
6333
+ for (const propName in normalisedProps) {
6334
+ const sanitised = sanitiseAttributeValue(propName, normalisedProps[propName]);
6335
+ if (sanitised === void 0) continue;
6336
+ if (CSS_ONLY_STYLE_PROPS.has(propName)) {
6337
+ element.style[propName] = String(sanitised);
6338
+ continue;
6339
+ }
6340
+ element.setAttribute(camelCaseToKebabWordIfNeeded(propName), sanitised);
6341
+ }
6342
+ if (style) {
6343
+ for (const styleProp in style) {
6344
+ element.style[styleProp] = String(style[styleProp]);
6345
+ }
6346
+ }
6347
+ if (children) {
6348
+ for (const child of children) {
6349
+ element.appendChild(child);
6350
+ }
6351
+ }
6352
+ if (textContent) element.textContent = textContent;
6353
+ return element;
6354
+ }
6355
+ function renderNode(node, defs) {
6356
+ if (!node) return null;
6357
+ const _a = node, { type, children, style } = _a, props = __objRest(_a, ["type", "children", "style"]);
6358
+ const domType = props.domType;
6359
+ if (domType !== void 0) delete props.domType;
6360
+ const nodeDefs = getDefs(node) || defs;
6361
+ const resolvedStyle = resolveStyle(style, nodeDefs);
6362
+ let childElements;
6363
+ if (children) {
6364
+ for (const ch of children) {
6365
+ const child = renderNode(ch, nodeDefs);
6366
+ if (child) {
6367
+ if (!childElements) childElements = [];
6368
+ childElements.push(child);
6369
+ }
6370
+ }
6371
+ }
6372
+ const element = createElement(
6373
+ type || "g",
6374
+ getNormalizedProps(props),
6375
+ resolvedStyle,
6376
+ childElements,
6377
+ props[TEXT_CONTENT_ATTR] || props[TEXT_ATTR]
6378
+ );
6379
+ if (element && domType !== void 0) element.setAttribute("type", domType);
6380
+ return element;
6381
+ }
6382
+
6383
+ // src/PxAnimatorKeys.ts
6384
+ var PX_ANIMATOR_DATA_KEY = "data";
6385
+
6386
+ // src/PxAnimator.ts
6387
+ function createAnimatorFromConfig(doc, adapter, callbacks, rootElement) {
6388
+ return bindWithEngineChoice(doc, adapter, callbacks, rootElement);
6389
+ }
6238
6390
  function createAnimatorImpl(doc, adapter, callbacks, containerElement) {
6239
6391
  const effectsWarnings = validateNodeEffects(doc);
6240
6392
  for (const w of effectsWarnings) console.warn("[PxAnimator] effects shape warning:", w);
6241
6393
  const animatorConfig = getAnimatorConfig(doc) || {};
6242
- const engine = animatorConfig.mode === PxAnimatorMode.frames ? PxAnimatorEngine.frames : PxAnimatorEngine.webapi;
6394
+ const engine = animatorConfig.mode === PxAnimatorMode.frames ? PxAnimatorEngine.frames : PxAnimatorEngine.waapi;
6243
6395
  doc = materialiseAllInTree(doc, engine);
6244
6396
  let rootElement = null;
6245
6397
  if (containerElement) {
@@ -6254,7 +6406,6 @@ function createAnimatorImpl(doc, adapter, callbacks, containerElement) {
6254
6406
  }
6255
6407
  return createAnimatorFromConfig(doc, adapter, callbacks, rootElement);
6256
6408
  }
6257
- var PX_ANIMATOR_DATA_KEY = "data";
6258
6409
  function createAnimator(options) {
6259
6410
  const { src, data, adapter, callbacks, container } = options;
6260
6411
  if (data !== void 0 && src !== void 0) {
@@ -6363,6 +6514,7 @@ if (typeof window !== "undefined") {
6363
6514
  PxGradientType,
6364
6515
  PxGradientUnits,
6365
6516
  PxKeyframeSchema,
6517
+ PxKeyframeValueSchema,
6366
6518
  PxLoopSchema,
6367
6519
  PxMaskedByEffectSchema,
6368
6520
  PxNodeBase,
@@ -6374,9 +6526,9 @@ if (typeof window !== "undefined") {
6374
6526
  PxSvgNodeExtra,
6375
6527
  PxTextEffectSchema,
6376
6528
  PxTextPathEffectSchema,
6529
+ PxTransformByEffectSchema,
6377
6530
  PxTransformPartsSchema,
6378
6531
  PxTransformValueSchema,
6379
- PxTransformationEffectSchema,
6380
6532
  PxTriggerSchema,
6381
6533
  PxTrimPathEffectSchema,
6382
6534
  STYLE_ATTR_NAMES,