@pixodesk/svg-animator-web 1.0.41 → 1.0.44

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.
@@ -575,14 +575,18 @@ var PixodeskAnimator = (() => {
575
575
  alternate: "alternate",
576
576
  alternateReverse: "alternate-reverse"
577
577
  };
578
- var PxStartOn = {
578
+ var PxTriggerStart = {
579
579
  load: "load",
580
580
  mouseOver: "mouseOver",
581
581
  click: "click",
582
- scrollIntoView: "scrollIntoView",
583
- programmatic: "programmatic"
582
+ none: "none"
583
+ };
584
+ var PxOffScreenAction = {
585
+ pause: "pause",
586
+ continue: "continue",
587
+ reset: "reset"
584
588
  };
585
- var PxOutAction = {
589
+ var PxMouseOutAction = {
586
590
  continue: "continue",
587
591
  pause: "pause",
588
592
  reset: "reset",
@@ -647,16 +651,20 @@ var PixodeskAnimator = (() => {
647
651
  return engine !== PxTimelineEngineSetting.js;
648
652
  }
649
653
  var PX_TRIGGER_DEFAULTS = {
650
- startOn: "load",
651
- outAction: "continue",
652
- scrollIntoViewThreshold: 0
654
+ start: "load",
655
+ offScreen: "pause",
656
+ mouseOut: "continue",
657
+ visibilityThreshold: 0.5,
658
+ visibilityDebounce: 150
653
659
  };
654
660
  function resolveTrigger(trigger) {
655
- var _a, _b, _c;
661
+ var _a, _b, _c, _d, _e;
656
662
  return {
657
- startOn: (_a = trigger == null ? void 0 : trigger.startOn) != null ? _a : PX_TRIGGER_DEFAULTS.startOn,
658
- outAction: (_b = trigger == null ? void 0 : trigger.outAction) != null ? _b : PX_TRIGGER_DEFAULTS.outAction,
659
- scrollIntoViewThreshold: (_c = trigger == null ? void 0 : trigger.scrollIntoViewThreshold) != null ? _c : PX_TRIGGER_DEFAULTS.scrollIntoViewThreshold
663
+ start: (_a = trigger == null ? void 0 : trigger.start) != null ? _a : PX_TRIGGER_DEFAULTS.start,
664
+ offScreen: (_b = trigger == null ? void 0 : trigger.offScreen) != null ? _b : PX_TRIGGER_DEFAULTS.offScreen,
665
+ mouseOut: (_c = trigger == null ? void 0 : trigger.mouseOut) != null ? _c : PX_TRIGGER_DEFAULTS.mouseOut,
666
+ visibilityThreshold: (_d = trigger == null ? void 0 : trigger.visibilityThreshold) != null ? _d : PX_TRIGGER_DEFAULTS.visibilityThreshold,
667
+ visibilityDebounce: (_e = trigger == null ? void 0 : trigger.visibilityDebounce) != null ? _e : PX_TRIGGER_DEFAULTS.visibilityDebounce
660
668
  };
661
669
  }
662
670
  var PxLoopRepeatAt = {
@@ -774,9 +782,9 @@ var PixodeskAnimator = (() => {
774
782
  } else {
775
783
  if (timeline.duration !== void 0) flat.duration = timeline.duration;
776
784
  if (timeline.trigger !== void 0) {
777
- const _b = timeline.trigger, { finishAction } = _b, restTrigger = __objRest(_b, ["finishAction"]);
785
+ const _b = timeline.trigger, { finish } = _b, restTrigger = __objRest(_b, ["finish"]);
778
786
  if (Object.keys(restTrigger).length) flat.trigger = restTrigger;
779
- if (finishAction !== void 0) flat.resetOnFinish = finishAction === "reset";
787
+ if (finish !== void 0) flat.resetOnFinish = finish === "reset";
780
788
  }
781
789
  if (timeline.delay !== void 0) flat.delay = timeline.delay;
782
790
  if (timeline.iterations !== void 0) flat.iterations = timeline.iterations;
@@ -877,13 +885,15 @@ var PixodeskAnimator = (() => {
877
885
  PxAnimationDefinitionSchema
878
886
  ]));
879
887
  var PxTriggerSchema = implementsInterface()(px.object({
880
- startOn: px.enum([PxStartOn.load, PxStartOn.mouseOver, PxStartOn.click, PxStartOn.scrollIntoView, PxStartOn.programmatic], PX_TRIGGER_DEFAULTS.startOn).optional(),
881
- outAction: px.enum([PxOutAction.continue, PxOutAction.pause, PxOutAction.reset, PxOutAction.reverse], PX_TRIGGER_DEFAULTS.outAction).optional(),
888
+ start: px.enum([PxTriggerStart.load, PxTriggerStart.mouseOver, PxTriggerStart.click, PxTriggerStart.none], PX_TRIGGER_DEFAULTS.start).optional(),
889
+ offScreen: px.enum([PxOffScreenAction.pause, PxOffScreenAction.continue, PxOffScreenAction.reset], PX_TRIGGER_DEFAULTS.offScreen).optional(),
890
+ mouseOut: px.enum([PxMouseOutAction.continue, PxMouseOutAction.pause, PxMouseOutAction.reset, PxMouseOutAction.reverse], PX_TRIGGER_DEFAULTS.mouseOut).optional(),
882
891
  // What happens after a NATURAL finish — `'hold'` (default: keep the end state per
883
- // `fill`) or `'reset'` (snap back to the start state). Pairs with `outAction` ("what
884
- // happens when the trigger condition ends"); both end-of-life knobs now read alike.
885
- finishAction: px.enum([PxFinishAction.hold, PxFinishAction.reset]).optional(),
886
- scrollIntoViewThreshold: px.number().optional()
892
+ // `fill`) or `'reset'` (snap back to the start state). One of four occasion keys
893
+ // (`start`, `offScreen`, `mouseOut`, `finish`), all named the same way.
894
+ finish: px.enum([PxFinishAction.hold, PxFinishAction.reset]).optional(),
895
+ visibilityThreshold: px.number().optional(),
896
+ visibilityDebounce: px.number().optional()
887
897
  }));
888
898
  var PxGlyphSchema = implementsInterface()(px.object({
889
899
  width: px.number(),
@@ -2949,32 +2959,34 @@ var PixodeskAnimator = (() => {
2949
2959
  /** The player failed where it did not expect to — report it to us. */
2950
2960
  internal: "internal"
2951
2961
  };
2952
- function asError(error) {
2953
- return typeof error === "string" ? new Error(error) : error;
2962
+ var DOCS_URL = "https://github.com/pixodesk/pixodesk-svg-animator/blob/main/docs/diagnostics.md";
2963
+ function codeLine(code) {
2964
+ return "PX" + code + " " + DOCS_URL + "#px" + code;
2965
+ }
2966
+ function errorIn(data) {
2967
+ return data.find((d) => d instanceof Error);
2954
2968
  }
2955
2969
  function createDiagnostics(config, prefix) {
2956
2970
  const tag = prefix ? prefix + " " : "";
2957
2971
  return {
2958
- warn: (kind, message, detail) => {
2972
+ warn: (kind, code, ...data) => {
2973
+ const message = codeLine(code);
2959
2974
  if (config == null ? void 0 : config.onWarn) {
2960
- config.onWarn({ kind, message, detail });
2975
+ config.onWarn({ code, kind, data, message });
2961
2976
  return;
2962
2977
  }
2963
2978
  if (config == null ? void 0 : config.muteWarn) return;
2964
- const line = tag + kind + ": " + message;
2965
- if (detail === void 0) console.warn(line);
2966
- else console.warn(line, detail);
2979
+ console.warn(tag + kind + " " + message, ...data);
2967
2980
  },
2968
- error: (kind, error, detail) => {
2969
- const err = asError(error);
2981
+ error: (kind, code, ...data) => {
2982
+ const message = codeLine(code);
2983
+ const error = errorIn(data);
2970
2984
  if (config == null ? void 0 : config.onError) {
2971
- config.onError({ kind, message: err.message, error: err, detail });
2985
+ config.onError({ code, kind, data, message, error });
2972
2986
  return;
2973
2987
  }
2974
2988
  if (config == null ? void 0 : config.muteError) return;
2975
- const line = tag + kind + ": " + err.message;
2976
- if (detail === void 0) console.error(line);
2977
- else console.error(line, detail);
2989
+ console.error(tag + kind + " " + message, ...data);
2978
2990
  }
2979
2991
  };
2980
2992
  }
@@ -3083,6 +3095,196 @@ var PixodeskAnimator = (() => {
3083
3095
  return e instanceof Error ? e : new Error(String(e));
3084
3096
  }
3085
3097
 
3098
+ // src/registry/PxAnimatorRegistry.ts
3099
+ var STORE_KEY = /* @__PURE__ */ Symbol.for("@pixodesk/svg-animator-web:animators");
3100
+ var GLOBAL_NAME = "__pixodeskAnimators";
3101
+ function store() {
3102
+ const g = globalThis;
3103
+ let s = g[STORE_KEY];
3104
+ if (!s) {
3105
+ const animators = /* @__PURE__ */ new Set();
3106
+ const listeners = /* @__PURE__ */ new Set();
3107
+ s = {
3108
+ animators,
3109
+ listeners,
3110
+ getAll: () => Array.from(animators),
3111
+ subscribe: (listener) => {
3112
+ listeners.add(listener);
3113
+ return () => {
3114
+ listeners.delete(listener);
3115
+ };
3116
+ }
3117
+ };
3118
+ g[STORE_KEY] = s;
3119
+ if (g[GLOBAL_NAME] === void 0) g[GLOBAL_NAME] = s;
3120
+ }
3121
+ return s;
3122
+ }
3123
+ function notify(event, animator) {
3124
+ for (const listener of store().listeners) {
3125
+ try {
3126
+ listener(event, animator);
3127
+ } catch (e) {
3128
+ setTimeout(() => {
3129
+ throw e;
3130
+ }, 0);
3131
+ }
3132
+ }
3133
+ }
3134
+ function registerAnimator(animator) {
3135
+ const s = store();
3136
+ if (s.animators.has(animator)) return;
3137
+ s.animators.add(animator);
3138
+ notify("add", animator);
3139
+ const destroy = animator.destroy.bind(animator);
3140
+ animator.destroy = () => {
3141
+ destroy();
3142
+ if (s.animators.delete(animator)) notify("remove", animator);
3143
+ };
3144
+ }
3145
+ function withRegistryEvents(callbacks, api) {
3146
+ const fire = (event) => {
3147
+ const a = api();
3148
+ if (a) notify(event, a);
3149
+ };
3150
+ return __spreadProps(__spreadValues({}, callbacks), {
3151
+ onPlay: () => {
3152
+ var _a;
3153
+ (_a = callbacks == null ? void 0 : callbacks.onPlay) == null ? void 0 : _a.call(callbacks);
3154
+ fire("play");
3155
+ },
3156
+ onPause: () => {
3157
+ var _a;
3158
+ (_a = callbacks == null ? void 0 : callbacks.onPause) == null ? void 0 : _a.call(callbacks);
3159
+ fire("pause");
3160
+ },
3161
+ onCancel: () => {
3162
+ var _a;
3163
+ (_a = callbacks == null ? void 0 : callbacks.onCancel) == null ? void 0 : _a.call(callbacks);
3164
+ fire("cancel");
3165
+ },
3166
+ onFinish: () => {
3167
+ var _a;
3168
+ (_a = callbacks == null ? void 0 : callbacks.onFinish) == null ? void 0 : _a.call(callbacks);
3169
+ fire("finish");
3170
+ }
3171
+ });
3172
+ }
3173
+
3174
+ // src/triggers/PxVisibilityGate.ts
3175
+ var PLAY_WHEN_VISIBLE_DEFAULTS = {
3176
+ offScreen: PX_TRIGGER_DEFAULTS.offScreen,
3177
+ visibilityThreshold: PX_TRIGGER_DEFAULTS.visibilityThreshold,
3178
+ visibilityDebounce: PX_TRIGGER_DEFAULTS.visibilityDebounce
3179
+ };
3180
+ var THRESHOLD_STEPS = Array.from({ length: 21 }, (_, i) => i / 20);
3181
+ function effectiveRatio(entry) {
3182
+ var _a, _b;
3183
+ const target = entry.boundingClientRect;
3184
+ const visible = entry.intersectionRect;
3185
+ if (!(target == null ? void 0 : target.height) || !visible) return entry.intersectionRatio;
3186
+ const live = typeof window !== "undefined" && window.innerHeight ? window.innerHeight : Infinity;
3187
+ const declared = (_b = (_a = entry.rootBounds) == null ? void 0 : _a.height) != null ? _b : Infinity;
3188
+ const viewport = Math.min(live, declared);
3189
+ const denom = Math.min(target.height, Number.isFinite(viewport) ? viewport : target.height);
3190
+ return denom > 0 ? visible.height / denom : entry.intersectionRatio;
3191
+ }
3192
+ function openGate(host) {
3193
+ return {
3194
+ requestStart: () => host.play(),
3195
+ dispose: () => {
3196
+ }
3197
+ };
3198
+ }
3199
+ function isGated(offScreen) {
3200
+ return offScreen !== PxOffScreenAction.continue;
3201
+ }
3202
+ function createVisibilityGate(root, trigger, host) {
3203
+ if (!isGated(trigger.offScreen)) return openGate(host);
3204
+ if (typeof IntersectionObserver === "undefined") return openGate(host);
3205
+ const threshold = trigger.visibilityThreshold;
3206
+ const debounceMs = trigger.visibilityDebounce;
3207
+ let isOpen = void 0;
3208
+ let startPending = false;
3209
+ let pausedByGate = false;
3210
+ let lastRatio = 0;
3211
+ let openTimer;
3212
+ const cancelPendingOpen = () => {
3213
+ if (openTimer !== void 0) {
3214
+ clearTimeout(openTimer);
3215
+ openTimer = void 0;
3216
+ }
3217
+ };
3218
+ const open = () => {
3219
+ openTimer = void 0;
3220
+ if (isOpen === true) return;
3221
+ isOpen = true;
3222
+ if (startPending || pausedByGate) {
3223
+ startPending = false;
3224
+ pausedByGate = false;
3225
+ host.play();
3226
+ }
3227
+ };
3228
+ const close = () => {
3229
+ cancelPendingOpen();
3230
+ if (isOpen === false) return;
3231
+ isOpen = false;
3232
+ if (!host.isPlaying()) return;
3233
+ if (trigger.offScreen === PxOffScreenAction.reset) {
3234
+ host.cancel();
3235
+ } else {
3236
+ host.pause();
3237
+ }
3238
+ pausedByGate = true;
3239
+ };
3240
+ const apply = (ratio) => {
3241
+ lastRatio = ratio;
3242
+ if (typeof document !== "undefined" && document.visibilityState === "hidden") {
3243
+ close();
3244
+ return;
3245
+ }
3246
+ if (ratio >= threshold) {
3247
+ if (isOpen === true || openTimer !== void 0) return;
3248
+ if (debounceMs > 0) openTimer = setTimeout(open, debounceMs);
3249
+ else open();
3250
+ return;
3251
+ }
3252
+ if (ratio <= 0) {
3253
+ close();
3254
+ return;
3255
+ }
3256
+ if (isOpen !== true) cancelPendingOpen();
3257
+ };
3258
+ const observer = new IntersectionObserver((entries) => {
3259
+ const last = entries[entries.length - 1];
3260
+ if (last) apply(last.isIntersecting ? effectiveRatio(last) : 0);
3261
+ }, { threshold: THRESHOLD_STEPS });
3262
+ observer.observe(root);
3263
+ const onVisibilityChange = () => {
3264
+ apply(lastRatio);
3265
+ };
3266
+ const hasDocument = typeof document !== "undefined";
3267
+ if (hasDocument) document.addEventListener("visibilitychange", onVisibilityChange);
3268
+ return {
3269
+ requestStart: (immediate) => {
3270
+ if (immediate || isOpen === true) {
3271
+ cancelPendingOpen();
3272
+ isOpen = true;
3273
+ startPending = false;
3274
+ pausedByGate = false;
3275
+ host.play();
3276
+ return;
3277
+ }
3278
+ startPending = true;
3279
+ },
3280
+ dispose: () => {
3281
+ cancelPendingOpen();
3282
+ observer.disconnect();
3283
+ if (hasDocument) document.removeEventListener("visibilitychange", onVisibilityChange);
3284
+ }
3285
+ };
3286
+ }
3287
+
3086
3288
  // src/triggers/PxAnimatorTriggers.ts
3087
3289
  function setupAnimationTriggers(api, trigger, diag) {
3088
3290
  const report = diag != null ? diag : createDiagnostics(void 0, "[PxAnimator]");
@@ -3090,10 +3292,10 @@ var PixodeskAnimator = (() => {
3090
3292
  const dispose = () => {
3091
3293
  for (const undo of cleanups.splice(0)) undo();
3092
3294
  };
3093
- const { startOn, outAction, scrollIntoViewThreshold } = resolveTrigger(trigger);
3295
+ const resolved = resolveTrigger(trigger);
3094
3296
  const root = api.getRootElement();
3095
3297
  if (!root) {
3096
- report.warn(PxDiagnosticKind.host, "setupAnimationTriggers: No root element found for animation.");
3298
+ report.warn(PxDiagnosticKind.host, 1201 /* triggersNoRoot */);
3097
3299
  return dispose;
3098
3300
  }
3099
3301
  let reversed = false;
@@ -3104,27 +3306,34 @@ var PixodeskAnimator = (() => {
3104
3306
  }
3105
3307
  api.play();
3106
3308
  };
3107
- const handleEndAction = () => {
3108
- switch (outAction) {
3109
- case "pause":
3309
+ const gate = createVisibilityGate(root, resolved, {
3310
+ isPlaying: () => api.isPlaying(),
3311
+ play: start,
3312
+ pause: () => api.pause(),
3313
+ cancel: () => api.cancel()
3314
+ });
3315
+ cleanups.push(() => gate.dispose());
3316
+ const handleMouseOut = () => {
3317
+ switch (resolved.mouseOut) {
3318
+ case PxMouseOutAction.pause:
3110
3319
  api.pause();
3111
3320
  break;
3112
- case "reset":
3321
+ case PxMouseOutAction.reset:
3113
3322
  api.cancel();
3114
3323
  break;
3115
- case "reverse":
3324
+ case PxMouseOutAction.reverse:
3116
3325
  reversed = true;
3117
3326
  api.setPlaybackRate(-1);
3118
3327
  api.play();
3119
3328
  break;
3120
- case "continue":
3329
+ case PxMouseOutAction.continue:
3121
3330
  default:
3122
3331
  break;
3123
3332
  }
3124
3333
  };
3125
- switch (startOn) {
3126
- case "load": {
3127
- const startHandler = () => start();
3334
+ switch (resolved.start) {
3335
+ case PxTriggerStart.load: {
3336
+ const startHandler = () => gate.requestStart(false);
3128
3337
  if (document.readyState === "complete") {
3129
3338
  startHandler();
3130
3339
  } else {
@@ -3133,14 +3342,14 @@ var PixodeskAnimator = (() => {
3133
3342
  }
3134
3343
  break;
3135
3344
  }
3136
- case "mouseOver": {
3345
+ case PxTriggerStart.mouseOver: {
3137
3346
  let enteredOnce = false;
3138
3347
  const mouseOverHandler = () => {
3139
3348
  enteredOnce = true;
3140
- start();
3349
+ gate.requestStart(true);
3141
3350
  };
3142
3351
  const mouseOutHandler = () => {
3143
- if (enteredOnce) handleEndAction();
3352
+ if (enteredOnce) handleMouseOut();
3144
3353
  };
3145
3354
  root.addEventListener("mouseenter", mouseOverHandler);
3146
3355
  root.addEventListener("mouseleave", mouseOutHandler);
@@ -3150,51 +3359,16 @@ var PixodeskAnimator = (() => {
3150
3359
  });
3151
3360
  break;
3152
3361
  }
3153
- case "click": {
3362
+ case PxTriggerStart.click: {
3154
3363
  const clickHandler = () => {
3155
- if (api.isPlaying()) {
3156
- handleEndAction();
3157
- } else {
3158
- start();
3159
- }
3364
+ if (api.isPlaying()) api.pause();
3365
+ else gate.requestStart(true);
3160
3366
  };
3161
3367
  root.addEventListener("click", clickHandler);
3162
3368
  cleanups.push(() => root.removeEventListener("click", clickHandler));
3163
3369
  break;
3164
3370
  }
3165
- case "scrollIntoView": {
3166
- const effectiveRatio = (entry) => {
3167
- var _a, _b;
3168
- const target = entry.boundingClientRect;
3169
- const visible = entry.intersectionRect;
3170
- if (!(target == null ? void 0 : target.height) || !visible) return entry.intersectionRatio;
3171
- const live = typeof window !== "undefined" && window.innerHeight ? window.innerHeight : Infinity;
3172
- const declared = (_b = (_a = entry.rootBounds) == null ? void 0 : _a.height) != null ? _b : Infinity;
3173
- const viewport = Math.min(live, declared);
3174
- const denom = Math.min(target.height, Number.isFinite(viewport) ? viewport : target.height);
3175
- return denom > 0 ? visible.height / denom : entry.intersectionRatio;
3176
- };
3177
- const thresholdSteps = Array.from({ length: 21 }, (_, i) => i / 20);
3178
- let wasIntersecting = false;
3179
- const observer = new IntersectionObserver(
3180
- (entries) => {
3181
- entries.forEach((entry) => {
3182
- if (entry.isIntersecting && effectiveRatio(entry) >= scrollIntoViewThreshold) {
3183
- wasIntersecting = true;
3184
- start();
3185
- } else if (wasIntersecting) {
3186
- wasIntersecting = false;
3187
- handleEndAction();
3188
- }
3189
- });
3190
- },
3191
- { threshold: thresholdSteps }
3192
- );
3193
- observer.observe(root);
3194
- cleanups.push(() => observer.disconnect());
3195
- break;
3196
- }
3197
- case "programmatic":
3371
+ case PxTriggerStart.none:
3198
3372
  break;
3199
3373
  }
3200
3374
  return dispose;
@@ -3202,7 +3376,12 @@ var PixodeskAnimator = (() => {
3202
3376
 
3203
3377
  // src/engines/PxAnimatorFrameLoop.ts
3204
3378
  function getSelector(id) {
3205
- return "#" + id;
3379
+ return "#" + escapeCssId(id);
3380
+ }
3381
+ function escapeCssId(id) {
3382
+ const css = globalThis.CSS;
3383
+ if (typeof (css == null ? void 0 : css.escape) === "function") return css.escape(id);
3384
+ return id.replace(/^([0-9])/, (_all, digit) => "\\3" + digit + " ").replace(/([^\w\-\\ ])/g, "\\$1");
3206
3385
  }
3207
3386
  function createFrameLoopAnimator(doc, adapter, callbacks, rootElement) {
3208
3387
  var _a;
@@ -3212,9 +3391,9 @@ var PixodeskAnimator = (() => {
3212
3391
  if (doc.id) {
3213
3392
  const rootSelector = getSelector(doc.id);
3214
3393
  rootElement = document.querySelector(rootSelector);
3215
- if (!rootElement) diag.warn(PxDiagnosticKind.host, "createFrameLoopAnimator: No root element found for selector: " + rootSelector);
3394
+ if (!rootElement) diag.warn(PxDiagnosticKind.host, 1202 /* noRootForSelector */, rootSelector);
3216
3395
  } else {
3217
- diag.warn(PxDiagnosticKind.host, "createFrameLoopAnimator: No root element provided");
3396
+ diag.warn(PxDiagnosticKind.host, 1203 /* noRootElement */);
3218
3397
  }
3219
3398
  }
3220
3399
  const basicApi = createAdapterAnimator(
@@ -3226,7 +3405,7 @@ var PixodeskAnimator = (() => {
3226
3405
  "getRootElement": () => rootElement || null
3227
3406
  });
3228
3407
  if (isScrollTimeline(config)) {
3229
- if (config.trigger) diag.warn(PxDiagnosticKind.usage, "scroll timeline: `animator.trigger` is ignored (triggers do not apply to scroll-driven playback)");
3408
+ if (config.trigger) diag.warn(PxDiagnosticKind.usage, 1306 /* scrollTriggerIgnored */);
3230
3409
  } else {
3231
3410
  const detachTriggers = setupAnimationTriggers(api, (_a = config.trigger) != null ? _a : {}, diag);
3232
3411
  const destroyEngine = api.destroy.bind(api);
@@ -3251,7 +3430,7 @@ var PixodeskAnimator = (() => {
3251
3430
  const elements = (rootElement == null ? void 0 : rootElement.querySelectorAll(selector)) || document.querySelectorAll(selector);
3252
3431
  if (elements.length === 0 && !warnedSelectors.has(selector)) {
3253
3432
  warnedSelectors.add(selector);
3254
- report.warn(PxDiagnosticKind.host, 'setAttribute: No elements found for selector "' + selector + '"');
3433
+ report.warn(PxDiagnosticKind.host, 1207 /* setAttributeNoElement */, selector);
3255
3434
  }
3256
3435
  for (let i = 0; i < elements.length; i++) {
3257
3436
  const element = elements[i];
@@ -3370,9 +3549,9 @@ var PixodeskAnimator = (() => {
3370
3549
  if (doc.id) {
3371
3550
  const rootSelector = getSelector(doc.id);
3372
3551
  rootElement = document.querySelector(rootSelector);
3373
- if (!rootElement) diag.warn(PxDiagnosticKind.host, "createWebApiAnimator: No root element found for selector: " + rootSelector);
3552
+ if (!rootElement) diag.warn(PxDiagnosticKind.host, 1202 /* noRootForSelector */, rootSelector);
3374
3553
  } else {
3375
- diag.warn(PxDiagnosticKind.host, "createWebApiAnimator: No root element provided");
3554
+ diag.warn(PxDiagnosticKind.host, 1203 /* noRootElement */);
3376
3555
  }
3377
3556
  }
3378
3557
  const bindings = normalizeBindings(doc, PxTimelineEngine.native);
@@ -3385,18 +3564,18 @@ var PixodeskAnimator = (() => {
3385
3564
  let finishNotified = false;
3386
3565
  let removeCalled = false;
3387
3566
  if (!(bindings == null ? void 0 : bindings.length)) {
3388
- diag.warn(PxDiagnosticKind.document, "createWebApiAnimator: No animation bindings defined");
3567
+ diag.warn(PxDiagnosticKind.document, 1105 /* noBindings */);
3389
3568
  }
3390
3569
  for (const binding of bindings || []) {
3391
3570
  const animDef = binding.animate;
3392
3571
  if (!animDef || typeof animDef !== "object" || Array.isArray(animDef)) {
3393
- diag.warn(PxDiagnosticKind.document, "createWebApiAnimator: Empty or unresolved binding", binding);
3572
+ diag.warn(PxDiagnosticKind.document, 1106 /* unresolvedBinding */, binding);
3394
3573
  continue;
3395
3574
  }
3396
3575
  const selector = getSelector(binding.id);
3397
3576
  const elements = (rootElement == null ? void 0 : rootElement.querySelectorAll(selector)) || document.querySelectorAll(selector);
3398
3577
  if (elements.length === 0) {
3399
- diag.warn(PxDiagnosticKind.host, 'createWebApiAnimator: No elements found for selector "' + selector + '"');
3578
+ diag.warn(PxDiagnosticKind.host, 1206 /* noElementsForSelector */, selector);
3400
3579
  }
3401
3580
  const keyframesMap = convertToWebApiKeyframes(animDef, unsupportedSet, config);
3402
3581
  const positiveDelay = config.delay && config.delay > 0 ? config.delay : void 0;
@@ -3445,14 +3624,14 @@ var PixodeskAnimator = (() => {
3445
3624
  }
3446
3625
  animations.push(anim);
3447
3626
  } catch (e) {
3448
- diag.warn(PxDiagnosticKind.internal, "createWebApiAnimator: could not build the animation", e);
3627
+ diag.warn(PxDiagnosticKind.internal, 1004 /* animationBuildFailed */, e);
3449
3628
  }
3450
3629
  }
3451
3630
  }
3452
3631
  }
3453
3632
  }
3454
3633
  if (!forceEvenIfHasUnsupportedAttrs && unsupportedSet.size) {
3455
- diag.warn(PxDiagnosticKind.platform, "Unsupported CSS attrs: " + [...unsupportedSet].join(", "));
3634
+ diag.warn(PxDiagnosticKind.platform, 1104 /* unsupportedAnimatedAttrs */, [...unsupportedSet].join(", "));
3456
3635
  return null;
3457
3636
  }
3458
3637
  const api = {
@@ -3497,7 +3676,7 @@ var PixodeskAnimator = (() => {
3497
3676
  },
3498
3677
  "setPlaybackRate": (rate) => {
3499
3678
  if (!isValidPlaybackRate(rate)) {
3500
- diag.warn(PxDiagnosticKind.usage, PX_RATE_REJECTED);
3679
+ diag.warn(PxDiagnosticKind.usage, 1401 /* rateRejected */);
3501
3680
  return api;
3502
3681
  }
3503
3682
  animations.forEach((a) => a.playbackRate = rate);
@@ -3537,7 +3716,7 @@ var PixodeskAnimator = (() => {
3537
3716
  }
3538
3717
  };
3539
3718
  if (config.timelineSource === "scroll") {
3540
- if (config.trigger) diag.warn(PxDiagnosticKind.usage, "scroll timeline: `animator.trigger` is ignored (triggers do not apply to scroll-driven playback)");
3719
+ if (config.trigger) diag.warn(PxDiagnosticKind.usage, 1306 /* scrollTriggerIgnored */);
3541
3720
  } else {
3542
3721
  const detachTriggers = setupAnimationTriggers(api, (_b = config.trigger) != null ? _b : {}, diag);
3543
3722
  const destroyEngine = api.destroy.bind(api);
@@ -3567,7 +3746,7 @@ var PixodeskAnimator = (() => {
3567
3746
  const scroll = config.scroll || {};
3568
3747
  const kind = (_a = scroll.kind) != null ? _a : "view";
3569
3748
  if (scroll.smoothing) {
3570
- report.warn(PxDiagnosticKind.platform, "scroll timeline: `smoothing` needs the built-in driver \u2014 using the built-in driver instead of the browser timeline");
3749
+ report.warn(PxDiagnosticKind.platform, 1301 /* scrollSmoothingNeedsOwnDriver */);
3571
3750
  return null;
3572
3751
  }
3573
3752
  const g = globalThis;
@@ -3584,7 +3763,7 @@ var PixodeskAnimator = (() => {
3584
3763
  timeline = new Ctor({ source, axis });
3585
3764
  }
3586
3765
  } catch (e) {
3587
- report.warn(PxDiagnosticKind.platform, "scroll timeline: native timeline construction failed \u2014 falling back to the player measuring progress itself", e);
3766
+ report.warn(PxDiagnosticKind.platform, 1302 /* scrollNativeUnavailable */, e);
3588
3767
  return null;
3589
3768
  }
3590
3769
  return {
@@ -3631,11 +3810,11 @@ var PixodeskAnimator = (() => {
3631
3810
  try {
3632
3811
  found = document.querySelector(spec);
3633
3812
  } catch (e) {
3634
- report.warn(PxDiagnosticKind.document, 'scroll timeline: subject "' + spec + '" is not a valid selector \u2014 measuring the SVG itself');
3813
+ report.warn(PxDiagnosticKind.document, 1303 /* scrollSubjectInvalid */, spec);
3635
3814
  return svgRoot;
3636
3815
  }
3637
3816
  if (!found) {
3638
- report.warn(PxDiagnosticKind.host, 'scroll timeline: subject "' + spec + '" matched no element \u2014 measuring the SVG itself');
3817
+ report.warn(PxDiagnosticKind.host, 1304 /* scrollSubjectNoMatch */, spec);
3639
3818
  return svgRoot;
3640
3819
  }
3641
3820
  return found;
@@ -3877,7 +4056,7 @@ var PixodeskAnimator = (() => {
3877
4056
  };
3878
4057
  }
3879
4058
  } else {
3880
- diag.warn(PxDiagnosticKind.host, "scroll timeline: no root element to observe \u2014 animation will stay at frame 0");
4059
+ diag.warn(PxDiagnosticKind.host, 1305 /* scrollNoRootToObserve */);
3881
4060
  }
3882
4061
  return api;
3883
4062
  });
@@ -3903,13 +4082,22 @@ var PixodeskAnimator = (() => {
3903
4082
  return build();
3904
4083
  } catch (e) {
3905
4084
  const err = asThrownError(e);
3906
- createDiagnostics(options, "[PxAnimator]").error(PxDiagnosticKind.internal, "createAnimator: could not build the player \u2014 " + err.message, err);
4085
+ createDiagnostics(options, "[PxAnimator]").error(PxDiagnosticKind.internal, 1001 /* buildFailed */, err);
3907
4086
  return createInertAnimator();
3908
4087
  }
3909
4088
  }
3910
4089
  function createPrerenderedAnimator(options) {
3911
4090
  const doc = requireDoc(options);
3912
- return buildOrReport(options, () => bindWithEngineChoice(doc, void 0, toEngineCallbacks(options), null));
4091
+ return registered(options, (callbacks) => buildOrReport(options, () => bindWithEngineChoice(doc, void 0, callbacks, null)));
4092
+ }
4093
+ function registered(options, build) {
4094
+ let apiRef;
4095
+ const api = build(withRegistryEvents(toEngineCallbacks(options), () => apiRef));
4096
+ if (api.isReady()) {
4097
+ apiRef = api;
4098
+ registerAnimator(api);
4099
+ }
4100
+ return api;
3913
4101
  }
3914
4102
 
3915
4103
  // src/shared/PxAnimatorKeys.ts