@pixodesk/svg-animator-web 1.0.43 → 1.0.45

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(),
@@ -1599,6 +1609,38 @@ var PixodeskAnimator = (() => {
1599
1609
  return cubicBezier(flipped);
1600
1610
  }
1601
1611
 
1612
+ // ../svg-animator-core/src/animation/PxStaticTransformMerge.ts
1613
+ function mergeStaticTransformIntoAnimDef(animDef, staticTransform) {
1614
+ if (!animDef) return animDef;
1615
+ const staticParts = staticTransform && typeof staticTransform === "object" && !Array.isArray(staticTransform) ? staticTransform : parseTransformParts(staticTransform);
1616
+ if (!staticParts || !Object.keys(staticParts).length) return animDef;
1617
+ const mergeKfValue = (v) => v && typeof v === "object" && !Array.isArray(v) ? __spreadValues(__spreadValues({}, staticParts), v) : v;
1618
+ const transformAnim = animDef[TRANSFORM_ATTR];
1619
+ if (transformAnim && typeof transformAnim === "object") {
1620
+ const anim = transformAnim;
1621
+ if (Array.isArray(anim.keyframes)) {
1622
+ const out = __spreadProps(__spreadValues({}, anim), {
1623
+ keyframes: anim.keyframes.map((kf) => __spreadProps(__spreadValues({}, kf), { value: mergeKfValue(kf.value) }))
1624
+ });
1625
+ if (out.value !== void 0) out.value = mergeKfValue(out.value);
1626
+ return __spreadProps(__spreadValues({}, animDef), { transform: out });
1627
+ }
1628
+ return animDef;
1629
+ }
1630
+ const channels = Object.keys(animDef).filter((k) => PX_TRANSFORM_FN_NAMES.has(k));
1631
+ if (channels.length !== 1) return animDef;
1632
+ const ch = channels[0];
1633
+ const chAnim = animDef[ch];
1634
+ if (!chAnim || typeof chAnim !== "object" || !Array.isArray(chAnim.keyframes)) return animDef;
1635
+ const lifted = __spreadProps(__spreadValues({}, chAnim), {
1636
+ keyframes: chAnim.keyframes.map((kf) => __spreadProps(__spreadValues({}, kf), { value: __spreadProps(__spreadValues({}, staticParts), { [ch]: kf.value }) }))
1637
+ });
1638
+ if (lifted.value !== void 0) lifted.value = __spreadProps(__spreadValues({}, staticParts), { [ch]: lifted.value });
1639
+ const rest = __spreadValues({}, animDef);
1640
+ delete rest[ch];
1641
+ return __spreadProps(__spreadValues({}, rest), { transform: lifted });
1642
+ }
1643
+
1602
1644
  // ../svg-animator-core/src/materialize/PxMotionPath.ts
1603
1645
  function getKfTranslate(kf) {
1604
1646
  const v = keyframeValue(kf);
@@ -2387,36 +2429,6 @@ var PixodeskAnimator = (() => {
2387
2429
  function generateElementId() {
2388
2430
  return "_px_el_" + ++_elementIdCounter;
2389
2431
  }
2390
- function mergeStaticTransformIntoAnimDef(animDef, staticTransform) {
2391
- if (!animDef) return animDef;
2392
- const staticParts = staticTransform && typeof staticTransform === "object" && !Array.isArray(staticTransform) ? staticTransform : parseTransformParts(staticTransform);
2393
- if (!staticParts || !Object.keys(staticParts).length) return animDef;
2394
- const mergeKfValue = (v) => v && typeof v === "object" && !Array.isArray(v) ? __spreadValues(__spreadValues({}, staticParts), v) : v;
2395
- const transformAnim = animDef[TRANSFORM_ATTR];
2396
- if (transformAnim && typeof transformAnim === "object") {
2397
- const anim = transformAnim;
2398
- if (Array.isArray(anim.keyframes)) {
2399
- const out = __spreadProps(__spreadValues({}, anim), {
2400
- keyframes: anim.keyframes.map((kf) => __spreadProps(__spreadValues({}, kf), { value: mergeKfValue(kf.value) }))
2401
- });
2402
- if (out.value !== void 0) out.value = mergeKfValue(out.value);
2403
- return __spreadProps(__spreadValues({}, animDef), { transform: out });
2404
- }
2405
- return animDef;
2406
- }
2407
- const channels = Object.keys(animDef).filter((k) => PX_TRANSFORM_FN_NAMES.has(k));
2408
- if (channels.length !== 1) return animDef;
2409
- const ch = channels[0];
2410
- const chAnim = animDef[ch];
2411
- if (!chAnim || typeof chAnim !== "object" || !Array.isArray(chAnim.keyframes)) return animDef;
2412
- const lifted = __spreadProps(__spreadValues({}, chAnim), {
2413
- keyframes: chAnim.keyframes.map((kf) => __spreadProps(__spreadValues({}, kf), { value: __spreadProps(__spreadValues({}, staticParts), { [ch]: kf.value }) }))
2414
- });
2415
- if (lifted.value !== void 0) lifted.value = __spreadProps(__spreadValues({}, staticParts), { [ch]: lifted.value });
2416
- const rest = __spreadValues({}, animDef);
2417
- delete rest[ch];
2418
- return __spreadProps(__spreadValues({}, rest), { transform: lifted });
2419
- }
2420
2432
  function normalizeAnimationDefinition(animDef, duration, defs, engine = PxTimelineEngine.native) {
2421
2433
  const normalized = {};
2422
2434
  for (const [propName, propAnim] of Object.entries(animDef)) {
@@ -2499,7 +2511,7 @@ var PixodeskAnimator = (() => {
2499
2511
  return { prevKf, nextKf };
2500
2512
  }
2501
2513
  function calcPropertyValue(propName, propAnim, progress) {
2502
- var _a, _b, _c, _d;
2514
+ var _a, _b, _c, _d, _e;
2503
2515
  const keyframes = propAnim.keyframes || [];
2504
2516
  if (keyframes.length === 0) return null;
2505
2517
  const { prevKf, nextKf } = getKeyframesPair(keyframes, progress);
@@ -2568,7 +2580,7 @@ var PixodeskAnimator = (() => {
2568
2580
  !!propAnim.autoOrient
2569
2581
  );
2570
2582
  partsResult.translate = [sample.translate[0], sample.translate[1]];
2571
- if (sample.rotateDeg !== void 0) partsResult.rotate = sample.rotateDeg;
2583
+ if (sample.rotateDeg !== void 0) partsResult.rotate = sample.rotateDeg + ((_e = partsResult.rotate) != null ? _e : 0);
2572
2584
  }
2573
2585
  }
2574
2586
  cssValue = composeTransformParts(partsResult, { withUnits: false });
@@ -3085,6 +3097,196 @@ var PixodeskAnimator = (() => {
3085
3097
  return e instanceof Error ? e : new Error(String(e));
3086
3098
  }
3087
3099
 
3100
+ // src/registry/PxAnimatorRegistry.ts
3101
+ var STORE_KEY = /* @__PURE__ */ Symbol.for("@pixodesk/svg-animator-web:animators");
3102
+ var GLOBAL_NAME = "__pixodeskAnimators";
3103
+ function store() {
3104
+ const g = globalThis;
3105
+ let s = g[STORE_KEY];
3106
+ if (!s) {
3107
+ const animators = /* @__PURE__ */ new Set();
3108
+ const listeners = /* @__PURE__ */ new Set();
3109
+ s = {
3110
+ animators,
3111
+ listeners,
3112
+ getAll: () => Array.from(animators),
3113
+ subscribe: (listener) => {
3114
+ listeners.add(listener);
3115
+ return () => {
3116
+ listeners.delete(listener);
3117
+ };
3118
+ }
3119
+ };
3120
+ g[STORE_KEY] = s;
3121
+ if (g[GLOBAL_NAME] === void 0) g[GLOBAL_NAME] = s;
3122
+ }
3123
+ return s;
3124
+ }
3125
+ function notify(event, animator) {
3126
+ for (const listener of store().listeners) {
3127
+ try {
3128
+ listener(event, animator);
3129
+ } catch (e) {
3130
+ setTimeout(() => {
3131
+ throw e;
3132
+ }, 0);
3133
+ }
3134
+ }
3135
+ }
3136
+ function registerAnimator(animator) {
3137
+ const s = store();
3138
+ if (s.animators.has(animator)) return;
3139
+ s.animators.add(animator);
3140
+ notify("add", animator);
3141
+ const destroy = animator.destroy.bind(animator);
3142
+ animator.destroy = () => {
3143
+ destroy();
3144
+ if (s.animators.delete(animator)) notify("remove", animator);
3145
+ };
3146
+ }
3147
+ function withRegistryEvents(callbacks, api) {
3148
+ const fire = (event) => {
3149
+ const a = api();
3150
+ if (a) notify(event, a);
3151
+ };
3152
+ return __spreadProps(__spreadValues({}, callbacks), {
3153
+ onPlay: () => {
3154
+ var _a;
3155
+ (_a = callbacks == null ? void 0 : callbacks.onPlay) == null ? void 0 : _a.call(callbacks);
3156
+ fire("play");
3157
+ },
3158
+ onPause: () => {
3159
+ var _a;
3160
+ (_a = callbacks == null ? void 0 : callbacks.onPause) == null ? void 0 : _a.call(callbacks);
3161
+ fire("pause");
3162
+ },
3163
+ onCancel: () => {
3164
+ var _a;
3165
+ (_a = callbacks == null ? void 0 : callbacks.onCancel) == null ? void 0 : _a.call(callbacks);
3166
+ fire("cancel");
3167
+ },
3168
+ onFinish: () => {
3169
+ var _a;
3170
+ (_a = callbacks == null ? void 0 : callbacks.onFinish) == null ? void 0 : _a.call(callbacks);
3171
+ fire("finish");
3172
+ }
3173
+ });
3174
+ }
3175
+
3176
+ // src/triggers/PxVisibilityGate.ts
3177
+ var PLAY_WHEN_VISIBLE_DEFAULTS = {
3178
+ offScreen: PX_TRIGGER_DEFAULTS.offScreen,
3179
+ visibilityThreshold: PX_TRIGGER_DEFAULTS.visibilityThreshold,
3180
+ visibilityDebounce: PX_TRIGGER_DEFAULTS.visibilityDebounce
3181
+ };
3182
+ var THRESHOLD_STEPS = Array.from({ length: 21 }, (_, i) => i / 20);
3183
+ function effectiveRatio(entry) {
3184
+ var _a, _b;
3185
+ const target = entry.boundingClientRect;
3186
+ const visible = entry.intersectionRect;
3187
+ if (!(target == null ? void 0 : target.height) || !visible) return entry.intersectionRatio;
3188
+ const live = typeof window !== "undefined" && window.innerHeight ? window.innerHeight : Infinity;
3189
+ const declared = (_b = (_a = entry.rootBounds) == null ? void 0 : _a.height) != null ? _b : Infinity;
3190
+ const viewport = Math.min(live, declared);
3191
+ const denom = Math.min(target.height, Number.isFinite(viewport) ? viewport : target.height);
3192
+ return denom > 0 ? visible.height / denom : entry.intersectionRatio;
3193
+ }
3194
+ function openGate(host) {
3195
+ return {
3196
+ requestStart: () => host.play(),
3197
+ dispose: () => {
3198
+ }
3199
+ };
3200
+ }
3201
+ function isGated(offScreen) {
3202
+ return offScreen !== PxOffScreenAction.continue;
3203
+ }
3204
+ function createVisibilityGate(root, trigger, host) {
3205
+ if (!isGated(trigger.offScreen)) return openGate(host);
3206
+ if (typeof IntersectionObserver === "undefined") return openGate(host);
3207
+ const threshold = trigger.visibilityThreshold;
3208
+ const debounceMs = trigger.visibilityDebounce;
3209
+ let isOpen = void 0;
3210
+ let startPending = false;
3211
+ let pausedByGate = false;
3212
+ let lastRatio = 0;
3213
+ let openTimer;
3214
+ const cancelPendingOpen = () => {
3215
+ if (openTimer !== void 0) {
3216
+ clearTimeout(openTimer);
3217
+ openTimer = void 0;
3218
+ }
3219
+ };
3220
+ const open = () => {
3221
+ openTimer = void 0;
3222
+ if (isOpen === true) return;
3223
+ isOpen = true;
3224
+ if (startPending || pausedByGate) {
3225
+ startPending = false;
3226
+ pausedByGate = false;
3227
+ host.play();
3228
+ }
3229
+ };
3230
+ const close = () => {
3231
+ cancelPendingOpen();
3232
+ if (isOpen === false) return;
3233
+ isOpen = false;
3234
+ if (!host.isPlaying()) return;
3235
+ if (trigger.offScreen === PxOffScreenAction.reset) {
3236
+ host.cancel();
3237
+ } else {
3238
+ host.pause();
3239
+ }
3240
+ pausedByGate = true;
3241
+ };
3242
+ const apply = (ratio) => {
3243
+ lastRatio = ratio;
3244
+ if (typeof document !== "undefined" && document.visibilityState === "hidden") {
3245
+ close();
3246
+ return;
3247
+ }
3248
+ if (ratio >= threshold) {
3249
+ if (isOpen === true || openTimer !== void 0) return;
3250
+ if (debounceMs > 0) openTimer = setTimeout(open, debounceMs);
3251
+ else open();
3252
+ return;
3253
+ }
3254
+ if (ratio <= 0) {
3255
+ close();
3256
+ return;
3257
+ }
3258
+ if (isOpen !== true) cancelPendingOpen();
3259
+ };
3260
+ const observer = new IntersectionObserver((entries) => {
3261
+ const last = entries[entries.length - 1];
3262
+ if (last) apply(last.isIntersecting ? effectiveRatio(last) : 0);
3263
+ }, { threshold: THRESHOLD_STEPS });
3264
+ observer.observe(root);
3265
+ const onVisibilityChange = () => {
3266
+ apply(lastRatio);
3267
+ };
3268
+ const hasDocument = typeof document !== "undefined";
3269
+ if (hasDocument) document.addEventListener("visibilitychange", onVisibilityChange);
3270
+ return {
3271
+ requestStart: (immediate) => {
3272
+ if (immediate || isOpen === true) {
3273
+ cancelPendingOpen();
3274
+ isOpen = true;
3275
+ startPending = false;
3276
+ pausedByGate = false;
3277
+ host.play();
3278
+ return;
3279
+ }
3280
+ startPending = true;
3281
+ },
3282
+ dispose: () => {
3283
+ cancelPendingOpen();
3284
+ observer.disconnect();
3285
+ if (hasDocument) document.removeEventListener("visibilitychange", onVisibilityChange);
3286
+ }
3287
+ };
3288
+ }
3289
+
3088
3290
  // src/triggers/PxAnimatorTriggers.ts
3089
3291
  function setupAnimationTriggers(api, trigger, diag) {
3090
3292
  const report = diag != null ? diag : createDiagnostics(void 0, "[PxAnimator]");
@@ -3092,7 +3294,7 @@ var PixodeskAnimator = (() => {
3092
3294
  const dispose = () => {
3093
3295
  for (const undo of cleanups.splice(0)) undo();
3094
3296
  };
3095
- const { startOn, outAction, scrollIntoViewThreshold } = resolveTrigger(trigger);
3297
+ const resolved = resolveTrigger(trigger);
3096
3298
  const root = api.getRootElement();
3097
3299
  if (!root) {
3098
3300
  report.warn(PxDiagnosticKind.host, 1201 /* triggersNoRoot */);
@@ -3106,27 +3308,34 @@ var PixodeskAnimator = (() => {
3106
3308
  }
3107
3309
  api.play();
3108
3310
  };
3109
- const handleEndAction = () => {
3110
- switch (outAction) {
3111
- case "pause":
3311
+ const gate = createVisibilityGate(root, resolved, {
3312
+ isPlaying: () => api.isPlaying(),
3313
+ play: start,
3314
+ pause: () => api.pause(),
3315
+ cancel: () => api.cancel()
3316
+ });
3317
+ cleanups.push(() => gate.dispose());
3318
+ const handleMouseOut = () => {
3319
+ switch (resolved.mouseOut) {
3320
+ case PxMouseOutAction.pause:
3112
3321
  api.pause();
3113
3322
  break;
3114
- case "reset":
3323
+ case PxMouseOutAction.reset:
3115
3324
  api.cancel();
3116
3325
  break;
3117
- case "reverse":
3326
+ case PxMouseOutAction.reverse:
3118
3327
  reversed = true;
3119
3328
  api.setPlaybackRate(-1);
3120
3329
  api.play();
3121
3330
  break;
3122
- case "continue":
3331
+ case PxMouseOutAction.continue:
3123
3332
  default:
3124
3333
  break;
3125
3334
  }
3126
3335
  };
3127
- switch (startOn) {
3128
- case "load": {
3129
- const startHandler = () => start();
3336
+ switch (resolved.start) {
3337
+ case PxTriggerStart.load: {
3338
+ const startHandler = () => gate.requestStart(false);
3130
3339
  if (document.readyState === "complete") {
3131
3340
  startHandler();
3132
3341
  } else {
@@ -3135,14 +3344,14 @@ var PixodeskAnimator = (() => {
3135
3344
  }
3136
3345
  break;
3137
3346
  }
3138
- case "mouseOver": {
3347
+ case PxTriggerStart.mouseOver: {
3139
3348
  let enteredOnce = false;
3140
3349
  const mouseOverHandler = () => {
3141
3350
  enteredOnce = true;
3142
- start();
3351
+ gate.requestStart(true);
3143
3352
  };
3144
3353
  const mouseOutHandler = () => {
3145
- if (enteredOnce) handleEndAction();
3354
+ if (enteredOnce) handleMouseOut();
3146
3355
  };
3147
3356
  root.addEventListener("mouseenter", mouseOverHandler);
3148
3357
  root.addEventListener("mouseleave", mouseOutHandler);
@@ -3152,51 +3361,16 @@ var PixodeskAnimator = (() => {
3152
3361
  });
3153
3362
  break;
3154
3363
  }
3155
- case "click": {
3364
+ case PxTriggerStart.click: {
3156
3365
  const clickHandler = () => {
3157
- if (api.isPlaying()) {
3158
- handleEndAction();
3159
- } else {
3160
- start();
3161
- }
3366
+ if (api.isPlaying()) api.pause();
3367
+ else gate.requestStart(true);
3162
3368
  };
3163
3369
  root.addEventListener("click", clickHandler);
3164
3370
  cleanups.push(() => root.removeEventListener("click", clickHandler));
3165
3371
  break;
3166
3372
  }
3167
- case "scrollIntoView": {
3168
- const effectiveRatio = (entry) => {
3169
- var _a, _b;
3170
- const target = entry.boundingClientRect;
3171
- const visible = entry.intersectionRect;
3172
- if (!(target == null ? void 0 : target.height) || !visible) return entry.intersectionRatio;
3173
- const live = typeof window !== "undefined" && window.innerHeight ? window.innerHeight : Infinity;
3174
- const declared = (_b = (_a = entry.rootBounds) == null ? void 0 : _a.height) != null ? _b : Infinity;
3175
- const viewport = Math.min(live, declared);
3176
- const denom = Math.min(target.height, Number.isFinite(viewport) ? viewport : target.height);
3177
- return denom > 0 ? visible.height / denom : entry.intersectionRatio;
3178
- };
3179
- const thresholdSteps = Array.from({ length: 21 }, (_, i) => i / 20);
3180
- let wasIntersecting = false;
3181
- const observer = new IntersectionObserver(
3182
- (entries) => {
3183
- entries.forEach((entry) => {
3184
- if (entry.isIntersecting && effectiveRatio(entry) >= scrollIntoViewThreshold) {
3185
- wasIntersecting = true;
3186
- start();
3187
- } else if (wasIntersecting) {
3188
- wasIntersecting = false;
3189
- handleEndAction();
3190
- }
3191
- });
3192
- },
3193
- { threshold: thresholdSteps }
3194
- );
3195
- observer.observe(root);
3196
- cleanups.push(() => observer.disconnect());
3197
- break;
3198
- }
3199
- case "programmatic":
3373
+ case PxTriggerStart.none:
3200
3374
  break;
3201
3375
  }
3202
3376
  return dispose;
@@ -3204,7 +3378,12 @@ var PixodeskAnimator = (() => {
3204
3378
 
3205
3379
  // src/engines/PxAnimatorFrameLoop.ts
3206
3380
  function getSelector(id) {
3207
- return "#" + id;
3381
+ return "#" + escapeCssId(id);
3382
+ }
3383
+ function escapeCssId(id) {
3384
+ const css = globalThis.CSS;
3385
+ if (typeof (css == null ? void 0 : css.escape) === "function") return css.escape(id);
3386
+ return id.replace(/^([0-9])/, (_all, digit) => "\\3" + digit + " ").replace(/([^\w\-\\ ])/g, "\\$1");
3208
3387
  }
3209
3388
  function createFrameLoopAnimator(doc, adapter, callbacks, rootElement) {
3210
3389
  var _a;
@@ -3911,7 +4090,16 @@ var PixodeskAnimator = (() => {
3911
4090
  }
3912
4091
  function createPrerenderedAnimator(options) {
3913
4092
  const doc = requireDoc(options);
3914
- return buildOrReport(options, () => bindWithEngineChoice(doc, void 0, toEngineCallbacks(options), null));
4093
+ return registered(options, (callbacks) => buildOrReport(options, () => bindWithEngineChoice(doc, void 0, callbacks, null)));
4094
+ }
4095
+ function registered(options, build) {
4096
+ let apiRef;
4097
+ const api = build(withRegistryEvents(toEngineCallbacks(options), () => apiRef));
4098
+ if (api.isReady()) {
4099
+ apiRef = api;
4100
+ registerAnimator(api);
4101
+ }
4102
+ return api;
3915
4103
  }
3916
4104
 
3917
4105
  // src/shared/PxAnimatorKeys.ts