@pixodesk/svg-animator-web 1.0.35 → 1.0.39

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.
@@ -50,7 +50,7 @@ var PixodeskAnimator = (() => {
50
50
  // src/index.prerendered.ts
51
51
  var index_prerendered_exports = {};
52
52
  __export(index_prerendered_exports, {
53
- PX_ANIMATOR_DATA_KEY: () => PX_ANIMATOR_DATA_KEY,
53
+ PX_ANIMATOR_DOC_KEY: () => PX_ANIMATOR_DOC_KEY,
54
54
  createAnimator: () => createPrerenderedAnimator,
55
55
  setupAnimationTriggers: () => setupAnimationTriggers
56
56
  });
@@ -285,7 +285,7 @@ var PixodeskAnimator = (() => {
285
285
  }
286
286
  return void 0;
287
287
  }
288
- var COLOUR_ATTR_NAMES = /* @__PURE__ */ new Set(["color", "fill", "flood-color", "lighting-color", "stop-color", "stroke"]);
288
+ var COLOR_ATTR_NAMES = /* @__PURE__ */ new Set(["color", "fill", "flood-color", "lighting-color", "stop-color", "stroke"]);
289
289
  var TRANSFORM_FN_NAMES = /* @__PURE__ */ new Set(["translate", "rotate", "scale", "skew"]);
290
290
  var PCT_BASED_ATTR_NAMES = /* @__PURE__ */ new Set(["offset-distance", "offsetDistance"]);
291
291
  function composeTransformParts(parts, opts) {
@@ -650,6 +650,7 @@ var PixodeskAnimator = (() => {
650
650
  return false;
651
651
  }
652
652
  };
653
+ var UNION_MEMBER_ERROR_LIMIT = 4;
653
654
  var Union = class extends Base {
654
655
  constructor(schemas, defaultVal) {
655
656
  super();
@@ -668,7 +669,35 @@ var PixodeskAnimator = (() => {
668
669
  var _a;
669
670
  const probe = ctx && { errors: [], warnings: [], strict: ctx.strict };
670
671
  if (this.schemas.some((s) => s.isValid(raw, probe, path ? [...path] : void 0))) return true;
671
- ctx == null ? void 0 : ctx.errors.push(pathStr(path != null ? path : []) + ": no union member matched for value " + ((_a = JSON.stringify(raw)) != null ? _a : "").slice(0, 240));
672
+ if (!ctx) return false;
673
+ const base = pathStr(path != null ? path : []);
674
+ ctx.errors.push(base + ": no union member matched for value " + ((_a = JSON.stringify(raw)) != null ? _a : "").slice(0, 240));
675
+ let best;
676
+ let bestDepth = -1;
677
+ const leafExpectations = [];
678
+ for (const member of this.schemas) {
679
+ const sink = { errors: [], warnings: [], strict: ctx.strict };
680
+ member.isValid(raw, sink, path ? [...path] : void 0);
681
+ if (!sink.errors.length) continue;
682
+ const depth = Math.max(...sink.errors.map((e) => e.slice(0, e.indexOf(":")).length));
683
+ if (depth > bestDepth || depth === bestDepth && best && sink.errors.length < best.length) {
684
+ bestDepth = depth;
685
+ best = sink.errors;
686
+ }
687
+ if (depth <= base.length) {
688
+ for (const e of sink.errors) {
689
+ const m = /: expected (.+?), got /.exec(e);
690
+ if (m && !leafExpectations.includes(m[1])) leafExpectations.push(m[1]);
691
+ }
692
+ }
693
+ }
694
+ if (best && bestDepth > base.length) {
695
+ for (const e of best.slice(0, UNION_MEMBER_ERROR_LIMIT)) {
696
+ if (!ctx.errors.includes(e)) ctx.errors.push(e);
697
+ }
698
+ } else if (leafExpectations.length) {
699
+ ctx.errors.push(base + ": expected " + leafExpectations.join(" | "));
700
+ }
672
701
  return false;
673
702
  }
674
703
  _canSanitize(raw) {
@@ -1020,6 +1049,76 @@ var PixodeskAnimator = (() => {
1020
1049
  };
1021
1050
 
1022
1051
  // ../svg-animator-core/src/format/PxAnimatorConstants.ts
1052
+ var PxFillMode = {
1053
+ forwards: "forwards",
1054
+ backwards: "backwards",
1055
+ both: "both",
1056
+ none: "none"
1057
+ };
1058
+ var PxPlaybackDirection = {
1059
+ normal: "normal",
1060
+ reverse: "reverse",
1061
+ alternate: "alternate",
1062
+ alternateReverse: "alternate-reverse"
1063
+ };
1064
+ var PxStartOn = {
1065
+ load: "load",
1066
+ mouseOver: "mouseOver",
1067
+ click: "click",
1068
+ scrollIntoView: "scrollIntoView",
1069
+ programmatic: "programmatic"
1070
+ };
1071
+ var PxOutAction = {
1072
+ continue: "continue",
1073
+ pause: "pause",
1074
+ reset: "reset",
1075
+ reverse: "reverse"
1076
+ };
1077
+ var PxFinishAction = {
1078
+ hold: "hold",
1079
+ reset: "reset"
1080
+ };
1081
+ var PxScrollKind = {
1082
+ view: "view",
1083
+ scroll: "scroll"
1084
+ };
1085
+ var PxScrollAxis = {
1086
+ block: "block",
1087
+ inline: "inline",
1088
+ x: "x",
1089
+ y: "y"
1090
+ };
1091
+ var PxScrollSource = {
1092
+ nearest: "nearest",
1093
+ root: "root"
1094
+ };
1095
+ var PxPinAlign = {
1096
+ top: "top",
1097
+ center: "center",
1098
+ bottom: "bottom"
1099
+ };
1100
+ var PxScrollPhase = {
1101
+ cover: "cover",
1102
+ contain: "contain",
1103
+ entry: "entry",
1104
+ exit: "exit",
1105
+ entryCrossing: "entry-crossing",
1106
+ exitCrossing: "exit-crossing"
1107
+ };
1108
+ var PxAlongPathMode = {
1109
+ sampled: "sampled",
1110
+ offsetPath: "offsetPath"
1111
+ };
1112
+ var PX_TIMELINE_SHARED_KEYS = ["duration", "iterations", "engine", "frameRate"];
1113
+ var PX_TIME_ONLY_TIMELINE_KEYS = ["trigger", "delay", "fillMode", "direction"];
1114
+ var PX_FLAT_RUNTIME_VIEW_KEYS = [
1115
+ ...PX_TIMELINE_SHARED_KEYS,
1116
+ ...PX_TIME_ONLY_TIMELINE_KEYS,
1117
+ "fill",
1118
+ "resetOnFinish",
1119
+ "timelineSource",
1120
+ "scroll"
1121
+ ];
1023
1122
  var PxTimelineEngine = {
1024
1123
  native: "native",
1025
1124
  js: "js"
@@ -1033,6 +1132,19 @@ var PixodeskAnimator = (() => {
1033
1132
  function mayUseNativeScrollTimeline(engine) {
1034
1133
  return engine !== PxTimelineEngineExtra.js;
1035
1134
  }
1135
+ var PX_TRIGGER_DEFAULTS = {
1136
+ startOn: "load",
1137
+ outAction: "continue",
1138
+ scrollIntoViewThreshold: 0
1139
+ };
1140
+ function resolveTrigger(trigger) {
1141
+ var _a, _b, _c;
1142
+ return {
1143
+ startOn: (_a = trigger == null ? void 0 : trigger.startOn) != null ? _a : PX_TRIGGER_DEFAULTS.startOn,
1144
+ outAction: (_b = trigger == null ? void 0 : trigger.outAction) != null ? _b : PX_TRIGGER_DEFAULTS.outAction,
1145
+ scrollIntoViewThreshold: (_c = trigger == null ? void 0 : trigger.scrollIntoViewThreshold) != null ? _c : PX_TRIGGER_DEFAULTS.scrollIntoViewThreshold
1146
+ };
1147
+ }
1036
1148
  var PxLoopRepeatAt = {
1037
1149
  /** Segment from the START; the repetition runs BEFORE the first keyframe
1038
1150
  * (intro loops that play until the main timeline begins). */
@@ -1092,10 +1204,6 @@ var PixodeskAnimator = (() => {
1092
1204
  TRANSFORM_PART.scale,
1093
1205
  TRANSFORM_PART.origin
1094
1206
  ];
1095
- var PxGradientUnits = {
1096
- userSpaceOnUse: "userSpaceOnUse",
1097
- objectBoundingBox: "objectBoundingBox"
1098
- };
1099
1207
  var PxGradientSpreadMethod = {
1100
1208
  pad: "pad",
1101
1209
  reflect: "reflect",
@@ -1108,8 +1216,18 @@ var PixodeskAnimator = (() => {
1108
1216
  function getAnimatorConfig(doc) {
1109
1217
  var _a;
1110
1218
  const cfg = (doc == null ? void 0 : doc.animator) || ((_a = doc == null ? void 0 : doc.meta) == null ? void 0 : _a.animator);
1111
- return cfg ? flattenAnimatorTimeline(cfg) : void 0;
1112
- }
1219
+ if (!cfg) return void 0;
1220
+ const memoised = wireViewMemo.get(cfg);
1221
+ if (memoised) return memoised;
1222
+ const wire = cfg;
1223
+ const stray = PX_FLAT_RUNTIME_VIEW_KEYS.filter((k) => wire[k] !== void 0);
1224
+ const source = stray.length ? __spreadValues({}, wire) : cfg;
1225
+ for (const k of stray) delete source[k];
1226
+ const view = flattenAnimatorTimeline(source);
1227
+ wireViewMemo.set(cfg, view);
1228
+ return view;
1229
+ }
1230
+ var wireViewMemo = /* @__PURE__ */ new WeakMap();
1113
1231
  var flattenMemo = /* @__PURE__ */ new WeakMap();
1114
1232
  function flattenAnimatorTimeline(cfg) {
1115
1233
  const timeline = cfg.timeline;
@@ -1135,7 +1253,7 @@ var PixodeskAnimator = (() => {
1135
1253
  else if (pin && typeof pin === "object") {
1136
1254
  scroll.pin = true;
1137
1255
  if (pin.align !== void 0) scroll.pinAlign = pin.align;
1138
- if (pin.top !== void 0) scroll.pinTop = pin.top;
1256
+ if (pin.offset !== void 0) scroll.pinOffset = pin.offset;
1139
1257
  if (pin.distance !== void 0) scroll.pinDistance = pin.distance;
1140
1258
  }
1141
1259
  flat.scroll = scroll;
@@ -1177,14 +1295,13 @@ var PixodeskAnimator = (() => {
1177
1295
  // e.g. for colors
1178
1296
  px.number(),
1179
1297
  px.array(px.number()),
1180
- // ORDER LAW: the key-discriminated object shapes (`{path}`, `{paths}`) come BEFORE the
1298
+ // ORDER LAW: the key-discriminated object shape (`{pathData}`) comes BEFORE the
1181
1299
  // all-optional transform-parts record. In default (non-strict) mode that record accepts
1182
1300
  // ANY object (every key optional, unknown keys ignored), so listing it earlier made
1183
- // Union.sanitize route `{path}`/`{paths}` values into it and strip them to `{}` —
1301
+ // Union.sanitize route `{pathData}` values into it and strip them to `{}` —
1184
1302
  // silent morph-data loss (repro: the editor's keyframeValueSanitize spec). Validity is
1185
1303
  // order-independent (`some()`); only sanitize routing depends on this order.
1186
- px.object({ path: px.string() }),
1187
- px.lazy(() => px.object({ paths: px.array(PxBezierPathSchema) }), { paths: [] }),
1304
+ px.object({ pathData: px.string() }),
1188
1305
  // Gradient `stops` timeline — each kf value is the full stops-array snapshot.
1189
1306
  px.lazy(() => px.array(PxGradientStopSchema), []),
1190
1307
  px.lazy(() => PxTransformPartsSchema, {})
@@ -1224,7 +1341,7 @@ var PixodeskAnimator = (() => {
1224
1341
  keyframes: px.array(PxKeyframeSchema).optional(),
1225
1342
  loop: px.union([PxLoopSchema, px.boolean()]).optional(),
1226
1343
  autoOrient: px.boolean().optional(),
1227
- alongPathMode: px.enum(["sampled", "offsetPath"]).optional()
1344
+ alongPathMode: px.enum([PxAlongPathMode.sampled, PxAlongPathMode.offsetPath]).optional()
1228
1345
  }));
1229
1346
  var PxTransformPartsSchema = implementsInterface()(px.object({
1230
1347
  translate: px.tuple([px.number(), px.number()]).optional(),
@@ -1248,17 +1365,17 @@ var PixodeskAnimator = (() => {
1248
1365
  PxAnimationDefinitionSchema
1249
1366
  ]));
1250
1367
  var PxTriggerSchema = implementsInterface()(px.object({
1251
- startOn: px.enum(["load", "mouseOver", "click", "scrollIntoView", "programmatic"]).optional(),
1252
- outAction: px.enum(["continue", "pause", "reset", "reverse"]).optional(),
1368
+ startOn: px.enum([PxStartOn.load, PxStartOn.mouseOver, PxStartOn.click, PxStartOn.scrollIntoView, PxStartOn.programmatic], PX_TRIGGER_DEFAULTS.startOn).optional(),
1369
+ outAction: px.enum([PxOutAction.continue, PxOutAction.pause, PxOutAction.reset, PxOutAction.reverse], PX_TRIGGER_DEFAULTS.outAction).optional(),
1253
1370
  // What happens after a NATURAL finish — `'hold'` (default: keep the end state per
1254
1371
  // `fill`) or `'reset'` (snap back to the start state). Pairs with `outAction` ("what
1255
1372
  // happens when the trigger condition ends"); both end-of-life knobs now read alike.
1256
- finishAction: px.enum(["hold", "reset"]).optional(),
1373
+ finishAction: px.enum([PxFinishAction.hold, PxFinishAction.reset]).optional(),
1257
1374
  scrollIntoViewThreshold: px.number().optional()
1258
1375
  }));
1259
1376
  var PxGlyphSchema = implementsInterface()(px.object({
1260
1377
  width: px.number(),
1261
- d: px.string()
1378
+ pathData: px.string()
1262
1379
  }));
1263
1380
  var PxGlyphFontSchema = implementsInterface()(px.object({
1264
1381
  fontFamily: px.string(),
@@ -1275,9 +1392,15 @@ var PixodeskAnimator = (() => {
1275
1392
  styles: px.record(px.record(px.union([px.string(), px.number()]))).optional(),
1276
1393
  fonts: px.record(PxGlyphFontSchema).optional()
1277
1394
  }));
1278
- var PX_SCROLL_PHASES = ["cover", "contain", "entry", "exit", "entry-crossing", "exit-crossing"];
1279
1395
  var PxScrollRangePointSchema = implementsInterface()(px.object({
1280
- phase: px.enum(PX_SCROLL_PHASES).optional(),
1396
+ phase: px.enum([
1397
+ PxScrollPhase.cover,
1398
+ PxScrollPhase.contain,
1399
+ PxScrollPhase.entry,
1400
+ PxScrollPhase.exit,
1401
+ PxScrollPhase.entryCrossing,
1402
+ PxScrollPhase.exitCrossing
1403
+ ]).optional(),
1281
1404
  fraction: px.number().optional()
1282
1405
  }));
1283
1406
  var PxScrollRangeSchema = px.object({
@@ -1285,21 +1408,21 @@ var PixodeskAnimator = (() => {
1285
1408
  end: PxScrollRangePointSchema.optional()
1286
1409
  });
1287
1410
  var PxScrollSchema = implementsInterface()(px.object({
1288
- kind: px.enum(["view", "scroll"]).optional(),
1289
- axis: px.enum(["block", "inline", "x", "y"]).optional(),
1290
- source: px.enum(["nearest", "root"]).optional(),
1411
+ kind: px.enum([PxScrollKind.view, PxScrollKind.scroll]).optional(),
1412
+ axis: px.enum([PxScrollAxis.block, PxScrollAxis.inline, PxScrollAxis.x, PxScrollAxis.y]).optional(),
1413
+ source: px.enum([PxScrollSource.nearest, PxScrollSource.root]).optional(),
1291
1414
  // Free-form: the two keywords `parent`/`scroller` plus any CSS selector.
1292
1415
  subject: px.string().optional(),
1293
1416
  smoothing: px.number().optional(),
1294
1417
  pin: px.boolean().optional(),
1295
- pinAlign: px.enum(["top", "center", "bottom"]).optional(),
1296
- pinTop: px.number().optional(),
1418
+ pinAlign: px.enum([PxPinAlign.top, PxPinAlign.center, PxPinAlign.bottom]).optional(),
1419
+ pinOffset: px.number().optional(),
1297
1420
  pinDistance: px.number().optional(),
1298
1421
  range: PxScrollRangeSchema.optional()
1299
1422
  }));
1300
1423
  var PxTimelinePinSchema = implementsInterface()(px.object({
1301
- align: px.enum(["top", "center", "bottom"]).optional(),
1302
- top: px.number().optional(),
1424
+ align: px.enum([PxPinAlign.top, PxPinAlign.center, PxPinAlign.bottom]).optional(),
1425
+ offset: px.number().optional(),
1303
1426
  distance: px.number().optional()
1304
1427
  }));
1305
1428
  var PxTimelineEngineSchema = px.enum([PxTimelineEngineExtra.auto, PxTimelineEngineExtra.native, PxTimelineEngineExtra.js]).optional();
@@ -1314,8 +1437,8 @@ var PixodeskAnimator = (() => {
1314
1437
  iterations: px.union([px.number(), px.literal("infinite")]).optional(),
1315
1438
  // `fillMode` on the wire (CSS `animation-fill-mode`; the runtime view calls it `fill`)
1316
1439
  // — never `fill`, which is paint everywhere else in the format.
1317
- fillMode: px.enum(["forwards", "backwards", "both", "none"]).optional(),
1318
- direction: px.enum(["normal", "reverse", "alternate", "alternate-reverse"]).optional()
1440
+ fillMode: px.enum([PxFillMode.forwards, PxFillMode.backwards, PxFillMode.both, PxFillMode.none]).optional(),
1441
+ direction: px.enum([PxPlaybackDirection.normal, PxPlaybackDirection.reverse, PxPlaybackDirection.alternate, PxPlaybackDirection.alternateReverse]).optional()
1319
1442
  }));
1320
1443
  var scrollishTimelineShape = {
1321
1444
  // §2.8: duration is a property of the TIMELINE — under scrubbing it is the keyframe
@@ -1326,8 +1449,8 @@ var PixodeskAnimator = (() => {
1326
1449
  iterations: px.number().optional(),
1327
1450
  engine: PxTimelineEngineSchema,
1328
1451
  frameRate: px.number().optional(),
1329
- axis: px.enum(["block", "inline", "x", "y"]).optional(),
1330
- source: px.enum(["nearest", "root"]).optional(),
1452
+ axis: px.enum([PxScrollAxis.block, PxScrollAxis.inline, PxScrollAxis.x, PxScrollAxis.y]).optional(),
1453
+ source: px.enum([PxScrollSource.nearest, PxScrollSource.root]).optional(),
1331
1454
  subject: px.string().optional(),
1332
1455
  // 'parent' | 'scroller' | any CSS selector
1333
1456
  smoothing: px.number().optional(),
@@ -1416,7 +1539,7 @@ var PixodeskAnimator = (() => {
1416
1539
  height: px.number().optional()
1417
1540
  }));
1418
1541
  var PxClipPathEffectSchema = implementsInterface()(px.object({
1419
- d: PxAnimatableStringSchema.optional()
1542
+ pathData: PxAnimatableStringSchema.optional()
1420
1543
  }));
1421
1544
  var PxStrokeTrimEffectSchema = implementsInterface()(px.object({
1422
1545
  offset: PxAnimatableNumberSchema.optional(),
@@ -1453,7 +1576,7 @@ var PixodeskAnimator = (() => {
1453
1576
  radius: PxAnimatableNumberSchema.optional(),
1454
1577
  focal: PxAnimatableVec2Schema.optional(),
1455
1578
  stops: PxAnimatableGradientStopsSchema.optional(),
1456
- gradientUnits: px.enum([PxGradientUnits.userSpaceOnUse, PxGradientUnits.objectBoundingBox]).optional(),
1579
+ gradientUnits: px.enum([PxUnits.userSpaceOnUse, PxUnits.objectBoundingBox]).optional(),
1457
1580
  spreadMethod: px.enum([PxGradientSpreadMethod.pad, PxGradientSpreadMethod.reflect, PxGradientSpreadMethod.repeat]).optional(),
1458
1581
  gradientTransform: px.string().optional()
1459
1582
  }));
@@ -1499,10 +1622,13 @@ var PixodeskAnimator = (() => {
1499
1622
  // documented — because a wire key that is not in a schema is invisible to the
1500
1623
  // minifier's reserve list and gets renamed (MINIFICATION-BOUNDARY-PLAN.md §1.1).
1501
1624
  domType: px.string().optional(),
1625
+ // Text content of a `<text>` / `<tspan>`. Declared, so a non-string value is a schema error
1626
+ // and the minifier reserves the key; `text` is NOT an alias for it and is not read anywhere.
1627
+ textContent: px.string().optional(),
1502
1628
  id: px.string().optional(),
1503
1629
  meta: px.any().optional(),
1504
1630
  // Player-effects bucket emitted by the Editor's lightweight design format.
1505
- // Consumed and removed by `applyPlayerEffects` before any other normalisation
1631
+ // Consumed and removed by `applyPlayerEffects` before any other normalization
1506
1632
  // (see `createAnimatorImpl`), so downstream code never sees it.
1507
1633
  effects: PxEffectsSchema.optional(),
1508
1634
  // `PxElementAnimation` (not just `PxAnimationDefinition`) — accepts
@@ -1534,7 +1660,7 @@ var PixodeskAnimator = (() => {
1534
1660
  c: px.boolean().optional()
1535
1661
  }));
1536
1662
 
1537
- // ../svg-animator-core/src/materialise/PxMotionPath.ts
1663
+ // ../svg-animator-core/src/materialize/PxMotionPath.ts
1538
1664
  function getKfTranslate(kf) {
1539
1665
  const v = kfValue(kf);
1540
1666
  if (!v) return void 0;
@@ -1615,7 +1741,7 @@ var PixodeskAnimator = (() => {
1615
1741
  var DEFAULT_FLATNESS_TOL = 0.5;
1616
1742
  var DEFAULT_ROTATION_TOL = 5;
1617
1743
  var DEFAULT_MAX_SAMPLES = 32;
1618
- function materialiseMotionPathInPropAnim(anim, opts) {
1744
+ function materializeMotionPathInPropAnim(anim, opts) {
1619
1745
  var _a, _b, _c;
1620
1746
  if (!propAnimIsMotionPath(anim)) return anim;
1621
1747
  const kfs = anim.keyframes;
@@ -1647,7 +1773,7 @@ var PixodeskAnimator = (() => {
1647
1773
  if (autoOrient && i > 0) {
1648
1774
  insertSharpCornerStepKfIfNeeded(out, prevKf, nextKf, prevPos, nextPos, rotationTol);
1649
1775
  }
1650
- materialiseSegment(out, prevKf, nextKf, prevPos, nextPos, autoOrient, flatnessTol, rotationTol, maxSamples);
1776
+ materializeSegment(out, prevKf, nextKf, prevPos, nextPos, autoOrient, flatnessTol, rotationTol, maxSamples);
1651
1777
  }
1652
1778
  const lastInE = getKfEasing(kfs[kfs.length - 1]);
1653
1779
  if (lastInE) out[out.length - 1].e = lastInE;
@@ -1761,7 +1887,7 @@ var PixodeskAnimator = (() => {
1761
1887
  out.push(makeOutKf(stepTime, dupValue));
1762
1888
  }
1763
1889
  var CORNER_STEP_AFTER_BOUNDARY_MS = 0.05;
1764
- function materialiseSegment(out, prevKf, nextKf, prevPos, nextPos, autoOrient, flatnessTol, rotationTol, maxSamples) {
1890
+ function materializeSegment(out, prevKf, nextKf, prevPos, nextPos, autoOrient, flatnessTol, rotationTol, maxSamples) {
1765
1891
  const seg = getSegmentCache(prevKf, nextKf, prevPos, nextPos);
1766
1892
  const prevTime = getKfTime(prevKf);
1767
1893
  const nextTime = getKfTime(nextKf);
@@ -1977,8 +2103,8 @@ var PixodeskAnimator = (() => {
1977
2103
  return typeof value === "string" && extractPathData(value) !== void 0;
1978
2104
  }
1979
2105
  function normalizePathValue(value) {
1980
- if (value && typeof value === "object" && typeof value.path === "string") {
1981
- const d = extractPathData(value.path);
2106
+ if (value && typeof value === "object" && typeof value.pathData === "string") {
2107
+ const d = extractPathData(value.pathData);
1982
2108
  return d ? { paths: parseSvgPathToBezier(d) } : value;
1983
2109
  }
1984
2110
  if (value && typeof value === "object" && "paths" in value) {
@@ -2062,7 +2188,7 @@ var PixodeskAnimator = (() => {
2062
2188
  const bPaths = (_b = b == null ? void 0 : b.paths) != null ? _b : Array.isArray(b) ? b : [];
2063
2189
  return { paths: interpolateBeziers(aPaths, bPaths, t) };
2064
2190
  }
2065
- if (COLOUR_ATTR_NAMES.has(propName)) {
2191
+ if (COLOR_ATTR_NAMES.has(propName)) {
2066
2192
  return interpolateColor(a || [0, 0, 0, 1], b || [0, 0, 0, 1], t);
2067
2193
  }
2068
2194
  if (propName === "transform" && typeof a === "object" && a !== null && !Array.isArray(a) && typeof b === "object" && b !== null && !Array.isArray(b)) {
@@ -2284,7 +2410,7 @@ var PixodeskAnimator = (() => {
2284
2410
  value = normalizePathValue(value);
2285
2411
  }
2286
2412
  const propNameKebab = isCamelCaseWord(propName) ? camelCaseToKebabWordIfNeeded(propName) : propName;
2287
- if (COLOUR_ATTR_NAMES.has(propNameKebab)) {
2413
+ if (COLOR_ATTR_NAMES.has(propNameKebab)) {
2288
2414
  value = (_a = parseColor(value)) != null ? _a : value;
2289
2415
  }
2290
2416
  const normKf = {
@@ -2363,12 +2489,12 @@ var PixodeskAnimator = (() => {
2363
2489
  const out = { keyframes: normalizedKfs };
2364
2490
  if (propAnim.autoOrient !== void 0) out.autoOrient = propAnim.autoOrient;
2365
2491
  if (propAnim.loop !== void 0) out.loop = propAnim.loop;
2366
- normalized[propName] = engine === PxTimelineEngine.native && propName === "transform" ? materialiseMotionPathInPropAnim(out) : out;
2492
+ normalized[propName] = engine === PxTimelineEngine.native && propName === "transform" ? materializeMotionPathInPropAnim(out) : out;
2367
2493
  }
2368
2494
  }
2369
2495
  return normalized;
2370
2496
  }
2371
- function getNormalisedBindings(doc, engine = PxTimelineEngine.native) {
2497
+ function getNormalizedBindings(doc, engine = PxTimelineEngine.native) {
2372
2498
  const animatorConfig = getAnimatorConfig(doc) || {};
2373
2499
  const defs = getDefs(doc);
2374
2500
  const duration = animatorConfig.duration || 1e3;
@@ -2459,7 +2585,7 @@ var PixodeskAnimator = (() => {
2459
2585
  nextPaths,
2460
2586
  localProgress
2461
2587
  ).map((bz) => bezierToSvgPath(bz)).join("");
2462
- } else if (COLOUR_ATTR_NAMES.has(cssAttrName)) {
2588
+ } else if (COLOR_ATTR_NAMES.has(cssAttrName)) {
2463
2589
  cssValue = toRGBA(interpolateColor(
2464
2590
  prevV || [0, 0, 0, 1],
2465
2591
  nextV || [0, 0, 0, 1],
@@ -2556,6 +2682,40 @@ var PixodeskAnimator = (() => {
2556
2682
  return result;
2557
2683
  }
2558
2684
 
2685
+ // ../svg-animator-core/src/playback/PxPlaybackTime.ts
2686
+ var PX_RATE_REJECTED = "setPlaybackRate: rate must be finite and non-zero";
2687
+ function isValidPlaybackRate(rate) {
2688
+ return Number.isFinite(rate) && rate !== 0;
2689
+ }
2690
+ function seekCeilingMs(durationMs, iterations) {
2691
+ if (!(durationMs > 0)) return 0;
2692
+ if (iterations === Infinity) return Infinity;
2693
+ return durationMs * (iterations > 0 ? iterations : 1);
2694
+ }
2695
+ function progressSpanMs(durationMs, iterations) {
2696
+ if (!(durationMs > 0)) return 0;
2697
+ if (iterations === Infinity) return durationMs;
2698
+ return durationMs * (iterations > 0 ? iterations : 1);
2699
+ }
2700
+ function clampSeekMs(timeMs, ceilingMs) {
2701
+ if (Number.isNaN(timeMs) || timeMs < 0) return 0;
2702
+ if (Number.isFinite(ceilingMs)) return timeMs > ceilingMs ? ceilingMs : timeMs;
2703
+ return Number.isFinite(timeMs) ? timeMs : 0;
2704
+ }
2705
+ function timeToProgress(timeMs, durationMs, iterations) {
2706
+ const span = progressSpanMs(durationMs, iterations);
2707
+ if (!(span > 0) || !Number.isFinite(timeMs)) return 0;
2708
+ if (timeMs <= 0) return 0;
2709
+ if (iterations === Infinity) return timeMs % span / span;
2710
+ return timeMs >= span ? 1 : timeMs / span;
2711
+ }
2712
+ function progressToTimeMs(progress, durationMs, iterations) {
2713
+ const span = progressSpanMs(durationMs, iterations);
2714
+ if (!(span > 0) || !Number.isFinite(progress)) return 0;
2715
+ if (progress <= 0) return 0;
2716
+ return progress >= 1 ? span : progress * span;
2717
+ }
2718
+
2559
2719
  // ../svg-animator-core/src/playback/PxFrameLoop.ts
2560
2720
  function requestFrame(cb) {
2561
2721
  const g = globalThis;
@@ -2573,7 +2733,7 @@ var PixodeskAnimator = (() => {
2573
2733
  function createBasicFrameLoopAnimator(doc, adapter, callbacks) {
2574
2734
  var _a;
2575
2735
  const config = getAnimatorConfig(doc) || {};
2576
- const bindings = getNormalisedBindings(doc, PxTimelineEngine.js);
2736
+ const bindings = getNormalizedBindings(doc, PxTimelineEngine.js);
2577
2737
  const _iterations = config.iterations;
2578
2738
  let iterations = 1;
2579
2739
  if (typeof _iterations === "number") iterations = _iterations || 1;
@@ -2803,8 +2963,8 @@ var PixodeskAnimator = (() => {
2803
2963
  finishAnim(true);
2804
2964
  },
2805
2965
  "setPlaybackRate": (rate) => {
2806
- if (!isFinite(rate) || rate === 0) {
2807
- console.warn("setPlaybackRate: rate must be finite and non-zero");
2966
+ if (!isValidPlaybackRate(rate)) {
2967
+ console.warn(PX_RATE_REJECTED);
2808
2968
  return;
2809
2969
  }
2810
2970
  let current = getRawAnimTime();
@@ -2818,13 +2978,16 @@ var PixodeskAnimator = (() => {
2818
2978
  return getAnimCurrentTime();
2819
2979
  },
2820
2980
  "setCurrentTime": (newTime) => {
2821
- if (newTime < 0) newTime = 0;
2822
- if (Number.isFinite(totalDuration) && newTime > totalDuration) newTime = totalDuration;
2981
+ newTime = clampSeekMs(newTime, totalDuration);
2823
2982
  timeBeforeLastStartMs = newTime;
2824
2983
  if (playing) lastStartedTs = Date.now();
2825
2984
  if (!Number.isFinite(totalDuration) || newTime < totalDuration) finishCalled = false;
2826
2985
  renderFrame(getAnimCurrentTime());
2827
2986
  },
2987
+ "getCurrentProgress": () => timeToProgress(getAnimCurrentTime(), duration, iterations),
2988
+ "setCurrentProgress": (progress) => {
2989
+ api.setCurrentTime(progressToTimeMs(progress, duration, iterations));
2990
+ },
2828
2991
  "destroy": () => {
2829
2992
  var _a2;
2830
2993
  api.cancel();
@@ -2834,13 +2997,82 @@ var PixodeskAnimator = (() => {
2834
2997
  return api;
2835
2998
  }
2836
2999
 
3000
+ // ../svg-animator-core/src/playback/PxDiagnostics.ts
3001
+ var PxDiagnosticKind = {
3002
+ /** The document is wrong — regenerate or repair the file. */
3003
+ document: "document",
3004
+ /** The page or app cannot provide what the document asks for — fix the mount. */
3005
+ host: "host",
3006
+ /** The platform cannot do it and the player degraded — usually nothing to fix. */
3007
+ platform: "platform",
3008
+ /** The call is wrong or self-contradictory — fix the options or props you passed. */
3009
+ usage: "usage",
3010
+ /** The player failed where it did not expect to — report it to us. */
3011
+ internal: "internal"
3012
+ };
3013
+ function asError(error) {
3014
+ return typeof error === "string" ? new Error(error) : error;
3015
+ }
3016
+ function isSilenced(silent, kind) {
3017
+ if (!silent) return false;
3018
+ return silent === true || silent.includes(kind);
3019
+ }
3020
+ function createDiagnostics(config, prefix) {
3021
+ const tag = prefix ? prefix + " " : "";
3022
+ return {
3023
+ warn: (kind, message, detail) => {
3024
+ if (config == null ? void 0 : config.onWarn) {
3025
+ config.onWarn({ kind, message, detail });
3026
+ return;
3027
+ }
3028
+ if (isSilenced(config == null ? void 0 : config.silent, kind)) return;
3029
+ const line = tag + kind + ": " + message;
3030
+ if (detail === void 0) console.warn(line);
3031
+ else console.warn(line, detail);
3032
+ },
3033
+ error: (kind, error) => {
3034
+ const err = asError(error);
3035
+ if (config == null ? void 0 : config.onError) {
3036
+ config.onError({ kind, message: err.message, error: err });
3037
+ return;
3038
+ }
3039
+ if (isSilenced(config == null ? void 0 : config.silent, kind)) return;
3040
+ console.error(tag + kind + ": " + err.message);
3041
+ }
3042
+ };
3043
+ }
3044
+
3045
+ // src/shared/PxAnimatorCallbacks.ts
3046
+ function toEngineCallbacks(inline) {
3047
+ const { onPlay, onPause, onCancel, onFinish, onRemove, onStop, onWarn, onError, silent } = inline != null ? inline : {};
3048
+ const withStop = (own) => own || onStop ? () => {
3049
+ own == null ? void 0 : own();
3050
+ onStop == null ? void 0 : onStop();
3051
+ } : void 0;
3052
+ return {
3053
+ onPlay,
3054
+ onPause: withStop(onPause),
3055
+ onCancel: withStop(onCancel),
3056
+ onFinish: withStop(onFinish),
3057
+ onRemove: withStop(onRemove),
3058
+ onWarn,
3059
+ onError,
3060
+ silent
3061
+ };
3062
+ }
3063
+
2837
3064
  // src/triggers/PxAnimatorTriggers.ts
2838
- function setupAnimationTriggers(api, config) {
2839
- const { startOn, outAction = "continue", scrollIntoViewThreshold = 0 } = config;
3065
+ function setupAnimationTriggers(api, config, diag) {
3066
+ const report = diag != null ? diag : createDiagnostics(void 0, "[PxAnimator]");
3067
+ const cleanups = [];
3068
+ const dispose = () => {
3069
+ for (const undo of cleanups.splice(0)) undo();
3070
+ };
3071
+ const { startOn, outAction, scrollIntoViewThreshold } = resolveTrigger(config);
2840
3072
  const root = api.getRootElement();
2841
3073
  if (!root) {
2842
- console.warn("setupAnimationTriggers: No root element found for animation.");
2843
- return api;
3074
+ report.warn(PxDiagnosticKind.host, "setupAnimationTriggers: No root element found for animation.");
3075
+ return dispose;
2844
3076
  }
2845
3077
  let reversed = false;
2846
3078
  const start = () => {
@@ -2875,6 +3107,7 @@ var PixodeskAnimator = (() => {
2875
3107
  startHandler();
2876
3108
  } else {
2877
3109
  window.addEventListener("load", startHandler, { once: true });
3110
+ cleanups.push(() => window.removeEventListener("load", startHandler));
2878
3111
  }
2879
3112
  break;
2880
3113
  }
@@ -2889,6 +3122,10 @@ var PixodeskAnimator = (() => {
2889
3122
  };
2890
3123
  root.addEventListener("mouseenter", mouseOverHandler);
2891
3124
  root.addEventListener("mouseleave", mouseOutHandler);
3125
+ cleanups.push(() => {
3126
+ root.removeEventListener("mouseenter", mouseOverHandler);
3127
+ root.removeEventListener("mouseleave", mouseOutHandler);
3128
+ });
2892
3129
  break;
2893
3130
  }
2894
3131
  case "click": {
@@ -2900,6 +3137,7 @@ var PixodeskAnimator = (() => {
2900
3137
  }
2901
3138
  };
2902
3139
  root.addEventListener("click", clickHandler);
3140
+ cleanups.push(() => root.removeEventListener("click", clickHandler));
2903
3141
  break;
2904
3142
  }
2905
3143
  case "scrollIntoView": {
@@ -2931,12 +3169,13 @@ var PixodeskAnimator = (() => {
2931
3169
  { threshold: thresholdSteps }
2932
3170
  );
2933
3171
  observer.observe(root);
3172
+ cleanups.push(() => observer.disconnect());
2934
3173
  break;
2935
3174
  }
2936
3175
  case "programmatic":
2937
3176
  break;
2938
3177
  }
2939
- return api;
3178
+ return dispose;
2940
3179
  }
2941
3180
 
2942
3181
  // src/engines/PxAnimatorFrameLoop.ts
@@ -2944,35 +3183,41 @@ var PixodeskAnimator = (() => {
2944
3183
  return "#" + id;
2945
3184
  }
2946
3185
  function createFrameLoopAnimator(doc, adapter, callbacks, rootElement) {
3186
+ var _a;
2947
3187
  const config = getAnimatorConfig(doc) || {};
3188
+ const diag = createDiagnostics(callbacks, "[PxAnimator]");
2948
3189
  if (!rootElement) {
2949
3190
  if (doc.id) {
2950
3191
  const rootSelector = getSelector(doc.id);
2951
3192
  rootElement = document.querySelector(rootSelector);
2952
- if (!rootElement) console.warn("createFrameLoopAnimator: No root element found for selector: ", rootSelector);
3193
+ if (!rootElement) diag.warn(PxDiagnosticKind.host, "createFrameLoopAnimator: No root element found for selector: " + rootSelector);
2953
3194
  } else {
2954
- console.warn("createFrameLoopAnimator: No root element provided");
3195
+ diag.warn(PxDiagnosticKind.host, "createFrameLoopAnimator: No root element provided");
2955
3196
  }
2956
3197
  }
2957
3198
  const basicApi = createBasicFrameLoopAnimator(
2958
3199
  doc,
2959
- adapter || createDomAdapter(rootElement),
3200
+ adapter || createDomAdapter(rootElement, diag),
2960
3201
  callbacks
2961
3202
  );
2962
3203
  const api = __spreadProps(__spreadValues({}, basicApi), {
2963
3204
  "getRootElement": () => rootElement || null
2964
3205
  });
2965
- if (config.trigger) {
2966
- if (isScrollTimeline(config)) {
2967
- console.warn("scroll timeline: `animator.trigger` is ignored (triggers do not apply to scroll-driven playback)");
2968
- } else {
2969
- setupAnimationTriggers(api, config.trigger);
2970
- }
3206
+ if (isScrollTimeline(config)) {
3207
+ if (config.trigger) diag.warn(PxDiagnosticKind.usage, "scroll timeline: `animator.trigger` is ignored (triggers do not apply to scroll-driven playback)");
3208
+ } else {
3209
+ const detachTriggers = setupAnimationTriggers(api, (_a = config.trigger) != null ? _a : {}, diag);
3210
+ const destroyEngine = api.destroy.bind(api);
3211
+ api.destroy = () => {
3212
+ detachTriggers();
3213
+ destroyEngine();
3214
+ };
2971
3215
  }
2972
3216
  return api;
2973
3217
  }
2974
- function createDomAdapter(rootElement) {
3218
+ function createDomAdapter(rootElement, diag) {
2975
3219
  const warnedSelectors = /* @__PURE__ */ new Set();
3220
+ const report = diag != null ? diag : createDiagnostics(void 0, "[PxAnimator]");
2976
3221
  const adapter = {
2977
3222
  isConnected: () => {
2978
3223
  if (!rootElement) return true;
@@ -2984,7 +3229,7 @@ var PixodeskAnimator = (() => {
2984
3229
  const elements = (rootElement == null ? void 0 : rootElement.querySelectorAll(selector)) || document.querySelectorAll(selector);
2985
3230
  if (elements.length === 0 && !warnedSelectors.has(selector)) {
2986
3231
  warnedSelectors.add(selector);
2987
- console.warn('setAttribute: No elements found for selector "' + selector + '"');
3232
+ report.warn(PxDiagnosticKind.host, 'setAttribute: No elements found for selector "' + selector + '"');
2988
3233
  }
2989
3234
  for (let i = 0; i < elements.length; i++) {
2990
3235
  const element = elements[i];
@@ -3009,7 +3254,7 @@ var PixodeskAnimator = (() => {
3009
3254
  };
3010
3255
  let cssValue;
3011
3256
  let cssKey = propName;
3012
- if (COLOUR_ATTR_NAMES.has(propName) && Array.isArray(value)) {
3257
+ if (COLOR_ATTR_NAMES.has(propName) && Array.isArray(value)) {
3013
3258
  cssValue = toRGBA(value);
3014
3259
  } else if (propName === "transform" && value !== null && typeof value === "object" && !Array.isArray(value)) {
3015
3260
  cssValue = composeTransformParts(value, { withUnits: true });
@@ -3096,18 +3341,19 @@ var PixodeskAnimator = (() => {
3096
3341
  return result;
3097
3342
  }
3098
3343
  function createWebApiAnimator(doc, callbacks, rootElement, forceEvenIfHasUnsupportedAttrs, scrollTimeline) {
3099
- var _a;
3344
+ var _a, _b;
3100
3345
  const config = getAnimatorConfig(doc) || {};
3346
+ const diag = createDiagnostics(callbacks, "[PxAnimator]");
3101
3347
  if (!rootElement) {
3102
3348
  if (doc.id) {
3103
3349
  const rootSelector = getSelector(doc.id);
3104
3350
  rootElement = document.querySelector(rootSelector);
3105
- if (!rootElement) console.warn("createFrameLoopAnimator: No root element found for selector: ", rootSelector);
3351
+ if (!rootElement) diag.warn(PxDiagnosticKind.host, "createWebApiAnimator: No root element found for selector: " + rootSelector);
3106
3352
  } else {
3107
- console.warn("createFrameLoopAnimator: No root element provided");
3353
+ diag.warn(PxDiagnosticKind.host, "createWebApiAnimator: No root element provided");
3108
3354
  }
3109
3355
  }
3110
- const bindings = getNormalisedBindings(doc, PxTimelineEngine.native);
3356
+ const bindings = getNormalizedBindings(doc, PxTimelineEngine.native);
3111
3357
  const animations = [];
3112
3358
  const _iterations = config.iterations;
3113
3359
  let iterations;
@@ -3117,18 +3363,18 @@ var PixodeskAnimator = (() => {
3117
3363
  let finishNotified = false;
3118
3364
  let removeCalled = false;
3119
3365
  if (!(bindings == null ? void 0 : bindings.length)) {
3120
- console.warn("createWebApiAnimator: No animation bindings defined");
3366
+ diag.warn(PxDiagnosticKind.document, "createWebApiAnimator: No animation bindings defined");
3121
3367
  }
3122
3368
  for (const binding of bindings || []) {
3123
3369
  const animDef = binding.animate;
3124
3370
  if (!animDef || typeof animDef !== "object" || Array.isArray(animDef)) {
3125
- console.warn("createWebApiAnimator: Empty or unresolved binding", binding);
3371
+ diag.warn(PxDiagnosticKind.document, "createWebApiAnimator: Empty or unresolved binding", binding);
3126
3372
  continue;
3127
3373
  }
3128
3374
  const selector = getSelector(binding.id);
3129
3375
  const elements = (rootElement == null ? void 0 : rootElement.querySelectorAll(selector)) || document.querySelectorAll(selector);
3130
3376
  if (elements.length === 0) {
3131
- console.warn('createWebApiAnimator: No elements found for selector "' + selector + '"');
3377
+ diag.warn(PxDiagnosticKind.host, 'createWebApiAnimator: No elements found for selector "' + selector + '"');
3132
3378
  }
3133
3379
  const keyframesMap = convertToWebApiKeyframes(animDef, unsupportedSet, config);
3134
3380
  const positiveDelay = config.delay && config.delay > 0 ? config.delay : void 0;
@@ -3177,14 +3423,14 @@ var PixodeskAnimator = (() => {
3177
3423
  }
3178
3424
  animations.push(anim);
3179
3425
  } catch (e) {
3180
- console.warn(e);
3426
+ diag.warn(PxDiagnosticKind.internal, "createWebApiAnimator: could not build the animation", e);
3181
3427
  }
3182
3428
  }
3183
3429
  }
3184
3430
  }
3185
3431
  }
3186
3432
  if (!forceEvenIfHasUnsupportedAttrs && unsupportedSet.size) {
3187
- console.warn("Unsupported CSS attrs: " + [...unsupportedSet].join(", "));
3433
+ diag.warn(PxDiagnosticKind.platform, "Unsupported CSS attrs: " + [...unsupportedSet].join(", "));
3188
3434
  return null;
3189
3435
  }
3190
3436
  const api = {
@@ -3228,20 +3474,36 @@ var PixodeskAnimator = (() => {
3228
3474
  }
3229
3475
  },
3230
3476
  "setPlaybackRate": (rate) => {
3477
+ if (!isValidPlaybackRate(rate)) {
3478
+ diag.warn(PxDiagnosticKind.usage, PX_RATE_REJECTED);
3479
+ return api;
3480
+ }
3231
3481
  animations.forEach((a) => a.playbackRate = rate);
3232
3482
  return api;
3233
3483
  },
3234
3484
  "getCurrentTime": () => {
3235
- var _a2, _b;
3236
- const res = (_b = (_a2 = animations[0]) == null ? void 0 : _a2.currentTime) != null ? _b : null;
3485
+ var _a2, _b2;
3486
+ const res = (_b2 = (_a2 = animations[0]) == null ? void 0 : _a2.currentTime) != null ? _b2 : null;
3237
3487
  return res !== null ? +res : null;
3238
3488
  },
3239
3489
  "setCurrentTime": (time) => {
3490
+ var _a2;
3491
+ const ceiling = seekCeilingMs((_a2 = config.duration) != null ? _a2 : 0, iterations != null ? iterations : 1);
3492
+ const seek = ceiling > 0 ? clampSeekMs(time, ceiling) : Math.max(0, time);
3240
3493
  finishNotified = false;
3241
3494
  animations.forEach((a) => {
3242
- a.currentTime = time;
3495
+ a.currentTime = seek;
3243
3496
  });
3244
3497
  },
3498
+ "getCurrentProgress": () => {
3499
+ var _a2;
3500
+ const t = api.getCurrentTime();
3501
+ return t === null ? null : timeToProgress(t, (_a2 = config.duration) != null ? _a2 : 0, iterations != null ? iterations : 1);
3502
+ },
3503
+ "setCurrentProgress": (progress) => {
3504
+ var _a2;
3505
+ api.setCurrentTime(progressToTimeMs(progress, (_a2 = config.duration) != null ? _a2 : 0, iterations != null ? iterations : 1));
3506
+ },
3245
3507
  "destroy": () => {
3246
3508
  var _a2;
3247
3509
  api.cancel();
@@ -3252,12 +3514,15 @@ var PixodeskAnimator = (() => {
3252
3514
  }
3253
3515
  }
3254
3516
  };
3255
- if (config.trigger) {
3256
- if (config.timelineSource === "scroll") {
3257
- console.warn("scroll timeline: `animator.trigger` is ignored (triggers do not apply to scroll-driven playback)");
3258
- } else {
3259
- setupAnimationTriggers(api, config.trigger);
3260
- }
3517
+ if (config.timelineSource === "scroll") {
3518
+ if (config.trigger) diag.warn(PxDiagnosticKind.usage, "scroll timeline: `animator.trigger` is ignored (triggers do not apply to scroll-driven playback)");
3519
+ } else {
3520
+ const detachTriggers = setupAnimationTriggers(api, (_b = config.trigger) != null ? _b : {}, diag);
3521
+ const destroyEngine = api.destroy.bind(api);
3522
+ api.destroy = () => {
3523
+ detachTriggers();
3524
+ destroyEngine();
3525
+ };
3261
3526
  }
3262
3527
  if (scrollTimeline) {
3263
3528
  animations.forEach((a) => a.play());
@@ -3273,13 +3538,14 @@ var PixodeskAnimator = (() => {
3273
3538
  if (pct === void 0) return void 0;
3274
3539
  return view ? { rangeName: (_c = point == null ? void 0 : point.phase) != null ? _c : "cover", offset: pct } : { offset: pct };
3275
3540
  }
3276
- function createNativeScrollTimeline(subject, config) {
3541
+ function createNativeScrollTimeline(subject, config, diag) {
3277
3542
  var _a, _b, _c, _d;
3543
+ const report = diag != null ? diag : createDiagnostics(void 0, "[PxAnimator]");
3278
3544
  if (!config || !isScrollTimeline(config)) return null;
3279
3545
  const scroll = config.scroll || {};
3280
3546
  const kind = (_a = scroll.kind) != null ? _a : "view";
3281
3547
  if (scroll.smoothing) {
3282
- console.warn("scroll timeline: `smoothing` needs the built-in driver \u2014 using the built-in driver instead of the browser timeline");
3548
+ report.warn(PxDiagnosticKind.platform, "scroll timeline: `smoothing` needs the built-in driver \u2014 using the built-in driver instead of the browser timeline");
3283
3549
  return null;
3284
3550
  }
3285
3551
  const g = globalThis;
@@ -3290,13 +3556,13 @@ var PixodeskAnimator = (() => {
3290
3556
  let timeline;
3291
3557
  try {
3292
3558
  if (view) {
3293
- timeline = new Ctor({ subject: resolveScrollSubject(subject, scroll.subject), axis });
3559
+ timeline = new Ctor({ subject: resolveScrollSubject(subject, scroll.subject, report), axis });
3294
3560
  } else {
3295
3561
  const source = scroll.source === "root" ? documentScroller() : findNearestScroller(subject, "y") || findNearestScroller(subject, "x") || documentScroller();
3296
3562
  timeline = new Ctor({ source, axis });
3297
3563
  }
3298
3564
  } catch (e) {
3299
- console.warn("scroll timeline: native timeline construction failed \u2014 falling back to the player measuring progress itself", e);
3565
+ report.warn(PxDiagnosticKind.platform, "scroll timeline: native timeline construction failed \u2014 falling back to the player measuring progress itself", e);
3300
3566
  return null;
3301
3567
  }
3302
3568
  return {
@@ -3323,8 +3589,9 @@ var PixodeskAnimator = (() => {
3323
3589
  }
3324
3590
  var SUBJECT_PARENT = "parent";
3325
3591
  var SUBJECT_SCROLLER = "scroller";
3326
- function resolveScrollSubject(svgRoot, subject) {
3592
+ function resolveScrollSubject(svgRoot, subject, diag) {
3327
3593
  var _a, _b;
3594
+ const report = diag != null ? diag : createDiagnostics(void 0, "[PxAnimator]");
3328
3595
  const spec = subject == null ? void 0 : subject.trim();
3329
3596
  if (!spec) return svgRoot;
3330
3597
  if (spec === SUBJECT_PARENT) {
@@ -3342,21 +3609,22 @@ var PixodeskAnimator = (() => {
3342
3609
  try {
3343
3610
  found = document.querySelector(spec);
3344
3611
  } catch (e) {
3345
- console.warn('scroll timeline: subject "' + spec + '" is not a valid selector \u2014 measuring the SVG itself');
3612
+ report.warn(PxDiagnosticKind.document, 'scroll timeline: subject "' + spec + '" is not a valid selector \u2014 measuring the SVG itself');
3346
3613
  return svgRoot;
3347
3614
  }
3348
3615
  if (!found) {
3349
- console.warn('scroll timeline: subject "' + spec + '" matched no element \u2014 measuring the SVG itself');
3616
+ report.warn(PxDiagnosticKind.host, 'scroll timeline: subject "' + spec + '" matched no element \u2014 measuring the SVG itself');
3350
3617
  return svgRoot;
3351
3618
  }
3352
3619
  return found;
3353
3620
  }
3354
- function createScrollDriver(subject, config, onProgress) {
3621
+ function createScrollDriver(subject, config, onProgress, diag) {
3355
3622
  var _a, _b;
3356
3623
  if (!config || !isScrollTimeline(config)) return null;
3624
+ const report = diag != null ? diag : createDiagnostics(void 0, "[PxAnimator]");
3357
3625
  const scroll = config.scroll || {};
3358
3626
  const kind = (_a = scroll.kind) != null ? _a : "view";
3359
- const measured = resolveScrollSubject(subject, scroll.subject);
3627
+ const measured = resolveScrollSubject(subject, scroll.subject, report);
3360
3628
  const nearest = findNearestScroller(subject, "y") || findNearestScroller(subject, "x");
3361
3629
  const scroller = kind === "scroll" && scroll.source === "root" ? documentScroller() : nearest || documentScroller();
3362
3630
  const isRootScroller = scroller === documentScroller();
@@ -3475,7 +3743,7 @@ var PixodeskAnimator = (() => {
3475
3743
  const alignFactor = scroll.pinAlign === "center" ? 0.5 : scroll.pinAlign === "bottom" ? 1 : 0;
3476
3744
  const applyTop = () => {
3477
3745
  var _a;
3478
- const extra = (_a = scroll.pinTop) != null ? _a : 0;
3746
+ const extra = (_a = scroll.pinOffset) != null ? _a : 0;
3479
3747
  if (!alignFactor) {
3480
3748
  style.top = extra + "px";
3481
3749
  return;
@@ -3537,6 +3805,7 @@ var PixodeskAnimator = (() => {
3537
3805
  }
3538
3806
  function bindWithEngineChoice(doc, adapter, callbacks, rootElement) {
3539
3807
  const animatorConfig = getAnimatorConfig(doc) || {};
3808
+ const diag = createDiagnostics(callbacks, "[PxAnimator]");
3540
3809
  if (isScrollTimeline(animatorConfig)) {
3541
3810
  return finaliseAnimator(animatorConfig, callbacks, (cb) => {
3542
3811
  var _a;
@@ -3544,7 +3813,7 @@ var PixodeskAnimator = (() => {
3544
3813
  };
3545
3814
  if (mayUseNativeScrollTimeline(animatorConfig.engine) && rootElement) {
3546
3815
  unpin = applyScrollPin(rootElement, animatorConfig.scroll);
3547
- const native = createNativeScrollTimeline(rootElement, animatorConfig);
3816
+ const native = createNativeScrollTimeline(rootElement, animatorConfig, diag);
3548
3817
  if (native) {
3549
3818
  const api2 = createWebApiAnimator(
3550
3819
  doc,
@@ -3574,7 +3843,8 @@ var PixodeskAnimator = (() => {
3574
3843
  const driver = createScrollDriver(
3575
3844
  subject,
3576
3845
  animatorConfig,
3577
- (progress) => api.setCurrentTime(progress * totalMs)
3846
+ (progress) => api.setCurrentTime(progress * totalMs),
3847
+ diag
3578
3848
  );
3579
3849
  if (driver) {
3580
3850
  const destroy = api.destroy.bind(api);
@@ -3585,7 +3855,7 @@ var PixodeskAnimator = (() => {
3585
3855
  };
3586
3856
  }
3587
3857
  } else {
3588
- console.warn("scroll timeline: no root element to observe \u2014 animation will stay at frame 0");
3858
+ diag.warn(PxDiagnosticKind.host, "scroll timeline: no root element to observe \u2014 animation will stay at frame 0");
3589
3859
  }
3590
3860
  return api;
3591
3861
  });
@@ -3602,16 +3872,16 @@ var PixodeskAnimator = (() => {
3602
3872
  ) || createFrameLoopAnimator(doc, adapter, cb, rootElement);
3603
3873
  });
3604
3874
  }
3605
- function requireData(options) {
3606
- if (!(options == null ? void 0 : options.data)) throw new Error("createAnimator: `data` is required");
3607
- return options.data;
3875
+ function requireDoc(options) {
3876
+ if (!(options == null ? void 0 : options.doc)) throw new Error("createAnimator: `doc` is required");
3877
+ return options.doc;
3608
3878
  }
3609
3879
  function createPrerenderedAnimator(options) {
3610
- return bindWithEngineChoice(requireData(options), options.adapter, options.callbacks, null);
3880
+ return bindWithEngineChoice(requireDoc(options), options.adapter, toEngineCallbacks(options), null);
3611
3881
  }
3612
3882
 
3613
3883
  // src/shared/PxAnimatorKeys.ts
3614
- var PX_ANIMATOR_DATA_KEY = "data";
3884
+ var PX_ANIMATOR_DOC_KEY = "doc";
3615
3885
  return __toCommonJS(index_prerendered_exports);
3616
3886
  })();
3617
3887
  //# sourceMappingURL=index.prerendered.umd.js.map