UNPKG

@ssgoi/core

Version:

Core animation engine for SSGOI - Native app-like page transitions with spring physics

1,129 lines (1,128 loc) 30.8 kB
var tt = Object.defineProperty; var et = (e, n, t) => n in e ? tt(e, n, { enumerable: !0, configurable: !0, writable: !0, value: t }) : e[n] = t; var m = (e, n, t) => et(e, typeof n != "symbol" ? n + "" : n, t); import { normalizeToMultiAnimation as M, normalizeSchedule as X } from "./types.js"; import { isCssAnimation as Nt, isMultiAnimation as Ut, isSingleAnimation as Ht, isTickAnimation as Xt } from "./types.js"; import { S as $, I as it, a as nt } from "./provider-Cu4NSF1Q.js"; class rt { constructor() { m(this, "listeners", /* @__PURE__ */ new Set()); m(this, "rafId", null); m(this, "isRunning", !1); // Timing m(this, "startTime", Date.now()); m(this, "lastUpdate", this.startTime); m(this, "elapsed", 0); // Lag smoothing (mobile optimization) m(this, "lagThreshold", 500); // ms - detect tab switches, backgrounding m(this, "adjustedLag", 33); // ms - max time jump to prevent animation skip m(this, "maxDeltaTime", 33); // ms - clamp for physics stability (30fps minimum) // FPS throttling m(this, "gap", 1e3 / 240); // max 240fps m(this, "nextTime", this.gap); m(this, "tick", () => { const n = Date.now(); let i = n - this.lastUpdate; i > this.lagThreshold || i < 0 ? (this.startTime += i - this.adjustedLag, i = this.adjustedLag) : i > this.maxDeltaTime && (i = this.maxDeltaTime), this.lastUpdate = n; const r = n - this.startTime, o = r - this.nextTime; if (o > 0) { const l = i / 1e3; this.elapsed = r / 1e3, this.nextTime += o + (o >= this.gap ? 4 : this.gap - o), this.listeners.forEach((c) => { c(l, this.elapsed); }); } this.listeners.size > 0 ? this.rafId = requestAnimationFrame(this.tick) : (this.isRunning = !1, this.rafId = null); }); } subscribe(n) { return this.listeners.add(n), this.isRunning || (this.isRunning = !0, this.rafId = requestAnimationFrame(this.tick)), () => { this.unsubscribe(n); }; } unsubscribe(n) { this.listeners.delete(n), this.listeners.size === 0 && this.rafId !== null && (cancelAnimationFrame(this.rafId), this.isRunning = !1, this.rafId = null); } /** * Configure lag smoothing behavior * @param threshold - Time threshold to detect lag (default: 500ms) * @param adjustedLag - Max time jump when lag detected (default: 33ms) */ lagSmoothing(n, t) { this.lagThreshold = n, this.adjustedLag = Math.min(t, n); } /** * Set maximum FPS * @param fps - Target FPS (default: 240) */ fps(n) { this.gap = 1e3 / n, this.nextTime = this.elapsed * 1e3 + this.gap; } getListenerCount() { return this.listeners.size; } getElapsed() { return this.elapsed; } } const _ = new rt(); function ot(e) { const { integrator: n, from: t, to: i, velocity: r = 0, onUpdate: o, onComplete: l, onStart: c } = e; let s = { position: t, velocity: r }, f = !0, h = 0, p = !1; const w = (v) => { if (f) { if (p || (p = !0, c == null || c()), s = n.step(s, i, v), n.isSettled(s, i)) { if (h += Math.min(v, 0.033), h >= $) { s = { position: i, velocity: 0 }, f = !1, o(s.position), _.unsubscribe(w), l(); return; } } else h = 0; o(s.position); } }; return _.subscribe(w), { stop: () => { f && (f = !1, _.unsubscribe(w)); }, getPosition: () => s.position, getVelocity: () => s.velocity, isRunning: () => f }; } const x = 1e3 / 60; function st(e, n, t, i = 0) { let o = { position: n, velocity: i }, l = 0; const c = []; for (let s = 0; s < 600; s++) { const f = s * x; if (c.push({ time: f, position: o.position, velocity: o.velocity }), o = e.step(o, t, x / 1e3), e.isSettled(o, t)) { if (l += x / 1e3, l >= $) { c.push({ time: (s + 1) * x, position: t, velocity: 0 }); break; } } else l = 0; } return c; } function Y(e, n) { if (e.length === 0) return { position: 0, velocity: 0 }; const t = e[0], i = e[e.length - 1]; if (n <= 0) return { position: t.position, velocity: t.velocity }; if (n >= i.time) return { position: i.position, velocity: i.velocity }; let r = 0, o = e.length - 1; for (; r < o - 1; ) { const f = Math.floor((r + o) / 2); e[f].time <= n ? r = f : o = f; } const l = e[r], c = e[o], s = (n - l.time) / (c.time - l.time); return { position: l.position + (c.position - l.position) * s, velocity: l.velocity + (c.velocity - l.velocity) * s }; } function at(e, n) { return e.map((t) => n(t.position)); } function ct(e) { const { integrator: n, element: t, from: i, to: r, velocity: o = 0, style: l, onComplete: c, onStart: s } = e, f = st(n, i, r, o); if (f.length === 0) return s == null || s(), c(), { stop: () => { }, getPosition: () => r, getVelocity: () => 0, isRunning: () => !1 }; const h = at(f, l), p = f[f.length - 1], w = p.time, v = h[0]; if (v) for (const y of Object.keys(v)) t.style[y] = ""; const d = t.animate(h, { duration: w, fill: "forwards", easing: "linear", composite: "replace" }); let u = !0; const C = performance.now(); return s == null || s(), d.onfinish = () => { u && (u = !1, c()); }, { stop: () => { u && (u = !1, d.cancel()); }, getPosition: () => { if (!u) return p.position; const y = performance.now() - C; return Y(f, y).position; }, getVelocity: () => { if (!u) return 0; const y = performance.now() - C; return Y(f, y).velocity; }, isRunning: () => u }; } function lt(e) { const { to: n, onStart: t, onComplete: i } = e; return t == null || t(), i(), { stop: () => { }, getPosition: () => n, getVelocity: () => 0, isRunning: () => !1 }; } class ut { /** * Get bound runner based on animation mode * * @param options Animation mode options (tick or css) * @returns Bound runner function (empty runner if no animation mode specified) * @throws Error if both tick and css are provided */ static from(n) { const { tick: t, css: i } = n; if (t && i) throw new Error("Cannot use both 'tick' and 'css' options together"); return i ? (r) => ct({ ...r, element: i.element, style: i.style }) : t ? (r) => ot({ ...r, onUpdate: t }) : lt; } } class K { } const ft = { stiffness: 300, damping: 30 }; class j extends K { constructor(t) { super(); m(this, "options"); m(this, "runner"); m(this, "controls", null); m(this, "isAnimating", !1); m(this, "currentValue"); m(this, "currentVelocity", 0); m(this, "updateFn"); if (this.options = { from: t.from ?? 0, to: t.to ?? 1, physics: t.physics, onComplete: t.onComplete ?? (() => { }), onStart: t.onStart }, this.currentValue = this.options.from, t.tick) this.updateFn = (i) => { var r; return (r = t.tick) == null ? void 0 : r.call(t, i); }; else if (t.css) { const { element: i, style: r } = t.css; this.updateFn = (o) => { const l = r(o); for (const [c, s] of Object.entries(l)) i.style[c] = typeof s == "number" ? String(s) : s; }; } else this.updateFn = () => { }; this.runner = ut.from({ tick: t.tick, css: t.css }); } /** * Sync element state to current progress value * Uses the update callback if provided */ syncState() { var t; (t = this.updateFn) == null || t.call(this, this.currentValue); } /** * Create Integrator from physics options * Priority: integrator factory > inertia/spring config > default spring */ createIntegrator() { const t = this.options.physics; return t != null && t.integrator ? t.integrator() : t != null && t.spring || t != null && t.inertia ? it.from({ spring: t.spring, inertia: t.inertia }) : new nt(ft); } runAnimation(t) { this.isAnimating = !0, this.controls = this.runner({ integrator: this.createIntegrator(), from: this.currentValue, to: t, velocity: this.currentVelocity, onStart: this.options.onStart, onComplete: () => { this.currentValue = t, this.currentVelocity = 0, this.isAnimating = !1, this.controls = null, this.options.onComplete(); } }); } forward() { this.stop(), this.runAnimation(this.options.to); } backward() { this.stop(), this.runAnimation(this.options.from); } reverse() { const t = this.options.from; this.options.from = this.options.to, this.options.to = t, this.isAnimating && (this.stop(), this.runAnimation(this.options.to)); } stop() { this.controls && (this.currentValue = this.controls.getPosition(), this.currentVelocity = this.controls.getVelocity(), this.controls.stop(), this.controls = null), this.isAnimating = !1; } getVelocity() { var t; return ((t = this.controls) == null ? void 0 : t.getVelocity()) ?? this.currentVelocity; } getCurrentValue() { var t; return ((t = this.controls) == null ? void 0 : t.getPosition()) ?? this.currentValue; } getIsAnimating() { return this.isAnimating; } getCurrentState() { return { position: this.getCurrentValue(), velocity: this.getVelocity(), from: this.options.from, to: this.options.to }; } setValue(t) { this.currentValue = t; } setVelocity(t) { this.currentVelocity = t; } updateOptions(t) { this.options = { ...this.options, ...t }; } } class D extends K { constructor(t) { super(); m(this, "config"); m(this, "animators", /* @__PURE__ */ new Map()); m(this, "itemOrder", []); m(this, "completedCount", 0); m(this, "completedAnimators", /* @__PURE__ */ new Set()); m(this, "direction", "forward"); m(this, "idCounter", 0); m(this, "rafId", null); m(this, "from"); m(this, "to"); m(this, "initialState"); this.config = t.config, this.from = t.from, this.to = t.to, this.initialState = t.state ?? { position: t.from, velocity: 0 }, this.initializeAnimators(); } generateId() { return `spring_${this.idCounter++}`; } initializeAnimators() { this.config.items.forEach((t, i) => { const r = this.generateId(), o = new j({ from: this.from, to: this.to, physics: t.physics, tick: t.tick, css: t.css, onComplete: () => this.onAnimatorComplete(r), onStart: t.onStart }); (i === 0 || t.normalizedOffset === 0) && (o.setValue(this.initialState.position), o.setVelocity(this.initialState.velocity), o.syncState()), this.animators.set(r, { id: r, item: t, animator: o, started: !1 }), this.itemOrder.push(r); }); } /** * Calculate progress of an animator (0-1) * Progress = |position - from| / |to - from| */ getAnimatorProgress(t) { const i = t.animator.getCurrentState(), r = Math.abs(i.to - i.from); return r === 0 ? 1 : Math.abs(i.position - i.from) / r; } /** * Get order of springs based on direction * Forward: 0, 1, 2, ... * Backward: n-1, n-2, ..., 0 */ getOrderedIds() { return this.direction === "forward" ? this.itemOrder : [...this.itemOrder].reverse(); } onAnimatorComplete(t) { var r, o, l, c, s, f; const i = this.animators.get(t); !i || this.completedAnimators.has(t) || (this.completedAnimators.add(t), this.completedCount++, (o = (r = i.item).onComplete) == null || o.call(r), (c = (l = this.config).onProgress) == null || c.call(l, this.completedCount, this.config.items.length), this.completedCount === this.config.items.length && (this.stopScheduler(), (f = (s = this.config).onEnd) == null || f.call(s))); } /** * Check and start springs based on previous spring's progress * Called on each frame while animation is running */ checkAndStartSprings() { const t = this.getOrderedIds(); for (let i = 0; i < t.length; i++) { const r = t[i], o = this.animators.get(r); if (!o || o.started) continue; if (i === 0) { this.startAnimator(r); continue; } const l = t[i - 1], c = this.animators.get(l); if (!c || !c.started) continue; const s = this.getAnimatorProgress(c), f = o.item.normalizedOffset; s >= f && this.startAnimator(r); } } startAnimator(t) { const i = this.animators.get(t); !i || i.started || (i.started = !0, this.direction === "forward" ? i.animator.forward() : i.animator.backward()); } /** * Start the scheduler loop that checks spring progress */ startScheduler() { const t = () => { this.checkAndStartSprings(), this.getIsAnimating() && (this.rafId = requestAnimationFrame(t)); }; t(); } stopScheduler() { this.rafId !== null && (cancelAnimationFrame(this.rafId), this.rafId = null); } getFirstAnimator() { var i; const t = this.itemOrder[0]; return t ? ((i = this.animators.get(t)) == null ? void 0 : i.animator) ?? null : null; } forward() { var t, i; this.stop(), this.direction = "forward", this.completedCount = 0, this.completedAnimators.clear(), this.resetStartedFlags(), (i = (t = this.config).onStart) == null || i.call(t), this.startScheduler(); } backward() { var t, i; this.stop(), this.direction = "backward", this.completedCount = 0, this.completedAnimators.clear(), this.resetStartedFlags(), (i = (t = this.config).onStart) == null || i.call(t), this.startScheduler(); } resetStartedFlags() { this.animators.forEach((t) => { t.started = !1; }); } stop() { this.stopScheduler(), this.animators.forEach((t) => { t.animator.stop(), t.started = !1; }); } reverse() { this.direction = this.direction === "forward" ? "backward" : "forward", this.animators.forEach((t) => { if (!t.started) return; const i = t.animator.getCurrentState(); if (i.position === i.to) { const o = new j({ from: this.to, to: this.from, physics: t.item.physics, tick: t.item.tick, css: t.item.css, onComplete: () => this.onAnimatorComplete(t.id), onStart: t.item.onStart }); o.setValue(this.to), o.setVelocity(0), o.syncState(), o.forward(), t.animator = o; } else t.animator.reverse(); }); } getCurrentState() { const t = this.getFirstAnimator(); return t ? t.getCurrentState() : { position: 0, velocity: 0, from: 0, to: 1 }; } /** * Get current position value from first animator */ getCurrentValue() { const t = this.getFirstAnimator(); return (t == null ? void 0 : t.getCurrentValue()) ?? 0; } /** * Get current velocity from first animator */ getVelocity() { const t = this.getFirstAnimator(); return (t == null ? void 0 : t.getVelocity()) ?? 0; } /** * Set position value on first animator * TODO: Support per-spring control */ setValue(t) { const i = this.getFirstAnimator(); i == null || i.setValue(t); } /** * Set velocity on first animator * TODO: Support per-spring control */ setVelocity(t) { const i = this.getFirstAnimator(); i == null || i.setVelocity(t); } /** * Check if any animation is currently running */ getIsAnimating() { for (const t of this.animators.values()) if (t.animator.getIsAnimating()) return !0; return !1; } /** * Create MultiAnimator from existing state * Uses first animator's state for initialization */ static fromState(t, i) { return new D({ ...i, state: t }); } } const B = Symbol.for("TRANSITION_STRATEGY"), mt = (e) => ({ runIn: async (n) => { const { currentAnimation: t } = e; if (t && t.direction === "out") { const r = t.controller.getCurrentValue(), o = t.controller.getVelocity(); if (t.controller.stop(), n.out) return { config: await n.out, state: { position: r, velocity: o }, from: 1, to: 0, direction: "backward" // Will actually go 0→1 (backward means toward 'from') }; } return n.in ? { config: await n.in, state: { position: 0, velocity: 0 }, from: 0, to: 1, direction: "forward" } : { state: { position: 0, velocity: 0 }, from: 0, to: 1, direction: "forward" }; }, runOut: async (n) => { const { currentAnimation: t } = e; if (t && t.direction === "in") { const r = t.controller.getCurrentValue(), o = t.controller.getVelocity(); if (t.controller.stop(), n.in) return { config: await n.in, state: { position: r, velocity: o }, from: 0, to: 1, direction: "backward" // Will actually go 1→0 (backward means toward 'from') }; } return n.out ? { config: await n.out, state: { position: 1, velocity: 0 }, from: 1, to: 0, direction: "forward" } : { state: { position: 1, velocity: 0 }, from: 1, to: 0, direction: "forward" }; } }), dt = () => ({ runIn: async (e) => e.in ? { config: await e.in, state: { position: 0, velocity: 0 }, from: 0, to: 1, direction: "forward" } : { state: { position: 0, velocity: 0 }, from: 0, to: 1, direction: "forward" }, runOut: async (e) => e.out ? { config: await e.out, state: { position: 1, velocity: 0 }, from: 1, to: 0, direction: "forward" } : { state: { position: 1, velocity: 0 }, from: 1, to: 0, direction: "forward" } }), J = "data-ssgoi-scope", Q = "data-ssgoi-scope-ready"; function Ft() { return (e) => { if (e) return e.setAttribute(J, ""), queueMicrotask(() => { queueMicrotask(() => { e.setAttribute(Q, "true"); }); }), () => { }; }; } function ht(e) { return e.hasAttribute(Q); } function gt(e) { return e.closest(`[${J}]`); } const pt = (e) => { let n = e.parentElement; for (; n && n !== document.body; ) { const t = window.getComputedStyle(n), i = t.overflow + t.overflowY + t.overflowX; if (i.includes("auto") || i.includes("scroll") || n.scrollHeight > n.clientHeight || n.scrollWidth > n.clientWidth) return n; n = n.parentElement; } return document.documentElement; }, wt = (e) => { let n = e.parentElement; for (; n && n !== document.body; ) { const t = window.getComputedStyle(n).position; if (t === "relative" || t === "absolute" || t === "fixed" || t === "sticky") return n; n = n.parentElement; } return document.body; }; function W(e) { return new Promise((n) => { requestAnimationFrame(() => { requestAnimationFrame(() => { n(); }); }); }); } function yt(e, n) { var v; let t = null, i = null, r = null, o = null; const l = { get currentAnimation() { return t; } }, c = ((v = n == null ? void 0 : n.strategy) == null ? void 0 : v.call(n, l)) || mt(l), s = async (d) => { var R, P; i && (i.remove(), i = null); const u = e(), C = u.in && u.in(d), y = !(n != null && n.strategy) && u.out ? u.out(d) : void 0; if (!C) return; const V = { in: M(C), out: y ? M(y) : void 0 }, g = await c.runIn(V); if (!g.config) { t && (t.direction = "in"); return; } const a = g.config; (R = a.prepare) == null || R.call(a); const S = X( { ...a, onEnd: () => { var E; t = null, (E = a.onEnd) == null || E.call(a); } }, d ); a.wait && await a.wait(); const A = D.fromState(g.state, { config: S, from: g.from, to: g.to }); t = { controller: A, direction: "in" }, (P = a.onReady) == null || P.call(a), await W(), g.direction === "forward" ? A.forward() : A.backward(); }, f = async (d) => { var P, E; i = d; const u = e(), C = !(n != null && n.strategy) && u.in ? u.in(d) : void 0, y = u.out && u.out(d); if (!y) return; const V = { in: C ? M(C) : void 0, out: M(y) }, g = await c.runOut(V); if (!g.config) { t && (t.direction = "out"), i && (i.remove(), i = null); return; } const a = g.config; R(), (P = a.prepare) == null || P.call(a); const S = X( { ...a, onEnd: () => { var I, k; (I = a.onEnd) == null || I.call(a), i && (i.remove(), i = null), t = null, (k = n == null ? void 0 : n.onCleanupEnd) == null || k.call(n); } }, d ); a.wait && await a.wait(); const A = D.fromState(g.state, { config: S, from: g.from, to: g.to }); t = { controller: A, direction: "out" }, (E = a.onReady) == null || E.call(a), await W(), g.direction === "forward" ? A.forward() : A.backward(); function R() { !r || !i || (o && r.contains(o) ? r.insertBefore(i, o) : r.appendChild(i)); } }; let h = null, p = !1; const w = (d) => () => { if (p) return; p = !0; const u = d.cloneNode(!0); h ? queueMicrotask(() => { document.contains(h) && f(u); }) : f(u); }; return (d) => { if (d) return requestAnimationFrame(() => { r = d.parentElement, o = d.nextElementSibling; }), p = !1, (n == null ? void 0 : n.scope) === "local" ? queueMicrotask(() => { h = gt(d), !(h && !ht(h)) && s(d); }) : s(d), w(d); }; } const b = /* @__PURE__ */ new Map(); let T = null, N = !1; function Z(e) { if (e instanceof HTMLElement && b.has(e)) { const t = b.get(e); b.delete(e), queueMicrotask(() => { t(); }); } const n = e.childNodes; for (let t = 0; t < n.length; t++) { const i = n[t]; i && Z(i); } } function vt() { N || typeof document > "u" || (N = !0, T = new MutationObserver((e) => { for (const n of e) { const t = n.removedNodes; for (let i = 0; i < t.length; i++) { const r = t[i]; r && Z(r); } } }), document.body ? T.observe(document.body, { childList: !0, subtree: !0 }) : document.addEventListener( "DOMContentLoaded", () => { T == null || T.observe(document.body, { childList: !0, subtree: !0 }); }, { once: !0 } )); } function St(e, n) { vt(), b.set(e, n); } function Mt(e) { return b.has(e); } function xt() { return b.size; } function Ot(e) { const n = b.get(e); return n ? (b.delete(e), n(), !0) : !1; } function Lt() { b.clear(), T == null || T.disconnect(), T = null, N = !1; } const L = /* @__PURE__ */ new Map(), U = /* @__PURE__ */ new Map(), H = /* @__PURE__ */ new Map(); function Ct(e, n, t) { L.set(e, n); let i = U.get(e); if (i) return i; const r = n; return i = yt( () => { const o = L.get(e); return o || (console.warn(`Transition "${String(e)}" not found`), {}); }, { strategy: t == null ? void 0 : t.strategy, scope: t == null ? void 0 : t.scope, onCleanupEnd: () => { L.get(e) === r && At(e); } } ), U.set(e, i), i; } function At(e) { L.delete(e), U.delete(e), H.delete(e); } function Dt(e, n = "manual") { const t = Ct( e.key, { in: e.in, out: e.out }, { strategy: e[B], scope: e.scope } ); if (n === "manual") return t; let i = H.get(e.key); return i || (i = (r) => { if (r) { const o = t(r); o && St(r, o); } }, H.set(e.key, i), i); } function Et(e) { const n = e.filter((t) => t.symmetric).map((t) => ({ from: t.to, to: t.from, transition: t.transition })); return [...e, ...n]; } function Tt(e) { let n = !1, t = 0, i = 0, r = !1; const o = 50, l = (d) => { if (!e) return; const u = d.touches[0]; u && (r = u.clientX < o, r && (t = u.clientX, i = u.clientY)); }, c = (d) => { if (!e || !r) return; const u = d.touches[0]; if (!u) return; const C = u.clientX - t, y = u.clientY - i; C > window.outerWidth / 2 - 5 && Math.abs(C) > Math.abs(y) ? n = !0 : n = !1; }, s = () => { e && (r = !1, t = 0, i = 0); }, f = () => n, h = () => { typeof window > "u" || e && (window.addEventListener("touchstart", l, { passive: !0 }), window.addEventListener("touchmove", c, { passive: !0 }), window.addEventListener("touchend", s, { passive: !0 })); }, p = () => { typeof window > "u" || (window.removeEventListener("touchstart", l), window.removeEventListener("touchmove", c), window.removeEventListener("touchend", s)); }; let w = 0; return { initialize: h, cleanup: p, isSwipePending: f, resetSwipeDetection: () => { requestAnimationFrame(() => { w++, w > 1 && (w = 0, n = !1); }); } }; } function bt() { let e = null, n = null; const t = /* @__PURE__ */ new Map(); let i = null; const r = () => { e && i && t.set(i, { x: e.scrollLeft, y: e.scrollTop }); }; return { initializeContext: (h, p) => { n = h, e || (e = pt(h), (e === document.documentElement ? window : e).addEventListener("scroll", r, { passive: !0 })), i = p; }, calculateScrollOffset: (h, p) => { const w = h && t.has(h) ? t.get(h) : { x: 0, y: 0 }, v = p && t.has(p) ? t.get(p) : { x: 0, y: 0 }; return { x: -v.x + w.x, y: -v.y + w.y }; }, getScrollContainer: () => e, getPositionedParentElement: () => n ? wt(n) : document.body, getScrollPosition: (h) => h && t.has(h) ? t.get(h) : { x: 0, y: 0 } }; } function O(e, n) { if (n === "*") return !0; if (n.endsWith("/*")) { const t = n.slice(0, -2); return e === t || e.startsWith(t + "/"); } return e === n; } function G(e, n, t) { for (const i of t) if (O(e, i.from) && O(n, i.to)) return i.transition; for (const i of t) if ((i.from === "*" || O(e, i.from)) && (i.to === "*" || O(n, i.to))) return i.transition; return null; } function kt() { let e = null; function n() { if (e != null && e.from && (e != null && e.to) && (e != null && e.outResolve) && (e != null && e.inResolve)) { const t = { from: e.from, to: e.to }; e.outResolve(t), e.inResolve(t), e = null; } } return { trigger(t, i) { e || (e = {}), i === "out" ? e.from = t : e.to = t; }, get(t) { return t === "in" && (!e || !e.from) ? Promise.resolve(null) : new Promise((i) => { e || (e = {}), t === "out" ? e.outResolve = i : e.inResolve = i, n(); }); } }; } function Rt() { let e = null; function n() { var i, r; e && ((i = e.outResolve) == null || i.call(e, null), (r = e.inResolve) == null || r.call(e, null), e = null); } function t() { if (e != null && e.from && (e != null && e.to) && (e != null && e.outResolve) && (e != null && e.inResolve)) { const i = { from: e.from, to: e.to }; e.outResolve(i), e.inResolve(i), e = null; } } return { trigger(i, r) { e && (r === "out" && e.from && e.from !== i || r === "in" && e.to && e.to !== i) && n(), e || (e = {}), r === "out" ? e.from = i : e.to = i; }, get(i) { return new Promise((r) => { e || (e = {}), i === "out" ? e.outResolve = r : e.inResolve = r, t(); }); } }; } function zt(e, n) { const { transitions: t = [], defaultTransition: i, middleware: r = (g, a) => ({ from: g, to: a }), // Identity function as default skipOnIosSwipe: o = !0 // Default to true - skip animations on iOS swipe } = e, { outFirst: l = !0, createNavigationDetector: c } = n || {}, s = (c == null ? void 0 : c()) ?? (l ? kt() : Rt()), f = Et(t), { initializeContext: h, calculateScrollOffset: p, getScrollContainer: w, getPositionedParentElement: v, getScrollPosition: d } = bt(), u = Tt(o); u.initialize(); const C = async (g, a) => { if (u.isSwipePending()) return u.resetSwipeDetection(), a === "in" ? async (k) => ({ onReady: () => { k.style.visibility = "visible"; } }) : () => ({}); s.trigger(g, a); const S = await s.get(a); if (!S) return () => ({}); const { from: A, to: R } = r( S.from, S.to ), E = G( A, R, f ) || i; if (!E) return () => ({}); const I = p(S.from, S.to); if (a === "out") { const k = { scrollOffset: I, scroll: d(S.from), get scrollingElement() { return w() || document.documentElement; }, get positionedParent() { return v(); } }; return (F) => E.out(F, k); } else { const k = { scrollOffset: I, get scroll() { return d(S.to); }, get scrollingElement() { return w() || document.documentElement; }, get positionedParent() { return v(); } }; return async (F) => { const z = await Promise.resolve(E.in(F, k)), q = z.onReady; return z.onReady = () => { F.style.visibility = "visible", q == null || q(); }, z; }; } }, y = (g) => ({ key: g, in: async (a) => (h(a, g), (await C(g, "in"))(a)), out: async (a) => (await C(g, "out"))(a), // Add page transition strategy for page-level transitions [B]: dt }), V = (g, a) => { if (u.isSwipePending()) return !1; const { from: S, to: A } = r(g, a); return !!(G( S, A, f ) || i); }; return c ? { getTransition: y, hasMatchingTransition: V } : y; } export { J as SCOPE_ATTR, Q as SCOPE_READY_ATTR, B as TRANSITION_STRATEGY, Rt as createAnyOrderDetector, mt as createDefaultStrategy, kt as createOutFirstDetector, dt as createPageTransitionStrategy, zt as createSggoiTransitionContext, Ft as createTransitionScope, gt as findScope, xt as getWatchedCount, Nt as isCssAnimation, Ut as isMultiAnimation, ht as isScopeReady, Ht as isSingleAnimation, Xt as isTickAnimation, Mt as isWatched, X as normalizeSchedule, M as normalizeToMultiAnimation, Lt as resetObserver, Dt as transition, Ot as triggerUnmount, St as watchUnmount };