@pixodesk/svg-animator-web 1.0.44 → 1.0.46

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.
@@ -77,19 +77,31 @@ var PixodeskAnimator = (() => {
77
77
  return result;
78
78
  }
79
79
  var Base = class {
80
+ /** Structural schemas (objects, arrays, unions of objects…) pass `false`: they state no scalar default. */
81
+ constructor(_statesDefault) {
82
+ this._statesDefault = _statesDefault;
83
+ }
80
84
  _canSanitize(raw) {
81
85
  return this.isValid(raw);
82
86
  }
87
+ /** A REQUIRED field is never absent; its default is the repair value. */
88
+ absentDefault() {
89
+ return this._default;
90
+ }
83
91
  optional() {
84
92
  return new Optional(this);
85
93
  }
86
94
  };
87
95
  var Optional = class extends Base {
88
96
  constructor(inner) {
89
- super();
97
+ super(inner._statesDefault);
90
98
  this.inner = inner;
91
99
  this._default = void 0;
92
100
  }
101
+ /** Absent means the inner schema's STATED default — or nothing at all when it states none. */
102
+ absentDefault() {
103
+ return this.inner._statesDefault ? this.inner._default : void 0;
104
+ }
93
105
  sanitize(raw) {
94
106
  if (raw === void 0 || raw === null) return void 0;
95
107
  return this.inner._canSanitize(raw) ? this.inner.sanitize(raw) : void 0;
@@ -103,8 +115,8 @@ var PixodeskAnimator = (() => {
103
115
  }
104
116
  };
105
117
  var Str = class extends Base {
106
- constructor(_default = "") {
107
- super();
118
+ constructor(_default, statesDefault) {
119
+ super(statesDefault);
108
120
  this._default = _default;
109
121
  }
110
122
  sanitize(raw) {
@@ -117,8 +129,8 @@ var PixodeskAnimator = (() => {
117
129
  }
118
130
  };
119
131
  var Num = class extends Base {
120
- constructor(_default = 0) {
121
- super();
132
+ constructor(_default, statesDefault) {
133
+ super(statesDefault);
122
134
  this._default = _default;
123
135
  }
124
136
  sanitize(raw) {
@@ -131,8 +143,8 @@ var PixodeskAnimator = (() => {
131
143
  }
132
144
  };
133
145
  var Bool = class extends Base {
134
- constructor(_default = false) {
135
- super();
146
+ constructor(_default, statesDefault) {
147
+ super(statesDefault);
136
148
  this._default = _default;
137
149
  }
138
150
  sanitize(raw) {
@@ -145,8 +157,9 @@ var PixodeskAnimator = (() => {
145
157
  }
146
158
  };
147
159
  var Literal = class extends Base {
160
+ /** A literal IS its own value: absent means it. */
148
161
  constructor(value) {
149
- super();
162
+ super(true);
150
163
  this.value = value;
151
164
  this._default = value;
152
165
  }
@@ -160,8 +173,8 @@ var PixodeskAnimator = (() => {
160
173
  }
161
174
  };
162
175
  var Enum = class extends Base {
163
- constructor(values, defaultVal) {
164
- super();
176
+ constructor(values, defaultVal, statesDefault) {
177
+ super(statesDefault);
165
178
  this.values = values;
166
179
  this._default = defaultVal != null ? defaultVal : values[0];
167
180
  }
@@ -176,8 +189,8 @@ var PixodeskAnimator = (() => {
176
189
  };
177
190
  var UNION_MEMBER_ERROR_LIMIT = 4;
178
191
  var Union = class extends Base {
179
- constructor(schemas, defaultVal) {
180
- super();
192
+ constructor(schemas, defaultVal, statesDefault) {
193
+ super(statesDefault);
181
194
  this.schemas = schemas;
182
195
  /** Structural tag read by {@link describeSchema} — `schemas` alone cannot tell Union from Tuple. */
183
196
  this._kind = "union";
@@ -231,7 +244,7 @@ var PixodeskAnimator = (() => {
231
244
  var DiscriminatedUnion = class extends Base {
232
245
  constructor(_key, _schemas, defaultVal) {
233
246
  var _a2;
234
- super();
247
+ super(false);
235
248
  this._key = _key;
236
249
  this._schemas = _schemas;
237
250
  /** Structural tag read by {@link describeSchema}. */
@@ -271,13 +284,19 @@ var PixodeskAnimator = (() => {
271
284
  return schema ? schema._canSanitize(raw) : this._schemas[0]._canSanitize(raw);
272
285
  }
273
286
  };
287
+ function statedDefaults(shape) {
288
+ const out = {};
289
+ for (const key of Object.keys(shape)) if (shape[key]._statesDefault) out[key] = shape[key].absentDefault();
290
+ return Object.freeze(out);
291
+ }
274
292
  var Obj = class extends Base {
275
293
  constructor(_shape) {
276
- super();
294
+ super(false);
277
295
  this._shape = _shape;
278
296
  const d = {};
279
297
  for (const key of Object.keys(_shape)) d[key] = _shape[key]._default;
280
298
  this._default = d;
299
+ this.defaults = statedDefaults(_shape);
281
300
  }
282
301
  sanitize(raw) {
283
302
  const src = raw && typeof raw === "object" && !Array.isArray(raw) ? raw : {};
@@ -319,12 +338,13 @@ var PixodeskAnimator = (() => {
319
338
  };
320
339
  var OpenObj = class extends Base {
321
340
  constructor(_shape, _openSchema) {
322
- super();
341
+ super(false);
323
342
  this._shape = _shape;
324
343
  this._openSchema = _openSchema;
325
344
  const d = {};
326
345
  for (const key of Object.keys(_shape)) d[key] = _shape[key]._default;
327
346
  this._default = d;
347
+ this.defaults = statedDefaults(_shape);
328
348
  }
329
349
  sanitize(raw) {
330
350
  const src = raw && typeof raw === "object" && !Array.isArray(raw) ? raw : {};
@@ -369,7 +389,7 @@ var PixodeskAnimator = (() => {
369
389
  };
370
390
  var Arr = class extends Base {
371
391
  constructor(item) {
372
- super();
392
+ super(false);
373
393
  this.item = item;
374
394
  this._default = [];
375
395
  }
@@ -401,7 +421,7 @@ var PixodeskAnimator = (() => {
401
421
  };
402
422
  var Rec = class extends Base {
403
423
  constructor(value) {
404
- super();
424
+ super(false);
405
425
  this.value = value;
406
426
  /** Structural tag read by {@link describeSchema}. */
407
427
  this._kind = "record";
@@ -435,7 +455,7 @@ var PixodeskAnimator = (() => {
435
455
  };
436
456
  var Any = class extends Base {
437
457
  constructor() {
438
- super(...arguments);
458
+ super(false);
439
459
  this._default = void 0;
440
460
  }
441
461
  sanitize(raw) {
@@ -450,7 +470,7 @@ var PixodeskAnimator = (() => {
450
470
  };
451
471
  var Defined = class extends Base {
452
472
  constructor() {
453
- super(...arguments);
473
+ super(false);
454
474
  this._default = void 0;
455
475
  }
456
476
  sanitize(raw) {
@@ -467,7 +487,7 @@ var PixodeskAnimator = (() => {
467
487
  };
468
488
  var Lazy = class extends Base {
469
489
  constructor(fn, _default) {
470
- super();
490
+ super(false);
471
491
  this.fn = fn;
472
492
  this._default = _default;
473
493
  this.resolved = null;
@@ -488,7 +508,7 @@ var PixodeskAnimator = (() => {
488
508
  };
489
509
  var Tuple = class extends Base {
490
510
  constructor(schemas) {
491
- super();
511
+ super(false);
492
512
  this.schemas = schemas;
493
513
  /** Structural tag read by {@link describeSchema} — `schemas` alone cannot tell Tuple from Union. */
494
514
  this._kind = "tuple";
@@ -520,22 +540,29 @@ var PixodeskAnimator = (() => {
520
540
  function implementsInterface() {
521
541
  return (schema) => schema;
522
542
  }
543
+ function string(defaultVal) {
544
+ return defaultVal === void 0 ? new Str("", false) : new Str(defaultVal, true);
545
+ }
546
+ function number(defaultVal) {
547
+ return defaultVal === void 0 ? new Num(0, false) : new Num(defaultVal, true);
548
+ }
549
+ function boolean(defaultVal) {
550
+ return defaultVal === void 0 ? new Bool(false, false) : new Bool(defaultVal, true);
551
+ }
552
+ function oneOf(values, defaultVal) {
553
+ return defaultVal === void 0 ? new Enum(values, void 0, false) : new Enum(values, defaultVal, true);
554
+ }
555
+ function unionOf(schemas, defaultVal) {
556
+ return defaultVal === void 0 ? new Union(schemas, void 0, false) : new Union(schemas, defaultVal, true);
557
+ }
523
558
  var px = {
524
- /** Matches a string. Default: '' or provided value. */
525
- string: (defaultVal = "") => new Str(defaultVal),
526
- /** Matches a finite number. Default: 0 or provided value. */
527
- number: (defaultVal = 0) => new Num(defaultVal),
528
- /** Matches a boolean. Default: false or provided value. */
529
- boolean: (defaultVal = false) => new Bool(defaultVal),
530
- /** Matches one exact primitive value; its default is the value itself. */
559
+ string,
560
+ number,
561
+ boolean,
562
+ /** Matches one exact primitive value; absent means the value itself. */
531
563
  literal: (value) => new Literal(value),
532
- /** Matches one of a fixed set of string/number values. Default: first value. */
533
- enum: (values, defaultVal) => new Enum(values, defaultVal),
534
- /**
535
- * Returns the first schema whose isValid passes.
536
- * TypeScript infers the union of all member types automatically.
537
- */
538
- union: (schemas, defaultVal) => new Union(schemas, defaultVal),
564
+ enum: oneOf,
565
+ union: unionOf,
539
566
  /**
540
567
  * Discriminated union — reads `raw[key]`, finds the member schema whose
541
568
  * literal at `key` matches, then delegates sanitize/isValid to that member.
@@ -543,7 +570,8 @@ var PixodeskAnimator = (() => {
543
570
  * TypeScript infers the union of all member types automatically.
544
571
  */
545
572
  discriminatedUnion: (key, schemas) => new DiscriminatedUnion(key, schemas),
546
- /** Typed object — unknown keys are stripped. Required fields fall back to their default. */
573
+ /** Typed object — unknown keys are stripped. Required fields fall back to their default.
574
+ * Its `defaults` say what each stated field means when a document leaves it out. */
547
575
  object: (shape) => new Obj(shape),
548
576
  /**
549
577
  * Open object — validates known keys; passes unknown keys through as-is,
@@ -684,8 +712,11 @@ var PixodeskAnimator = (() => {
684
712
  offScreen: "pause",
685
713
  mouseOut: "continue",
686
714
  visibilityThreshold: 0.5,
687
- visibilityDebounce: 150
715
+ visibilityDebounce: 150,
716
+ finish: "hold"
688
717
  };
718
+ var PX_DEFAULT_DURATION_MS = 1e3;
719
+ var PX_DEFAULT_ITERATIONS = 1;
689
720
  function resolveTrigger(trigger) {
690
721
  var _a2, _b, _c, _d, _e;
691
722
  return {
@@ -900,15 +931,15 @@ var PixodeskAnimator = (() => {
900
931
  var keyframeTangentOut = (kf) => anyKf(kf).tangentOut;
901
932
  var PxLoopSchema = implementsInterface()(px.object({
902
933
  segmentCount: px.number().optional(),
903
- repeatAt: px.enum([PxLoopRepeatAt.start, PxLoopRepeatAt.end]).optional(),
904
- direction: px.enum([PxLoopDirection.normal, PxLoopDirection.alternate]).optional()
934
+ repeatAt: px.enum([PxLoopRepeatAt.start, PxLoopRepeatAt.end], PxLoopRepeatAt.end).optional(),
935
+ direction: px.enum([PxLoopDirection.normal, PxLoopDirection.alternate], PxLoopDirection.normal).optional()
905
936
  }));
906
937
  var PxPropertyAnimationSchema = implementsInterface()(px.object({
907
938
  value: PxKeyframeValueSchema.optional(),
908
939
  keyframes: px.array(PxKeyframeSchema).optional(),
909
940
  loop: px.union([PxLoopSchema, px.boolean()]).optional(),
910
941
  autoOrient: px.boolean().optional(),
911
- alongPathMode: px.enum([PxAlongPathMode.sampled, PxAlongPathMode.offsetPath]).optional()
942
+ alongPathMode: px.enum([PxAlongPathMode.sampled, PxAlongPathMode.offsetPath], PxAlongPathMode.sampled).optional()
912
943
  }));
913
944
  var PxTransformPartsSchema = implementsInterface()(px.object({
914
945
  translate: px.tuple([px.number(), px.number()]).optional(),
@@ -938,9 +969,9 @@ var PixodeskAnimator = (() => {
938
969
  // What happens after a NATURAL finish — `'hold'` (default: keep the end state per
939
970
  // `fill`) or `'reset'` (snap back to the start state). One of four occasion keys
940
971
  // (`start`, `offScreen`, `mouseOut`, `finish`), all named the same way.
941
- finish: px.enum([PxFinishAction.hold, PxFinishAction.reset]).optional(),
942
- visibilityThreshold: px.number().optional(),
943
- visibilityDebounce: px.number().optional()
972
+ finish: px.enum([PxFinishAction.hold, PxFinishAction.reset], PX_TRIGGER_DEFAULTS.finish).optional(),
973
+ visibilityThreshold: px.number(PX_TRIGGER_DEFAULTS.visibilityThreshold).optional(),
974
+ visibilityDebounce: px.number(PX_TRIGGER_DEFAULTS.visibilityDebounce).optional()
944
975
  }));
945
976
  var PxGlyphSchema = implementsInterface()(px.object({
946
977
  width: px.number(),
@@ -966,7 +997,7 @@ var PixodeskAnimator = (() => {
966
997
  PxScrollPhase.exit,
967
998
  PxScrollPhase.entryCrossing,
968
999
  PxScrollPhase.exitCrossing
969
- ]).optional(),
1000
+ ], PxScrollPhase.cover).optional(),
970
1001
  fraction: px.number().optional()
971
1002
  }));
972
1003
  var PxScrollRangeSchema = px.object({
@@ -974,37 +1005,37 @@ var PixodeskAnimator = (() => {
974
1005
  end: PxScrollRangePointSchema.optional()
975
1006
  });
976
1007
  var PxScrollSchema = implementsInterface()(px.object({
977
- kind: px.enum([PxScrollKind.view, PxScrollKind.scroll]).optional(),
978
- axis: px.enum([PxScrollAxis.block, PxScrollAxis.inline, PxScrollAxis.x, PxScrollAxis.y]).optional(),
979
- source: px.enum([PxScrollSource.nearest, PxScrollSource.root]).optional(),
1008
+ kind: px.enum([PxScrollKind.view, PxScrollKind.scroll], PxScrollKind.view).optional(),
1009
+ axis: px.enum([PxScrollAxis.block, PxScrollAxis.inline, PxScrollAxis.x, PxScrollAxis.y], PxScrollAxis.block).optional(),
1010
+ source: px.enum([PxScrollSource.nearest, PxScrollSource.root], PxScrollSource.nearest).optional(),
980
1011
  // Free-form: the two keywords `parent`/`scroller` plus any CSS selector.
981
1012
  subject: px.string().optional(),
982
1013
  smoothing: px.number().optional(),
983
- pin: px.boolean().optional(),
984
- pinAlign: px.enum([PxPinAlign.top, PxPinAlign.center, PxPinAlign.bottom]).optional(),
1014
+ pin: px.boolean(false).optional(),
1015
+ pinAlign: px.enum([PxPinAlign.top, PxPinAlign.center, PxPinAlign.bottom], PxPinAlign.top).optional(),
985
1016
  pinOffset: px.number().optional(),
986
1017
  pinDistance: px.number().optional(),
987
1018
  range: PxScrollRangeSchema.optional()
988
1019
  }));
989
1020
  var PxTimelinePinSchema = implementsInterface()(px.object({
990
- align: px.enum([PxPinAlign.top, PxPinAlign.center, PxPinAlign.bottom]).optional(),
1021
+ align: px.enum([PxPinAlign.top, PxPinAlign.center, PxPinAlign.bottom], PxPinAlign.top).optional(),
991
1022
  offset: px.number().optional(),
992
1023
  distance: px.number().optional()
993
1024
  }));
994
- var PxTimelineEngineSchema = px.enum([PxTimelineEngineSetting.auto, PxTimelineEngineSetting.native, PxTimelineEngineSetting.js]).optional();
1025
+ var PxTimelineEngineSchema = px.enum([PxTimelineEngineSetting.auto, PxTimelineEngineSetting.native, PxTimelineEngineSetting.js], PxTimelineEngineSetting.auto).optional();
995
1026
  var PxTimeTimelineSchema = implementsInterface()(px.object({
996
1027
  type: px.literal("time").optional(),
997
1028
  engine: PxTimelineEngineSchema,
998
1029
  frameRate: px.number().optional(),
999
1030
  // §2.8: duration is a property of the TIMELINE — how long one pass takes.
1000
- duration: px.number().optional(),
1031
+ duration: px.number(PX_DEFAULT_DURATION_MS).optional(),
1001
1032
  trigger: PxTriggerSchema.optional(),
1002
- delay: px.number().optional(),
1003
- iterations: px.union([px.number(), px.literal("infinite")]).optional(),
1033
+ delay: px.number(0).optional(),
1034
+ iterations: px.union([px.number(PX_DEFAULT_ITERATIONS), px.literal("infinite")], PX_DEFAULT_ITERATIONS).optional(),
1004
1035
  // `fillMode` on the wire (CSS `animation-fill-mode`; the runtime view calls it `fill`)
1005
1036
  // — never `fill`, which is paint everywhere else in the format.
1006
- fillMode: px.enum([PxFillMode.forwards, PxFillMode.backwards, PxFillMode.both, PxFillMode.none]).optional(),
1007
- direction: px.enum([PxPlaybackDirection.normal, PxPlaybackDirection.reverse, PxPlaybackDirection.alternate, PxPlaybackDirection.alternateReverse]).optional()
1037
+ fillMode: px.enum([PxFillMode.forwards, PxFillMode.backwards, PxFillMode.both, PxFillMode.none], PxFillMode.forwards).optional(),
1038
+ direction: px.enum([PxPlaybackDirection.normal, PxPlaybackDirection.reverse, PxPlaybackDirection.alternate, PxPlaybackDirection.alternateReverse], PxPlaybackDirection.normal).optional()
1008
1039
  }));
1009
1040
  var scrollishTimelineShape = {
1010
1041
  // §2.8: duration is a property of the TIMELINE — under scrubbing it is the keyframe
@@ -1015,8 +1046,8 @@ var PixodeskAnimator = (() => {
1015
1046
  iterations: px.number().optional(),
1016
1047
  engine: PxTimelineEngineSchema,
1017
1048
  frameRate: px.number().optional(),
1018
- axis: px.enum([PxScrollAxis.block, PxScrollAxis.inline, PxScrollAxis.x, PxScrollAxis.y]).optional(),
1019
- source: px.enum([PxScrollSource.nearest, PxScrollSource.root]).optional(),
1049
+ axis: px.enum([PxScrollAxis.block, PxScrollAxis.inline, PxScrollAxis.x, PxScrollAxis.y], PxScrollAxis.block).optional(),
1050
+ source: px.enum([PxScrollSource.nearest, PxScrollSource.root], PxScrollSource.nearest).optional(),
1020
1051
  subject: px.string().optional(),
1021
1052
  // 'parent' | 'scroller' | any CSS selector
1022
1053
  smoothing: px.number().optional(),
@@ -1096,9 +1127,10 @@ var PixodeskAnimator = (() => {
1096
1127
  }));
1097
1128
  var PxMaskedByEffectSchema = implementsInterface()(px.object({
1098
1129
  source: px.string().optional(),
1099
- maskType: px.enum([PxMaskType.luminance, PxMaskType.alpha]).optional(),
1100
- maskUnits: px.enum([PxUnits.userSpaceOnUse, PxUnits.objectBoundingBox]).optional(),
1101
- maskContentUnits: px.enum([PxUnits.userSpaceOnUse, PxUnits.objectBoundingBox]).optional(),
1130
+ // SVG's own initial values — what a <mask> does when the attribute is not there.
1131
+ maskType: px.enum([PxMaskType.luminance, PxMaskType.alpha], PxMaskType.luminance).optional(),
1132
+ maskUnits: px.enum([PxUnits.userSpaceOnUse, PxUnits.objectBoundingBox], PxUnits.objectBoundingBox).optional(),
1133
+ maskContentUnits: px.enum([PxUnits.userSpaceOnUse, PxUnits.objectBoundingBox], PxUnits.userSpaceOnUse).optional(),
1102
1134
  x: px.number().optional(),
1103
1135
  y: px.number().optional(),
1104
1136
  width: px.number().optional(),
@@ -1110,7 +1142,7 @@ var PixodeskAnimator = (() => {
1110
1142
  var PxStrokeTrimEffectSchema = implementsInterface()(px.object({
1111
1143
  offset: PxAnimatableNumberSchema.optional(),
1112
1144
  range: PxAnimatableVec2Schema.optional(),
1113
- subPaths: px.enum([PxStrokeTrimSubPaths.separate, PxStrokeTrimSubPaths.combined]).optional()
1145
+ subPaths: px.enum([PxStrokeTrimSubPaths.separate, PxStrokeTrimSubPaths.combined], PxStrokeTrimSubPaths.separate).optional()
1114
1146
  }));
1115
1147
  var PxRetimeEffectSchema = implementsInterface()(px.object({
1116
1148
  start: px.number().optional(),
@@ -1142,17 +1174,20 @@ var PixodeskAnimator = (() => {
1142
1174
  radius: PxAnimatableNumberSchema.optional(),
1143
1175
  focal: PxAnimatableVec2Schema.optional(),
1144
1176
  stops: PxAnimatableGradientStopsSchema.optional(),
1145
- gradientUnits: px.enum([PxUnits.userSpaceOnUse, PxUnits.objectBoundingBox]).optional(),
1146
- spreadMethod: px.enum([PxGradientSpreadMethod.pad, PxGradientSpreadMethod.reflect, PxGradientSpreadMethod.repeat]).optional(),
1177
+ // SVG's own initial values — what a gradient does when the attribute is not there.
1178
+ gradientUnits: px.enum([PxUnits.userSpaceOnUse, PxUnits.objectBoundingBox], PxUnits.objectBoundingBox).optional(),
1179
+ spreadMethod: px.enum([PxGradientSpreadMethod.pad, PxGradientSpreadMethod.reflect, PxGradientSpreadMethod.repeat], PxGradientSpreadMethod.pad).optional(),
1147
1180
  gradientTransform: px.string().optional()
1148
1181
  }));
1149
1182
  var PxStrokeGradientEffectSchema = PxFillGradientEffectSchema;
1150
1183
  var PxTextPathEffectSchema = implementsInterface()(px.object({
1151
1184
  pathData: px.string(),
1152
- pathOverflow: px.enum([PxPathOverflow.clip, PxPathOverflow.extend]).optional(),
1153
- lengthAdjust: px.enum([PxLengthAdjust.spacing, PxLengthAdjust.spacingAndGlyphs]).optional(),
1154
- method: px.enum([PxTextPathMethod.align, PxTextPathMethod.stretch]).optional(),
1155
- spacing: px.enum([PxTextPathSpacing.auto, PxTextPathSpacing.exact]).optional(),
1185
+ // `extend` is what an omitted pathOverflow means (glyphs continue along the tangent); the
1186
+ // other three are SVG's own initial values for the native <textPath> attributes.
1187
+ pathOverflow: px.enum([PxPathOverflow.clip, PxPathOverflow.extend], PxPathOverflow.extend).optional(),
1188
+ lengthAdjust: px.enum([PxLengthAdjust.spacing, PxLengthAdjust.spacingAndGlyphs], PxLengthAdjust.spacing).optional(),
1189
+ method: px.enum([PxTextPathMethod.align, PxTextPathMethod.stretch], PxTextPathMethod.align).optional(),
1190
+ spacing: px.enum([PxTextPathSpacing.auto, PxTextPathSpacing.exact], PxTextPathSpacing.exact).optional(),
1156
1191
  startOffset: PxAnimatableNumberSchema.optional(),
1157
1192
  textLength: PxAnimatableNumberSchema.optional()
1158
1193
  }));
@@ -1716,7 +1751,6 @@ var PixodeskAnimator = (() => {
1716
1751
  return Object.keys(out).length ? out : void 0;
1717
1752
  }
1718
1753
  var PX_STYLE_ATTR_NAMES = /* @__PURE__ */ new Set(["offset-distance", "offsetDistance"]);
1719
- var PX_DEFAULT_DURATION_MS = 1e3;
1720
1754
  function kebabToCamelCaseWord(kebab) {
1721
1755
  return kebab.includes("-") ? kebab.replace(/-([a-z])/g, (_, letter) => letter.toUpperCase()) : kebab;
1722
1756
  }
@@ -1969,6 +2003,38 @@ var PixodeskAnimator = (() => {
1969
2003
  return propsCopy;
1970
2004
  }
1971
2005
 
2006
+ // ../svg-animator-core/src/animation/PxStaticTransformMerge.ts
2007
+ function mergeStaticTransformIntoAnimDef(animDef, staticTransform) {
2008
+ if (!animDef) return animDef;
2009
+ const staticParts = staticTransform && typeof staticTransform === "object" && !Array.isArray(staticTransform) ? staticTransform : parseTransformParts(staticTransform);
2010
+ if (!staticParts || !Object.keys(staticParts).length) return animDef;
2011
+ const mergeKfValue = (v) => v && typeof v === "object" && !Array.isArray(v) ? __spreadValues(__spreadValues({}, staticParts), v) : v;
2012
+ const transformAnim = animDef[TRANSFORM_ATTR];
2013
+ if (transformAnim && typeof transformAnim === "object") {
2014
+ const anim = transformAnim;
2015
+ if (Array.isArray(anim.keyframes)) {
2016
+ const out = __spreadProps(__spreadValues({}, anim), {
2017
+ keyframes: anim.keyframes.map((kf) => __spreadProps(__spreadValues({}, kf), { value: mergeKfValue(kf.value) }))
2018
+ });
2019
+ if (out.value !== void 0) out.value = mergeKfValue(out.value);
2020
+ return __spreadProps(__spreadValues({}, animDef), { transform: out });
2021
+ }
2022
+ return animDef;
2023
+ }
2024
+ const channels = Object.keys(animDef).filter((k) => PX_TRANSFORM_FN_NAMES.has(k));
2025
+ if (channels.length !== 1) return animDef;
2026
+ const ch = channels[0];
2027
+ const chAnim = animDef[ch];
2028
+ if (!chAnim || typeof chAnim !== "object" || !Array.isArray(chAnim.keyframes)) return animDef;
2029
+ const lifted = __spreadProps(__spreadValues({}, chAnim), {
2030
+ keyframes: chAnim.keyframes.map((kf) => __spreadProps(__spreadValues({}, kf), { value: __spreadProps(__spreadValues({}, staticParts), { [ch]: kf.value }) }))
2031
+ });
2032
+ if (lifted.value !== void 0) lifted.value = __spreadProps(__spreadValues({}, staticParts), { [ch]: lifted.value });
2033
+ const rest = __spreadValues({}, animDef);
2034
+ delete rest[ch];
2035
+ return __spreadProps(__spreadValues({}, rest), { transform: lifted });
2036
+ }
2037
+
1972
2038
  // ../svg-animator-core/src/materialize/PxMotionPath.ts
1973
2039
  function getKfTranslate(kf) {
1974
2040
  const v = keyframeValue(kf);
@@ -2338,7 +2404,7 @@ var PixodeskAnimator = (() => {
2338
2404
  let newAnimate;
2339
2405
  const animBucket = node.animate;
2340
2406
  if (animBucket && typeof animBucket === "object" && !Array.isArray(animBucket)) {
2341
- const animDef = animBucket;
2407
+ const animDef = mergeStaticTransformIntoAnimDef(animBucket, node.transform);
2342
2408
  const transformAnim = animDef.transform;
2343
2409
  if (transformAnim && typeof transformAnim === "object" && propAnimIsMotionPath(transformAnim)) {
2344
2410
  const materialized = materializeMotionPathInPropAnim(transformAnim, opts);
@@ -2852,36 +2918,6 @@ var PixodeskAnimator = (() => {
2852
2918
  function generateElementId() {
2853
2919
  return "_px_el_" + ++_elementIdCounter;
2854
2920
  }
2855
- function mergeStaticTransformIntoAnimDef(animDef, staticTransform) {
2856
- if (!animDef) return animDef;
2857
- const staticParts = staticTransform && typeof staticTransform === "object" && !Array.isArray(staticTransform) ? staticTransform : parseTransformParts(staticTransform);
2858
- if (!staticParts || !Object.keys(staticParts).length) return animDef;
2859
- const mergeKfValue = (v) => v && typeof v === "object" && !Array.isArray(v) ? __spreadValues(__spreadValues({}, staticParts), v) : v;
2860
- const transformAnim = animDef[TRANSFORM_ATTR];
2861
- if (transformAnim && typeof transformAnim === "object") {
2862
- const anim = transformAnim;
2863
- if (Array.isArray(anim.keyframes)) {
2864
- const out = __spreadProps(__spreadValues({}, anim), {
2865
- keyframes: anim.keyframes.map((kf) => __spreadProps(__spreadValues({}, kf), { value: mergeKfValue(kf.value) }))
2866
- });
2867
- if (out.value !== void 0) out.value = mergeKfValue(out.value);
2868
- return __spreadProps(__spreadValues({}, animDef), { transform: out });
2869
- }
2870
- return animDef;
2871
- }
2872
- const channels = Object.keys(animDef).filter((k) => PX_TRANSFORM_FN_NAMES.has(k));
2873
- if (channels.length !== 1) return animDef;
2874
- const ch = channels[0];
2875
- const chAnim = animDef[ch];
2876
- if (!chAnim || typeof chAnim !== "object" || !Array.isArray(chAnim.keyframes)) return animDef;
2877
- const lifted = __spreadProps(__spreadValues({}, chAnim), {
2878
- keyframes: chAnim.keyframes.map((kf) => __spreadProps(__spreadValues({}, kf), { value: __spreadProps(__spreadValues({}, staticParts), { [ch]: kf.value }) }))
2879
- });
2880
- if (lifted.value !== void 0) lifted.value = __spreadProps(__spreadValues({}, staticParts), { [ch]: lifted.value });
2881
- const rest = __spreadValues({}, animDef);
2882
- delete rest[ch];
2883
- return __spreadProps(__spreadValues({}, rest), { transform: lifted });
2884
- }
2885
2921
  function normalizeAnimationDefinition(animDef, duration, defs, engine = PxTimelineEngine.native) {
2886
2922
  const normalized = {};
2887
2923
  for (const [propName, propAnim] of Object.entries(animDef)) {
@@ -2964,7 +3000,7 @@ var PixodeskAnimator = (() => {
2964
3000
  return { prevKf, nextKf };
2965
3001
  }
2966
3002
  function calcPropertyValue(propName, propAnim, progress) {
2967
- var _a2, _b, _c, _d;
3003
+ var _a2, _b, _c, _d, _e;
2968
3004
  const keyframes = propAnim.keyframes || [];
2969
3005
  if (keyframes.length === 0) return null;
2970
3006
  const { prevKf, nextKf } = getKeyframesPair(keyframes, progress);
@@ -3033,7 +3069,7 @@ var PixodeskAnimator = (() => {
3033
3069
  !!propAnim.autoOrient
3034
3070
  );
3035
3071
  partsResult.translate = [sample.translate[0], sample.translate[1]];
3036
- if (sample.rotateDeg !== void 0) partsResult.rotate = sample.rotateDeg;
3072
+ if (sample.rotateDeg !== void 0) partsResult.rotate = sample.rotateDeg + ((_e = partsResult.rotate) != null ? _e : 0);
3037
3073
  }
3038
3074
  }
3039
3075
  cssValue = composeTransformParts(partsResult, { withUnits: false });
@@ -5516,12 +5552,17 @@ var PixodeskAnimator = (() => {
5516
5552
  const first = keyframeValue(kfs[0]);
5517
5553
  const anchor = (first == null ? void 0 : first.origin) && first.origin.length >= 2 ? [first.origin[0], first.origin[1]] : [0, 0];
5518
5554
  const points = [];
5555
+ let keyframesCarryRotate = false;
5519
5556
  for (const kf of kfs) {
5520
5557
  const v = keyframeValue(kf);
5521
5558
  const tr = v == null ? void 0 : v.translate;
5522
5559
  if (!tr || tr.length < 2) return void 0;
5523
5560
  const parts = Object.keys(v);
5524
- if (parts.some((p) => p !== "translate" && p !== "origin")) return void 0;
5561
+ if (parts.some((p) => p !== TRANSFORM_PART.translate && p !== TRANSFORM_PART.origin && p !== TRANSFORM_PART.rotate)) return void 0;
5562
+ if ((v == null ? void 0 : v.rotate) !== void 0) {
5563
+ if (v.rotate !== 0) return void 0;
5564
+ keyframesCarryRotate = true;
5565
+ }
5525
5566
  const o = (_a2 = v == null ? void 0 : v.origin) != null ? _a2 : [0, 0];
5526
5567
  if (o[0] !== anchor[0] || o[1] !== anchor[1]) return void 0;
5527
5568
  points.push([tr[0] + anchor[0], tr[1] + anchor[1]]);
@@ -5549,7 +5590,7 @@ var PixodeskAnimator = (() => {
5549
5590
  if (e !== void 0) out.e = e;
5550
5591
  distanceKfs.push(out);
5551
5592
  }
5552
- return { pathStr: d, distanceKfs, autoOrient: !!propAnim.autoOrient, anchor };
5593
+ return { pathStr: d, distanceKfs, autoOrient: !!propAnim.autoOrient, anchor, keyframesCarryRotate };
5553
5594
  }
5554
5595
  function materializeOffsetPathsInTree(root) {
5555
5596
  const walk = (node) => {
@@ -5571,6 +5612,7 @@ var PixodeskAnimator = (() => {
5571
5612
  const t = __spreadValues({}, staticTr);
5572
5613
  delete t[TRANSFORM_PART.translate];
5573
5614
  delete t[TRANSFORM_PART.origin];
5615
+ if (built.keyframesCarryRotate) delete t[TRANSFORM_PART.rotate];
5574
5616
  newTransform = Object.keys(t).length ? t : void 0;
5575
5617
  }
5576
5618
  out = __spreadProps(__spreadValues({}, node), {
@@ -5743,6 +5785,103 @@ var PixodeskAnimator = (() => {
5743
5785
  return changed ? __spreadProps(__spreadValues({}, node), { children: newChildren }) : node;
5744
5786
  }
5745
5787
 
5788
+ // ../svg-animator-core/src/materialize/PxRestPose.ts
5789
+ var TRANSFORM_CHANNEL = "transform";
5790
+ var REVERSED_DIRECTIONS = /* @__PURE__ */ new Set(["reverse", "alternate-reverse"]);
5791
+ var VERIFY_SAMPLE_FRACTIONS = [0, 0.25, 0.5, 0.75, 1];
5792
+ var SCRATCH_ID_PREFIX = "__px_rest_";
5793
+ function materializeRestPosesInTree(root, engine) {
5794
+ var _a2, _b;
5795
+ const out = deepClone(root);
5796
+ const config = getAnimatorConfig(out) || {};
5797
+ const duration = +(config.duration || PX_DEFAULT_DURATION_MS);
5798
+ const firstFrameTime = REVERSED_DIRECTIONS.has(String(config.direction)) ? duration : 0;
5799
+ const nodes = animatedNodes(out);
5800
+ if (!nodes.size) return out;
5801
+ const before = bindingsOf(out, engine);
5802
+ const added = /* @__PURE__ */ new Map();
5803
+ for (const [key, animate] of before) {
5804
+ const node = nodes.get(key);
5805
+ if (!node) continue;
5806
+ const channels = Object.keys(animate);
5807
+ for (const channel of channels) {
5808
+ if (PX_TRANSFORM_FN_NAMES.has(channel)) continue;
5809
+ if (!mayCarryRestPose(node, channel)) continue;
5810
+ const value = firstFrameValue(animate, channel, firstFrameTime);
5811
+ if (value === void 0) continue;
5812
+ node[channel] = value;
5813
+ added.set(key, [...(_a2 = added.get(key)) != null ? _a2 : [], channel]);
5814
+ }
5815
+ if (channels.some((channel) => PX_TRANSFORM_FN_NAMES.has(channel)) && mayCarryTransformRestPose(node)) {
5816
+ const parts = firstFrameTransformParts(animate, firstFrameTime);
5817
+ if (parts) {
5818
+ node[TRANSFORM_CHANNEL] = parts;
5819
+ added.set(key, [...(_b = added.get(key)) != null ? _b : [], TRANSFORM_CHANNEL]);
5820
+ }
5821
+ }
5822
+ }
5823
+ if (added.size) {
5824
+ const after = bindingsOf(out, engine);
5825
+ for (const [key, channels] of added) {
5826
+ if (writesTheSameFrames(before.get(key), after.get(key), duration)) continue;
5827
+ const node = nodes.get(key);
5828
+ if (node) for (const channel of channels) delete node[channel];
5829
+ }
5830
+ }
5831
+ return out;
5832
+ }
5833
+ function mayCarryRestPose(node, channel) {
5834
+ if (node[channel] !== void 0) return false;
5835
+ if (channel === TRANSFORM_CHANNEL) return mayCarryTransformRestPose(node);
5836
+ return true;
5837
+ }
5838
+ function mayCarryTransformRestPose(node) {
5839
+ if (node[TRANSFORM_CHANNEL] !== void 0) return false;
5840
+ for (const part of PX_TRANSFORM_FN_NAMES) if (node[part] !== void 0) return false;
5841
+ return true;
5842
+ }
5843
+ function firstFrameValue(animate, channel, timeMs) {
5844
+ const values = Object.values(calcAnimationValues({ [channel]: animate[channel] }, timeMs));
5845
+ return values.length === 1 && values[0] !== "" ? values[0] : void 0;
5846
+ }
5847
+ function firstFrameTransformParts(animate, timeMs) {
5848
+ const family = {};
5849
+ for (const channel of Object.keys(animate)) if (PX_TRANSFORM_FN_NAMES.has(channel)) family[channel] = animate[channel];
5850
+ const written = calcAnimationValues(family, timeMs)[TRANSFORM_CHANNEL];
5851
+ if (!written) return void 0;
5852
+ const parts = parseTransformParts(written.replace(/(px|deg)\b/g, ""));
5853
+ return parts && Object.keys(parts).length ? parts : void 0;
5854
+ }
5855
+ function writesTheSameFrames(a, b, durationMs) {
5856
+ if (!a || !b) return a === b;
5857
+ const frame = (animate, t) => JSON.stringify(calcAnimationValues(animate, t)).replace(/\s+/g, "");
5858
+ return VERIFY_SAMPLE_FRACTIONS.every((fraction) => frame(a, fraction * durationMs) === frame(b, fraction * durationMs));
5859
+ }
5860
+ function bindingsOf(tree, engine) {
5861
+ const scratch = deepClone(tree);
5862
+ const keyById = /* @__PURE__ */ new Map();
5863
+ for (const [key, node] of animatedNodes(scratch)) {
5864
+ if (node.id === void 0) node.id = SCRATCH_ID_PREFIX + key;
5865
+ keyById.set(String(node.id), key);
5866
+ }
5867
+ const out = /* @__PURE__ */ new Map();
5868
+ for (const binding of normalizeBindings(scratch, engine)) {
5869
+ const key = keyById.get(binding.id);
5870
+ if (key !== void 0) out.set(key, binding.animate);
5871
+ }
5872
+ return out;
5873
+ }
5874
+ function animatedNodes(tree) {
5875
+ const out = /* @__PURE__ */ new Map();
5876
+ let counter = 0;
5877
+ const visit = (node) => {
5878
+ if (node.animate) out.set(String(counter++), node);
5879
+ if (node.children) for (const child of node.children) visit(child);
5880
+ };
5881
+ if (tree.children) for (const child of tree.children) visit(child);
5882
+ return out;
5883
+ }
5884
+
5746
5885
  // ../svg-animator-core/src/materialize/PxAnimatorMaterializeAll.ts
5747
5886
  function materializeAllInTree(doc, engine, options) {
5748
5887
  var _a2, _b;
@@ -5755,6 +5894,7 @@ var PixodeskAnimator = (() => {
5755
5894
  root = materializeAnimatedUseInstances(root);
5756
5895
  root = pruneUnreferencedDefs(root);
5757
5896
  }
5897
+ root = materializeRestPosesInTree(root, engine);
5758
5898
  return root;
5759
5899
  }
5760
5900
  function pruneUnreferencedDefs(root) {
@@ -5841,13 +5981,13 @@ var PixodeskAnimator = (() => {
5841
5981
  const bindings = normalizeBindings(doc, PxTimelineEngine.js);
5842
5982
  const _iterations = config.iterations;
5843
5983
  let iterations = 1;
5844
- if (typeof _iterations === "number") iterations = _iterations || 1;
5984
+ if (typeof _iterations === "number") iterations = _iterations || PX_DEFAULT_ITERATIONS;
5845
5985
  if (_iterations === "infinite") iterations = Infinity;
5846
5986
  if (iterations < 1) iterations = 1;
5847
5987
  const duration = +(config.duration || PX_DEFAULT_DURATION_MS);
5848
- const totalDuration = duration && iterations ? duration * (iterations === Infinity ? Infinity : iterations) : duration ? (iterations != null ? iterations : 1) * duration : 0;
5849
- const direction = config.direction || "normal";
5850
- const fill = (_a2 = config.fill) != null ? _a2 : "forwards";
5988
+ const totalDuration = duration && iterations ? duration * (iterations === Infinity ? Infinity : iterations) : duration ? (iterations != null ? iterations : PX_DEFAULT_ITERATIONS) * duration : 0;
5989
+ const direction = config.direction || PxTimeTimelineSchema.defaults.direction;
5990
+ const fill = (_a2 = config.fill) != null ? _a2 : PxTimeTimelineSchema.defaults.fillMode;
5851
5991
  const fillsForwards = fill === "forwards" || fill === "both";
5852
5992
  const fillsBackwards = fill === "backwards" || fill === "both";
5853
5993
  let timerId = null;
@@ -6318,6 +6458,52 @@ var PixodeskAnimator = (() => {
6318
6458
  );
6319
6459
  }
6320
6460
 
6461
+ // ../svg-animator-core/src/render/PxRenderTree.ts
6462
+ var CLASS_NAME_KEY = "className";
6463
+ var CLASS_ATTR2 = "class";
6464
+ var DOM_TYPE_KEY = "domType";
6465
+ var TYPE_ATTR = "type";
6466
+ var DEFAULT_TAG = "g";
6467
+ function renderPxTree(node, factory, diag) {
6468
+ return node ? renderOne(node, factory, diag, true, 0) : null;
6469
+ }
6470
+ function renderOne(node, factory, diag, isRoot, index) {
6471
+ const _a2 = node, { type, children, style } = _a2, props = __objRest(_a2, ["type", "children", "style"]);
6472
+ const tag = type || DEFAULT_TAG;
6473
+ if (PX_DISALLOWED_SVG_TAGS_LOWER.has(tag.toLowerCase())) {
6474
+ (diag != null ? diag : createDiagnostics(void 0, "[PxAnimator]")).warn(PxDiagnosticKind.document, 1103 /* blockedTag */, tag);
6475
+ return null;
6476
+ }
6477
+ const domType = props[DOM_TYPE_KEY];
6478
+ if (domType !== void 0) delete props[DOM_TYPE_KEY];
6479
+ const attrs = {};
6480
+ let inlineStyle;
6481
+ const domProps = toDomProps(props);
6482
+ for (const propName of Object.keys(domProps)) {
6483
+ const sanitized = sanitizeAttributeValue(propName, domProps[propName]);
6484
+ if (sanitized === void 0) continue;
6485
+ if (PX_CSS_ONLY_STYLE_PROPS.has(propName)) {
6486
+ (inlineStyle != null ? inlineStyle : inlineStyle = {})[propName] = String(sanitized);
6487
+ continue;
6488
+ }
6489
+ attrs[propName === CLASS_NAME_KEY ? CLASS_ATTR2 : camelCaseToKebabWordIfNeeded(propName)] = sanitized;
6490
+ }
6491
+ if (domType !== void 0) attrs[TYPE_ATTR] = String(domType);
6492
+ if (style) {
6493
+ for (const styleProp of Object.keys(style)) (inlineStyle != null ? inlineStyle : inlineStyle = {})[styleProp] = String(style[styleProp]);
6494
+ }
6495
+ const rendered = [];
6496
+ if (children) {
6497
+ children.forEach((child, i) => {
6498
+ const el = renderOne(child, factory, diag, false, i);
6499
+ if (el !== null) rendered.push(el);
6500
+ });
6501
+ }
6502
+ const ownText = props[PX_TEXT_CONTENT_ATTR];
6503
+ const text = !rendered.length && typeof ownText === "string" && ownText ? ownText : void 0;
6504
+ return factory({ tag, attrs, style: inlineStyle, children: rendered, text, node, isRoot, index });
6505
+ }
6506
+
6321
6507
  // ../svg-animator-core/src/playback/PxScrollMath.ts
6322
6508
  function isScrollTimeline(config) {
6323
6509
  return (config == null ? void 0 : config.timelineSource) === "scroll";
@@ -6890,7 +7076,7 @@ var PixodeskAnimator = (() => {
6890
7076
  let seekPosition;
6891
7077
  if (config.delay && config.delay < 0 && config.duration) {
6892
7078
  const rawSeek = -config.delay;
6893
- seekPosition = iterations === Infinity ? rawSeek % config.duration : Math.min(rawSeek, config.duration * (iterations != null ? iterations : 1));
7079
+ seekPosition = iterations === Infinity ? rawSeek % config.duration : Math.min(rawSeek, config.duration * (iterations != null ? iterations : PX_DEFAULT_ITERATIONS));
6894
7080
  }
6895
7081
  const effectOptions = {
6896
7082
  duration: config.duration,
@@ -6997,7 +7183,7 @@ var PixodeskAnimator = (() => {
6997
7183
  },
6998
7184
  "setCurrentTime": (time) => {
6999
7185
  var _a3;
7000
- const ceiling = seekCeilingMs((_a3 = config.duration) != null ? _a3 : 0, iterations != null ? iterations : 1);
7186
+ const ceiling = seekCeilingMs((_a3 = config.duration) != null ? _a3 : 0, iterations != null ? iterations : PX_DEFAULT_ITERATIONS);
7001
7187
  const seek = ceiling > 0 ? clampSeekMs(time, ceiling) : Math.max(0, time);
7002
7188
  finishNotified = false;
7003
7189
  animations.forEach((a) => {
@@ -7007,11 +7193,11 @@ var PixodeskAnimator = (() => {
7007
7193
  "getCurrentProgress": () => {
7008
7194
  var _a3;
7009
7195
  const t = api.getCurrentTime();
7010
- return t === null ? null : timeToProgress(t, (_a3 = config.duration) != null ? _a3 : 0, iterations != null ? iterations : 1);
7196
+ return t === null ? null : timeToProgress(t, (_a3 = config.duration) != null ? _a3 : 0, iterations != null ? iterations : PX_DEFAULT_ITERATIONS);
7011
7197
  },
7012
7198
  "setCurrentProgress": (progress) => {
7013
7199
  var _a3;
7014
- api.setCurrentTime(progressToTimeMs(progress, (_a3 = config.duration) != null ? _a3 : 0, iterations != null ? iterations : 1));
7200
+ api.setCurrentTime(progressToTimeMs(progress, (_a3 = config.duration) != null ? _a3 : 0, iterations != null ? iterations : PX_DEFAULT_ITERATIONS));
7015
7201
  },
7016
7202
  "destroy": () => {
7017
7203
  var _a3;
@@ -7384,62 +7570,19 @@ var PixodeskAnimator = (() => {
7384
7570
 
7385
7571
  // src/dom/PxAnimatorDOM.ts
7386
7572
  var SVG_NS = "http://www.w3.org/2000/svg";
7387
- function createElement(tagName, normalizedProps, style, children, textContent, diag) {
7388
- if (PX_DISALLOWED_SVG_TAGS_LOWER.has(tagName.toLowerCase())) {
7389
- (diag != null ? diag : createDiagnostics(void 0, "[PxAnimator]")).warn(PxDiagnosticKind.document, 1103 /* blockedTag */, tagName);
7390
- return null;
7391
- }
7392
- const element = document.createElementNS(SVG_NS, tagName);
7393
- for (const propName in normalizedProps) {
7394
- const sanitized = sanitizeAttributeValue(propName, normalizedProps[propName]);
7395
- if (sanitized === void 0) continue;
7396
- if (PX_CSS_ONLY_STYLE_PROPS.has(propName)) {
7397
- element.style[propName] = String(sanitized);
7398
- continue;
7399
- }
7400
- element.setAttribute(camelCaseToKebabWordIfNeeded(propName), sanitized);
7401
- }
7573
+ var createDomElement = ({ tag, attrs, style, children, text }) => {
7574
+ const element = document.createElementNS(SVG_NS, tag);
7575
+ for (const name of Object.keys(attrs)) element.setAttribute(name, attrs[name]);
7402
7576
  if (style) {
7403
- for (const styleProp in style) {
7404
- element.style[styleProp] = String(style[styleProp]);
7405
- }
7406
- }
7407
- if (children == null ? void 0 : children.length) {
7408
- for (const child of children) {
7409
- element.appendChild(child);
7410
- }
7411
- } else if (textContent) {
7412
- element.textContent = textContent;
7413
- }
7414
- return element;
7415
- }
7416
- function renderNode(node, defs, diag) {
7417
- if (!node) return null;
7418
- const _a2 = node, { type, children, style } = _a2, props = __objRest(_a2, ["type", "children", "style"]);
7419
- const domType = props.domType;
7420
- if (domType !== void 0) delete props.domType;
7421
- const nodeDefs = getDefinitions(node) || defs;
7422
- const resolvedStyle = style;
7423
- let childElements;
7424
- if (children) {
7425
- for (const ch of children) {
7426
- const child = renderNode(ch, nodeDefs, diag);
7427
- if (child) {
7428
- if (!childElements) childElements = [];
7429
- childElements.push(child);
7430
- }
7431
- }
7577
+ const target = element.style;
7578
+ for (const prop of Object.keys(style)) target[prop] = style[prop];
7432
7579
  }
7433
- const element = createElement(
7434
- type || "g",
7435
- toDomProps(props),
7436
- resolvedStyle,
7437
- childElements,
7438
- props[PX_TEXT_CONTENT_ATTR],
7439
- diag
7440
- );
7441
- if (element && domType !== void 0) element.setAttribute("type", domType);
7580
+ for (const child of children) element.appendChild(child);
7581
+ if (text !== void 0) element.textContent = text;
7442
7582
  return element;
7583
+ };
7584
+ function renderNode(node, _defs, diag) {
7585
+ return renderPxTree(node, createDomElement, diag);
7443
7586
  }
7444
7587
 
7445
7588
  // src/shared/PxAnimatorKeys.ts
@@ -7449,7 +7592,7 @@ var PixodeskAnimator = (() => {
7449
7592
  function createAnimatorFromConfig(doc, adapter, callbacks, rootElement) {
7450
7593
  return bindWithEngineChoice(doc, adapter, callbacks, rootElement);
7451
7594
  }
7452
- function createAnimatorImpl(doc, adapter, callbacks, containerElement, patch, resetTimeline) {
7595
+ function createAnimatorImpl(doc, adapter, callbacks, containerElement, patch, resetTimeline, providedRoot) {
7453
7596
  const diag = createDiagnostics(callbacks, "[PxAnimator]");
7454
7597
  const effectsWarnings = validateNodeEffects(doc);
7455
7598
  for (const w of effectsWarnings) diag.warn(PxDiagnosticKind.document, 1101 /* effectsShape */, w);
@@ -7473,6 +7616,7 @@ var PixodeskAnimator = (() => {
7473
7616
  }
7474
7617
  }
7475
7618
  }
7619
+ if (!rootElement && providedRoot) rootElement = providedRoot;
7476
7620
  const api = createAnimatorFromConfig(doc, adapter, callbacks, rootElement);
7477
7621
  if (containerElement && rootElement) {
7478
7622
  const rendered = rootElement;
@@ -7485,7 +7629,7 @@ var PixodeskAnimator = (() => {
7485
7629
  return api;
7486
7630
  }
7487
7631
  function isInternalOptions(options) {
7488
- return "adapter" in options;
7632
+ return "adapter" in options || "rootElement" in options;
7489
7633
  }
7490
7634
  function resolveTimelineOption(options) {
7491
7635
  const { timeline, duration, delay, iterations, start } = options;
@@ -7494,6 +7638,7 @@ var PixodeskAnimator = (() => {
7494
7638
  function createAnimator(options) {
7495
7639
  const { src, doc, container, resetTimeline } = options;
7496
7640
  const adapter = isInternalOptions(options) ? options.adapter : void 0;
7641
+ const providedRoot = isInternalOptions(options) ? options.rootElement : void 0;
7497
7642
  const patch = resolveTimelineOption(options);
7498
7643
  let proxy;
7499
7644
  const callbacks = withRegistryEvents(toEngineCallbacks(options), () => proxy);
@@ -7526,7 +7671,7 @@ var PixodeskAnimator = (() => {
7526
7671
  };
7527
7672
  const build = (document2) => {
7528
7673
  try {
7529
- ready(createAnimatorImpl(document2, adapter, callbacks, container, patch, resetTimeline));
7674
+ ready(createAnimatorImpl(document2, adapter, callbacks, container, patch, resetTimeline, providedRoot));
7530
7675
  } catch (e) {
7531
7676
  const err = asThrownError(e);
7532
7677
  failed(PxDiagnosticKind.internal, 1001 /* buildFailed */, err);