@pixodesk/svg-animator-web 1.0.30 → 1.0.34

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -316,6 +316,38 @@ var PixodeskAnimator = (() => {
316
316
  if (o) segs.push("translate(" + -o[0] + tu + "," + -o[1] + tu + ")");
317
317
  return segs.join("");
318
318
  }
319
+ function parseTransformParts(str2) {
320
+ var _a, _b;
321
+ if (!str2 || typeof str2 !== "string") return void 0;
322
+ const out = {};
323
+ const re = /([a-zA-Z]+)\s*\(([^)]*)\)/g;
324
+ const order = ["translate", "rotate", "skewX", "scale"];
325
+ let lastIdx = -1;
326
+ let m;
327
+ while ((m = re.exec(str2)) !== null) {
328
+ const fn = m[1];
329
+ const idx = order.indexOf(fn);
330
+ if (idx < 0 || idx <= lastIdx) return void 0;
331
+ lastIdx = idx;
332
+ const nums = m[2].split(/[\s,]+/).filter(Boolean).map(Number);
333
+ if (nums.some((n) => Number.isNaN(n))) return void 0;
334
+ if (fn === "translate") {
335
+ if (nums.length < 1 || nums.length > 2) return void 0;
336
+ out.translate = [nums[0], (_a = nums[1]) != null ? _a : 0];
337
+ } else if (fn === "rotate") {
338
+ if (nums.length !== 1) return void 0;
339
+ out.rotate = nums[0];
340
+ } else if (fn === "skewX") {
341
+ if (nums.length !== 1) return void 0;
342
+ out.skew = nums[0];
343
+ } else {
344
+ if (nums.length < 1 || nums.length > 2) return void 0;
345
+ out.scale = [nums[0], (_b = nums[1]) != null ? _b : nums[0]];
346
+ }
347
+ }
348
+ if (str2.replace(/([a-zA-Z]+)\s*\(([^)]*)\)/g, "").replace(/[\s,]/g, "").length) return void 0;
349
+ return Object.keys(out).length ? out : void 0;
350
+ }
319
351
  var STYLE_ATTR_NAMES = /* @__PURE__ */ new Set(["offset-distance", "offsetDistance"]);
320
352
  var DEFAULT_DURATION_MS = 1e3;
