@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.
package/dist/index.cjs CHANGED
@@ -20,18 +20,6 @@ var __spreadValues = (a, b) => {
20
20
  return a;
21
21
  };
22
22
  var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
23
- var __objRest = (source, exclude) => {
24
- var target = {};
25
- for (var prop in source)
26
- if (__hasOwnProp.call(source, prop) && exclude.indexOf(prop) < 0)
27
- target[prop] = source[prop];
28
- if (source != null && __getOwnPropSymbols)
29
- for (var prop of __getOwnPropSymbols(source)) {
30
- if (exclude.indexOf(prop) < 0 && __propIsEnum.call(source, prop))
31
- target[prop] = source[prop];
32
- }
33
- return target;
34
- };
35
23
  var __export = (target, all) => {
36
24
  for (var name in all)
37
25
  __defProp(target, name, { get: all[name], enumerable: true });
@@ -71,7 +59,7 @@ __export(index_exports, {
71
59
  });
72
60
  module.exports = __toCommonJS(index_exports);
73
61
 
74
- // ../svg-animator-core/dist/chunk-EFQLDGFY.js
62
+ // ../svg-animator-core/dist/chunk-37OFJ3RX.js
75
63
  var __defProp2 = Object.defineProperty;
76
64
  var __defProps2 = Object.defineProperties;
77
65
  var __getOwnPropDescs2 = Object.getOwnPropertyDescriptors;
@@ -92,7 +80,7 @@ var __spreadValues2 = (a, b) => {
92
80
  return a;
93
81
  };
94
82
  var __spreadProps2 = (a, b) => __defProps2(a, __getOwnPropDescs2(b));
95
- var __objRest2 = (source, exclude) => {
83
+ var __objRest = (source, exclude) => {
96
84
  var target = {};
97
85
  for (var prop in source)
98
86
  if (__hasOwnProp2.call(source, prop) && exclude.indexOf(prop) < 0)
@@ -115,19 +103,31 @@ function pathStr(path) {
115
103
  return result;
116
104
  }
117
105
  var Base = class {
106
+ /** Structural schemas (objects, arrays, unions of objects…) pass `false`: they state no scalar default. */
107
+ constructor(_statesDefault) {
108
+ this._statesDefault = _statesDefault;
109
+ }
118
110
  _canSanitize(raw) {
119
111
  return this.isValid(raw);
120
112
  }
113
+ /** A REQUIRED field is never absent; its default is the repair value. */
114
+ absentDefault() {
115
+ return this._default;
116
+ }
121
117
  optional() {
122
118
  return new Optional(this);
123
119
  }
124
120
  };
125
121
  var Optional = class extends Base {
126
122
  constructor(inner) {
127
- super();
123
+ super(inner._statesDefault);
128
124
  this.inner = inner;
129
125
  this._default = void 0;
130
126
  }
127
+ /** Absent means the inner schema's STATED default — or nothing at all when it states none. */
128
+ absentDefault() {
129
+ return this.inner._statesDefault ? this.inner._default : void 0;
130
+ }
131
131
  sanitize(raw) {
132
132
  if (raw === void 0 || raw === null) return void 0;
133
133
  return this.inner._canSanitize(raw) ? this.inner.sanitize(raw) : void 0;
@@ -141,8 +141,8 @@ var Optional = class extends Base {
141
141
  }
142
142
  };
143
143
  var Str = class extends Base {
144
- constructor(_default = "") {
145
- super();
144
+ constructor(_default, statesDefault) {
145
+ super(statesDefault);
146
146
  this._default = _default;
147
147
  }
148
148
  sanitize(raw) {
@@ -155,8 +155,8 @@ var Str = class extends Base {
155
155
  }
156
156
  };
157
157
  var Num = class extends Base {
158
- constructor(_default = 0) {
159
- super();
158
+ constructor(_default, statesDefault) {
159
+ super(statesDefault);
160
160
  this._default = _default;
161
161
  }
162
162
  sanitize(raw) {
@@ -169,8 +169,8 @@ var Num = class extends Base {
169
169
  }
170
170
  };
171
171
  var Bool = class extends Base {
172
- constructor(_default = false) {
173
- super();
172
+ constructor(_default, statesDefault) {
173
+ super(statesDefault);
174
174
  this._default = _default;
175
175
  }
176
176
  sanitize(raw) {
@@ -183,8 +183,9 @@ var Bool = class extends Base {
183
183
  }
184
184
  };
185
185
  var Literal = class extends Base {
186
+ /** A literal IS its own value: absent means it. */
186
187
  constructor(value) {
187
- super();
188
+ super(true);
188
189
  this.value = value;
189
190
  this._default = value;
190
191
  }
@@ -198,8 +199,8 @@ var Literal = class extends Base {
198
199
  }
199
200
  };
200
201
  var Enum = class extends Base {
201
- constructor(values, defaultVal) {
202
- super();
202
+ constructor(values, defaultVal, statesDefault) {
203
+ super(statesDefault);
203
204
  this.values = values;
204
205
  this._default = defaultVal != null ? defaultVal : values[0];
205
206
  }
@@ -214,8 +215,8 @@ var Enum = class extends Base {
214
215
  };
215
216
  var UNION_MEMBER_ERROR_LIMIT = 4;
216
217
  var Union = class extends Base {
217
- constructor(schemas, defaultVal) {
218
- super();
218
+ constructor(schemas, defaultVal, statesDefault) {
219
+ super(statesDefault);
219
220
  this.schemas = schemas;
220
221
  this._kind = "union";
221
222
  this._default = defaultVal != null ? defaultVal : schemas[0]._default;
@@ -268,7 +269,7 @@ var Union = class extends Base {
268
269
  var DiscriminatedUnion = class extends Base {
269
270
  constructor(_key, _schemas, defaultVal) {
270
271
  var _a2;
271
- super();
272
+ super(false);
272
273
  this._key = _key;
273
274
  this._schemas = _schemas;
274
275
  this._kind = "discriminatedUnion";
@@ -307,13 +308,19 @@ var DiscriminatedUnion = class extends Base {
307
308
  return schema ? schema._canSanitize(raw) : this._schemas[0]._canSanitize(raw);
308
309
  }
309
310
  };
311
+ function statedDefaults(shape) {
312
+ const out = {};
313
+ for (const key of Object.keys(shape)) if (shape[key]._statesDefault) out[key] = shape[key].absentDefault();
314
+ return Object.freeze(out);
315
+ }
310
316
  var Obj = class extends Base {
311
317
  constructor(_shape) {
312
- super();
318
+ super(false);
313
319
  this._shape = _shape;
314
320
  const d = {};
315
321
  for (const key of Object.keys(_shape)) d[key] = _shape[key]._default;
316
322
  this._default = d;
323
+ this.defaults = statedDefaults(_shape);
317
324
  }
318
325
  sanitize(raw) {
319
326
  const src = raw && typeof raw === "object" && !Array.isArray(raw) ? raw : {};
@@ -355,12 +362,13 @@ var Obj = class extends Base {
355
362
  };
356
363
  var OpenObj = class extends Base {
357
364
  constructor(_shape, _openSchema) {
358
- super();
365
+ super(false);
359
366
  this._shape = _shape;
360
367
  this._openSchema = _openSchema;
361
368
  const d = {};
362
369
  for (const key of Object.keys(_shape)) d[key] = _shape[key]._default;
363
370
  this._default = d;
371
+ this.defaults = statedDefaults(_shape);
364
372
  }
365
373
  sanitize(raw) {
366
374
  const src = raw && typeof raw === "object" && !Array.isArray(raw) ? raw : {};
@@ -405,7 +413,7 @@ var OpenObj = class extends Base {
405
413
  };
406
414
  var Arr = class extends Base {
407
415
  constructor(item) {
408
- super();
416
+ super(false);
409
417
  this.item = item;
410
418
  this._default = [];
411
419
  }
@@ -437,7 +445,7 @@ var Arr = class extends Base {
437
445
  };
438
446
  var Rec = class extends Base {
439
447
  constructor(value) {
440
- super();
448
+ super(false);
441
449
  this.value = value;
442
450
  this._kind = "record";
443
451
  this._default = {};
@@ -470,7 +478,7 @@ var Rec = class extends Base {
470
478
  };
471
479
  var Any = class extends Base {
472
480
  constructor() {
473
- super(...arguments);
481
+ super(false);
474
482
  this._default = void 0;
475
483
  }
476
484
  sanitize(raw) {
@@ -485,7 +493,7 @@ var Any = class extends Base {
485
493
  };
486
494
  var Defined = class extends Base {
487
495
  constructor() {
488
- super(...arguments);
496
+ super(false);
489
497
  this._default = void 0;
490
498
  }
491
499
  sanitize(raw) {
@@ -502,7 +510,7 @@ var Defined = class extends Base {
502
510
  };
503
511
  var Lazy = class extends Base {
504
512
  constructor(fn, _default) {
505
- super();
513
+ super(false);
506
514
  this.fn = fn;
507
515
  this._default = _default;
508
516
  this.resolved = null;
@@ -523,7 +531,7 @@ var Lazy = class extends Base {
523
531
  };
524
532
  var Tuple = class extends Base {
525
533
  constructor(schemas) {
526
- super();
534
+ super(false);
527
535
  this.schemas = schemas;
528
536
  this._kind = "tuple";
529
537
  this._default = schemas.map((s) => s._default);
@@ -554,22 +562,29 @@ var Tuple = class extends Base {
554
562
  function implementsInterface() {
555
563
  return (schema) => schema;
556
564
  }
565
+ function string(defaultVal) {
566
+ return defaultVal === void 0 ? new Str("", false) : new Str(defaultVal, true);
567
+ }
568
+ function number(defaultVal) {
569
+ return defaultVal === void 0 ? new Num(0, false) : new Num(defaultVal, true);
570
+ }
571
+ function boolean(defaultVal) {
572
+ return defaultVal === void 0 ? new Bool(false, false) : new Bool(defaultVal, true);
573
+ }
574
+ function oneOf(values, defaultVal) {
575
+ return defaultVal === void 0 ? new Enum(values, void 0, false) : new Enum(values, defaultVal, true);
576
+ }
577
+ function unionOf(schemas, defaultVal) {
578
+ return defaultVal === void 0 ? new Union(schemas, void 0, false) : new Union(schemas, defaultVal, true);
579
+ }
557
580
  var px = {
558
- /** Matches a string. Default: '' or provided value. */
559
- string: (defaultVal = "") => new Str(defaultVal),
560
- /** Matches a finite number. Default: 0 or provided value. */
561
- number: (defaultVal = 0) => new Num(defaultVal),
562
- /** Matches a boolean. Default: false or provided value. */
563
- boolean: (defaultVal = false) => new Bool(defaultVal),
564
- /** Matches one exact primitive value; its default is the value itself. */
581
+ string,
582
+ number,
583
+ boolean,
584
+ /** Matches one exact primitive value; absent means the value itself. */
565
585
  literal: (value) => new Literal(value),
566
- /** Matches one of a fixed set of string/number values. Default: first value. */
567
- enum: (values, defaultVal) => new Enum(values, defaultVal),
568
- /**
569
- * Returns the first schema whose isValid passes.
570
- * TypeScript infers the union of all member types automatically.
571
- */
572
- union: (schemas, defaultVal) => new Union(schemas, defaultVal),
586
+ enum: oneOf,
587
+ union: unionOf,
573
588
  /**
574
589
  * Discriminated union — reads `raw[key]`, finds the member schema whose
575
590
  * literal at `key` matches, then delegates sanitize/isValid to that member.
@@ -577,7 +592,8 @@ var px = {
577
592
  * TypeScript infers the union of all member types automatically.
578
593
  */
579
594
  discriminatedUnion: (key, schemas) => new DiscriminatedUnion(key, schemas),
580
- /** Typed object — unknown keys are stripped. Required fields fall back to their default. */
595
+ /** Typed object — unknown keys are stripped. Required fields fall back to their default.
596
+ * Its `defaults` say what each stated field means when a document leaves it out. */
581
597
  object: (shape) => new Obj(shape),
582
598
  /**
583
599
  * Open object — validates known keys; passes unknown keys through as-is,
@@ -712,8 +728,11 @@ var PX_TRIGGER_DEFAULTS = {
712
728
  offScreen: "pause",
713
729
  mouseOut: "continue",
714
730
  visibilityThreshold: 0.5,
715
- visibilityDebounce: 150
731
+ visibilityDebounce: 150,
732
+ finish: "hold"
716
733
  };
734
+ var PX_DEFAULT_DURATION_MS = 1e3;
735
+ var PX_DEFAULT_ITERATIONS = 1;
717
736
  function resolveTrigger(trigger) {
718
737
  var _a2, _b, _c, _d, _e;
719
738
  return {
@@ -831,7 +850,7 @@ function flattenAnimatorTimeline(cfg) {
831
850
  if (timeline === void 0 || timeline === null || typeof timeline !== "object") return cfg;
832
851
  const memoised = flattenMemo.get(cfg);
833
852
  if (memoised) return memoised;
834
- const _a2 = cfg, { timeline: _dropped } = _a2, flat = __objRest2(_a2, ["timeline"]);
853
+ const _a2 = cfg, { timeline: _dropped } = _a2, flat = __objRest(_a2, ["timeline"]);
835
854
  if (timeline.engine !== void 0) flat.engine = timeline.engine;
836
855
  if (timeline.frameRate !== void 0) flat.frameRate = timeline.frameRate;
837
856
  if (timeline.type === "scroll" || timeline.type === "view") {
@@ -857,7 +876,7 @@ function flattenAnimatorTimeline(cfg) {
857
876
  } else {
858
877
  if (timeline.duration !== void 0) flat.duration = timeline.duration;
859
878
  if (timeline.trigger !== void 0) {
860
- const _b = timeline.trigger, { finish } = _b, restTrigger = __objRest2(_b, ["finish"]);
879
+ const _b = timeline.trigger, { finish } = _b, restTrigger = __objRest(_b, ["finish"]);
861
880
  if (Object.keys(restTrigger).length) flat.trigger = restTrigger;
862
881
  if (finish !== void 0) flat.resetOnFinish = finish === "reset";
863
882
  }
@@ -926,15 +945,15 @@ var keyframeTangentIn = (kf) => anyKf(kf).tangentIn;
926
945
  var keyframeTangentOut = (kf) => anyKf(kf).tangentOut;
927
946
  var PxLoopSchema = implementsInterface()(px.object({
928
947
  segmentCount: px.number().optional(),
929
- repeatAt: px.enum([PxLoopRepeatAt.start, PxLoopRepeatAt.end]).optional(),
930
- direction: px.enum([PxLoopDirection.normal, PxLoopDirection.alternate]).optional()
948
+ repeatAt: px.enum([PxLoopRepeatAt.start, PxLoopRepeatAt.end], PxLoopRepeatAt.end).optional(),
949
+ direction: px.enum([PxLoopDirection.normal, PxLoopDirection.alternate], PxLoopDirection.normal).optional()
931
950
  }));
932
951
  var PxPropertyAnimationSchema = implementsInterface()(px.object({
933
952
  value: PxKeyframeValueSchema.optional(),
934
953
  keyframes: px.array(PxKeyframeSchema).optional(),
935
954
  loop: px.union([PxLoopSchema, px.boolean()]).optional(),
936
955
  autoOrient: px.boolean().optional(),
937
- alongPathMode: px.enum([PxAlongPathMode.sampled, PxAlongPathMode.offsetPath]).optional()
956
+ alongPathMode: px.enum([PxAlongPathMode.sampled, PxAlongPathMode.offsetPath], PxAlongPathMode.sampled).optional()
938
957
  }));
939
958
  var PxTransformPartsSchema = implementsInterface()(px.object({
940
959
  translate: px.tuple([px.number(), px.number()]).optional(),
@@ -964,9 +983,9 @@ var PxTriggerSchema = implementsInterface()(px.object({
964
983
  // What happens after a NATURAL finish — `'hold'` (default: keep the end state per
965
984
  // `fill`) or `'reset'` (snap back to the start state). One of four occasion keys
966
985
  // (`start`, `offScreen`, `mouseOut`, `finish`), all named the same way.
967
- finish: px.enum([PxFinishAction.hold, PxFinishAction.reset]).optional(),
968
- visibilityThreshold: px.number().optional(),
969
- visibilityDebounce: px.number().optional()
986
+ finish: px.enum([PxFinishAction.hold, PxFinishAction.reset], PX_TRIGGER_DEFAULTS.finish).optional(),
987
+ visibilityThreshold: px.number(PX_TRIGGER_DEFAULTS.visibilityThreshold).optional(),
988
+ visibilityDebounce: px.number(PX_TRIGGER_DEFAULTS.visibilityDebounce).optional()
970
989
  }));
971
990
  var PxGlyphSchema = implementsInterface()(px.object({
972
991
  width: px.number(),
@@ -992,7 +1011,7 @@ var PxScrollRangePointSchema = implementsInterface()(px.object({
992
1011
  PxScrollPhase.exit,
993
1012
  PxScrollPhase.entryCrossing,
994
1013
  PxScrollPhase.exitCrossing
995
- ]).optional(),
1014
+ ], PxScrollPhase.cover).optional(),
996
1015
  fraction: px.number().optional()
997
1016
  }));
998
1017
  var PxScrollRangeSchema = px.object({
@@ -1000,37 +1019,37 @@ var PxScrollRangeSchema = px.object({
1000
1019
  end: PxScrollRangePointSchema.optional()
1001
1020
  });
1002
1021
  var PxScrollSchema = implementsInterface()(px.object({
1003
- kind: px.enum([PxScrollKind.view, PxScrollKind.scroll]).optional(),
1004
- axis: px.enum([PxScrollAxis.block, PxScrollAxis.inline, PxScrollAxis.x, PxScrollAxis.y]).optional(),
1005
- source: px.enum([PxScrollSource.nearest, PxScrollSource.root]).optional(),
1022
+ kind: px.enum([PxScrollKind.view, PxScrollKind.scroll], PxScrollKind.view).optional(),
1023
+ axis: px.enum([PxScrollAxis.block, PxScrollAxis.inline, PxScrollAxis.x, PxScrollAxis.y], PxScrollAxis.block).optional(),
1024
+ source: px.enum([PxScrollSource.nearest, PxScrollSource.root], PxScrollSource.nearest).optional(),
1006
1025
  // Free-form: the two keywords `parent`/`scroller` plus any CSS selector.
1007
1026
  subject: px.string().optional(),
1008
1027
  smoothing: px.number().optional(),
1009
- pin: px.boolean().optional(),
1010
- pinAlign: px.enum([PxPinAlign.top, PxPinAlign.center, PxPinAlign.bottom]).optional(),
1028
+ pin: px.boolean(false).optional(),
1029
+ pinAlign: px.enum([PxPinAlign.top, PxPinAlign.center, PxPinAlign.bottom], PxPinAlign.top).optional(),
1011
1030
  pinOffset: px.number().optional(),
1012
1031
  pinDistance: px.number().optional(),
1013
1032
  range: PxScrollRangeSchema.optional()
1014
1033
  }));
1015
1034
  var PxTimelinePinSchema = implementsInterface()(px.object({
1016
- align: px.enum([PxPinAlign.top, PxPinAlign.center, PxPinAlign.bottom]).optional(),
1035
+ align: px.enum([PxPinAlign.top, PxPinAlign.center, PxPinAlign.bottom], PxPinAlign.top).optional(),
1017
1036
  offset: px.number().optional(),
1018
1037
  distance: px.number().optional()
1019
1038
  }));
1020
- var PxTimelineEngineSchema = px.enum([PxTimelineEngineSetting.auto, PxTimelineEngineSetting.native, PxTimelineEngineSetting.js]).optional();
1039
+ var PxTimelineEngineSchema = px.enum([PxTimelineEngineSetting.auto, PxTimelineEngineSetting.native, PxTimelineEngineSetting.js], PxTimelineEngineSetting.auto).optional();
1021
1040
  var PxTimeTimelineSchema = implementsInterface()(px.object({
1022
1041
  type: px.literal("time").optional(),
1023
1042
  engine: PxTimelineEngineSchema,
1024
1043
  frameRate: px.number().optional(),
1025
1044
  // §2.8: duration is a property of the TIMELINE — how long one pass takes.
1026
- duration: px.number().optional(),
1045
+ duration: px.number(PX_DEFAULT_DURATION_MS).optional(),
1027
1046
  trigger: PxTriggerSchema.optional(),
1028
- delay: px.number().optional(),
1029
- iterations: px.union([px.number(), px.literal("infinite")]).optional(),
1047
+ delay: px.number(0).optional(),
1048
+ iterations: px.union([px.number(PX_DEFAULT_ITERATIONS), px.literal("infinite")], PX_DEFAULT_ITERATIONS).optional(),
1030
1049
  // `fillMode` on the wire (CSS `animation-fill-mode`; the runtime view calls it `fill`)
1031
1050
  // — never `fill`, which is paint everywhere else in the format.
1032
- fillMode: px.enum([PxFillMode.forwards, PxFillMode.backwards, PxFillMode.both, PxFillMode.none]).optional(),
1033
- direction: px.enum([PxPlaybackDirection.normal, PxPlaybackDirection.reverse, PxPlaybackDirection.alternate, PxPlaybackDirection.alternateReverse]).optional()
1051
+ fillMode: px.enum([PxFillMode.forwards, PxFillMode.backwards, PxFillMode.both, PxFillMode.none], PxFillMode.forwards).optional(),
1052
+ direction: px.enum([PxPlaybackDirection.normal, PxPlaybackDirection.reverse, PxPlaybackDirection.alternate, PxPlaybackDirection.alternateReverse], PxPlaybackDirection.normal).optional()
1034
1053
  }));
1035
1054
  var scrollishTimelineShape = {
1036
1055
  // §2.8: duration is a property of the TIMELINE — under scrubbing it is the keyframe
@@ -1041,8 +1060,8 @@ var scrollishTimelineShape = {
1041
1060
  iterations: px.number().optional(),
1042
1061
  engine: PxTimelineEngineSchema,
1043
1062
  frameRate: px.number().optional(),
1044
- axis: px.enum([PxScrollAxis.block, PxScrollAxis.inline, PxScrollAxis.x, PxScrollAxis.y]).optional(),
1045
- source: px.enum([PxScrollSource.nearest, PxScrollSource.root]).optional(),
1063
+ axis: px.enum([PxScrollAxis.block, PxScrollAxis.inline, PxScrollAxis.x, PxScrollAxis.y], PxScrollAxis.block).optional(),
1064
+ source: px.enum([PxScrollSource.nearest, PxScrollSource.root], PxScrollSource.nearest).optional(),
1046
1065
  subject: px.string().optional(),
1047
1066
  // 'parent' | 'scroller' | any CSS selector
1048
1067
  smoothing: px.number().optional(),
@@ -1122,9 +1141,10 @@ var PxRepeaterEffectSchema = implementsInterface()(px.object({
1122
1141
  }));
1123
1142
  var PxMaskedByEffectSchema = implementsInterface()(px.object({
1124
1143
  source: px.string().optional(),
1125
- maskType: px.enum([PxMaskType.luminance, PxMaskType.alpha]).optional(),
1126
- maskUnits: px.enum([PxUnits.userSpaceOnUse, PxUnits.objectBoundingBox]).optional(),
1127
- maskContentUnits: px.enum([PxUnits.userSpaceOnUse, PxUnits.objectBoundingBox]).optional(),
1144
+ // SVG's own initial values — what a <mask> does when the attribute is not there.
1145
+ maskType: px.enum([PxMaskType.luminance, PxMaskType.alpha], PxMaskType.luminance).optional(),
1146
+ maskUnits: px.enum([PxUnits.userSpaceOnUse, PxUnits.objectBoundingBox], PxUnits.objectBoundingBox).optional(),
1147
+ maskContentUnits: px.enum([PxUnits.userSpaceOnUse, PxUnits.objectBoundingBox], PxUnits.userSpaceOnUse).optional(),
1128
1148
  x: px.number().optional(),
1129
1149
  y: px.number().optional(),
1130
1150
  width: px.number().optional(),
@@ -1136,7 +1156,7 @@ var PxClipPathEffectSchema = implementsInterface()(px.object({
1136
1156
  var PxStrokeTrimEffectSchema = implementsInterface()(px.object({
1137
1157
  offset: PxAnimatableNumberSchema.optional(),
1138
1158
  range: PxAnimatableVec2Schema.optional(),
1139
- subPaths: px.enum([PxStrokeTrimSubPaths.separate, PxStrokeTrimSubPaths.combined]).optional()
1159
+ subPaths: px.enum([PxStrokeTrimSubPaths.separate, PxStrokeTrimSubPaths.combined], PxStrokeTrimSubPaths.separate).optional()
1140
1160
  }));
1141
1161
  var PxRetimeEffectSchema = implementsInterface()(px.object({
1142
1162
  start: px.number().optional(),
@@ -1168,17 +1188,20 @@ var PxFillGradientEffectSchema = implementsInterface()(px.object({
1168
1188
  radius: PxAnimatableNumberSchema.optional(),
1169
1189
  focal: PxAnimatableVec2Schema.optional(),
1170
1190
  stops: PxAnimatableGradientStopsSchema.optional(),
1171
- gradientUnits: px.enum([PxUnits.userSpaceOnUse, PxUnits.objectBoundingBox]).optional(),
1172
- spreadMethod: px.enum([PxGradientSpreadMethod.pad, PxGradientSpreadMethod.reflect, PxGradientSpreadMethod.repeat]).optional(),
1191
+ // SVG's own initial values — what a gradient does when the attribute is not there.
1192
+ gradientUnits: px.enum([PxUnits.userSpaceOnUse, PxUnits.objectBoundingBox], PxUnits.objectBoundingBox).optional(),
1193
+ spreadMethod: px.enum([PxGradientSpreadMethod.pad, PxGradientSpreadMethod.reflect, PxGradientSpreadMethod.repeat], PxGradientSpreadMethod.pad).optional(),
1173
1194
  gradientTransform: px.string().optional()
1174
1195
  }));
1175
1196
  var PxStrokeGradientEffectSchema = PxFillGradientEffectSchema;
1176
1197
  var PxTextPathEffectSchema = implementsInterface()(px.object({
1177
1198
  pathData: px.string(),
1178
- pathOverflow: px.enum([PxPathOverflow.clip, PxPathOverflow.extend]).optional(),
1179
- lengthAdjust: px.enum([PxLengthAdjust.spacing, PxLengthAdjust.spacingAndGlyphs]).optional(),
1180
- method: px.enum([PxTextPathMethod.align, PxTextPathMethod.stretch]).optional(),
1181
- spacing: px.enum([PxTextPathSpacing.auto, PxTextPathSpacing.exact]).optional(),
1199
+ // `extend` is what an omitted pathOverflow means (glyphs continue along the tangent); the
1200
+ // other three are SVG's own initial values for the native <textPath> attributes.
1201
+ pathOverflow: px.enum([PxPathOverflow.clip, PxPathOverflow.extend], PxPathOverflow.extend).optional(),
1202
+ lengthAdjust: px.enum([PxLengthAdjust.spacing, PxLengthAdjust.spacingAndGlyphs], PxLengthAdjust.spacing).optional(),
1203
+ method: px.enum([PxTextPathMethod.align, PxTextPathMethod.stretch], PxTextPathMethod.align).optional(),
1204
+ spacing: px.enum([PxTextPathSpacing.auto, PxTextPathSpacing.exact], PxTextPathSpacing.exact).optional(),
1182
1205
  startOffset: PxAnimatableNumberSchema.optional(),
1183
1206
  textLength: PxAnimatableNumberSchema.optional()
1184
1207
  }));
@@ -1738,7 +1761,6 @@ function parseTransformParts(str2) {
1738
1761
  return Object.keys(out).length ? out : void 0;
1739
1762
  }
1740
1763
  var PX_STYLE_ATTR_NAMES = /* @__PURE__ */ new Set(["offset-distance", "offsetDistance"]);
1741
- var PX_DEFAULT_DURATION_MS = 1e3;
1742
1764
  function kebabToCamelCaseWord(kebab) {
1743
1765
  return kebab.includes("-") ? kebab.replace(/-([a-z])/g, (_, letter) => letter.toUpperCase()) : kebab;
1744
1766
  }
@@ -1988,6 +2010,36 @@ function toDomProps(props) {
1988
2010
  }
1989
2011
  return propsCopy;
1990
2012
  }
2013
+ function mergeStaticTransformIntoAnimDef(animDef, staticTransform) {
2014
+ if (!animDef) return animDef;
2015
+ const staticParts = staticTransform && typeof staticTransform === "object" && !Array.isArray(staticTransform) ? staticTransform : parseTransformParts(staticTransform);
2016
+ if (!staticParts || !Object.keys(staticParts).length) return animDef;
2017
+ const mergeKfValue = (v) => v && typeof v === "object" && !Array.isArray(v) ? __spreadValues2(__spreadValues2({}, staticParts), v) : v;
2018
+ const transformAnim = animDef[TRANSFORM_ATTR];
2019
+ if (transformAnim && typeof transformAnim === "object") {
2020
+ const anim = transformAnim;
2021
+ if (Array.isArray(anim.keyframes)) {
2022
+ const out = __spreadProps2(__spreadValues2({}, anim), {
2023
+ keyframes: anim.keyframes.map((kf) => __spreadProps2(__spreadValues2({}, kf), { value: mergeKfValue(kf.value) }))
2024
+ });
2025
+ if (out.value !== void 0) out.value = mergeKfValue(out.value);
2026
+ return __spreadProps2(__spreadValues2({}, animDef), { transform: out });
2027
+ }
2028
+ return animDef;
2029
+ }
2030
+ const channels = Object.keys(animDef).filter((k) => PX_TRANSFORM_FN_NAMES.has(k));
2031
+ if (channels.length !== 1) return animDef;
2032
+ const ch = channels[0];
2033
+ const chAnim = animDef[ch];
2034
+ if (!chAnim || typeof chAnim !== "object" || !Array.isArray(chAnim.keyframes)) return animDef;
2035
+ const lifted = __spreadProps2(__spreadValues2({}, chAnim), {
2036
+ keyframes: chAnim.keyframes.map((kf) => __spreadProps2(__spreadValues2({}, kf), { value: __spreadProps2(__spreadValues2({}, staticParts), { [ch]: kf.value }) }))
2037
+ });
2038
+ if (lifted.value !== void 0) lifted.value = __spreadProps2(__spreadValues2({}, staticParts), { [ch]: lifted.value });
2039
+ const rest = __spreadValues2({}, animDef);
2040
+ delete rest[ch];
2041
+ return __spreadProps2(__spreadValues2({}, rest), { transform: lifted });
2042
+ }
1991
2043
  function getKfTranslate(kf) {
1992
2044
  const v = keyframeValue(kf);
1993
2045
  if (!v) return void 0;
@@ -2356,7 +2408,7 @@ function walkAndMaterialize(node, opts) {
2356
2408
  let newAnimate;
2357
2409
  const animBucket = node.animate;
2358
2410
  if (animBucket && typeof animBucket === "object" && !Array.isArray(animBucket)) {
2359
- const animDef = animBucket;
2411
+ const animDef = mergeStaticTransformIntoAnimDef(animBucket, node.transform);
2360
2412
  const transformAnim = animDef.transform;
2361
2413
  if (transformAnim && typeof transformAnim === "object" && propAnimIsMotionPath(transformAnim)) {
2362
2414
  const materialized = materializeMotionPathInPropAnim(transformAnim, opts);
@@ -2868,36 +2920,6 @@ var _elementIdCounter = 0;
2868
2920
  function generateElementId() {
2869
2921
  return "_px_el_" + ++_elementIdCounter;
2870
2922
  }
2871
- function mergeStaticTransformIntoAnimDef(animDef, staticTransform) {
2872
- if (!animDef) return animDef;
2873
- const staticParts = staticTransform && typeof staticTransform === "object" && !Array.isArray(staticTransform) ? staticTransform : parseTransformParts(staticTransform);
2874
- if (!staticParts || !Object.keys(staticParts).length) return animDef;
2875
- const mergeKfValue = (v) => v && typeof v === "object" && !Array.isArray(v) ? __spreadValues2(__spreadValues2({}, staticParts), v) : v;
2876
- const transformAnim = animDef[TRANSFORM_ATTR];
2877
- if (transformAnim && typeof transformAnim === "object") {
2878
- const anim = transformAnim;
2879
- if (Array.isArray(anim.keyframes)) {
2880
- const out = __spreadProps2(__spreadValues2({}, anim), {
2881
- keyframes: anim.keyframes.map((kf) => __spreadProps2(__spreadValues2({}, kf), { value: mergeKfValue(kf.value) }))
2882
- });
2883
- if (out.value !== void 0) out.value = mergeKfValue(out.value);
2884
- return __spreadProps2(__spreadValues2({}, animDef), { transform: out });
2885
- }
2886
- return animDef;
2887
- }
2888
- const channels = Object.keys(animDef).filter((k) => PX_TRANSFORM_FN_NAMES.has(k));
2889
- if (channels.length !== 1) return animDef;
2890
- const ch = channels[0];
2891
- const chAnim = animDef[ch];
2892
- if (!chAnim || typeof chAnim !== "object" || !Array.isArray(chAnim.keyframes)) return animDef;
2893
- const lifted = __spreadProps2(__spreadValues2({}, chAnim), {
2894
- keyframes: chAnim.keyframes.map((kf) => __spreadProps2(__spreadValues2({}, kf), { value: __spreadProps2(__spreadValues2({}, staticParts), { [ch]: kf.value }) }))
2895
- });
2896
- if (lifted.value !== void 0) lifted.value = __spreadProps2(__spreadValues2({}, staticParts), { [ch]: lifted.value });
2897
- const rest = __spreadValues2({}, animDef);
2898
- delete rest[ch];
2899
- return __spreadProps2(__spreadValues2({}, rest), { transform: lifted });
2900
- }
2901
2923
  function normalizeAnimationDefinition(animDef, duration, defs, engine = PxTimelineEngine.native) {
2902
2924
  const normalized = {};
2903
2925
  for (const [propName, propAnim] of Object.entries(animDef)) {
@@ -2980,7 +3002,7 @@ function getKeyframesPair(keyframes, progress) {
2980
3002
  return { prevKf, nextKf };
2981
3003
  }
2982
3004
  function calcPropertyValue(propName, propAnim, progress) {
2983
- var _a2, _b, _c, _d;
3005
+ var _a2, _b, _c, _d, _e;
2984
3006
  const keyframes = propAnim.keyframes || [];
2985
3007
  if (keyframes.length === 0) return null;
2986
3008
  const { prevKf, nextKf } = getKeyframesPair(keyframes, progress);
@@ -3049,7 +3071,7 @@ function calcPropertyValue(propName, propAnim, progress) {
3049
3071
  !!propAnim.autoOrient
3050
3072
  );
3051
3073
  partsResult.translate = [sample.translate[0], sample.translate[1]];
3052
- if (sample.rotateDeg !== void 0) partsResult.rotate = sample.rotateDeg;
3074
+ if (sample.rotateDeg !== void 0) partsResult.rotate = sample.rotateDeg + ((_e = partsResult.rotate) != null ? _e : 0);
3053
3075
  }
3054
3076
  }
3055
3077
  cssValue = composeTransformParts(partsResult, { withUnits: false });
@@ -3332,12 +3354,12 @@ function deepClonePxNode(value) {
3332
3354
  for (const k of Object.keys(value)) out[k] = deepClonePxNode(value[k]);
3333
3355
  return out;
3334
3356
  }
3335
- function regenerateIdsAndRewriteRefs(root, genId2) {
3357
+ function regenerateIdsAndRewriteRefs(root, genId3) {
3336
3358
  const oldToNew = /* @__PURE__ */ new Map();
3337
3359
  const walkAssign = (n) => {
3338
3360
  var _a2;
3339
3361
  if (typeof n.id === "string") {
3340
- const newId = genId2();
3362
+ const newId = genId3();
3341
3363
  oldToNew.set(n.id, newId);
3342
3364
  n.id = newId;
3343
3365
  }
@@ -3986,68 +4008,6 @@ function applyTextGlyphsAlongPath(node, ctx, pathD, startOffset, textLength, pat
3986
4008
  }
3987
4009
  return materializeGlyphTextAlongPath(node, pathD, startOffset, { glyphs: ctx.glyphs, warnings: ctx.warnings }, textLength, pathOverflow);
3988
4010
  }
3989
- var PxDiagnosticKind = {
3990
- /** The document is wrong — regenerate or repair the file. */
3991
- document: "document",
3992
- /** The page or app cannot provide what the document asks for — fix the mount. */
3993
- host: "host",
3994
- /** The platform cannot do it and the player degraded — usually nothing to fix. */
3995
- platform: "platform",
3996
- /** The call is wrong or self-contradictory — fix the options or props you passed. */
3997
- usage: "usage",
3998
- /** The player failed where it did not expect to — report it to us. */
3999
- internal: "internal"
4000
- };
4001
- var DOCS_URL = "https://github.com/pixodesk/pixodesk-svg-animator/blob/main/docs/diagnostics.md";
4002
- function codeLine(code) {
4003
- return "PX" + code + " " + DOCS_URL + "#px" + code;
4004
- }
4005
- function errorIn(data) {
4006
- return data.find((d) => d instanceof Error);
4007
- }
4008
- function createDiagnostics(config, prefix) {
4009
- const tag = prefix ? prefix + " " : "";
4010
- return {
4011
- warn: (kind, code, ...data) => {
4012
- const message = codeLine(code);
4013
- if (config == null ? void 0 : config.onWarn) {
4014
- config.onWarn({ code, kind, data, message });
4015
- return;
4016
- }
4017
- if (config == null ? void 0 : config.muteWarn) return;
4018
- console.warn(tag + kind + " " + message, ...data);
4019
- },
4020
- error: (kind, code, ...data) => {
4021
- const message = codeLine(code);
4022
- const error = errorIn(data);
4023
- if (config == null ? void 0 : config.onError) {
4024
- config.onError({ code, kind, data, message, error });
4025
- return;
4026
- }
4027
- if (config == null ? void 0 : config.muteError) return;
4028
- console.error(tag + kind + " " + message, ...data);
4029
- }
4030
- };
4031
- }
4032
- var MAX_REPORTED = 6;
4033
- function diagnoseDocument(doc) {
4034
- try {
4035
- return { problems: validateDocument(doc) };
4036
- } catch (e) {
4037
- return { problems: [] };
4038
- }
4039
- }
4040
- function reportDocumentDiagnostics(doc, where) {
4041
- const { problems } = diagnoseDocument(doc);
4042
- if (!problems.length) return;
4043
- const shown = problems.slice(0, MAX_REPORTED);
4044
- const more = problems.length - shown.length;
4045
- console.warn(
4046
- where + ": this document does not match the animation schema in " + problems.length + " place" + (problems.length === 1 ? "" : "s") + ".\n" + shown.map((p) => " - " + p).join("\n") + (more > 0 ? "\n \u2026 and " + more + " more" : "") + "\n\nIf you did not author these keys, the usual cause is a build that MANGLES PROPERTY NAMES. An animation document is data loaded at runtime, so renaming the property reads inside the player stops them matching the keys in the JSON, and the animation silently does nothing. Feed the published reserved-name list to your minifier \u2014 @pixodesk/svg-animator-web/mangle-reserved.json \u2014 see docs/library/minification.md."
4047
- );
4048
- }
4049
-
4050
- // ../svg-animator-core/dist/index.js
4051
4011
  function applyTransformByEffect(node, fx, ctx) {
4052
4012
  if (!fx) return node;
4053
4013
  delete node.transform;
@@ -5565,12 +5525,17 @@ function buildOffsetPath(propAnim) {
5565
5525
  const first = keyframeValue(kfs[0]);
5566
5526
  const anchor = (first == null ? void 0 : first.origin) && first.origin.length >= 2 ? [first.origin[0], first.origin[1]] : [0, 0];
5567
5527
  const points = [];
5528
+ let keyframesCarryRotate = false;
5568
5529
  for (const kf of kfs) {
5569
5530
  const v = keyframeValue(kf);
5570
5531
  const tr = v == null ? void 0 : v.translate;
5571
5532
  if (!tr || tr.length < 2) return void 0;
5572
5533
  const parts = Object.keys(v);
5573
- if (parts.some((p) => p !== "translate" && p !== "origin")) return void 0;
5534
+ if (parts.some((p) => p !== TRANSFORM_PART.translate && p !== TRANSFORM_PART.origin && p !== TRANSFORM_PART.rotate)) return void 0;
5535
+ if ((v == null ? void 0 : v.rotate) !== void 0) {
5536
+ if (v.rotate !== 0) return void 0;
5537
+ keyframesCarryRotate = true;
5538
+ }
5574
5539
  const o = (_a2 = v == null ? void 0 : v.origin) != null ? _a2 : [0, 0];
5575
5540
  if (o[0] !== anchor[0] || o[1] !== anchor[1]) return void 0;
5576
5541
  points.push([tr[0] + anchor[0], tr[1] + anchor[1]]);
@@ -5598,7 +5563,7 @@ function buildOffsetPath(propAnim) {
5598
5563
  if (e !== void 0) out.e = e;
5599
5564
  distanceKfs.push(out);
5600
5565
  }
5601
- return { pathStr: d, distanceKfs, autoOrient: !!propAnim.autoOrient, anchor };
5566
+ return { pathStr: d, distanceKfs, autoOrient: !!propAnim.autoOrient, anchor, keyframesCarryRotate };
5602
5567
  }
5603
5568
  function materializeOffsetPathsInTree(root) {
5604
5569
  const walk = (node) => {
@@ -5620,6 +5585,7 @@ function materializeOffsetPathsInTree(root) {
5620
5585
  const t = __spreadValues2({}, staticTr);
5621
5586
  delete t[TRANSFORM_PART.translate];
5622
5587
  delete t[TRANSFORM_PART.origin];
5588
+ if (built.keyframesCarryRotate) delete t[TRANSFORM_PART.rotate];
5623
5589
  newTransform = Object.keys(t).length ? t : void 0;
5624
5590
  }
5625
5591
  out = __spreadProps2(__spreadValues2({}, node), {
@@ -5789,6 +5755,101 @@ function walkAndMaterialize2(node, idMap, animatedIds, genId3, defsCollector, ro
5789
5755
  });
5790
5756
  return changed ? __spreadProps2(__spreadValues2({}, node), { children: newChildren }) : node;
5791
5757
  }
5758
+ var TRANSFORM_CHANNEL = "transform";
5759
+ var REVERSED_DIRECTIONS = /* @__PURE__ */ new Set(["reverse", "alternate-reverse"]);
5760
+ var VERIFY_SAMPLE_FRACTIONS = [0, 0.25, 0.5, 0.75, 1];
5761
+ var SCRATCH_ID_PREFIX = "__px_rest_";
5762
+ function materializeRestPosesInTree(root, engine) {
5763
+ var _a2, _b;
5764
+ const out = deepClone(root);
5765
+ const config = getAnimatorConfig(out) || {};
5766
+ const duration = +(config.duration || PX_DEFAULT_DURATION_MS);
5767
+ const firstFrameTime = REVERSED_DIRECTIONS.has(String(config.direction)) ? duration : 0;
5768
+ const nodes = animatedNodes(out);
5769
+ if (!nodes.size) return out;
5770
+ const before = bindingsOf(out, engine);
5771
+ const added = /* @__PURE__ */ new Map();
5772
+ for (const [key, animate] of before) {
5773
+ const node = nodes.get(key);
5774
+ if (!node) continue;
5775
+ const channels = Object.keys(animate);
5776
+ for (const channel of channels) {
5777
+ if (PX_TRANSFORM_FN_NAMES.has(channel)) continue;
5778
+ if (!mayCarryRestPose(node, channel)) continue;
5779
+ const value = firstFrameValue(animate, channel, firstFrameTime);
5780
+ if (value === void 0) continue;
5781
+ node[channel] = value;
5782
+ added.set(key, [...(_a2 = added.get(key)) != null ? _a2 : [], channel]);
5783
+ }
5784
+ if (channels.some((channel) => PX_TRANSFORM_FN_NAMES.has(channel)) && mayCarryTransformRestPose(node)) {
5785
+ const parts = firstFrameTransformParts(animate, firstFrameTime);
5786
+ if (parts) {
5787
+ node[TRANSFORM_CHANNEL] = parts;
5788
+ added.set(key, [...(_b = added.get(key)) != null ? _b : [], TRANSFORM_CHANNEL]);
5789
+ }
5790
+ }
5791
+ }
5792
+ if (added.size) {
5793
+ const after = bindingsOf(out, engine);
5794
+ for (const [key, channels] of added) {
5795
+ if (writesTheSameFrames(before.get(key), after.get(key), duration)) continue;
5796
+ const node = nodes.get(key);
5797
+ if (node) for (const channel of channels) delete node[channel];
5798
+ }
5799
+ }
5800
+ return out;
5801
+ }
5802
+ function mayCarryRestPose(node, channel) {
5803
+ if (node[channel] !== void 0) return false;
5804
+ if (channel === TRANSFORM_CHANNEL) return mayCarryTransformRestPose(node);
5805
+ return true;
5806
+ }
5807
+ function mayCarryTransformRestPose(node) {
5808
+ if (node[TRANSFORM_CHANNEL] !== void 0) return false;
5809
+ for (const part of PX_TRANSFORM_FN_NAMES) if (node[part] !== void 0) return false;
5810
+ return true;
5811
+ }
5812
+ function firstFrameValue(animate, channel, timeMs) {
5813
+ const values = Object.values(calcAnimationValues({ [channel]: animate[channel] }, timeMs));
5814
+ return values.length === 1 && values[0] !== "" ? values[0] : void 0;
5815
+ }
5816
+ function firstFrameTransformParts(animate, timeMs) {
5817
+ const family = {};
5818
+ for (const channel of Object.keys(animate)) if (PX_TRANSFORM_FN_NAMES.has(channel)) family[channel] = animate[channel];
5819
+ const written = calcAnimationValues(family, timeMs)[TRANSFORM_CHANNEL];
5820
+ if (!written) return void 0;
5821
+ const parts = parseTransformParts(written.replace(/(px|deg)\b/g, ""));
5822
+ return parts && Object.keys(parts).length ? parts : void 0;
5823
+ }
5824
+ function writesTheSameFrames(a, b, durationMs) {
5825
+ if (!a || !b) return a === b;
5826
+ const frame = (animate, t) => JSON.stringify(calcAnimationValues(animate, t)).replace(/\s+/g, "");
5827
+ return VERIFY_SAMPLE_FRACTIONS.every((fraction) => frame(a, fraction * durationMs) === frame(b, fraction * durationMs));
5828
+ }
5829
+ function bindingsOf(tree, engine) {
5830
+ const scratch = deepClone(tree);
5831
+ const keyById = /* @__PURE__ */ new Map();
5832
+ for (const [key, node] of animatedNodes(scratch)) {
5833
+ if (node.id === void 0) node.id = SCRATCH_ID_PREFIX + key;
5834
+ keyById.set(String(node.id), key);
5835
+ }
5836
+ const out = /* @__PURE__ */ new Map();
5837
+ for (const binding of normalizeBindings(scratch, engine)) {
5838
+ const key = keyById.get(binding.id);
5839
+ if (key !== void 0) out.set(key, binding.animate);
5840
+ }
5841
+ return out;
5842
+ }
5843
+ function animatedNodes(tree) {
5844
+ const out = /* @__PURE__ */ new Map();
5845
+ let counter = 0;
5846
+ const visit = (node) => {
5847
+ if (node.animate) out.set(String(counter++), node);
5848
+ if (node.children) for (const child of node.children) visit(child);
5849
+ };
5850
+ if (tree.children) for (const child of tree.children) visit(child);
5851
+ return out;
5852
+ }
5792
5853
  function materializeAllInTree(doc, engine, options) {
5793
5854
  var _a2, _b;
5794
5855
  let root = materializeNodeEffects(doc).root;
@@ -5800,6 +5861,7 @@ function materializeAllInTree(doc, engine, options) {
5800
5861
  root = materializeAnimatedUseInstances(root);
5801
5862
  root = pruneUnreferencedDefs(root);
5802
5863
  }
5864
+ root = materializeRestPosesInTree(root, engine);
5803
5865
  return root;
5804
5866
  }
5805
5867
  function pruneUnreferencedDefs(root) {
@@ -5831,6 +5893,98 @@ function pruneUnreferencedDefs(root) {
5831
5893
  }
5832
5894
  return root;
5833
5895
  }
5896
+ var PxDiagnosticCode = /* @__PURE__ */ ((PxDiagnosticCode2) => {
5897
+ PxDiagnosticCode2[PxDiagnosticCode2["buildFailed"] = 1001] = "buildFailed";
5898
+ PxDiagnosticCode2[PxDiagnosticCode2["invalidDocumentAtSrc"] = 1002] = "invalidDocumentAtSrc";
5899
+ PxDiagnosticCode2[PxDiagnosticCode2["loadFailed"] = 1003] = "loadFailed";
5900
+ PxDiagnosticCode2[PxDiagnosticCode2["animationBuildFailed"] = 1004] = "animationBuildFailed";
5901
+ PxDiagnosticCode2[PxDiagnosticCode2["effectsShape"] = 1101] = "effectsShape";
5902
+ PxDiagnosticCode2[PxDiagnosticCode2["timelineOverrideIgnored"] = 1102] = "timelineOverrideIgnored";
5903
+ PxDiagnosticCode2[PxDiagnosticCode2["blockedTag"] = 1103] = "blockedTag";
5904
+ PxDiagnosticCode2[PxDiagnosticCode2["unsupportedAnimatedAttrs"] = 1104] = "unsupportedAnimatedAttrs";
5905
+ PxDiagnosticCode2[PxDiagnosticCode2["noBindings"] = 1105] = "noBindings";
5906
+ PxDiagnosticCode2[PxDiagnosticCode2["unresolvedBinding"] = 1106] = "unresolvedBinding";
5907
+ PxDiagnosticCode2[PxDiagnosticCode2["triggersNoRoot"] = 1201] = "triggersNoRoot";
5908
+ PxDiagnosticCode2[PxDiagnosticCode2["noRootForSelector"] = 1202] = "noRootForSelector";
5909
+ PxDiagnosticCode2[PxDiagnosticCode2["noRootElement"] = 1203] = "noRootElement";
5910
+ PxDiagnosticCode2[PxDiagnosticCode2["noElementsForSelector"] = 1206] = "noElementsForSelector";
5911
+ PxDiagnosticCode2[PxDiagnosticCode2["setAttributeNoElement"] = 1207] = "setAttributeNoElement";
5912
+ PxDiagnosticCode2[PxDiagnosticCode2["scrollSmoothingNeedsOwnDriver"] = 1301] = "scrollSmoothingNeedsOwnDriver";
5913
+ PxDiagnosticCode2[PxDiagnosticCode2["scrollNativeUnavailable"] = 1302] = "scrollNativeUnavailable";
5914
+ PxDiagnosticCode2[PxDiagnosticCode2["scrollSubjectInvalid"] = 1303] = "scrollSubjectInvalid";
5915
+ PxDiagnosticCode2[PxDiagnosticCode2["scrollSubjectNoMatch"] = 1304] = "scrollSubjectNoMatch";
5916
+ PxDiagnosticCode2[PxDiagnosticCode2["scrollNoRootToObserve"] = 1305] = "scrollNoRootToObserve";
5917
+ PxDiagnosticCode2[PxDiagnosticCode2["scrollTriggerIgnored"] = 1306] = "scrollTriggerIgnored";
5918
+ PxDiagnosticCode2[PxDiagnosticCode2["rateRejected"] = 1401] = "rateRejected";
5919
+ PxDiagnosticCode2[PxDiagnosticCode2["controlPropsConflict"] = 1501] = "controlPropsConflict";
5920
+ PxDiagnosticCode2[PxDiagnosticCode2["rnCompileFailed"] = 1601] = "rnCompileFailed";
5921
+ PxDiagnosticCode2[PxDiagnosticCode2["rnRenderFailed"] = 1602] = "rnRenderFailed";
5922
+ PxDiagnosticCode2[PxDiagnosticCode2["rnBoundaryCaught"] = 1603] = "rnBoundaryCaught";
5923
+ PxDiagnosticCode2[PxDiagnosticCode2["rnUnsupported"] = 1604] = "rnUnsupported";
5924
+ return PxDiagnosticCode2;
5925
+ })(PxDiagnosticCode || {});
5926
+ var PxDiagnosticKind = {
5927
+ /** The document is wrong — regenerate or repair the file. */
5928
+ document: "document",
5929
+ /** The page or app cannot provide what the document asks for — fix the mount. */
5930
+ host: "host",
5931
+ /** The platform cannot do it and the player degraded — usually nothing to fix. */
5932
+ platform: "platform",
5933
+ /** The call is wrong or self-contradictory — fix the options or props you passed. */
5934
+ usage: "usage",
5935
+ /** The player failed where it did not expect to — report it to us. */
5936
+ internal: "internal"
5937
+ };
5938
+ var DOCS_URL = "https://github.com/pixodesk/pixodesk-svg-animator/blob/main/docs/diagnostics.md";
5939
+ function codeLine(code) {
5940
+ return "PX" + code + " " + DOCS_URL + "#px" + code;
5941
+ }
5942
+ function errorIn(data) {
5943
+ return data.find((d) => d instanceof Error);
5944
+ }
5945
+ function createDiagnostics(config, prefix) {
5946
+ const tag = prefix ? prefix + " " : "";
5947
+ return {
5948
+ warn: (kind, code, ...data) => {
5949
+ const message = codeLine(code);
5950
+ if (config == null ? void 0 : config.onWarn) {
5951
+ config.onWarn({ code, kind, data, message });
5952
+ return;
5953
+ }
5954
+ if (config == null ? void 0 : config.muteWarn) return;
5955
+ console.warn(tag + kind + " " + message, ...data);
5956
+ },
5957
+ error: (kind, code, ...data) => {
5958
+ const message = codeLine(code);
5959
+ const error = errorIn(data);
5960
+ if (config == null ? void 0 : config.onError) {
5961
+ config.onError({ code, kind, data, message, error });
5962
+ return;
5963
+ }
5964
+ if (config == null ? void 0 : config.muteError) return;
5965
+ console.error(tag + kind + " " + message, ...data);
5966
+ }
5967
+ };
5968
+ }
5969
+ var MAX_REPORTED = 6;
5970
+ function diagnoseDocument(doc) {
5971
+ try {
5972
+ return { problems: validateDocument(doc) };
5973
+ } catch (e) {
5974
+ return { problems: [] };
5975
+ }
5976
+ }
5977
+ function reportDocumentDiagnostics(doc, where) {
5978
+ const { problems } = diagnoseDocument(doc);
5979
+ if (!problems.length) return;
5980
+ const shown = problems.slice(0, MAX_REPORTED);
5981
+ const more = problems.length - shown.length;
5982
+ console.warn(
5983
+ where + ": this document does not match the animation schema in " + problems.length + " place" + (problems.length === 1 ? "" : "s") + ".\n" + shown.map((p) => " - " + p).join("\n") + (more > 0 ? "\n \u2026 and " + more + " more" : "") + "\n\nIf you did not author these keys, the usual cause is a build that MANGLES PROPERTY NAMES. An animation document is data loaded at runtime, so renaming the property reads inside the player stops them matching the keys in the JSON, and the animation silently does nothing. Feed the published reserved-name list to your minifier \u2014 @pixodesk/svg-animator-web/mangle-reserved.json \u2014 see docs/library/minification.md."
5984
+ );
5985
+ }
5986
+
5987
+ // ../svg-animator-core/dist/index.js
5834
5988
  var PX_RATE_REJECTED = "setPlaybackRate: rate must be finite and non-zero";
5835
5989
  function isValidPlaybackRate(rate) {
5836
5990
  return Number.isFinite(rate) && rate !== 0;
@@ -5882,13 +6036,13 @@ function createAdapterAnimator(doc, adapter, callbacks) {
5882
6036
  const bindings = normalizeBindings(doc, PxTimelineEngine.js);
5883
6037
  const _iterations = config.iterations;
5884
6038
  let iterations = 1;
5885
- if (typeof _iterations === "number") iterations = _iterations || 1;
6039
+ if (typeof _iterations === "number") iterations = _iterations || PX_DEFAULT_ITERATIONS;
5886
6040
  if (_iterations === "infinite") iterations = Infinity;
5887
6041
  if (iterations < 1) iterations = 1;
5888
6042
  const duration = +(config.duration || PX_DEFAULT_DURATION_MS);
5889
- const totalDuration = duration && iterations ? duration * (iterations === Infinity ? Infinity : iterations) : duration ? (iterations != null ? iterations : 1) * duration : 0;
5890
- const direction = config.direction || "normal";
5891
- const fill = (_a2 = config.fill) != null ? _a2 : "forwards";
6043
+ const totalDuration = duration && iterations ? duration * (iterations === Infinity ? Infinity : iterations) : duration ? (iterations != null ? iterations : PX_DEFAULT_ITERATIONS) * duration : 0;
6044
+ const direction = config.direction || PxTimeTimelineSchema.defaults.direction;
6045
+ const fill = (_a2 = config.fill) != null ? _a2 : PxTimeTimelineSchema.defaults.fillMode;
5892
6046
  const fillsForwards = fill === "forwards" || fill === "both";
5893
6047
  const fillsBackwards = fill === "backwards" || fill === "both";
5894
6048
  let timerId = null;
@@ -6142,36 +6296,6 @@ function createAdapterAnimator(doc, adapter, callbacks) {
6142
6296
  };
6143
6297
  return api;
6144
6298
  }
6145
- var PxDiagnosticCode = /* @__PURE__ */ ((PxDiagnosticCode2) => {
6146
- PxDiagnosticCode2[PxDiagnosticCode2["buildFailed"] = 1001] = "buildFailed";
6147
- PxDiagnosticCode2[PxDiagnosticCode2["invalidDocumentAtSrc"] = 1002] = "invalidDocumentAtSrc";
6148
- PxDiagnosticCode2[PxDiagnosticCode2["loadFailed"] = 1003] = "loadFailed";
6149
- PxDiagnosticCode2[PxDiagnosticCode2["animationBuildFailed"] = 1004] = "animationBuildFailed";
6150
- PxDiagnosticCode2[PxDiagnosticCode2["effectsShape"] = 1101] = "effectsShape";
6151
- PxDiagnosticCode2[PxDiagnosticCode2["timelineOverrideIgnored"] = 1102] = "timelineOverrideIgnored";
6152
- PxDiagnosticCode2[PxDiagnosticCode2["blockedTag"] = 1103] = "blockedTag";
6153
- PxDiagnosticCode2[PxDiagnosticCode2["unsupportedAnimatedAttrs"] = 1104] = "unsupportedAnimatedAttrs";
6154
- PxDiagnosticCode2[PxDiagnosticCode2["noBindings"] = 1105] = "noBindings";
6155
- PxDiagnosticCode2[PxDiagnosticCode2["unresolvedBinding"] = 1106] = "unresolvedBinding";
6156
- PxDiagnosticCode2[PxDiagnosticCode2["triggersNoRoot"] = 1201] = "triggersNoRoot";
6157
- PxDiagnosticCode2[PxDiagnosticCode2["noRootForSelector"] = 1202] = "noRootForSelector";
6158
- PxDiagnosticCode2[PxDiagnosticCode2["noRootElement"] = 1203] = "noRootElement";
6159
- PxDiagnosticCode2[PxDiagnosticCode2["noElementsForSelector"] = 1206] = "noElementsForSelector";
6160
- PxDiagnosticCode2[PxDiagnosticCode2["setAttributeNoElement"] = 1207] = "setAttributeNoElement";
6161
- PxDiagnosticCode2[PxDiagnosticCode2["scrollSmoothingNeedsOwnDriver"] = 1301] = "scrollSmoothingNeedsOwnDriver";
6162
- PxDiagnosticCode2[PxDiagnosticCode2["scrollNativeUnavailable"] = 1302] = "scrollNativeUnavailable";
6163
- PxDiagnosticCode2[PxDiagnosticCode2["scrollSubjectInvalid"] = 1303] = "scrollSubjectInvalid";
6164
- PxDiagnosticCode2[PxDiagnosticCode2["scrollSubjectNoMatch"] = 1304] = "scrollSubjectNoMatch";
6165
- PxDiagnosticCode2[PxDiagnosticCode2["scrollNoRootToObserve"] = 1305] = "scrollNoRootToObserve";
6166
- PxDiagnosticCode2[PxDiagnosticCode2["scrollTriggerIgnored"] = 1306] = "scrollTriggerIgnored";
6167
- PxDiagnosticCode2[PxDiagnosticCode2["rateRejected"] = 1401] = "rateRejected";
6168
- PxDiagnosticCode2[PxDiagnosticCode2["controlPropsConflict"] = 1501] = "controlPropsConflict";
6169
- PxDiagnosticCode2[PxDiagnosticCode2["rnCompileFailed"] = 1601] = "rnCompileFailed";
6170
- PxDiagnosticCode2[PxDiagnosticCode2["rnRenderFailed"] = 1602] = "rnRenderFailed";
6171
- PxDiagnosticCode2[PxDiagnosticCode2["rnBoundaryCaught"] = 1603] = "rnBoundaryCaught";
6172
- PxDiagnosticCode2[PxDiagnosticCode2["rnUnsupported"] = 1604] = "rnUnsupported";
6173
- return PxDiagnosticCode2;
6174
- })(PxDiagnosticCode || {});
6175
6299
  var FLAT_ONLY_KEYS = [
6176
6300
  "timelineSource",
6177
6301
  "scroll",
@@ -6324,6 +6448,50 @@ function applyAnimatorConfig(doc, patch, options) {
6324
6448
  }
6325
6449
 
6326
6450
  // ../svg-animator-core/dist/internal.js
6451
+ var CLASS_NAME_KEY = "className";
6452
+ var CLASS_ATTR2 = "class";
6453
+ var DOM_TYPE_KEY = "domType";
6454
+ var TYPE_ATTR = "type";
6455
+ var DEFAULT_TAG = "g";
6456
+ function renderPxTree(node, factory, diag) {
6457
+ return node ? renderOne(node, factory, diag, true, 0) : null;
6458
+ }
6459
+ function renderOne(node, factory, diag, isRoot, index) {
6460
+ const _a2 = node, { type, children, style } = _a2, props = __objRest(_a2, ["type", "children", "style"]);
6461
+ const tag = type || DEFAULT_TAG;
6462
+ if (PX_DISALLOWED_SVG_TAGS_LOWER.has(tag.toLowerCase())) {
6463
+ (diag != null ? diag : createDiagnostics(void 0, "[PxAnimator]")).warn(PxDiagnosticKind.document, 1103, tag);
6464
+ return null;
6465
+ }
6466
+ const domType = props[DOM_TYPE_KEY];
6467
+ if (domType !== void 0) delete props[DOM_TYPE_KEY];
6468
+ const attrs = {};
6469
+ let inlineStyle;
6470
+ const domProps = toDomProps(props);
6471
+ for (const propName of Object.keys(domProps)) {
6472
+ const sanitized = sanitizeAttributeValue(propName, domProps[propName]);
6473
+ if (sanitized === void 0) continue;
6474
+ if (PX_CSS_ONLY_STYLE_PROPS.has(propName)) {
6475
+ (inlineStyle != null ? inlineStyle : inlineStyle = {})[propName] = String(sanitized);
6476
+ continue;
6477
+ }
6478
+ attrs[propName === CLASS_NAME_KEY ? CLASS_ATTR2 : camelCaseToKebabWordIfNeeded(propName)] = sanitized;
6479
+ }
6480
+ if (domType !== void 0) attrs[TYPE_ATTR] = String(domType);
6481
+ if (style) {
6482
+ for (const styleProp of Object.keys(style)) (inlineStyle != null ? inlineStyle : inlineStyle = {})[styleProp] = String(style[styleProp]);
6483
+ }
6484
+ const rendered = [];
6485
+ if (children) {
6486
+ children.forEach((child, i) => {
6487
+ const el = renderOne(child, factory, diag, false, i);
6488
+ if (el !== null) rendered.push(el);
6489
+ });
6490
+ }
6491
+ const ownText = props[PX_TEXT_CONTENT_ATTR];
6492
+ const text = !rendered.length && typeof ownText === "string" && ownText ? ownText : void 0;
6493
+ return factory({ tag, attrs, style: inlineStyle, children: rendered, text, node, isRoot, index });
6494
+ }
6327
6495
  function isScrollTimeline(config) {
6328
6496
  return (config == null ? void 0 : config.timelineSource) === "scroll";
6329
6497
  }
@@ -6895,7 +7063,7 @@ function createWebApiAnimator(doc, callbacks, rootElement, forceEvenIfHasUnsuppo
6895
7063
  let seekPosition;
6896
7064
  if (config.delay && config.delay < 0 && config.duration) {
6897
7065
  const rawSeek = -config.delay;
6898
- seekPosition = iterations === Infinity ? rawSeek % config.duration : Math.min(rawSeek, config.duration * (iterations != null ? iterations : 1));
7066
+ seekPosition = iterations === Infinity ? rawSeek % config.duration : Math.min(rawSeek, config.duration * (iterations != null ? iterations : PX_DEFAULT_ITERATIONS));
6899
7067
  }
6900
7068
  const effectOptions = {
6901
7069
  duration: config.duration,
@@ -7002,7 +7170,7 @@ function createWebApiAnimator(doc, callbacks, rootElement, forceEvenIfHasUnsuppo
7002
7170
  },
7003
7171
  "setCurrentTime": (time) => {
7004
7172
  var _a3;
7005
- const ceiling = seekCeilingMs((_a3 = config.duration) != null ? _a3 : 0, iterations != null ? iterations : 1);
7173
+ const ceiling = seekCeilingMs((_a3 = config.duration) != null ? _a3 : 0, iterations != null ? iterations : PX_DEFAULT_ITERATIONS);
7006
7174
  const seek = ceiling > 0 ? clampSeekMs(time, ceiling) : Math.max(0, time);
7007
7175
  finishNotified = false;
7008
7176
  animations.forEach((a) => {
@@ -7012,11 +7180,11 @@ function createWebApiAnimator(doc, callbacks, rootElement, forceEvenIfHasUnsuppo
7012
7180
  "getCurrentProgress": () => {
7013
7181
  var _a3;
7014
7182
  const t = api.getCurrentTime();
7015
- return t === null ? null : timeToProgress(t, (_a3 = config.duration) != null ? _a3 : 0, iterations != null ? iterations : 1);
7183
+ return t === null ? null : timeToProgress(t, (_a3 = config.duration) != null ? _a3 : 0, iterations != null ? iterations : PX_DEFAULT_ITERATIONS);
7016
7184
  },
7017
7185
  "setCurrentProgress": (progress) => {
7018
7186
  var _a3;
7019
- api.setCurrentTime(progressToTimeMs(progress, (_a3 = config.duration) != null ? _a3 : 0, iterations != null ? iterations : 1));
7187
+ api.setCurrentTime(progressToTimeMs(progress, (_a3 = config.duration) != null ? _a3 : 0, iterations != null ? iterations : PX_DEFAULT_ITERATIONS));
7020
7188
  },
7021
7189
  "destroy": () => {
7022
7190
  var _a3;
@@ -7389,69 +7557,26 @@ function bindWithEngineChoice(doc, adapter, callbacks, rootElement) {
7389
7557
 
7390
7558
  // src/dom/PxAnimatorDOM.ts
7391
7559
  var SVG_NS = "http://www.w3.org/2000/svg";
7392
- function createElement(tagName, normalizedProps, style, children, textContent, diag) {
7393
- if (PX_DISALLOWED_SVG_TAGS_LOWER.has(tagName.toLowerCase())) {
7394
- (diag != null ? diag : createDiagnostics(void 0, "[PxAnimator]")).warn(PxDiagnosticKind.document, PxDiagnosticCode.blockedTag, tagName);
7395
- return null;
7396
- }
7397
- const element = document.createElementNS(SVG_NS, tagName);
7398
- for (const propName in normalizedProps) {
7399
- const sanitized = sanitizeAttributeValue(propName, normalizedProps[propName]);
7400
- if (sanitized === void 0) continue;
7401
- if (PX_CSS_ONLY_STYLE_PROPS.has(propName)) {
7402
- element.style[propName] = String(sanitized);
7403
- continue;
7404
- }
7405
- element.setAttribute(camelCaseToKebabWordIfNeeded(propName), sanitized);
7406
- }
7560
+ var createDomElement = ({ tag, attrs, style, children, text }) => {
7561
+ const element = document.createElementNS(SVG_NS, tag);
7562
+ for (const name of Object.keys(attrs)) element.setAttribute(name, attrs[name]);
7407
7563
  if (style) {
7408
- for (const styleProp in style) {
7409
- element.style[styleProp] = String(style[styleProp]);
7410
- }
7411
- }
7412
- if (children == null ? void 0 : children.length) {
7413
- for (const child of children) {
7414
- element.appendChild(child);
7415
- }
7416
- } else if (textContent) {
7417
- element.textContent = textContent;
7418
- }
7419
- return element;
7420
- }
7421
- function renderNode(node, defs, diag) {
7422
- if (!node) return null;
7423
- const _a2 = node, { type, children, style } = _a2, props = __objRest(_a2, ["type", "children", "style"]);
7424
- const domType = props.domType;
7425
- if (domType !== void 0) delete props.domType;
7426
- const nodeDefs = getDefinitions(node) || defs;
7427
- const resolvedStyle = style;
7428
- let childElements;
7429
- if (children) {
7430
- for (const ch of children) {
7431
- const child = renderNode(ch, nodeDefs, diag);
7432
- if (child) {
7433
- if (!childElements) childElements = [];
7434
- childElements.push(child);
7435
- }
7436
- }
7564
+ const target = element.style;
7565
+ for (const prop of Object.keys(style)) target[prop] = style[prop];
7437
7566
  }
7438
- const element = createElement(
7439
- type || "g",
7440
- toDomProps(props),
7441
- resolvedStyle,
7442
- childElements,
7443
- props[PX_TEXT_CONTENT_ATTR],
7444
- diag
7445
- );
7446
- if (element && domType !== void 0) element.setAttribute("type", domType);
7567
+ for (const child of children) element.appendChild(child);
7568
+ if (text !== void 0) element.textContent = text;
7447
7569
  return element;
7570
+ };
7571
+ function renderNode(node, _defs, diag) {
7572
+ return renderPxTree(node, createDomElement, diag);
7448
7573
  }
7449
7574
 
7450
7575
  // src/animator/PxAnimator.ts
7451
7576
  function createAnimatorFromConfig(doc, adapter, callbacks, rootElement) {
7452
7577
  return bindWithEngineChoice(doc, adapter, callbacks, rootElement);
7453
7578
  }
7454
- function createAnimatorImpl(doc, adapter, callbacks, containerElement, patch, resetTimeline) {
7579
+ function createAnimatorImpl(doc, adapter, callbacks, containerElement, patch, resetTimeline, providedRoot) {
7455
7580
  const diag = createDiagnostics(callbacks, "[PxAnimator]");
7456
7581
  const effectsWarnings = validateNodeEffects(doc);
7457
7582
  for (const w of effectsWarnings) diag.warn(PxDiagnosticKind.document, PxDiagnosticCode.effectsShape, w);
@@ -7475,6 +7600,7 @@ function createAnimatorImpl(doc, adapter, callbacks, containerElement, patch, re
7475
7600
  }
7476
7601
  }
7477
7602
  }
7603
+ if (!rootElement && providedRoot) rootElement = providedRoot;
7478
7604
  const api = createAnimatorFromConfig(doc, adapter, callbacks, rootElement);
7479
7605
  if (containerElement && rootElement) {
7480
7606
  const rendered = rootElement;
@@ -7487,7 +7613,7 @@ function createAnimatorImpl(doc, adapter, callbacks, containerElement, patch, re
7487
7613
  return api;
7488
7614
  }
7489
7615
  function isInternalOptions(options) {
7490
- return "adapter" in options;
7616
+ return "adapter" in options || "rootElement" in options;
7491
7617
  }
7492
7618
  function resolveTimelineOption(options) {
7493
7619
  const { timeline, duration, delay, iterations, start } = options;
@@ -7496,6 +7622,7 @@ function resolveTimelineOption(options) {
7496
7622
  function createAnimator(options) {
7497
7623
  const { src, doc, container, resetTimeline } = options;
7498
7624
  const adapter = isInternalOptions(options) ? options.adapter : void 0;
7625
+ const providedRoot = isInternalOptions(options) ? options.rootElement : void 0;
7499
7626
  const patch = resolveTimelineOption(options);
7500
7627
  let proxy;
7501
7628
  const callbacks = withRegistryEvents(toEngineCallbacks(options), () => proxy);
@@ -7528,7 +7655,7 @@ function createAnimator(options) {
7528
7655
  };
7529
7656
  const build = (document2) => {
7530
7657
  try {
7531
- ready(createAnimatorImpl(document2, adapter, callbacks, container, patch, resetTimeline));
7658
+ ready(createAnimatorImpl(document2, adapter, callbacks, container, patch, resetTimeline, providedRoot));
7532
7659
  } catch (e) {
7533
7660
  const err = asThrownError(e);
7534
7661
  failed(PxDiagnosticKind.internal, PxDiagnosticCode.buildFailed, err);