@pixodesk/svg-animator-react 1.0.30 → 1.0.34

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
@@ -1815,6 +1815,18 @@ var PixodeskAnimatorReact = (() => {
1815
1815
  return a;
1816
1816
  };
1817
1817
  var __spreadProps2 = (a, b) => __defProps2(a, __getOwnPropDescs2(b));
1818
+ var __objRest2 = (source, exclude) => {
1819
+ var target = {};
1820
+ for (var prop in source)
1821
+ if (__hasOwnProp22.call(source, prop) && exclude.indexOf(prop) < 0)
1822
+ target[prop] = source[prop];
1823
+ if (source != null && __getOwnPropSymbols2)
1824
+ for (var prop of __getOwnPropSymbols2(source)) {
1825
+ if (exclude.indexOf(prop) < 0 && __propIsEnum2.call(source, prop))
1826
+ target[prop] = source[prop];
1827
+ }
1828
+ return target;
1829
+ };
1818
1830
  function bezierToSvgPath(path, forceCurves = false) {
1819
1831
  var _a, _b, _c, _d;
1820
1832
  const v = path.v;
@@ -2067,6 +2079,38 @@ var PixodeskAnimatorReact = (() => {
2067
2079
  if (o) segs.push("translate(" + -o[0] + tu + "," + -o[1] + tu + ")");
2068
2080
  return segs.join("");
2069
2081
  }
2082
+ function parseTransformParts(str2) {
2083
+ var _a, _b;
2084
+ if (!str2 || typeof str2 !== "string") return void 0;
2085
+ const out = {};
2086
+ const re = /([a-zA-Z]+)\s*\(([^)]*)\)/g;
2087
+ const order = ["translate", "rotate", "skewX", "scale"];
2088
+ let lastIdx = -1;
2089
+ let m;
2090
+ while ((m = re.exec(str2)) !== null) {
2091
+ const fn = m[1];
2092
+ const idx = order.indexOf(fn);
2093
+ if (idx < 0 || idx <= lastIdx) return void 0;
2094
+ lastIdx = idx;
2095
+ const nums = m[2].split(/[\s,]+/).filter(Boolean).map(Number);
2096
+ if (nums.some((n) => Number.isNaN(n))) return void 0;
2097
+ if (fn === "translate") {
2098
+ if (nums.length < 1 || nums.length > 2) return void 0;
2099
+ out.translate = [nums[0], (_a = nums[1]) != null ? _a : 0];
2100
+ } else if (fn === "rotate") {
2101
+ if (nums.length !== 1) return void 0;
2102
+ out.rotate = nums[0];
2103
+ } else if (fn === "skewX") {
2104
+ if (nums.length !== 1) return void 0;
2105
+ out.skew = nums[0];
2106
+ } else {
2107
+ if (nums.length < 1 || nums.length > 2) return void 0;
2108
+ out.scale = [nums[0], (_b = nums[1]) != null ? _b : nums[0]];
2109
+ }
2110
+ }
2111
+ if (str2.replace(/([a-zA-Z]+)\s*\(([^)]*)\)/g, "").replace(/[\s,]/g, "").length) return void 0;
2112
+ return Object.keys(out).length ? out : void 0;
2113
+ }
2070
2114
  var STYLE_ATTR_NAMES = /* @__PURE__ */ new Set(["offset-distance", "offsetDistance"]);
2071
2115
  var DEFAULT_DURATION_MS = 1e3;
2072
2116
  function kebabToCamelCaseWord(kebab) {
@@ -2394,6 +2438,7 @@ var PixodeskAnimatorReact = (() => {
2394
2438
  constructor(schemas, defaultVal) {
2395
2439
  super();
2396
2440
  this.schemas = schemas;
2441
+ this._kind = "union";
2397
2442
  this._default = defaultVal != null ? defaultVal : schemas[0]._default;
2398
2443
  }
2399
2444
  sanitize(raw) {
@@ -2418,6 +2463,7 @@ var PixodeskAnimatorReact = (() => {
2418
2463
  super();
2419
2464
  this._key = _key;
2420
2465
  this._schemas = _schemas;
2466
+ this._kind = "discriminatedUnion";
2421
2467
  this._default = defaultVal != null ? defaultVal : _schemas[0]._default;
2422
2468
  this._map = /* @__PURE__ */ new Map();
2423
2469
  for (const s of _schemas) {
@@ -2580,6 +2626,7 @@ var PixodeskAnimatorReact = (() => {
2580
2626
  constructor(value) {
2581
2627
  super();
2582
2628
  this.value = value;
2629
+ this._kind = "record";
2583
2630
  this._default = {};
2584
2631
  }
2585
2632
  sanitize(raw) {
@@ -2665,6 +2712,7 @@ var PixodeskAnimatorReact = (() => {
2665
2712
  constructor(schemas) {
2666
2713
  super();
2667
2714
  this.schemas = schemas;
2715
+ this._kind = "tuple";
2668
2716
  this._default = schemas.map((s) => s._default);
2669
2717
  }
2670
2718
  sanitize(raw) {
@@ -2827,7 +2875,51 @@ var PixodeskAnimatorReact = (() => {
2827
2875
  }
2828
2876
  function getAnimatorConfig(doc) {
2829
2877
  var _a;
2830
- return (doc == null ? void 0 : doc.animator) || ((_a = doc == null ? void 0 : doc.meta) == null ? void 0 : _a.animator);
2878
+ const cfg = (doc == null ? void 0 : doc.animator) || ((_a = doc == null ? void 0 : doc.meta) == null ? void 0 : _a.animator);
2879
+ return cfg ? flattenAnimatorTimeline(cfg) : void 0;
2880
+ }
2881
+ var flattenMemo = /* @__PURE__ */ new WeakMap();
2882
+ function flattenAnimatorTimeline(cfg) {
2883
+ const timeline = cfg.timeline;
2884
+ if (timeline === void 0 || timeline === null || typeof timeline !== "object") return cfg;
2885
+ const memoised = flattenMemo.get(cfg);
2886
+ if (memoised) return memoised;
2887
+ const _a = cfg, { timeline: _dropped } = _a, flat = __objRest2(_a, ["timeline"]);
2888
+ if (timeline.type === "scroll" || timeline.type === "view") {
2889
+ flat.timelineSource = "scroll";
2890
+ if (timeline.duration !== void 0) flat.duration = timeline.duration;
2891
+ if (timeline.iterations !== void 0) flat.iterations = timeline.iterations;
2892
+ const scroll = __spreadValues2({}, flat.scroll || {});
2893
+ scroll.kind = timeline.type;
2894
+ if (timeline.engine !== void 0) scroll.driver = timeline.engine;
2895
+ if (timeline.axis !== void 0) scroll.axis = timeline.axis;
2896
+ if (timeline.source !== void 0) scroll.source = timeline.source;
2897
+ if (timeline.subject !== void 0) scroll.subject = timeline.subject;
2898
+ if (timeline.smoothing !== void 0) scroll.smoothing = timeline.smoothing;
2899
+ if (timeline.range !== void 0) scroll.range = timeline.range;
2900
+ const pin = timeline.pin;
2901
+ if (typeof pin === "boolean") scroll.pin = pin;
2902
+ else if (pin && typeof pin === "object") {
2903
+ scroll.pin = true;
2904
+ if (pin.align !== void 0) scroll.pinAlign = pin.align;
2905
+ if (pin.top !== void 0) scroll.pinTop = pin.top;
2906
+ if (pin.distance !== void 0) scroll.pinDistance = pin.distance;
2907
+ }
2908
+ flat.scroll = scroll;
2909
+ } else {
2910
+ if (timeline.duration !== void 0) flat.duration = timeline.duration;
2911
+ if (timeline.trigger !== void 0) {
2912
+ const _b = timeline.trigger, { onFinish } = _b, restTrigger = __objRest2(_b, ["onFinish"]);
2913
+ if (Object.keys(restTrigger).length) flat.trigger = restTrigger;
2914
+ if (onFinish !== void 0) flat.resetOnFinish = onFinish === "reset";
2915
+ }
2916
+ if (timeline.delay !== void 0) flat.delay = timeline.delay;
2917
+ if (timeline.iterations !== void 0) flat.iterations = timeline.iterations;
2918
+ if (timeline.direction !== void 0) flat.direction = timeline.direction;
2919
+ if (timeline.fill !== void 0) flat.fill = timeline.fill;
2920
+ }
2921
+ flattenMemo.set(cfg, flat);
2922
+ return flat;
2831
2923
  }
2832
2924
  function getDefs(doc) {
2833
2925
  var _a;
@@ -2839,7 +2931,7 @@ var PixodeskAnimatorReact = (() => {
2839
2931
  if (!doc) return void 0;
2840
2932
  const animateById = (_a = getAnimatorConfig(doc)) == null ? void 0 : _a.animateById;
2841
2933
  if (!animateById) return void 0;
2842
- return Object.entries(animateById).map(([id, anim]) => ({ id, animate: anim }));
2934
+ return Object.entries(animateById).map(([id, anim]) => ({ id: id.startsWith("#") ? id.slice(1) : id, animate: anim }));
2843
2935
  }
2844
2936
  var PxEasingOrRefSchema = px.union([
2845
2937
  px.string(),
@@ -2850,27 +2942,27 @@ var PixodeskAnimatorReact = (() => {
2850
2942
  // e.g. for colors
2851
2943
  px.number(),
2852
2944
  px.array(px.number()),
2853
- px.lazy(() => PxTransformPartsSchema, {}),
2945
+ // ORDER LAW: the key-discriminated object shapes (`{path}`, `{paths}`) come BEFORE the
2946
+ // all-optional transform-parts record. In default (non-strict) mode that record accepts
2947
+ // ANY object (every key optional, unknown keys ignored), so listing it earlier made
2948
+ // Union.sanitize route `{path}`/`{paths}` values into it and strip them to `{}` —
2949
+ // silent morph-data loss (repro: the editor's keyframeValueSanitize spec). Validity is
2950
+ // order-independent (`some()`); only sanitize routing depends on this order.
2854
2951
  px.object({ path: px.string() }),
2855
2952
  px.lazy(() => px.object({ paths: px.array(PxBezierPathSchema) }), { paths: [] }),
2856
2953
  // Gradient `stops` timeline — each kf value is the full stops-array snapshot.
2857
- px.lazy(() => px.array(PxGradientStopSchema), [])
2954
+ px.lazy(() => px.array(PxGradientStopSchema), []),
2955
+ px.lazy(() => PxTransformPartsSchema, {})
2858
2956
  ]));
2859
2957
  var PxKeyframeSchema = implementsInterface()(px.object({
2860
2958
  time: px.number().optional(),
2861
- t: px.number().optional(),
2862
2959
  value: PxKeyframeValueSchema.optional(),
2863
- v: PxKeyframeValueSchema.optional(),
2864
2960
  easing: PxEasingOrRefSchema.optional(),
2865
- e: PxEasingOrRefSchema.optional(),
2866
2961
  tangentOut: px.tuple([px.number(), px.number()]).optional(),
2867
- to: px.tuple([px.number(), px.number()]).optional(),
2868
- // short alias
2869
- tangentIn: px.tuple([px.number(), px.number()]).optional(),
2870
- ti: px.tuple([px.number(), px.number()]).optional(),
2871
- // short alias
2872
- selected: px.boolean().optional()
2873
- // editor-side UI state (Player ignores it)
2962
+ tangentIn: px.tuple([px.number(), px.number()]).optional()
2963
+ // (`selected` — editor timeline-selection UI state — was REMOVED from the wire
2964
+ // (review §1.3): editor data lives under `meta`. The editor still carries it on
2965
+ // its internal COPY-PASTE payload, which never validates against this schema.)
2874
2966
  }));
2875
2967
  var PxLoopSchema = implementsInterface()(px.object({
2876
2968
  segmentCount: px.number().optional(),
@@ -2880,7 +2972,6 @@ var PixodeskAnimatorReact = (() => {
2880
2972
  var PxPropertyAnimationSchema = implementsInterface()(px.object({
2881
2973
  value: PxKeyframeValueSchema.optional(),
2882
2974
  keyframes: px.array(PxKeyframeSchema).optional(),
2883
- kfs: px.array(PxKeyframeSchema).optional(),
2884
2975
  loop: px.union([PxLoopSchema, px.boolean()]).optional(),
2885
2976
  autoOrient: px.boolean().optional()
2886
2977
  }));
@@ -2908,6 +2999,11 @@ var PixodeskAnimatorReact = (() => {
2908
2999
  var PxTriggerSchema = implementsInterface()(px.object({
2909
3000
  startOn: px.enum(["load", "mouseOver", "click", "scrollIntoView", "programmatic"]).optional(),
2910
3001
  outAction: px.enum(["continue", "pause", "reset", "reverse"]).optional(),
3002
+ // What happens after a NATURAL finish — `'hold'` (default: keep the end state per
3003
+ // `fill`) or `'reset'` (snap back to the start state). The trigger-vocabulary home of
3004
+ // the old top-level `resetOnFinish: boolean` (read-legacy) — review §2.3: both
3005
+ // "what happens at the end" knobs now sit side by side and share one style of value.
3006
+ onFinish: px.enum(["hold", "reset"]).optional(),
2911
3007
  scrollIntoViewThreshold: px.number().optional()
2912
3008
  }));
2913
3009
  var PxGlyphSchema = implementsInterface()(px.object({
@@ -2915,8 +3011,8 @@ var PixodeskAnimatorReact = (() => {
2915
3011
  d: px.string()
2916
3012
  }));
2917
3013
  var PxGlyphFontSchema = implementsInterface()(px.object({
2918
- fFamily: px.string(),
2919
- style: px.string(),
3014
+ fontFamily: px.string(),
3015
+ fontStyle: px.string(),
2920
3016
  ascent: px.number(),
2921
3017
  unitsPerEm: px.number(),
2922
3018
  glyphs: px.record(PxGlyphSchema)
@@ -2924,7 +3020,9 @@ var PixodeskAnimatorReact = (() => {
2924
3020
  var PxDefsSchema = implementsInterface()(px.object({
2925
3021
  easings: px.record(px.tuple([px.number(), px.number(), px.number(), px.number()])).optional(),
2926
3022
  animations: px.record(PxAnimationDefinitionSchema).optional(),
2927
- styles: px.record(px.any()).optional(),
3023
+ // Review §2.6: the schema now matches the declared type — a style preset is a flat
3024
+ // record of string|number attribute values, nothing nested.
3025
+ styles: px.record(px.record(px.union([px.string(), px.number()]))).optional(),
2928
3026
  glyphs: px.record(PxGlyphFontSchema).optional()
2929
3027
  }));
2930
3028
  var PX_SCROLL_PHASES = ["cover", "contain", "entry", "exit", "entry-crossing", "exit-crossing"];
@@ -2950,22 +3048,54 @@ var PixodeskAnimatorReact = (() => {
2950
3048
  pinDistance: px.number().optional(),
2951
3049
  range: PxScrollRangeSchema.optional()
2952
3050
  }));
2953
- var PxAnimatorConfigSchema = implementsInterface()(px.object({
2954
- mode: px.enum([PxAnimatorMode.auto, PxAnimatorMode.waapi, PxAnimatorMode.frames]).optional(),
3051
+ var PxTimelinePinSchema = px.object({
3052
+ align: px.enum(["top", "center", "bottom"]).optional(),
3053
+ top: px.number().optional(),
3054
+ distance: px.number().optional()
3055
+ });
3056
+ var PxClockTimelineSchema = px.object({
3057
+ type: px.literal("clock"),
3058
+ // §2.8: duration is a property of the TIMELINE — how long one pass takes.
2955
3059
  duration: px.number().optional(),
3060
+ trigger: PxTriggerSchema.optional(),
2956
3061
  delay: px.number().optional(),
2957
- // LAW (SCHEMA-DESIGN R3, S10): the ONE sanctioned string-in-number union
2958
- // (CSS animation-iteration-count familiarity) — do not add more mixed unions.
2959
3062
  iterations: px.union([px.number(), px.literal("infinite")]).optional(),
2960
3063
  fill: px.enum(["forwards", "backwards", "both", "none"]).optional(),
2961
- direction: px.enum(["normal", "reverse", "alternate", "alternate-reverse"]).optional(),
3064
+ direction: px.enum(["normal", "reverse", "alternate", "alternate-reverse"]).optional()
3065
+ });
3066
+ var scrollishTimelineShape = {
3067
+ // §2.8: duration is a property of the TIMELINE — under scrubbing it is the keyframe
3068
+ // span the scroll range maps onto.
3069
+ duration: px.number().optional(),
3070
+ // Finite repeat count IS meaningful when scrubbing — the scroll range maps onto
3071
+ // duration × iterations (rule D4; `'infinite'` cannot map to a range, so no literal here).
3072
+ iterations: px.number().optional(),
3073
+ engine: px.enum(["custom", "native"]).optional(),
3074
+ axis: px.enum(["block", "inline", "x", "y"]).optional(),
3075
+ source: px.enum(["nearest", "root"]).optional(),
3076
+ subject: px.string().optional(),
3077
+ // 'parent' | 'scroller' | any CSS selector
3078
+ smoothing: px.number().optional(),
3079
+ // ms
3080
+ pin: px.union([px.boolean(), PxTimelinePinSchema]).optional(),
3081
+ range: PxScrollRangeSchema.optional()
3082
+ };
3083
+ var PxScrollTimelineSchema = px.object(__spreadValues2({ type: px.literal("scroll") }, scrollishTimelineShape));
3084
+ var PxViewTimelineSchema = px.object(__spreadValues2({ type: px.literal("view") }, scrollishTimelineShape));
3085
+ var PxTimelineSchema = px.discriminatedUnion("type", [
3086
+ PxClockTimelineSchema,
3087
+ PxScrollTimelineSchema,
3088
+ PxViewTimelineSchema
3089
+ ]);
3090
+ var PxAnimatorConfigSchema = implementsInterface()(px.object({
3091
+ mode: px.enum([PxAnimatorMode.auto, PxAnimatorMode.waapi, PxAnimatorMode.frames]).optional(),
3092
+ // (`duration` lives INSIDE `timeline` on the wire — §2.8; the flat field below
3093
+ // exists only on the runtime view, like the rest of the playback dynamics.)
2962
3094
  frameRate: px.number().optional(),
2963
- trigger: PxTriggerSchema.optional(),
2964
- resetOnFinish: px.boolean().optional(),
3095
+ // THE spelling of "what advances progress" — clock / scroll / view (review §2.1).
3096
+ timeline: PxTimelineSchema.optional(),
2965
3097
  definitions: PxDefsSchema.optional(),
2966
3098
  animateById: px.record(PxElementAnimationSchema).optional(),
2967
- timelineSource: px.string().optional(),
2968
- scroll: PxScrollSchema.optional(),
2969
3099
  debugInstName: px.string().optional()
2970
3100
  }));
2971
3101
  var PxBindingSchema = implementsInterface()(px.object({
@@ -2984,18 +3114,18 @@ var PixodeskAnimatorReact = (() => {
2984
3114
  ]);
2985
3115
  var PxAnimatableNumberSchema = px.union([
2986
3116
  px.number(),
2987
- px.object({ value: px.number() }),
2988
- PxPropertyAnimationSchema
3117
+ PxPropertyAnimationSchema,
3118
+ px.object({ value: px.number() })
2989
3119
  ]);
2990
3120
  var PxAnimatableVec2Schema = px.union([
2991
3121
  px.tuple([px.number(), px.number()]),
2992
- px.object({ value: px.tuple([px.number(), px.number()]) }),
2993
- PxPropertyAnimationSchema
3122
+ PxPropertyAnimationSchema,
3123
+ px.object({ value: px.tuple([px.number(), px.number()]) })
2994
3124
  ]);
2995
3125
  var PxAnimatableStringSchema = px.union([
2996
3126
  px.string(),
2997
- px.object({ value: px.string() }),
2998
- PxPropertyAnimationSchema
3127
+ PxPropertyAnimationSchema,
3128
+ px.object({ value: px.string() })
2999
3129
  ]);
3000
3130
  var PxTransformByEffectSchema = implementsInterface()(px.object({
3001
3131
  translate: PxAnimatableVec2Schema.optional(),
@@ -3025,8 +3155,7 @@ var PixodeskAnimatorReact = (() => {
3025
3155
  height: px.number().optional()
3026
3156
  }));
3027
3157
  var PxClipPathEffectSchema = implementsInterface()(px.object({
3028
- d: PxAnimatableStringSchema.optional(),
3029
- animate: PxPropertyAnimationSchema.optional()
3158
+ d: PxAnimatableStringSchema.optional()
3030
3159
  }));
3031
3160
  var PxStrokeTrimEffectSchema = implementsInterface()(px.object({
3032
3161
  offset: PxAnimatableNumberSchema.optional(),
@@ -3034,7 +3163,6 @@ var PixodeskAnimatorReact = (() => {
3034
3163
  subPaths: px.enum([PxStrokeTrimSubPaths.separate, PxStrokeTrimSubPaths.combined]).optional()
3035
3164
  }));
3036
3165
  var PxRetimeEffectSchema = implementsInterface()(px.object({
3037
- sourceId: px.string().optional(),
3038
3166
  start: px.number().optional(),
3039
3167
  stretch: px.number().optional(),
3040
3168
  timeCrop: px.tuple([px.number(), px.number()]).optional()
@@ -3057,11 +3185,11 @@ var PixodeskAnimatorReact = (() => {
3057
3185
  var PxFillGradientEffectSchema = implementsInterface()(px.object({
3058
3186
  // Contextual kind — the `type` convention, see `PxNodeBase.type`.
3059
3187
  type: px.enum([PxGradientType.linear, PxGradientType.radial]),
3060
- p1: PxAnimatableVec2Schema.optional(),
3061
- p2: PxAnimatableVec2Schema.optional(),
3062
- c: PxAnimatableVec2Schema.optional(),
3063
- r: PxAnimatableNumberSchema.optional(),
3064
- fp: PxAnimatableVec2Schema.optional(),
3188
+ start: PxAnimatableVec2Schema.optional(),
3189
+ end: PxAnimatableVec2Schema.optional(),
3190
+ center: PxAnimatableVec2Schema.optional(),
3191
+ radius: PxAnimatableNumberSchema.optional(),
3192
+ focal: PxAnimatableVec2Schema.optional(),
3065
3193
  stops: PxAnimatableGradientStopsSchema.optional(),
3066
3194
  gradientUnits: px.enum([PxGradientUnits.userSpaceOnUse, PxGradientUnits.objectBoundingBox]).optional(),
3067
3195
  spreadMethod: px.enum([PxGradientSpreadMethod.pad, PxGradientSpreadMethod.reflect, PxGradientSpreadMethod.repeat]).optional(),
@@ -3251,9 +3379,11 @@ var PixodeskAnimatorReact = (() => {
3251
3379
  const docAnimate = (_a = cloned.animator) == null ? void 0 : _a.animateById;
3252
3380
  if (docAnimate && typeof docAnimate === "object") {
3253
3381
  const updatedAnimate = {};
3254
- for (const [id, anim] of Object.entries(docAnimate)) {
3382
+ for (const [key, anim] of Object.entries(docAnimate)) {
3383
+ const hashed = key.startsWith("#");
3384
+ const id = hashed ? key.slice(1) : key;
3255
3385
  const newId = (_b = idMap.get(id)) != null ? _b : id;
3256
- updatedAnimate[newId] = anim;
3386
+ updatedAnimate[hashed ? "#" + newId : newId] = anim;
3257
3387
  }
3258
3388
  cloned.animator = __spreadProps2(__spreadValues2({}, cloned.animator), { animateById: updatedAnimate });
3259
3389
  }
@@ -3344,7 +3474,7 @@ var PixodeskAnimatorReact = (() => {
3344
3474
  let value = props[rawKey];
3345
3475
  if (COLOUR_ATTR_NAMES.has(key) && Array.isArray(value)) {
3346
3476
  propsCopy[key] = toRGBA(value);
3347
- } else if (key === "transform" && value !== null && typeof value === "object" && !Array.isArray(value) && !value.keyframes && !value.kfs) {
3477
+ } else if (key === "transform" && value !== null && typeof value === "object" && !Array.isArray(value) && !value.keyframes) {
3348
3478
  const parts = value.value && typeof value.value === "object" ? value.value : value;
3349
3479
  propsCopy["transform"] = composeTransformParts(parts, { withUnits: false });
3350
3480
  } else if (TRANSFORM_FN_NAMES.has(key)) {
@@ -3382,12 +3512,12 @@ var PixodeskAnimatorReact = (() => {
3382
3512
  return (_a = kf.easing) != null ? _a : kf.e;
3383
3513
  }
3384
3514
  function propAnimIsMotionPath(anim) {
3385
- var _a, _b, _c;
3386
- const kfs = (_a = anim.keyframes) != null ? _a : anim.kfs;
3515
+ var _a, _b;
3516
+ const kfs = anim.keyframes;
3387
3517
  if (!Array.isArray(kfs)) return false;
3388
3518
  if (anim.autoOrient) return true;
3389
3519
  for (const kf of kfs) {
3390
- if (((_b = kf.tangentIn) != null ? _b : kf.ti) || ((_c = kf.tangentOut) != null ? _c : kf.to)) return true;
3520
+ if (((_a = kf.tangentIn) != null ? _a : kf.ti) || ((_b = kf.tangentOut) != null ? _b : kf.to)) return true;
3391
3521
  }
3392
3522
  return false;
3393
3523
  }
@@ -3448,14 +3578,14 @@ var PixodeskAnimatorReact = (() => {
3448
3578
  var DEFAULT_ROTATION_TOL = 5;
3449
3579
  var DEFAULT_MAX_SAMPLES = 32;
3450
3580
  function materialiseMotionPathInPropAnim(anim, opts) {
3451
- var _a, _b, _c, _d;
3581
+ var _a, _b, _c;
3452
3582
  if (!propAnimIsMotionPath(anim)) return anim;
3453
- const kfs = (_a = anim.keyframes) != null ? _a : anim.kfs;
3583
+ const kfs = anim.keyframes;
3454
3584
  if (!Array.isArray(kfs) || kfs.length < 2) return anim;
3455
3585
  const autoOrient = !!anim.autoOrient;
3456
- const flatnessTol = (_b = opts == null ? void 0 : opts.flatnessTolerance) != null ? _b : DEFAULT_FLATNESS_TOL;
3457
- const rotationTol = (_c = opts == null ? void 0 : opts.rotationTolerance) != null ? _c : DEFAULT_ROTATION_TOL;
3458
- const maxSamples = (_d = opts == null ? void 0 : opts.maxSamplesPerSegment) != null ? _d : DEFAULT_MAX_SAMPLES;
3586
+ const flatnessTol = (_a = opts == null ? void 0 : opts.flatnessTolerance) != null ? _a : DEFAULT_FLATNESS_TOL;
3587
+ const rotationTol = (_b = opts == null ? void 0 : opts.rotationTolerance) != null ? _b : DEFAULT_ROTATION_TOL;
3588
+ const maxSamples = (_c = opts == null ? void 0 : opts.maxSamplesPerSegment) != null ? _c : DEFAULT_MAX_SAMPLES;
3459
3589
  const out = [];
3460
3590
  const firstPos = getKfTranslate(kfs[0]);
3461
3591
  if (!firstPos) return anim;
@@ -3484,7 +3614,7 @@ var PixodeskAnimatorReact = (() => {
3484
3614
  const lastInE = getKfEasing(kfs[kfs.length - 1]);
3485
3615
  if (lastInE) out[out.length - 1].e = lastInE;
3486
3616
  if (autoOrient) unwrapAutoOrientRotations(out);
3487
- const result = { kfs: out };
3617
+ const result = { keyframes: out };
3488
3618
  if (anim.loop !== void 0) result.loop = anim.loop;
3489
3619
  return result;
3490
3620
  }
@@ -4144,7 +4274,7 @@ var PixodeskAnimatorReact = (() => {
4144
4274
  }
4145
4275
  function normalizeKeyframes(propName, propAnim, duration, defs) {
4146
4276
  var _a, _b, _c, _d, _e, _f, _g;
4147
- const keyframes = propAnim.keyframes || propAnim.kfs || [];
4277
+ const keyframes = propAnim.keyframes || [];
4148
4278
  const normalized = [];
4149
4279
  for (const kf of keyframes) {
4150
4280
  const timePct = (_b = (_a = kf.time) != null ? _a : kf.t) != null ? _b : 0;
@@ -4189,17 +4319,16 @@ var PixodeskAnimatorReact = (() => {
4189
4319
  return merged;
4190
4320
  }
4191
4321
  function materialiseInternalLoopsInPropAnim(propName, propAnim, duration) {
4192
- var _a;
4193
4322
  const loopRaw = propAnim.loop;
4194
4323
  if (loopRaw === void 0 || loopRaw === null || loopRaw === false) return propAnim;
4195
4324
  const loop = loopRaw === true ? {} : loopRaw;
4196
- const rawKfs = (_a = propAnim.keyframes) != null ? _a : propAnim.kfs;
4325
+ const rawKfs = propAnim.keyframes;
4197
4326
  if (!Array.isArray(rawKfs) || rawKfs.length < 2) return propAnim;
4198
4327
  const propNameKebab = isCamelCaseWord(propName) ? camelCaseToKebabWordIfNeeded(propName) : propName;
4199
4328
  const isColour = COLOUR_ATTR_NAMES.has(propNameKebab);
4200
4329
  const kfs = rawKfs.map((kf) => {
4201
- var _a2, _b, _c, _d, _e, _f, _g, _h;
4202
- const t = (_a2 = kf.t) != null ? _a2 : kf.time;
4330
+ var _a, _b, _c, _d, _e, _f, _g, _h;
4331
+ const t = (_a = kf.t) != null ? _a : kf.time;
4203
4332
  let v = (_b = kf.v) != null ? _b : kf.value;
4204
4333
  if (propName === "d") v = normalizePathValue(v);
4205
4334
  if (isColour) v = (_c = parseColor(v)) != null ? _c : v;
@@ -4210,7 +4339,7 @@ var PixodeskAnimatorReact = (() => {
4210
4339
  return out2;
4211
4340
  });
4212
4341
  const expanded = expandLoopKeyframes(propName, kfs, loop, duration);
4213
- const out = { kfs: expanded };
4342
+ const out = { keyframes: expanded };
4214
4343
  if (propAnim.autoOrient !== void 0) out.autoOrient = propAnim.autoOrient;
4215
4344
  return out;
4216
4345
  }
@@ -4252,6 +4381,36 @@ var PixodeskAnimatorReact = (() => {
4252
4381
  function generateElementId() {
4253
4382
  return "_px_el_" + ++_elementIdCounter;
4254
4383
  }
4384
+ function mergeStaticTransformIntoAnimDef(animDef, staticTransform) {
4385
+ if (!animDef) return animDef;
4386
+ const staticParts = staticTransform && typeof staticTransform === "object" && !Array.isArray(staticTransform) ? staticTransform : parseTransformParts(staticTransform);
4387
+ if (!staticParts || !Object.keys(staticParts).length) return animDef;
4388
+ const mergeKfValue = (v) => v && typeof v === "object" && !Array.isArray(v) ? __spreadValues2(__spreadValues2({}, staticParts), v) : v;
4389
+ const transformAnim = animDef["transform"];
4390
+ if (transformAnim && typeof transformAnim === "object") {
4391
+ const anim = transformAnim;
4392
+ if (Array.isArray(anim.keyframes)) {
4393
+ const out = __spreadProps2(__spreadValues2({}, anim), {
4394
+ keyframes: anim.keyframes.map((kf) => __spreadProps2(__spreadValues2({}, kf), { value: mergeKfValue(kf.value) }))
4395
+ });
4396
+ if (out.value !== void 0) out.value = mergeKfValue(out.value);
4397
+ return __spreadProps2(__spreadValues2({}, animDef), { transform: out });
4398
+ }
4399
+ return animDef;
4400
+ }
4401
+ const channels = Object.keys(animDef).filter((k) => TRANSFORM_FN_NAMES.has(k));
4402
+ if (channels.length !== 1) return animDef;
4403
+ const ch = channels[0];
4404
+ const chAnim = animDef[ch];
4405
+ if (!chAnim || typeof chAnim !== "object" || !Array.isArray(chAnim.keyframes)) return animDef;
4406
+ const lifted = __spreadProps2(__spreadValues2({}, chAnim), {
4407
+ keyframes: chAnim.keyframes.map((kf) => __spreadProps2(__spreadValues2({}, kf), { value: __spreadProps2(__spreadValues2({}, staticParts), { [ch]: kf.value }) }))
4408
+ });
4409
+ if (lifted.value !== void 0) lifted.value = __spreadProps2(__spreadValues2({}, staticParts), { [ch]: lifted.value });
4410
+ const rest = __spreadValues2({}, animDef);
4411
+ delete rest[ch];
4412
+ return __spreadProps2(__spreadValues2({}, rest), { transform: lifted });
4413
+ }
4255
4414
  function normalizeAnimationDefinition(animDef, duration, defs, engine = PxAnimatorEngine.waapi) {
4256
4415
  const normalized = {};
4257
4416
  for (const [propName, propAnim] of Object.entries(animDef)) {
@@ -4260,7 +4419,7 @@ var PixodeskAnimatorReact = (() => {
4260
4419
  }
4261
4420
  const normalizedKfs = normalizeKeyframes(propName, propAnim, duration, defs);
4262
4421
  if (normalizedKfs.length > 0) {
4263
- const out = { kfs: normalizedKfs };
4422
+ const out = { keyframes: normalizedKfs };
4264
4423
  if (propAnim.autoOrient !== void 0) out.autoOrient = propAnim.autoOrient;
4265
4424
  if (propAnim.loop !== void 0) out.loop = propAnim.loop;
4266
4425
  normalized[propName] = engine === PxAnimatorEngine.waapi && propName === "transform" ? materialiseMotionPathInPropAnim(out) : out;
@@ -4273,11 +4432,11 @@ var PixodeskAnimatorReact = (() => {
4273
4432
  const defs = getDefs(doc);
4274
4433
  const duration = animatorConfig.duration || 1e3;
4275
4434
  const bindings = [];
4276
- const processAnimation = (id, animate) => {
4435
+ const processAnimation = (id, animate, staticTransform) => {
4277
4436
  if (!animate) return null;
4278
4437
  const animDefs = resolveElementAnimation(animate, defs);
4279
4438
  if (animDefs.length === 0) return null;
4280
- const merged = mergeAnimationDefinitions(animDefs);
4439
+ const merged = mergeStaticTransformIntoAnimDef(mergeAnimationDefinitions(animDefs), staticTransform);
4281
4440
  const normalizedAnim = normalizeAnimationDefinition(merged, duration, defs, engine);
4282
4441
  if (Object.keys(normalizedAnim).length === 0) return null;
4283
4442
  return {
@@ -4297,7 +4456,7 @@ var PixodeskAnimatorReact = (() => {
4297
4456
  if (inlineAnim && Object.keys(inlineAnim).length > 0) {
4298
4457
  const nodeId = node.id || generateElementId();
4299
4458
  node.id = nodeId;
4300
- const normalized = processAnimation(nodeId, inlineAnim);
4459
+ const normalized = processAnimation(nodeId, inlineAnim, node.transform);
4301
4460
  if (normalized) bindings.push(normalized);
4302
4461
  }
4303
4462
  if (node.children) {
@@ -4335,7 +4494,7 @@ var PixodeskAnimatorReact = (() => {
4335
4494
  }
4336
4495
  function calcPropertyValue(propName, propAnim, progress) {
4337
4496
  var _a, _b, _c, _d, _e, _f, _g;
4338
- const keyframes = propAnim.kfs || propAnim.keyframes || [];
4497
+ const keyframes = propAnim.keyframes || [];
4339
4498
  if (keyframes.length === 0) return null;
4340
4499
  const { prevKf, nextKf } = getKeyframesPair(keyframes, progress);
4341
4500
  let localProgress = prevKf === nextKf ? 0 : remap(progress, (_a = prevKf.t) != null ? _a : 0, (_b = nextKf.t) != null ? _b : 0, 0, 1);
@@ -4950,7 +5109,7 @@ var PixodeskAnimatorReact = (() => {
4950
5109
  if (split.rest) node.transform = split.rest;
4951
5110
  else delete node.transform;
4952
5111
  }
4953
- } else if (node.transform && typeof node.transform === "object" && !Array.isArray(node.transform) && !node.transform.keyframes && !node.transform.kfs) {
5112
+ } else if (node.transform && typeof node.transform === "object" && !Array.isArray(node.transform) && !node.transform.keyframes) {
4954
5113
  const wrapped = node.transform.value;
4955
5114
  const isWrapped = !!(wrapped && typeof wrapped === "object");
4956
5115
  const value = isWrapped ? wrapped : node.transform;
@@ -5083,12 +5242,12 @@ var PixodeskAnimatorReact = (() => {
5083
5242
  id
5084
5243
  };
5085
5244
  if (fx.type === PxGradientType.linear) {
5086
- applyGeomVec(out, "x1", "y1", fx.p1);
5087
- applyGeomVec(out, "x2", "y2", fx.p2);
5245
+ applyGeomVec(out, "x1", "y1", fx.start);
5246
+ applyGeomVec(out, "x2", "y2", fx.end);
5088
5247
  } else {
5089
- applyGeomVec(out, "cx", "cy", fx.c);
5090
- applyGeomNumber(out, "r", fx.r);
5091
- applyGeomVec(out, "fx", "fy", fx.fp);
5248
+ applyGeomVec(out, "cx", "cy", fx.center);
5249
+ applyGeomNumber(out, "r", fx.radius);
5250
+ applyGeomVec(out, "fx", "fy", fx.focal);
5092
5251
  }
5093
5252
  if (fx.gradientUnits) out.gradientUnits = fx.gradientUnits;
5094
5253
  if (fx.spreadMethod) out.spreadMethod = fx.spreadMethod;
@@ -5214,8 +5373,7 @@ var PixodeskAnimatorReact = (() => {
5214
5373
  return pct + "%";
5215
5374
  }
5216
5375
  function applyClipPathEffect(node, fx, ctx) {
5217
- var _a, _b;
5218
- if (!fx || !fx.d && !fx.animate) return node;
5376
+ if (!(fx == null ? void 0 : fx.d)) return node;
5219
5377
  const clipId = genId(ctx, "clip");
5220
5378
  const pathChild = { type: "path" };
5221
5379
  const read = readAnimatable(fx.d);
@@ -5227,11 +5385,6 @@ var PixodeskAnimatorReact = (() => {
5227
5385
  if (pathChild.d !== void 0) pathChild.d = pathString(pathChild.d);
5228
5386
  }
5229
5387
  }
5230
- if (fx.animate && !((_a = pathChild.animate) == null ? void 0 : _a.d)) {
5231
- const animate = (_b = pathChild.animate) != null ? _b : {};
5232
- animate.d = fx.animate;
5233
- pathChild.animate = animate;
5234
- }
5235
5388
  ctx.defs.push({ type: "clipPath", id: clipId, children: [pathChild] });
5236
5389
  node.clipPath = "url(#" + clipId + ")";
5237
5390
  return node;
@@ -5374,7 +5527,7 @@ var PixodeskAnimatorReact = (() => {
5374
5527
  if (parts.origin) out.origin = parts.origin;
5375
5528
  return Object.keys(out).length ? out : void 0;
5376
5529
  }
5377
- if (node.transform && typeof node.transform === "object" && !node.transform.keyframes && !node.transform.kfs) {
5530
+ if (node.transform && typeof node.transform === "object" && !node.transform.keyframes) {
5378
5531
  const wrapped = node.transform.value;
5379
5532
  const value = wrapped && typeof wrapped === "object" ? wrapped : node.transform;
5380
5533
  if (value && typeof value === "object") {
@@ -7033,9 +7186,9 @@ var PixodeskAnimatorReact = (() => {
7033
7186
  return Object.is(r, -0) ? "0" : String(r);
7034
7187
  };
7035
7188
  function buildOffsetPath(propAnim) {
7036
- var _a, _b, _c, _d;
7189
+ var _a, _b, _c;
7037
7190
  if (propAnim.alongPathMode !== "offsetPath") return void 0;
7038
- const kfs = (_a = propAnim.keyframes) != null ? _a : propAnim.kfs;
7191
+ const kfs = propAnim.keyframes;
7039
7192
  if (!kfs || kfs.length < 2) return void 0;
7040
7193
  const first = kfValue(kfs[0]);
7041
7194
  const anchor = (first == null ? void 0 : first.origin) && first.origin.length >= 2 ? [first.origin[0], first.origin[1]] : [0, 0];
@@ -7046,7 +7199,7 @@ var PixodeskAnimatorReact = (() => {
7046
7199
  if (!tr || tr.length < 2) return void 0;
7047
7200
  const parts = Object.keys(v);
7048
7201
  if (parts.some((p) => p !== "translate" && p !== "origin")) return void 0;
7049
- const o = (_b = v == null ? void 0 : v.origin) != null ? _b : [0, 0];
7202
+ const o = (_a = v == null ? void 0 : v.origin) != null ? _a : [0, 0];
7050
7203
  if (o[0] !== anchor[0] || o[1] !== anchor[1]) return void 0;
7051
7204
  points.push([tr[0] + anchor[0], tr[1] + anchor[1]]);
7052
7205
  }
@@ -7055,8 +7208,8 @@ var PixodeskAnimatorReact = (() => {
7055
7208
  const segLens = [];
7056
7209
  for (let i = 0; i < points.length - 1; i++) {
7057
7210
  const p0 = points[i], p1 = points[i + 1];
7058
- const to = (_c = kfTangentOut(kfs[i])) != null ? _c : [0, 0];
7059
- const ti = (_d = kfTangentIn(kfs[i + 1])) != null ? _d : [0, 0];
7211
+ const to = (_b = kfTangentOut(kfs[i])) != null ? _b : [0, 0];
7212
+ const ti = (_c = kfTangentIn(kfs[i + 1])) != null ? _c : [0, 0];
7060
7213
  const c1 = [p0[0] + to[0], p0[1] + to[1]];
7061
7214
  const c2 = [p1[0] + ti[0], p1[1] + ti[1]];
7062
7215
  d += "C" + fmt2(c1[0]) + "," + fmt2(c1[1]) + "," + fmt2(c2[0]) + "," + fmt2(c2[1]) + "," + fmt2(p1[0]) + "," + fmt2(p1[1]);
@@ -7671,7 +7824,7 @@ var PixodeskAnimatorReact = (() => {
7671
7824
  const result = /* @__PURE__ */ new Map();
7672
7825
  for (const [propName, propAnim] of Object.entries(animDef)) {
7673
7826
  const duration = config.duration || 1;
7674
- const clippedKeyframes = clipKeyframesToDuration(propName, propAnim.kfs || propAnim.keyframes || [], duration);
7827
+ const clippedKeyframes = clipKeyframesToDuration(propName, propAnim.keyframes || [], duration);
7675
7828
  const cssKeyframes = [];
7676
7829
  for (let i = 0; i < clippedKeyframes.length; i++) {
7677
7830
  const kf = clippedKeyframes[i];
@@ -8273,7 +8426,16 @@ var PixodeskAnimatorReact = (() => {
8273
8426
  }
8274
8427
  }
8275
8428
  }
8276
- return createAnimatorFromConfig(doc, adapter, callbacks, rootElement);
8429
+ const api = createAnimatorFromConfig(doc, adapter, callbacks, rootElement);
8430
+ if (containerElement && rootElement) {
8431
+ const rendered = rootElement;
8432
+ const destroyNative = api.destroy.bind(api);
8433
+ api.destroy = () => {
8434
+ destroyNative();
8435
+ rendered.remove();
8436
+ };
8437
+ }
8438
+ return api;
8277
8439
  }
8278
8440
  function createAnimator(options) {
8279
8441
  const { src, data, adapter, callbacks, container } = options;
@@ -8463,10 +8625,11 @@ var PixodeskAnimatorReact = (() => {
8463
8625
  }) => {
8464
8626
  doc = generateNewIds(doc);
8465
8627
  const elementRefs = (0, import_react2.useRef)(/* @__PURE__ */ new Map());
8466
- const renderNode2 = (node, isRoot = false) => {
8628
+ const renderNode2 = (node, isRoot = false, key) => {
8467
8629
  if (!node) return null;
8468
8630
  const { type, animate, meta, children, ...props } = node;
8469
8631
  const normProps = getNormalizedProps(props);
8632
+ if (key !== void 0) normProps["key"] = key;
8470
8633
  normProps["ref"] = (domEl) => {
8471
8634
  if (node["id"]) elementRefs.current.set(node["id"], domEl);
8472
8635
  };
@@ -8476,7 +8639,7 @@ var PixodeskAnimatorReact = (() => {
8476
8639
  }
8477
8640
  if (style) normProps["style"] = style;
8478
8641
  }
8479
- return (0, import_react2.createElement)(type, normProps, children?.map((child) => renderNode2(child)));
8642
+ return (0, import_react2.createElement)(type, normProps, children?.map((child, i) => renderNode2(child, false, child["id"] ?? i)));
8480
8643
  };
8481
8644
  const root = doc ? renderNode2(doc, true) : null;
8482
8645
  (0, import_react2.useEffect)(() => {
@@ -8512,8 +8675,8 @@ var PixodeskAnimatorReact = (() => {
8512
8675
  autoplay,
8513
8676
  play,
8514
8677
  pause,
8678
+ progress,
8515
8679
  time,
8516
- timeMs,
8517
8680
  apiRef,
8518
8681
  // Overrides
8519
8682
  mode,
@@ -8538,7 +8701,7 @@ var PixodeskAnimatorReact = (() => {
8538
8701
  compMode = "imperativeApi" /* imperativeApi */;
8539
8702
  } else if (autoplay) {
8540
8703
  compMode = "autoplay" /* autoplay */;
8541
- } else if (time !== void 0 || timeMs !== void 0) {
8704
+ } else if (progress !== void 0 || time !== void 0) {
8542
8705
  compMode = "fixedTime" /* fixedTime */;
8543
8706
  } else if (play !== void 0 || pause !== void 0) {
8544
8707
  compMode = "play" /* play */;
@@ -8593,13 +8756,13 @@ var PixodeskAnimatorReact = (() => {
8593
8756
  let seekMs;
8594
8757
  if (compMode === "fixedTime" /* fixedTime */) {
8595
8758
  const animator = doc.animator || {};
8596
- if (time !== void 0) {
8759
+ if (progress !== void 0) {
8597
8760
  const iterationsValue = iterations ?? animator.iterations;
8598
8761
  const iterationsCount = typeof iterationsValue === "number" && iterationsValue >= 1 ? iterationsValue : 1;
8599
8762
  const singleDuration = duration ?? animator.duration ?? 1e3;
8600
- seekMs = time * singleDuration * iterationsCount;
8763
+ seekMs = progress * singleDuration * iterationsCount;
8601
8764
  }
8602
- if (timeMs !== void 0) seekMs = timeMs;
8765
+ if (time !== void 0) seekMs = time;
8603
8766
  }
8604
8767
  const apiHolderRef = (0, import_react2.useRef)(null);
8605
8768
  const callbacksRef = (0, import_react2.useRef)({});