321
353
  function kebabToCamelCaseWord(kebab) {
@@ -647,6 +679,8 @@ var PixodeskAnimator = (() => {
647
679
  constructor(schemas, defaultVal) {
648
680
  super();
649
681
  this.schemas = schemas;
682
+ /** Structural tag read by {@link describeSchema} — `schemas` alone cannot tell Union from Tuple. */
683
+ this._kind = "union";
650
684
  this._default = defaultVal != null ? defaultVal : schemas[0]._default;
651
685
  }
652
686
  sanitize(raw) {
@@ -671,6 +705,8 @@ var PixodeskAnimator = (() => {
671
705
  super();
672
706
  this._key = _key;
673
707
  this._schemas = _schemas;
708
+ /** Structural tag read by {@link describeSchema}. */
709
+ this._kind = "discriminatedUnion";
674
710
  this._default = defaultVal != null ? defaultVal : _schemas[0]._default;
675
711
  this._map = /* @__PURE__ */ new Map();
676
712
  for (const s of _schemas) {
@@ -833,6 +869,8 @@ var PixodeskAnimator = (() => {
833
869
  constructor(value) {
834
870
  super();
835
871
  this.value = value;
872
+ /** Structural tag read by {@link describeSchema}. */
873
+ this._kind = "record";
836
874
  this._default = {};
837
875
  }
838
876
  sanitize(raw) {
@@ -918,6 +956,8 @@ var PixodeskAnimator = (() => {
918
956
  constructor(schemas) {
919
957
  super();
920
958
  this.schemas = schemas;
959
+ /** Structural tag read by {@link describeSchema} — `schemas` alone cannot tell Tuple from Union. */
960
+ this._kind = "tuple";
921
961
  this._default = schemas.map((s) => s._default);
922
962
  }
923
963
  sanitize(raw) {
@@ -1082,7 +1122,51 @@ var PixodeskAnimator = (() => {
1082
1122
  }
1083
1123
  function getAnimatorConfig(doc) {
1084
1124
  var _a;
1085
- return (doc == null ? void 0 : doc.animator) || ((_a = doc == null ? void 0 : doc.meta) == null ? void 0 : _a.animator);
1125
+ const cfg = (doc == null ? void 0 : doc.animator) || ((_a = doc == null ? void 0 : doc.meta) == null ? void 0 : _a.animator);
1126
+ return cfg ? flattenAnimatorTimeline(cfg) : void 0;
1127
+ }
1128
+ var flattenMemo = /* @__PURE__ */ new WeakMap();
1129
+ function flattenAnimatorTimeline(cfg) {
1130
+ const timeline = cfg.timeline;
1131
+ if (timeline === void 0 || timeline === null || typeof timeline !== "object") return cfg;
1132
+ const memoised = flattenMemo.get(cfg);
1133
+ if (memoised) return memoised;
1134
+ const _a = cfg, { timeline: _dropped } = _a, flat = __objRest(_a, ["timeline"]);
1135
+ if (timeline.type === "scroll" || timeline.type === "view") {
1136
+ flat.timelineSource = "scroll";
1137
+ if (timeline.duration !== void 0) flat.duration = timeline.duration;
1138
+ if (timeline.iterations !== void 0) flat.iterations = timeline.iterations;
1139
+ const scroll = __spreadValues({}, flat.scroll || {});
1140
+ scroll.kind = timeline.type;
1141
+ if (timeline.engine !== void 0) scroll.driver = timeline.engine;
1142
+ if (timeline.axis !== void 0) scroll.axis = timeline.axis;
1143
+ if (timeline.source !== void 0) scroll.source = timeline.source;
1144
+ if (timeline.subject !== void 0) scroll.subject = timeline.subject;
1145
+ if (timeline.smoothing !== void 0) scroll.smoothing = timeline.smoothing;
1146
+ if (timeline.range !== void 0) scroll.range = timeline.range;
1147
+ const pin = timeline.pin;
1148
+ if (typeof pin === "boolean") scroll.pin = pin;
1149
+ else if (pin && typeof pin === "object") {
1150
+ scroll.pin = true;
1151
+ if (pin.align !== void 0) scroll.pinAlign = pin.align;
1152
+ if (pin.top !== void 0) scroll.pinTop = pin.top;
1153
+ if (pin.distance !== void 0) scroll.pinDistance = pin.distance;
1154
+ }
1155
+ flat.scroll = scroll;
1156
+ } else {
1157
+ if (timeline.duration !== void 0) flat.duration = timeline.duration;
1158
+ if (timeline.trigger !== void 0) {
1159
+ const _b = timeline.trigger, { onFinish } = _b, restTrigger = __objRest(_b, ["onFinish"]);
1160
+ if (Object.keys(restTrigger).length) flat.trigger = restTrigger;
1161
+ if (onFinish !== void 0) flat.resetOnFinish = onFinish === "reset";
1162
+ }
1163
+ if (timeline.delay !== void 0) flat.delay = timeline.delay;
1164
+ if (timeline.iterations !== void 0) flat.iterations = timeline.iterations;
1165
+ if (timeline.direction !== void 0) flat.direction = timeline.direction;
1166
+ if (timeline.fill !== void 0) flat.fill = timeline.fill;
1167
+ }
1168
+ flattenMemo.set(cfg, flat);
1169
+ return flat;
1086
1170
  }
1087
1171
  function getDefs(doc) {
1088
1172
  var _a;
@@ -1094,7 +1178,7 @@ var PixodeskAnimator = (() => {
1094
1178
  if (!doc) return void 0;
1095
1179
  const animateById = (_a = getAnimatorConfig(doc)) == null ? void 0 : _a.animateById;
1096
1180
  if (!animateById) return void 0;
1097
- return Object.entries(animateById).map(([id, anim]) => ({ id, animate: anim }));
1181
+ return Object.entries(animateById).map(([id, anim]) => ({ id: id.startsWith("#") ? id.slice(1) : id, animate: anim }));
1098
1182
  }
1099
1183
 
1100
1184
  // ../svg-animator-core/src/PxAnimatorTypes.ts
@@ -1107,27 +1191,27 @@ var PixodeskAnimator = (() => {
1107
1191
  // e.g. for colors
1108
1192
  px.number(),
1109
1193
  px.array(px.number()),
1110
- px.lazy(() => PxTransformPartsSchema, {}),
1194
+ // ORDER LAW: the key-discriminated object shapes (`{path}`, `{paths}`) come BEFORE the
1195
+ // all-optional transform-parts record. In default (non-strict) mode that record accepts
1196
+ // ANY object (every key optional, unknown keys ignored), so listing it earlier made
1197
+ // Union.sanitize route `{path}`/`{paths}` values into it and strip them to `{}` —
1198
+ // silent morph-data loss (repro: the editor's keyframeValueSanitize spec). Validity is
1199
+ // order-independent (`some()`); only sanitize routing depends on this order.
1111
1200
  px.object({ path: px.string() }),
1112
1201
  px.lazy(() => px.object({ paths: px.array(PxBezierPathSchema) }), { paths: [] }),
1113
1202
  // Gradient `stops` timeline — each kf value is the full stops-array snapshot.
1114
- px.lazy(() => px.array(PxGradientStopSchema), [])
1203
+ px.lazy(() => px.array(PxGradientStopSchema), []),
1204
+ px.lazy(() => PxTransformPartsSchema, {})
1115
1205
  ]));
1116
1206
  var PxKeyframeSchema = implementsInterface()(px.object({
1117
1207
  time: px.number().optional(),
1118
- t: px.number().optional(),
1119
1208
  value: PxKeyframeValueSchema.optional(),
1120
- v: PxKeyframeValueSchema.optional(),
1121
1209
  easing: PxEasingOrRefSchema.optional(),
1122
- e: PxEasingOrRefSchema.optional(),
1123
1210
  tangentOut: px.tuple([px.number(), px.number()]).optional(),
1124
- to: px.tuple([px.number(), px.number()]).optional(),
1125
- // short alias
1126
- tangentIn: px.tuple([px.number(), px.number()]).optional(),
1127
- ti: px.tuple([px.number(), px.number()]).optional(),
1128
- // short alias
1129
- selected: px.boolean().optional()
1130
- // editor-side UI state (Player ignores it)
1211
+ tangentIn: px.tuple([px.number(), px.number()]).optional()
1212
+ // (`selected` — editor timeline-selection UI state — was REMOVED from the wire
1213
+ // (review §1.3): editor data lives under `meta`. The editor still carries it on
1214
+ // its internal COPY-PASTE payload, which never validates against this schema.)
1131
1215
  }));
1132
1216
  var PxLoopSchema = implementsInterface()(px.object({
1133
1217
  segmentCount: px.number().optional(),
@@ -1137,7 +1221,6 @@ var PixodeskAnimator = (() => {
1137
1221
  var PxPropertyAnimationSchema = implementsInterface()(px.object({
1138
1222
  value: PxKeyframeValueSchema.optional(),
1139
1223
  keyframes: px.array(PxKeyframeSchema).optional(),
1140
- kfs: px.array(PxKeyframeSchema).optional(),
1141
1224
  loop: px.union([PxLoopSchema, px.boolean()]).optional(),
1142
1225
  autoOrient: px.boolean().optional()
1143
1226
  }));
@@ -1165,6 +1248,11 @@ var PixodeskAnimator = (() => {
1165
1248
  var PxTriggerSchema = implementsInterface()(px.object({
1166
1249
  startOn: px.enum(["load", "mouseOver", "click", "scrollIntoView", "programmatic"]).optional(),
1167
1250
  outAction: px.enum(["continue", "pause", "reset", "reverse"]).optional(),
1251
+ // What happens after a NATURAL finish — `'hold'` (default: keep the end state per
1252
+ // `fill`) or `'reset'` (snap back to the start state). The trigger-vocabulary home of
1253
+ // the old top-level `resetOnFinish: boolean` (read-legacy) — review §2.3: both
1254
+ // "what happens at the end" knobs now sit side by side and share one style of value.
1255
+ onFinish: px.enum(["hold", "reset"]).optional(),
1168
1256
  scrollIntoViewThreshold: px.number().optional()
1169
1257
  }));
1170
1258
  var PxGlyphSchema = implementsInterface()(px.object({
@@ -1172,8 +1260,8 @@ var PixodeskAnimator = (() => {
1172
1260
  d: px.string()
1173
1261
  }));
1174
1262
  var PxGlyphFontSchema = implementsInterface()(px.object({
1175
- fFamily: px.string(),
1176
- style: px.string(),
1263
+ fontFamily: px.string(),
1264
+ fontStyle: px.string(),
1177
1265
  ascent: px.number(),
1178
1266
  unitsPerEm: px.number(),
1179
1267
  glyphs: px.record(PxGlyphSchema)
@@ -1181,7 +1269,9 @@ var PixodeskAnimator = (() => {
1181
1269
  var PxDefsSchema = implementsInterface()(px.object({
1182
1270
  easings: px.record(px.tuple([px.number(), px.number(), px.number(), px.number()])).optional(),
1183
1271
  animations: px.record(PxAnimationDefinitionSchema).optional(),
1184
- styles: px.record(px.any()).optional(),
1272
+ // Review §2.6: the schema now matches the declared type — a style preset is a flat
1273
+ // record of string|number attribute values, nothing nested.
1274
+ styles: px.record(px.record(px.union([px.string(), px.number()]))).optional(),
1185
1275
  glyphs: px.record(PxGlyphFontSchema).optional()
1186
1276
  }));
1187
1277
  var PX_SCROLL_PHASES = ["cover", "contain", "entry", "exit", "entry-crossing", "exit-crossing"];
@@ -1207,22 +1297,54 @@ var PixodeskAnimator = (() => {
1207
1297
  pinDistance: px.number().optional(),
1208
1298
  range: PxScrollRangeSchema.optional()
1209
1299
  }));
1210
- var PxAnimatorConfigSchema = implementsInterface()(px.object({
1211
- mode: px.enum([PxAnimatorMode.auto, PxAnimatorMode.waapi, PxAnimatorMode.frames]).optional(),
1300
+ var PxTimelinePinSchema = px.object({
1301
+ align: px.enum(["top", "center", "bottom"]).optional(),
1302
+ top: px.number().optional(),
1303
+ distance: px.number().optional()
1304
+ });
1305
+ var PxClockTimelineSchema = px.object({
1306
+ type: px.literal("clock"),
1307
+ // §2.8: duration is a property of the TIMELINE — how long one pass takes.
1212
1308
  duration: px.number().optional(),
1309
+ trigger: PxTriggerSchema.optional(),
1213
1310
  delay: px.number().optional(),
1214
- // LAW (SCHEMA-DESIGN R3, S10): the ONE sanctioned string-in-number union
1215
- // (CSS animation-iteration-count familiarity) — do not add more mixed unions.
1216
1311
  iterations: px.union([px.number(), px.literal("infinite")]).optional(),
1217
1312
  fill: px.enum(["forwards", "backwards", "both", "none"]).optional(),
1218
- direction: px.enum(["normal", "reverse", "alternate", "alternate-reverse"]).optional(),
1313
+ direction: px.enum(["normal", "reverse", "alternate", "alternate-reverse"]).optional()
1314
+ });
1315
+ var scrollishTimelineShape = {
1316
+ // §2.8: duration is a property of the TIMELINE — under scrubbing it is the keyframe
1317
+ // span the scroll range maps onto.
1318
+ duration: px.number().optional(),
1319
+ // Finite repeat count IS meaningful when scrubbing — the scroll range maps onto
1320
+ // duration × iterations (rule D4; `'infinite'` cannot map to a range, so no literal here).
1321
+ iterations: px.number().optional(),
1322
+ engine: px.enum(["custom", "native"]).optional(),
1323
+ axis: px.enum(["block", "inline", "x", "y"]).optional(),
1324
+ source: px.enum(["nearest", "root"]).optional(),
1325
+ subject: px.string().optional(),
1326
+ // 'parent' | 'scroller' | any CSS selector
1327
+ smoothing: px.number().optional(),
1328
+ // ms
1329
+ pin: px.union([px.boolean(), PxTimelinePinSchema]).optional(),
1330
+ range: PxScrollRangeSchema.optional()
1331
+ };
1332
+ var PxScrollTimelineSchema = px.object(__spreadValues({ type: px.literal("scroll") }, scrollishTimelineShape));
1333
+ var PxViewTimelineSchema = px.object(__spreadValues({ type: px.literal("view") }, scrollishTimelineShape));
1334
+ var PxTimelineSchema = px.discriminatedUnion("type", [
1335
+ PxClockTimelineSchema,
1336
+ PxScrollTimelineSchema,
1337
+ PxViewTimelineSchema
1338
+ ]);
1339
+ var PxAnimatorConfigSchema = implementsInterface()(px.object({
1340
+ mode: px.enum([PxAnimatorMode.auto, PxAnimatorMode.waapi, PxAnimatorMode.frames]).optional(),
1341
+ // (`duration` lives INSIDE `timeline` on the wire — §2.8; the flat field below
1342
+ // exists only on the runtime view, like the rest of the playback dynamics.)
1219
1343
  frameRate: px.number().optional(),
1220
- trigger: PxTriggerSchema.optional(),
1221
- resetOnFinish: px.boolean().optional(),
1344
+ // THE spelling of "what advances progress" — clock / scroll / view (review §2.1).
1345
+ timeline: PxTimelineSchema.optional(),
1222
1346
  definitions: PxDefsSchema.optional(),
1223
1347
  animateById: px.record(PxElementAnimationSchema).optional(),
1224
- timelineSource: px.string().optional(),
1225
- scroll: PxScrollSchema.optional(),
1226
1348
  debugInstName: px.string().optional()
1227
1349
  }));
1228
1350
  var PxBindingSchema = implementsInterface()(px.object({
@@ -1241,18 +1363,18 @@ var PixodeskAnimator = (() => {
1241
1363
  ]);
1242
1364
  var PxAnimatableNumberSchema = px.union([
1243
1365
  px.number(),
1244
- px.object({ value: px.number() }),
1245
- PxPropertyAnimationSchema
1366
+ PxPropertyAnimationSchema,
1367
+ px.object({ value: px.number() })
1246
1368
  ]);
1247
1369
  var PxAnimatableVec2Schema = px.union([
1248
1370
  px.tuple([px.number(), px.number()]),
1249
- px.object({ value: px.tuple([px.number(), px.number()]) }),
1250
- PxPropertyAnimationSchema
1371
+ PxPropertyAnimationSchema,
1372
+ px.object({ value: px.tuple([px.number(), px.number()]) })
1251
1373
  ]);
1252
1374
  var PxAnimatableStringSchema = px.union([
1253
1375
  px.string(),
1254
- px.object({ value: px.string() }),
1255
- PxPropertyAnimationSchema
1376
+ PxPropertyAnimationSchema,
1377
+ px.object({ value: px.string() })
1256
1378
  ]);
1257
1379
  var PxTransformByEffectSchema = implementsInterface()(px.object({
1258
1380
  translate: PxAnimatableVec2Schema.optional(),
@@ -1282,8 +1404,7 @@ var PixodeskAnimator = (() => {
1282
1404
  height: px.number().optional()
1283
1405
  }));
1284
1406
  var PxClipPathEffectSchema = implementsInterface()(px.object({
1285
- d: PxAnimatableStringSchema.optional(),
1286
- animate: PxPropertyAnimationSchema.optional()
1407
+ d: PxAnimatableStringSchema.optional()
1287
1408
  }));
1288
1409
  var PxStrokeTrimEffectSchema = implementsInterface()(px.object({
1289
1410
  offset: PxAnimatableNumberSchema.optional(),
@@ -1291,7 +1412,6 @@ var PixodeskAnimator = (() => {
1291
1412
  subPaths: px.enum([PxStrokeTrimSubPaths.separate, PxStrokeTrimSubPaths.combined]).optional()
1292
1413
  }));
1293
1414
  var PxRetimeEffectSchema = implementsInterface()(px.object({
1294
- sourceId: px.string().optional(),
1295
1415
  start: px.number().optional(),
1296
1416
  stretch: px.number().optional(),
1297
1417
  timeCrop: px.tuple([px.number(), px.number()]).optional()
@@ -1314,11 +1434,11 @@ var PixodeskAnimator = (() => {
1314
1434
  var PxFillGradientEffectSchema = implementsInterface()(px.object({
1315
1435
  // Contextual kind — the `type` convention, see `PxNodeBase.type`.
1316
1436
  type: px.enum([PxGradientType.linear, PxGradientType.radial]),
1317
- p1: PxAnimatableVec2Schema.optional(),
1318
- p2: PxAnimatableVec2Schema.optional(),
1319
- c: PxAnimatableVec2Schema.optional(),
1320
- r: PxAnimatableNumberSchema.optional(),
1321
- fp: PxAnimatableVec2Schema.optional(),
1437
+ start: PxAnimatableVec2Schema.optional(),
1438
+ end: PxAnimatableVec2Schema.optional(),
1439
+ center: PxAnimatableVec2Schema.optional(),
1440
+ radius: PxAnimatableNumberSchema.optional(),
1441
+ focal: PxAnimatableVec2Schema.optional(),
1322
1442
  stops: PxAnimatableGradientStopsSchema.optional(),
1323
1443
  gradientUnits: px.enum([PxGradientUnits.userSpaceOnUse, PxGradientUnits.objectBoundingBox]).optional(),
1324
1444
  spreadMethod: px.enum([PxGradientSpreadMethod.pad, PxGradientSpreadMethod.reflect, PxGradientSpreadMethod.repeat]).optional(),
@@ -1510,9 +1630,11 @@ var PixodeskAnimator = (() => {
1510
1630
  const docAnimate = (_a = cloned.animator) == null ? void 0 : _a.animateById;
1511
1631
  if (docAnimate && typeof docAnimate === "object") {
1512
1632
  const updatedAnimate = {};
1513
- for (const [id, anim] of Object.entries(docAnimate)) {
1633
+ for (const [key, anim] of Object.entries(docAnimate)) {
1634
+ const hashed = key.startsWith("#");
1635
+ const id = hashed ? key.slice(1) : key;
1514
1636
  const newId = (_b = idMap.get(id)) != null ? _b : id;
1515
- updatedAnimate[newId] = anim;
1637
+ updatedAnimate[hashed ? "#" + newId : newId] = anim;
1516
1638
  }
1517
1639
  cloned.animator = __spreadProps(__spreadValues({}, cloned.animator), { animateById: updatedAnimate });
1518
1640
  }
@@ -1605,7 +1727,7 @@ var PixodeskAnimator = (() => {
1605
1727
  let value = props[rawKey];
1606
1728
  if (COLOUR_ATTR_NAMES.has(key) && Array.isArray(value)) {
1607
1729
  propsCopy[key] = toRGBA(value);
1608
- } else if (key === "transform" && value !== null && typeof value === "object" && !Array.isArray(value) && !value.keyframes && !value.kfs) {
1730
+ } else if (key === "transform" && value !== null && typeof value === "object" && !Array.isArray(value) && !value.keyframes) {
1609
1731
  const parts = value.value && typeof value.value === "object" ? value.value : value;
1610
1732
  propsCopy["transform"] = composeTransformParts(parts, { withUnits: false });
1611
1733
  } else if (TRANSFORM_FN_NAMES.has(key)) {
@@ -1645,12 +1767,12 @@ var PixodeskAnimator = (() => {
1645
1767
  return (_a = kf.easing) != null ? _a : kf.e;
1646
1768
  }
1647
1769
  function propAnimIsMotionPath(anim) {
1648
- var _a, _b, _c;
1649
- const kfs = (_a = anim.keyframes) != null ? _a : anim.kfs;
1770
+ var _a, _b;
1771
+ const kfs = anim.keyframes;
1650
1772
  if (!Array.isArray(kfs)) return false;
1651
1773
  if (anim.autoOrient) return true;
1652
1774
  for (const kf of kfs) {
1653
- if (((_b = kf.tangentIn) != null ? _b : kf.ti) || ((_c = kf.tangentOut) != null ? _c : kf.to)) return true;
1775
+ if (((_a = kf.tangentIn) != null ? _a : kf.ti) || ((_b = kf.tangentOut) != null ? _b : kf.to)) return true;
1654
1776
  }
1655
1777
  return false;
1656
1778
  }
@@ -1711,14 +1833,14 @@ var PixodeskAnimator = (() => {
1711
1833
  var DEFAULT_ROTATION_TOL = 5;
1712
1834
  var DEFAULT_MAX_SAMPLES = 32;
1713
1835
  function materialiseMotionPathInPropAnim(anim, opts) {
1714
- var _a, _b, _c, _d;
1836
+ var _a, _b, _c;
1715
1837
  if (!propAnimIsMotionPath(anim)) return anim;
1716
- const kfs = (_a = anim.keyframes) != null ? _a : anim.kfs;
1838
+ const kfs = anim.keyframes;
1717
1839
  if (!Array.isArray(kfs) || kfs.length < 2) return anim;
1718
1840
  const autoOrient = !!anim.autoOrient;
1719
- const flatnessTol = (_b = opts == null ? void 0 : opts.flatnessTolerance) != null ? _b : DEFAULT_FLATNESS_TOL;
1720
- const rotationTol = (_c = opts == null ? void 0 : opts.rotationTolerance) != null ? _c : DEFAULT_ROTATION_TOL;
1721
- const maxSamples = (_d = opts == null ? void 0 : opts.maxSamplesPerSegment) != null ? _d : DEFAULT_MAX_SAMPLES;
1841
+ const flatnessTol = (_a = opts == null ? void 0 : opts.flatnessTolerance) != null ? _a : DEFAULT_FLATNESS_TOL;
1842
+ const rotationTol = (_b = opts == null ? void 0 : opts.rotationTolerance) != null ? _b : DEFAULT_ROTATION_TOL;
1843
+ const maxSamples = (_c = opts == null ? void 0 : opts.maxSamplesPerSegment) != null ? _c : DEFAULT_MAX_SAMPLES;
1722
1844
  const out = [];
1723
1845
  const firstPos = getKfTranslate(kfs[0]);
1724
1846
  if (!firstPos) return anim;
@@ -1747,7 +1869,7 @@ var PixodeskAnimator = (() => {
1747
1869
  const lastInE = getKfEasing(kfs[kfs.length - 1]);
1748
1870
  if (lastInE) out[out.length - 1].e = lastInE;
1749
1871
  if (autoOrient) unwrapAutoOrientRotations(out);
1750
- const result = { kfs: out };
1872
+ const result = { keyframes: out };
1751
1873
  if (anim.loop !== void 0) result.loop = anim.loop;
1752
1874
  return result;
1753
1875
  }
@@ -2409,7 +2531,7 @@ var PixodeskAnimator = (() => {
2409
2531
  }
2410
2532
  function normalizeKeyframes(propName, propAnim, duration, defs) {
2411
2533
  var _a, _b, _c, _d, _e, _f, _g;
2412
- const keyframes = propAnim.keyframes || propAnim.kfs || [];
2534
+ const keyframes = propAnim.keyframes || [];
2413
2535
  const normalized = [];
2414
2536
  for (const kf of keyframes) {
2415
2537
  const timePct = (_b = (_a = kf.time) != null ? _a : kf.t) != null ? _b : 0;
@@ -2454,17 +2576,16 @@ var PixodeskAnimator = (() => {
2454
2576
  return merged;
2455
2577
  }
2456
2578
  function materialiseInternalLoopsInPropAnim(propName, propAnim, duration) {
2457
- var _a;
2458
2579
  const loopRaw = propAnim.loop;
2459
2580
  if (loopRaw === void 0 || loopRaw === null || loopRaw === false) return propAnim;
2460
2581
  const loop = loopRaw === true ? {} : loopRaw;
2461
- const rawKfs = (_a = propAnim.keyframes) != null ? _a : propAnim.kfs;
2582
+ const rawKfs = propAnim.keyframes;
2462
2583
  if (!Array.isArray(rawKfs) || rawKfs.length < 2) return propAnim;
2463
2584
  const propNameKebab = isCamelCaseWord(propName) ? camelCaseToKebabWordIfNeeded(propName) : propName;
2464
2585
  const isColour = COLOUR_ATTR_NAMES.has(propNameKebab);
2465
2586
  const kfs = rawKfs.map((kf) => {
2466
- var _a2, _b, _c, _d, _e, _f, _g, _h;
2467
- const t = (_a2 = kf.t) != null ? _a2 : kf.time;
2587
+ var _a, _b, _c, _d, _e, _f, _g, _h;
2588
+ const t = (_a = kf.t) != null ? _a : kf.time;
2468
2589
  let v = (_b = kf.v) != null ? _b : kf.value;
2469
2590
  if (propName === "d") v = normalizePathValue(v);
2470
2591
  if (isColour) v = (_c = parseColor(v)) != null ? _c : v;
@@ -2475,7 +2596,7 @@ var PixodeskAnimator = (() => {
2475
2596
  return out2;
2476
2597
  });
2477
2598
  const expanded = expandLoopKeyframes(propName, kfs, loop, duration);
2478
- const out = { kfs: expanded };
2599
+ const out = { keyframes: expanded };
2479
2600
  if (propAnim.autoOrient !== void 0) out.autoOrient = propAnim.autoOrient;
2480
2601
  return out;
2481
2602
  }
@@ -2517,6 +2638,36 @@ var PixodeskAnimator = (() => {
2517
2638
  function generateElementId() {
2518
2639
  return "_px_el_" + ++_elementIdCounter;
2519
2640
  }
2641
+ function mergeStaticTransformIntoAnimDef(animDef, staticTransform) {
2642
+ if (!animDef) return animDef;
2643
+ const staticParts = staticTransform && typeof staticTransform === "object" && !Array.isArray(staticTransform) ? staticTransform : parseTransformParts(staticTransform);
2644
+ if (!staticParts || !Object.keys(staticParts).length) return animDef;
2645
+ const mergeKfValue = (v) => v && typeof v === "object" && !Array.isArray(v) ? __spreadValues(__spreadValues({}, staticParts), v) : v;
2646
+ const transformAnim = animDef["transform"];
2647
+ if (transformAnim && typeof transformAnim === "object") {
2648
+ const anim = transformAnim;
2649
+ if (Array.isArray(anim.keyframes)) {
2650
+ const out = __spreadProps(__spreadValues({}, anim), {
2651
+ keyframes: anim.keyframes.map((kf) => __spreadProps(__spreadValues({}, kf), { value: mergeKfValue(kf.value) }))
2652
+ });
2653
+ if (out.value !== void 0) out.value = mergeKfValue(out.value);
2654
+ return __spreadProps(__spreadValues({}, animDef), { transform: out });
2655
+ }
2656
+ return animDef;
2657
+ }
2658
+ const channels = Object.keys(animDef).filter((k) => TRANSFORM_FN_NAMES.has(k));
2659
+ if (channels.length !== 1) return animDef;
2660
+ const ch = channels[0];
2661
+ const chAnim = animDef[ch];
2662
+ if (!chAnim || typeof chAnim !== "object" || !Array.isArray(chAnim.keyframes)) return animDef;
2663
+ const lifted = __spreadProps(__spreadValues({}, chAnim), {
2664
+ keyframes: chAnim.keyframes.map((kf) => __spreadProps(__spreadValues({}, kf), { value: __spreadProps(__spreadValues({}, staticParts), { [ch]: kf.value }) }))
2665
+ });
2666
+ if (lifted.value !== void 0) lifted.value = __spreadProps(__spreadValues({}, staticParts), { [ch]: lifted.value });
2667
+ const rest = __spreadValues({}, animDef);
2668
+ delete rest[ch];
2669
+ return __spreadProps(__spreadValues({}, rest), { transform: lifted });
2670
+ }
2520
2671
  function normalizeAnimationDefinition(animDef, duration, defs, engine = PxAnimatorEngine.waapi) {
2521
2672
  const normalized = {};
2522
2673
  for (const [propName, propAnim] of Object.entries(animDef)) {
@@ -2525,7 +2676,7 @@ var PixodeskAnimator = (() => {
2525
2676
  }
2526
2677
  const normalizedKfs = normalizeKeyframes(propName, propAnim, duration, defs);
2527
2678
  if (normalizedKfs.length > 0) {
2528
- const out = { kfs: normalizedKfs };
2679
+ const out = { keyframes: normalizedKfs };
2529
2680
  if (propAnim.autoOrient !== void 0) out.autoOrient = propAnim.autoOrient;
2530
2681
  if (propAnim.loop !== void 0) out.loop = propAnim.loop;
2531
2682
  normalized[propName] = engine === PxAnimatorEngine.waapi && propName === "transform" ? materialiseMotionPathInPropAnim(out) : out;
@@ -2538,11 +2689,11 @@ var PixodeskAnimator = (() => {
2538
2689
  const defs = getDefs(doc);
2539
2690
  const duration = animatorConfig.duration || 1e3;
2540
2691
  const bindings = [];
2541
- const processAnimation = (id, animate) => {
2692
+ const processAnimation = (id, animate, staticTransform) => {
2542
2693
  if (!animate) return null;
2543
2694
  const animDefs = resolveElementAnimation(animate, defs);
2544
2695
  if (animDefs.length === 0) return null;
2545
- const merged = mergeAnimationDefinitions(animDefs);
2696
+ const merged = mergeStaticTransformIntoAnimDef(mergeAnimationDefinitions(animDefs), staticTransform);
2546
2697
  const normalizedAnim = normalizeAnimationDefinition(merged, duration, defs, engine);
2547
2698
  if (Object.keys(normalizedAnim).length === 0) return null;
2548
2699
  return {
@@ -2562,7 +2713,7 @@ var PixodeskAnimator = (() => {
2562
2713
  if (inlineAnim && Object.keys(inlineAnim).length > 0) {
2563
2714
  const nodeId = node.id || generateElementId();
2564
2715
  node.id = nodeId;
2565
- const normalized = processAnimation(nodeId, inlineAnim);
2716
+ const normalized = processAnimation(nodeId, inlineAnim, node.transform);
2566
2717
  if (normalized) bindings.push(normalized);
2567
2718
  }
2568
2719
  if (node.children) {
@@ -2600,7 +2751,7 @@ var PixodeskAnimator = (() => {
2600
2751
  }
2601
2752
  function calcPropertyValue(propName, propAnim, progress) {
2602
2753
  var _a, _b, _c, _d, _e, _f, _g;
2603
- const keyframes = propAnim.kfs || propAnim.keyframes || [];
2754
+ const keyframes = propAnim.keyframes || [];
2604
2755
  if (keyframes.length === 0) return null;
2605
2756
  const { prevKf, nextKf } = getKeyframesPair(keyframes, progress);
2606
2757
  let localProgress = prevKf === nextKf ? 0 : remap(progress, (_a = prevKf.t) != null ? _a : 0, (_b = nextKf.t) != null ? _b : 0, 0, 1);
@@ -3224,7 +3375,7 @@ var PixodeskAnimator = (() => {
3224
3375
  if (split.rest) node.transform = split.rest;
3225
3376
  else delete node.transform;
3226
3377
  }
3227
- } else if (node.transform && typeof node.transform === "object" && !Array.isArray(node.transform) && !node.transform.keyframes && !node.transform.kfs) {
3378
+ } else if (node.transform && typeof node.transform === "object" && !Array.isArray(node.transform) && !node.transform.keyframes) {
3228
3379
  const wrapped = node.transform.value;
3229
3380
  const isWrapped = !!(wrapped && typeof wrapped === "object");
3230
3381
  const value = isWrapped ? wrapped : node.transform;
@@ -3359,12 +3510,12 @@ var PixodeskAnimator = (() => {
3359
3510
  id
3360
3511
  };
3361
3512
  if (fx.type === PxGradientType.linear) {
3362
- applyGeomVec(out, "x1", "y1", fx.p1);
3363
- applyGeomVec(out, "x2", "y2", fx.p2);
3513
+ applyGeomVec(out, "x1", "y1", fx.start);
3514
+ applyGeomVec(out, "x2", "y2", fx.end);
3364
3515
  } else {
3365
- applyGeomVec(out, "cx", "cy", fx.c);
3366
- applyGeomNumber(out, "r", fx.r);
3367
- applyGeomVec(out, "fx", "fy", fx.fp);
3516
+ applyGeomVec(out, "cx", "cy", fx.center);
3517
+ applyGeomNumber(out, "r", fx.radius);
3518
+ applyGeomVec(out, "fx", "fy", fx.focal);
3368
3519
  }
3369
3520
  if (fx.gradientUnits) out.gradientUnits = fx.gradientUnits;
3370
3521
  if (fx.spreadMethod) out.spreadMethod = fx.spreadMethod;
@@ -3492,8 +3643,7 @@ var PixodeskAnimator = (() => {
3492
3643
 
3493
3644
  // ../svg-animator-core/src/effects/clipPathEffect.ts
3494
3645
  function applyClipPathEffect(node, fx, ctx) {
3495
- var _a, _b;
3496
- if (!fx || !fx.d && !fx.animate) return node;
3646
+ if (!(fx == null ? void 0 : fx.d)) return node;
3497
3647
  const clipId = genId(ctx, "clip");
3498
3648
  const pathChild = { type: "path" };
3499
3649
  const read = readAnimatable(fx.d);
@@ -3505,11 +3655,6 @@ var PixodeskAnimator = (() => {
3505
3655
  if (pathChild.d !== void 0) pathChild.d = pathString(pathChild.d);
3506
3656
  }
3507
3657
  }
3508
- if (fx.animate && !((_a = pathChild.animate) == null ? void 0 : _a.d)) {
3509
- const animate = (_b = pathChild.animate) != null ? _b : {};
3510
- animate.d = fx.animate;
3511
- pathChild.animate = animate;
3512
- }
3513
3658
  ctx.defs.push({ type: "clipPath", id: clipId, children: [pathChild] });
3514
3659
  node.clipPath = "url(#" + clipId + ")";
3515
3660
  return node;
@@ -3654,7 +3799,7 @@ var PixodeskAnimator = (() => {
3654
3799
  if (parts.origin) out.origin = parts.origin;
3655
3800
  return Object.keys(out).length ? out : void 0;
3656
3801
  }
3657
- if (node.transform && typeof node.transform === "object" && !node.transform.keyframes && !node.transform.kfs) {
3802
+ if (node.transform && typeof node.transform === "object" && !node.transform.keyframes) {
3658
3803
  const wrapped = node.transform.value;
3659
3804
  const value = wrapped && typeof wrapped === "object" ? wrapped : node.transform;
3660
3805
  if (value && typeof value === "object") {
@@ -5329,9 +5474,9 @@ var PixodeskAnimator = (() => {
5329
5474
  return Object.is(r, -0) ? "0" : String(r);
5330
5475
  };
5331
5476
  function buildOffsetPath(propAnim) {
5332
- var _a, _b, _c, _d;
5477
+ var _a, _b, _c;
5333
5478
  if (propAnim.alongPathMode !== "offsetPath") return void 0;
5334
- const kfs = (_a = propAnim.keyframes) != null ? _a : propAnim.kfs;
5479
+ const kfs = propAnim.keyframes;
5335
5480
  if (!kfs || kfs.length < 2) return void 0;
5336
5481
  const first = kfValue(kfs[0]);
5337
5482
  const anchor = (first == null ? void 0 : first.origin) && first.origin.length >= 2 ? [first.origin[0], first.origin[1]] : [0, 0];
@@ -5342,7 +5487,7 @@ var PixodeskAnimator = (() => {
5342
5487
  if (!tr || tr.length < 2) return void 0;
5343
5488
  const parts = Object.keys(v);
5344
5489
  if (parts.some((p) => p !== "translate" && p !== "origin")) return void 0;
5345
- const o = (_b = v == null ? void 0 : v.origin) != null ? _b : [0, 0];
5490
+ const o = (_a = v == null ? void 0 : v.origin) != null ? _a : [0, 0];
5346
5491
  if (o[0] !== anchor[0] || o[1] !== anchor[1]) return void 0;
5347
5492
  points.push([tr[0] + anchor[0], tr[1] + anchor[1]]);
5348
5493
  }
@@ -5351,8 +5496,8 @@ var PixodeskAnimator = (() => {
5351
5496
  const segLens = [];
5352
5497
  for (let i = 0; i < points.length - 1; i++) {
5353
5498
  const p0 = points[i], p1 = points[i + 1];
5354
- const to = (_c = kfTangentOut(kfs[i])) != null ? _c : [0, 0];
5355
- const ti = (_d = kfTangentIn(kfs[i + 1])) != null ? _d : [0, 0];
5499
+ const to = (_b = kfTangentOut(kfs[i])) != null ? _b : [0, 0];
5500
+ const ti = (_c = kfTangentIn(kfs[i + 1])) != null ? _c : [0, 0];
5356
5501
  const c1 = [p0[0] + to[0], p0[1] + to[1]];
5357
5502
  const c2 = [p1[0] + ti[0], p1[1] + ti[1]];
5358
5503
  d += "C" + fmt2(c1[0]) + "," + fmt2(c1[1]) + "," + fmt2(c2[0]) + "," + fmt2(c2[1]) + "," + fmt2(p1[0]) + "," + fmt2(p1[1]);
@@ -5977,7 +6122,7 @@ var PixodeskAnimator = (() => {
5977
6122
  const result = /* @__PURE__ */ new Map();
5978
6123
  for (const [propName, propAnim] of Object.entries(animDef)) {
5979
6124
  const duration = config.duration || 1;
5980
- const clippedKeyframes = clipKeyframesToDuration(propName, propAnim.kfs || propAnim.keyframes || [], duration);
6125
+ const clippedKeyframes = clipKeyframesToDuration(propName, propAnim.keyframes || [], duration);
5981
6126
  const cssKeyframes = [];
5982
6127
  for (let i = 0; i < clippedKeyframes.length; i++) {
5983
6128
  const kf = clippedKeyframes[i];
@@ -6590,7 +6735,16 @@ var PixodeskAnimator = (() => {
6590
6735
  }
6591
6736
  }
6592
6737
  }
6593
- return createAnimatorFromConfig(doc, adapter, callbacks, rootElement);
6738
+ const api = createAnimatorFromConfig(doc, adapter, callbacks, rootElement);
6739
+ if (containerElement && rootElement) {
6740
+ const rendered = rootElement;
6741
+ const destroyNative = api.destroy.bind(api);
6742
+ api.destroy = () => {
6743
+ destroyNative();
6744
+ rendered.remove();
6745
+ };
6746
+ }
6747
+ return api;
6594
6748
  }
6595
6749
  function createAnimator(options) {
6596
6750
  const { src, data, adapter, callbacks, container } = options;
@@ -6676,4 +6830,4 @@ var PixodeskAnimator = (() => {
6676
6830
  }
6677
6831
  return __toCommonJS(index_player_exports);
6678
6832
  })();
6679
- //# sourceMappingURL=index.umd.js.map
6833
+ //# sourceMappingURL=pixodesk-svg-animator.umd.js.map