flemo
Version:
A modern React router library with built-in motion animations and smooth transitions
1,705 lines (1,704 loc) • 46.1 kB
JavaScript
import { jsx as D, jsxs as ct } from "react/jsx-runtime";
import nt, { useEffect as z, createContext as dt, useContext as pt, useReducer as Ht, Children as It, Suspense as _t, useImperativeHandle as jt, useState as mt, useRef as H, useLayoutEffect as Et } from "react";
import { transform as ft, useAnimate as Lt, motion as J, useDragControls as Ft, AnimatePresence as Qt, MotionConfig as qt } from "motion/react";
var _ = {}, wt;
function Yt() {
if (wt) return _;
wt = 1, Object.defineProperty(_, "__esModule", { value: !0 }), _.PathError = _.TokenData = void 0, _.parse = l, _.compile = m, _.match = P, _.pathToRegexp = L, _.stringify = U;
const n = "/", e = (i) => i, t = /^[$_\p{ID_Start}]$/u, r = /^[$\u200c\u200d\p{ID_Continue}]$/u, s = {
// Groups.
"{": "{",
"}": "}",
// Reserved.
"(": "(",
")": ")",
"[": "[",
"]": "]",
"+": "+",
"?": "?",
"!": "!"
};
function a(i) {
return i.replace(/[{}()\[\]+?!:*\\]/g, "\\$&");
}
function o(i) {
return i.replace(/[.+*?^${}()[\]|/\\]/g, "\\$&");
}
class c {
constructor(y, g) {
this.tokens = y, this.originalPath = g;
}
}
_.TokenData = c;
class h extends TypeError {
constructor(y, g) {
let E = y;
g && (E += `: ${g}`), E += "; visit https://git.new/pathToRegexpError for info", super(E), this.originalPath = g;
}
}
_.PathError = h;
function l(i, y = {}) {
const { encodePath: g = e } = y, E = [...i], p = [];
let f = 0, I = 0;
function T() {
let S = "";
if (t.test(E[f]))
do
S += E[f++];
while (r.test(E[f]));
else if (E[f] === '"') {
let M = f;
for (; f++ < E.length; ) {
if (E[f] === '"') {
f++, M = 0;
break;
}
E[f] === "\\" && f++, S += E[f];
}
if (M)
throw new h(`Unterminated quote at index ${M}`, i);
}
if (!S)
throw new h(`Missing parameter name at index ${f}`, i);
return S;
}
for (; f < E.length; ) {
const S = E[f], M = s[S];
M ? p.push({ type: M, index: f++, value: S }) : S === "\\" ? p.push({ type: "escape", index: f++, value: E[f++] }) : S === ":" ? p.push({ type: "param", index: f++, value: T() }) : S === "*" ? p.push({ type: "wildcard", index: f++, value: T() }) : p.push({ type: "char", index: f++, value: S });
}
p.push({ type: "end", index: f, value: "" });
function O(S) {
const M = [];
for (; ; ) {
const x = p[I++];
if (x.type === S)
break;
if (x.type === "char" || x.type === "escape") {
let C = x.value, b = p[I];
for (; b.type === "char" || b.type === "escape"; )
C += b.value, b = p[++I];
M.push({
type: "text",
value: g(C)
});
continue;
}
if (x.type === "param" || x.type === "wildcard") {
M.push({
type: x.type,
name: x.value
});
continue;
}
if (x.type === "{") {
M.push({
type: "group",
tokens: O("}")
});
continue;
}
throw new h(`Unexpected ${x.type} at index ${x.index}, expected ${S}`, i);
}
return M;
}
return new c(O("end"), i);
}
function m(i, y = {}) {
const { encode: g = encodeURIComponent, delimiter: E = n } = y, p = typeof i == "object" ? i : l(i, y), f = d(p.tokens, E, g);
return function(T = {}) {
const [O, ...S] = f(T);
if (S.length)
throw new TypeError(`Missing parameters: ${S.join(", ")}`);
return O;
};
}
function d(i, y, g) {
const E = i.map((p) => u(p, y, g));
return (p) => {
const f = [""];
for (const I of E) {
const [T, ...O] = I(p);
f[0] += T, f.push(...O);
}
return f;
};
}
function u(i, y, g) {
if (i.type === "text")
return () => [i.value];
if (i.type === "group") {
const p = d(i.tokens, y, g);
return (f) => {
const [I, ...T] = p(f);
return T.length ? [""] : [I];
};
}
const E = g || e;
return i.type === "wildcard" && g !== !1 ? (p) => {
const f = p[i.name];
if (f == null)
return ["", i.name];
if (!Array.isArray(f) || f.length === 0)
throw new TypeError(`Expected "${i.name}" to be a non-empty array`);
return [
f.map((I, T) => {
if (typeof I != "string")
throw new TypeError(`Expected "${i.name}/${T}" to be a string`);
return E(I);
}).join(y)
];
} : (p) => {
const f = p[i.name];
if (f == null)
return ["", i.name];
if (typeof f != "string")
throw new TypeError(`Expected "${i.name}" to be a string`);
return [E(f)];
};
}
function P(i, y = {}) {
const { decode: g = decodeURIComponent, delimiter: E = n } = y, { regexp: p, keys: f } = L(i, y), I = f.map((T) => g === !1 ? e : T.type === "param" ? g : (O) => O.split(E).map(g));
return function(O) {
const S = p.exec(O);
if (!S)
return !1;
const M = S[0], x = /* @__PURE__ */ Object.create(null);
for (let C = 1; C < S.length; C++) {
if (S[C] === void 0)
continue;
const b = f[C - 1], W = I[C - 1];
x[b.name] = W(S[C]);
}
return { path: M, params: x };
};
}
function L(i, y = {}) {
const { delimiter: g = n, end: E = !0, sensitive: p = !1, trailing: f = !0 } = y, I = [], T = p ? "" : "i", O = [];
for (const x of N(i, [])) {
const C = typeof x == "object" ? x : l(x, y);
for (const b of w(C.tokens, 0, []))
O.push(k(b, g, I, C.originalPath));
}
let S = `^(?:${O.join("|")})`;
return f && (S += `(?:${o(g)}$)?`), S += E ? "$" : `(?=${o(g)}|$)`, { regexp: new RegExp(S, T), keys: I };
}
function N(i, y) {
if (Array.isArray(i))
for (const g of i)
N(g, y);
else
y.push(i);
return y;
}
function* w(i, y, g) {
if (y === i.length)
return yield g;
const E = i[y];
if (E.type === "group")
for (const p of w(E.tokens, 0, g.slice()))
yield* w(i, y + 1, p);
else
g.push(E);
yield* w(i, y + 1, g);
}
function k(i, y, g, E) {
let p = "", f = "", I = !0;
for (const T of i) {
if (T.type === "text") {
p += o(T.value), f += T.value, I || (I = T.value.includes(y));
continue;
}
if (T.type === "param" || T.type === "wildcard") {
if (!I && !f)
throw new h(`Missing text before "${T.name}" ${T.type}`, E);
T.type === "param" ? p += `(${F(y, I ? "" : f)}+)` : p += "([\\s\\S]+)", g.push(T), f = "", I = !1;
continue;
}
}
return p;
}
function F(i, y) {
return y.length < 2 ? i.length < 2 ? `[^${o(i + y)}]` : `(?:(?!${o(i)})[^${o(y)}])` : i.length < 2 ? `(?:(?!${o(y)})[^${o(i)}])` : `(?:(?!${o(y)}|${o(i)})[\\s\\S])`;
}
function Q(i) {
let y = "", g = 0;
function E(p) {
return R(p) && A(i[g]) ? p : JSON.stringify(p);
}
for (; g < i.length; ) {
const p = i[g++];
if (p.type === "text") {
y += a(p.value);
continue;
}
if (p.type === "group") {
y += `{${Q(p.tokens)}}`;
continue;
}
if (p.type === "param") {
y += `:${E(p.name)}`;
continue;
}
if (p.type === "wildcard") {
y += `*${E(p.name)}`;
continue;
}
throw new TypeError(`Unknown token type: ${p.type}`);
}
return y;
}
function U(i) {
return Q(i.tokens);
}
function R(i) {
const [y, ...g] = i;
return t.test(y) && g.every((E) => r.test(E));
}
function A(i) {
return i && i.type === "text" ? !r.test(i.value[0]) : !0;
}
return _;
}
var V = Yt();
function Bt(n, e, t) {
const r = Array.isArray(n) ? n.find((c) => V.pathToRegexp(c).regexp.test(e)) || "" : V.pathToRegexp(n).regexp.test(e) ? n : "", s = V.match(r)(e), a = new URLSearchParams(t), o = Object.fromEntries(a.entries());
return s ? { ...s.params, ...o } : {};
}
function St() {
return typeof document > "u";
}
class Xt {
tasks = /* @__PURE__ */ new Map();
instanceId = Date.now().toString();
isLocked = !1;
currentTaskId = null;
taskQueue = Promise.resolve();
signalListeners = /* @__PURE__ */ new Map();
pendingTaskQueue = [];
isProcessingPending = !1;
async acquireLock(e) {
for (let s = 0; s < 10; s++) {
if (!this.isLocked)
return this.isLocked = !0, this.currentTaskId = e, !0;
await new Promise((a) => setTimeout(a, 100));
}
return !1;
}
releaseLock(e) {
this.currentTaskId === e && (this.isLocked = !1, this.currentTaskId = null);
}
generateTaskId() {
return `${this.instanceId}-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
}
emitSignal(e) {
const t = this.signalListeners.get(e);
t && (t.forEach((r) => {
this.resolveTask(r);
}), this.signalListeners.delete(e));
}
// 대기 중인 태스크들을 처리하는 메서드
async processPendingTasks() {
if (!(this.isProcessingPending || this.pendingTaskQueue.length === 0)) {
this.isProcessingPending = !0;
try {
for (; this.pendingTaskQueue.length > 0; ) {
const e = this.pendingTaskQueue[0];
if (e.status === "COMPLETED" || e.status === "FAILED" || e.status === "ROLLEDBACK") {
this.pendingTaskQueue.shift();
continue;
}
if (e.status === "MANUAL_PENDING" || e.status === "SIGNAL_PENDING" || e.status === "PROCESSING" || e.status === "PENDING")
break;
}
} finally {
this.isProcessingPending = !1;
}
}
}
// 모든 대기 중인 태스크가 완료될 때까지 대기
async waitForPendingTasks() {
return new Promise((e) => {
const t = () => {
this.pendingTaskQueue.filter(
(s) => s.status === "MANUAL_PENDING" || s.status === "SIGNAL_PENDING"
).length === 0 ? e() : setTimeout(t, 100);
};
t();
});
}
// 태스크 상태 변경 시 대기 큐 처리
async onTaskStatusChange(e, t) {
(t === "COMPLETED" || t === "FAILED" || t === "ROLLEDBACK") && (this.pendingTaskQueue = this.pendingTaskQueue.filter((r) => r.id !== e), await this.processPendingTasks());
}
async addTask(e, t = {}) {
const r = t.id || this.generateTaskId();
return new Promise((s, a) => {
this.taskQueue = this.taskQueue.then(async () => {
try {
const { control: o, validate: c, rollback: h, dependencies: l = [], delay: m } = t, d = new AbortController(), u = {
id: r,
execute: e,
timestamp: Date.now(),
retryCount: 0,
status: "PENDING",
dependencies: l,
instanceId: this.instanceId,
validate: c,
rollback: h,
control: o,
abortController: d
};
this.tasks.set(u.id, u), this.pendingTaskQueue.length > 0 && (this.pendingTaskQueue.push(u), await this.waitForPendingTasks(), this.pendingTaskQueue = this.pendingTaskQueue.filter((L) => L.id !== u.id));
try {
if (!await this.acquireLock(u.id))
throw u.status = "FAILED", new Error("FAILED");
try {
u.status = "PROCESSING";
for (const w of u.dependencies) {
const k = this.tasks.get(w);
if (!k || k.status !== "COMPLETED")
throw u.status = "FAILED", new Error("FAILED");
}
if (u.validate && !await u.validate())
throw u.status = "FAILED", new Error("FAILED");
m && m > 0 && await new Promise((w) => setTimeout(w, m));
const N = await u.execute(u.abortController);
if (u.abortController.signal.aborted) {
u.status = "COMPLETED", await this.onTaskStatusChange(u.id, "COMPLETED"), s({
success: !0,
result: void 0,
taskId: u.id,
timestamp: Date.now(),
instanceId: this.instanceId
});
return;
}
if (t.control) {
const w = t.control;
if (w.delay && w.delay > 0 && await new Promise((k) => setTimeout(k, w.delay)), w.manual) {
u.status = "MANUAL_PENDING", u.manualResolver = { resolve: s, reject: a, result: N }, this.pendingTaskQueue.push(u), await this.onTaskStatusChange(u.id, "MANUAL_PENDING");
return;
}
if (w.signal) {
u.status = "SIGNAL_PENDING", u.manualResolver = { resolve: s, reject: a, result: N }, this.signalListeners.has(w.signal) || this.signalListeners.set(w.signal, /* @__PURE__ */ new Set()), this.signalListeners.get(w.signal).add(u.id), this.pendingTaskQueue.push(u), await this.onTaskStatusChange(u.id, "SIGNAL_PENDING");
return;
}
if (w.condition && !await w.condition()) {
u.status = "MANUAL_PENDING", u.manualResolver = { resolve: s, reject: a, result: N }, this.pendingTaskQueue.push(u), await this.onTaskStatusChange(u.id, "MANUAL_PENDING");
return;
}
}
u.status = "COMPLETED", await this.onTaskStatusChange(u.id, "COMPLETED"), s({
success: !0,
result: N,
taskId: u.id,
timestamp: Date.now(),
instanceId: this.instanceId
});
} catch (N) {
if (u.status = "FAILED", u.rollback)
try {
await u.rollback(), u.status = "ROLLEDBACK";
} catch {
}
throw await this.onTaskStatusChange(u.id, u.status), N;
} finally {
this.releaseLock(u.id);
}
} catch (L) {
a(L);
}
} catch (o) {
a(o);
}
}).catch(a);
});
}
async resolveTask(e) {
const t = this.tasks.get(e);
if (!t || t.status !== "MANUAL_PENDING")
return !1;
if (t.manualResolver) {
if (t.control?.condition && !await t.control.condition())
return !1;
t.status = "COMPLETED";
const r = t.manualResolver;
return r.resolve({
success: !0,
result: r.result,
taskId: t.id,
timestamp: Date.now(),
instanceId: this.instanceId
}), delete t.manualResolver, await this.onTaskStatusChange(e, "COMPLETED"), !0;
}
return !1;
}
async resolveAllPending() {
const e = Array.from(this.tasks.values()).filter(
(t) => ["PENDING", "MANUAL_PENDING", "SIGNAL_PENDING"].includes(t.status)
);
await Promise.all(e.map((t) => this.resolveTask(t.id)));
}
}
const q = new Xt(), Pt = (n) => {
let e;
const t = /* @__PURE__ */ new Set(), r = (l, m) => {
const d = typeof l == "function" ? l(e) : l;
if (!Object.is(d, e)) {
const u = e;
e = m ?? (typeof d != "object" || d === null) ? d : Object.assign({}, e, d), t.forEach((P) => P(e, u));
}
}, s = () => e, c = { setState: r, getState: s, getInitialState: () => h, subscribe: (l) => (t.add(l), () => t.delete(l)) }, h = e = n(r, s, c);
return c;
}, Kt = ((n) => n ? Pt(n) : Pt), Vt = (n) => n;
function zt(n, e = Vt) {
const t = nt.useSyncExternalStore(
n.subscribe,
nt.useCallback(() => e(n.getState()), [n, e]),
nt.useCallback(() => e(n.getInitialState()), [n, e])
);
return nt.useDebugValue(t), t;
}
const Tt = (n) => {
const e = Kt(n), t = (r) => zt(e, r);
return Object.assign(t, e), t;
}, st = ((n) => n ? Tt(n) : Tt), Y = st((n) => ({
index: -1,
histories: [],
addHistory: (e) => n((t) => ({
index: t.index + 1,
histories: t.histories.concat(e)
})),
replaceHistory: (e) => n((t) => (t.histories.splice(e, 1), {
index: t.index - 1,
histories: t.histories
})),
popHistory: (e) => n((t) => ({
index: t.index - 1,
histories: t.histories.filter((r, s) => s !== e)
}))
})), j = st((n) => ({
status: "IDLE",
setStatus: (e) => n({ status: e })
}));
function Wt() {
return z(() => {
const n = async (e) => {
const t = e.state?.id;
(await q.addTask(
async (r) => {
const s = e.state?.index, a = e.state?.status, o = e.state?.params, c = e.state?.transitionName, h = e.state?.layoutId, l = j.getState().setStatus, { index: m, addHistory: d, popHistory: u } = Y.getState(), P = s < m, L = a === "PUSHING" && s > m, N = a === "REPLACING" && s > m, w = window.location.pathname;
if (!P && !L && !N) {
r.abort();
return;
}
return P ? l("POPPING") : L ? (l("PUSHING"), d({
id: t,
pathname: w,
params: o,
transitionName: c,
layoutId: h
})) : N && (l("REPLACING"), d({
id: t,
pathname: w,
params: o,
transitionName: c,
layoutId: h
})), async () => {
P && u(s + 1), l("COMPLETED");
};
},
{
id: t,
control: {
manual: !0
}
}
)).result?.();
};
return window.addEventListener("popstate", n), () => {
window.removeEventListener("popstate", n);
};
}, []), null;
}
const xt = dt({}), Nt = dt(() => {
});
function Jt(n, e) {
switch (e.type) {
case "SET":
return e.params;
default:
return n;
}
}
const kt = dt({
id: "",
isActive: !1,
isRoot: !0,
isPrev: !1,
zIndex: 0,
pathname: "",
params: {},
transitionName: "none",
prevTransitionName: "none",
layoutId: null
});
function tt() {
return pt(kt);
}
function Zt({ children: n }) {
const { isActive: e, params: t } = tt(), [r, s] = Ht(Jt, t);
return z(() => {
const a = async (o) => {
o.state?.step && await q.addTask(async () => {
s({ type: "SET", params: o.state?.params || {} });
});
};
return e && window.addEventListener("popstate", a), () => {
window.removeEventListener("popstate", a);
};
}, [e, s]), /* @__PURE__ */ D(Nt.Provider, { value: s, children: /* @__PURE__ */ D(xt.Provider, { value: r, children: n }) });
}
function te({ children: n }) {
const e = Y((r) => r.index), t = Y((r) => r.histories);
return t.map(
(r) => It.toArray(n).filter(
(s) => V.pathToRegexp(s.props.path).regexp.test(
r.pathname
)
)
).map(([r], s) => /* @__PURE__ */ D(
kt.Provider,
{
value: {
id: t[s].id,
isActive: s === e,
isRoot: s === 0,
isPrev: s < e - 1,
zIndex: s,
pathname: t[s].pathname,
params: t[s].params,
transitionName: t[e].transitionName,
prevTransitionName: t[e - 1]?.transitionName,
layoutId: t[s].layoutId
},
children: /* @__PURE__ */ D(Zt, { children: r })
},
t[s].id
));
}
function ee({
name: n,
initial: e,
enter: t,
exit: r,
options: s
}) {
return {
name: n,
initial: e,
variants: {
"IDLE-true": t,
"IDLE-false": t,
"PUSHING-false": r,
"PUSHING-true": t,
"REPLACING-false": r,
"REPLACING-true": t,
"POPPING-false": t,
"POPPING-true": t,
"COMPLETED-false": r,
"COMPLETED-true": t
},
...s
};
}
const ne = ee({
name: "overlay",
initial: {
opacity: 0,
backgroundColor: "rgba(0, 0, 0, 0)"
},
enter: {
value: {
opacity: 0,
backgroundColor: "rgba(0, 0, 0, 0.3)"
},
options: {
duration: 0.3
}
},
exit: {
value: {
opacity: 1,
backgroundColor: "rgba(0, 0, 0, 0.3)"
},
options: {
duration: 0.3
}
},
options: {
onSwipeStart: (n, { animate: e, prevDecorator: t }) => e(
t,
{
opacity: n ? 1 : 0
},
{
duration: 0.3
}
),
onSwipe: (n, e, { animate: t, prevDecorator: r }) => t(
r,
{
opacity: Math.max(0, 1 - e / 100)
},
{
duration: 0
}
),
onSwipeEnd: (n, { animate: e, prevDecorator: t }) => e(
t,
{
opacity: n ? 0 : 1
},
{
duration: 0.3
}
)
}
}), ht = /* @__PURE__ */ new Map([["overlay", ne]]), ut = st((n) => ({
defaultTransitionName: "cupertino",
setDefaultTransitionName: (e) => n({ defaultTransitionName: e })
}));
function rt({
name: n,
initial: e,
idle: t,
enter: r,
enterBack: s,
exit: a,
exitBack: o,
options: c
}) {
return {
name: n,
initial: e,
variants: {
"IDLE-true": t,
"IDLE-false": t,
"PUSHING-false": a,
"PUSHING-true": r,
"REPLACING-false": a,
"REPLACING-true": r,
"POPPING-false": o,
"POPPING-true": s,
"COMPLETED-false": a,
"COMPLETED-true": r
},
...c
};
}
const se = rt({
name: "cupertino",
initial: {
x: "100%"
},
idle: {
value: {
x: 0
},
options: {
duration: 0
}
},
enter: {
value: {
x: 0
},
options: {
duration: 0.3,
ease: [0.32, 0.72, 0, 1]
}
},
enterBack: {
value: {
x: "100%"
},
options: {
duration: 0.3,
ease: [0.32, 0.72, 0, 1]
}
},
exit: {
value: {
x: -100
},
options: {
duration: 0.3,
ease: [0.32, 0.72, 0, 1]
}
},
exitBack: {
value: {
x: 0
},
options: {
duration: 0.3,
ease: [0.32, 0.72, 0, 1]
}
},
options: {
decoratorName: "overlay",
swipeDirection: "x",
onSwipeStart: async () => !0,
onSwipe: (n, e, { animate: t, currentScreen: r, prevScreen: s, onProgress: a }) => {
const { offset: o } = e, c = o.x, h = ft(c, [0, window.innerWidth], [0, 100]);
return a?.(!0, h), t(
r,
{
x: Math.max(0, c)
},
{
duration: 0
}
), t(
s,
{
x: -100 + h
},
{
duration: 0
}
), h;
},
onSwipeEnd: async (n, e, { animate: t, currentScreen: r, prevScreen: s, onStart: a }) => {
const { offset: o, velocity: c } = e, l = o.x > 50 || c.x > 20;
return a?.(l), await Promise.all([
t(
r,
{
x: l ? "100%" : 0
},
{
duration: 0.3,
ease: [0.32, 0.72, 0, 1]
}
),
t(
s,
{
x: l ? 0 : -100
},
{
duration: 0.3,
ease: [0.32, 0.72, 0, 1]
}
)
]), l;
}
}
}), re = rt({
name: "layout",
initial: {
opacity: 0.97
},
idle: {
value: {
opacity: 1
},
options: {
duration: 0.3
}
},
enter: {
value: {
opacity: 1
},
options: {
duration: 0.3
}
},
enterBack: {
value: {
opacity: 0.97
},
options: {
duration: 0.3
}
},
exit: {
value: {
opacity: 0.97
},
options: {
duration: 0.3
}
},
exitBack: {
value: {
opacity: 1
},
options: {
duration: 0.3
}
},
options: {
decoratorName: "overlay",
swipeDirection: "y",
onSwipeStart: async () => !0,
onSwipe: (n, e, { animate: t, currentScreen: r, onProgress: s }) => {
const { offset: a } = e, o = a.y, c = Math.max(0, Math.min(56, o)), h = ft(c, [0, 56], [1, 0.96]), l = Math.max(0, o - 56), m = Math.min(1, l / 160), d = Math.sqrt(m) * 12, u = Math.max(0, c + d), P = Math.min(56, u);
return s?.(!0, 100), t(
r,
{
y: u,
opacity: h
},
{
duration: 0
}
), P;
},
onSwipeEnd: async (n, e, { animate: t, currentScreen: r, prevScreen: s, onStart: a }) => {
const { offset: o, velocity: c } = e, l = o.y > 56 || c.y > 20;
return a?.(l), await Promise.all([
t(
r,
{
y: l ? "100%" : 0,
opacity: l ? 0.96 : 1
},
{
duration: 0.3
}
),
t(
s,
{
y: 0,
opacity: l ? 1 : 0.97
},
{
duration: 0.3
}
)
]), l;
}
}
}), ae = rt({
name: "material",
initial: {
y: "100%",
opacity: 0.96
},
idle: {
value: {
y: 0,
opacity: 1
},
options: {
duration: 0
}
},
enter: {
value: {
y: 0,
opacity: 1
},
options: {
duration: 0.24,
ease: [0, 0, 0.2, 1]
}
},
enterBack: {
value: {
y: "100%",
opacity: 0.96
},
options: {
duration: 0.22,
ease: [0.4, 0, 1, 1]
}
},
exit: {
value: {
y: -56,
opacity: 0.96
},
options: {
duration: 0.22,
ease: [0.4, 0, 1, 1]
}
},
exitBack: {
value: {
y: 0,
opacity: 1
},
options: {
duration: 0.24,
ease: [0, 0, 0.2, 1]
}
},
options: {
swipeDirection: "y",
onSwipeStart: async () => !0,
onSwipe: (n, e, { animate: t, currentScreen: r, prevScreen: s, onProgress: a }) => {
const { offset: o } = e, c = o.y, h = Math.max(0, Math.min(56, c)), l = ft(h, [0, 56], [1, 0.96]), m = Math.max(0, c - 56), d = Math.min(1, m / 160), u = Math.sqrt(d) * 12, P = Math.max(0, h + u), L = Math.min(56, P);
return a?.(!0, L), t(
r,
{
y: P,
opacity: l
},
{
duration: 0
}
), t(
s,
{
y: -56 + L,
opacity: L / 56
},
{ duration: 0 }
), L;
},
onSwipeEnd: async (n, e, { animate: t, currentScreen: r, prevScreen: s, onStart: a }) => {
const { offset: o, velocity: c } = e, l = o.y > 56 || c.y > 20;
return a?.(l), await Promise.all([
t(
r,
{
y: l ? "100%" : 0,
opacity: l ? 0.96 : 1
},
{
duration: l ? 0.22 : 0.24,
ease: l ? [0.4, 0, 1, 1] : [0, 0, 0.2, 1]
}
),
t(
s,
{
y: l ? 0 : -56,
opacity: l ? 1 : 0.96
},
{
duration: l ? 0.22 : 0.24,
ease: l ? [0, 0, 0.2, 1] : [0.4, 0, 1, 1]
}
)
]), l;
}
}
}), oe = rt({
name: "none",
initial: {},
idle: {
value: {},
options: {
duration: 0
}
},
enter: {
value: {},
options: {
duration: 0
}
},
enterBack: {
value: {},
options: {
duration: 0
}
},
exit: {
value: {},
options: {
duration: 0
}
},
exitBack: {
value: {},
options: {
duration: 0
}
}
}), et = /* @__PURE__ */ new Map([
["none", oe],
["cupertino", se],
["material", ae],
["layout", re]
]), ie = (() => {
const n = /* @__PURE__ */ Object.create(null), e = Object.prototype.hasOwnProperty;
for (const t of et.values()) {
const r = t.variants["IDLE-true"].value;
for (const s in r)
e.call(r, s) && (n[s] = r[s]);
}
return n;
})();
function ye({
children: n,
initPath: e = "/",
defaultTransitionName: t = "cupertino",
transitions: r = [],
decorators: s = []
}) {
const a = St() ? e || "/" : window.location.pathname, o = St() ? a.split("?")[1] || "" : window.location.search;
return ut.setState({
defaultTransitionName: t
}), Y.setState({
index: 0,
histories: [
{
id: "root",
pathname: a,
params: Bt(
It.toArray(n).map((c) => c.props.path).flat(),
a,
o
),
transitionName: t,
layoutId: null
}
]
}), z(() => {
window.history.state?.index || window.history.replaceState(
{
id: "root",
index: 0,
status: "IDLE",
params: {},
transitionName: t,
layoutId: null
},
"",
window.location.pathname
);
}, [t]), z(() => {
r.forEach((c) => et.set(c.name, c));
}, [r]), z(() => {
s.forEach((c) => ht.set(c.name, c));
}, [s]), /* @__PURE__ */ ct(
"div",
{
style: {
position: "fixed",
top: 0,
left: 0,
width: "100%",
height: "100%"
},
children: [
/* @__PURE__ */ D(Wt, {}),
/* @__PURE__ */ D(te, { children: n })
]
}
);
}
function ge({ element: n }) {
return n;
}
function me() {
return {
push: async (r, s, a = {}) => {
const { status: o, setStatus: c } = j.getState();
if (o !== "COMPLETED" && o !== "IDLE")
return;
const { index: h, addHistory: l } = Y.getState(), m = ut.getState().defaultTransitionName, { transitionName: d = m, layoutId: u = null } = a, P = q.generateTaskId();
(await q.addTask(
async () => {
c("PUSHING");
const L = V.compile(r), N = Object.fromEntries(
Object.entries(s).map(([R, A]) => [R, String(A)])
), w = L(N), k = V.parse(r).tokens.filter((R) => R.type === "param").map((R) => R.name), F = Object.fromEntries(
Object.entries(s).filter(([R]) => !k.includes(R))
), Q = new URLSearchParams(F).toString(), U = `${w}${Q ? `?${Q}` : ""}`;
return window.history.pushState(
{
id: P,
index: h + 1,
status: "PUSHING",
params: s,
transitionName: d,
layoutId: u
},
"",
U
), l({
id: P,
pathname: w,
params: s,
transitionName: d,
layoutId: u
}), () => {
c("COMPLETED");
};
},
{
id: P,
control: {
manual: !0
}
}
)).result?.();
},
replace: async (r, s, a = {}) => {
const { status: o, setStatus: c } = j.getState();
if (o !== "COMPLETED" && o !== "IDLE")
return;
const { index: h, addHistory: l } = Y.getState(), m = Y.getState().replaceHistory, d = ut.getState().defaultTransitionName, { transitionName: u = d, layoutId: P = null } = a, L = q.generateTaskId();
(await q.addTask(
async () => {
c("REPLACING");
const N = V.compile(r), w = Object.fromEntries(
Object.entries(s).map(([A, i]) => [A, String(i)])
), k = N(w), F = V.parse(r).tokens.filter((A) => A.type === "param").map((A) => A.name), Q = Object.fromEntries(
Object.entries(s).filter(([A]) => !F.includes(A))
), U = new URLSearchParams(Q).toString(), R = `${k}${U ? `?${U}` : ""}`;
return window.history.replaceState(
{
id: L,
index: h,
status: "REPLACING",
params: s,
transitionName: u,
layoutId: P
},
"",
R
), l({
id: L,
pathname: k,
params: s,
transitionName: u,
layoutId: P
}), async () => {
m(h), c("COMPLETED");
};
},
{
id: L,
control: {
manual: !0
}
}
)).result?.();
},
pop: () => {
const r = j.getState().status;
r !== "COMPLETED" && r !== "IDLE" || window.history.back();
}
};
}
function Ee() {
const n = pt(Nt);
return {
pushStep: async (s) => {
const a = j.getState().status;
a !== "COMPLETED" && a !== "IDLE" || (await q.addTask(async () => {
const o = new URLSearchParams(s).toString(), c = `${window.location.pathname}${o ? `?${o}` : ""}`;
return window.history.state?.step || window.history.replaceState(
{
...window.history.state,
step: !0
},
"",
window.location.pathname
), window.history.pushState(
{
...window.history.state,
step: !0,
params: s
},
"",
c
), async () => n({ type: "SET", params: s });
})).result?.();
},
replaceStep: async (s) => {
const a = j.getState().status;
a !== "COMPLETED" && a !== "IDLE" || (await q.addTask(async () => {
const o = new URLSearchParams(s).toString(), c = `${window.location.pathname}${o ? `?${o}` : ""}`;
return window.history.replaceState(
{
...window.history.state,
step: !0,
params: s
},
"",
c
), async () => n({ type: "SET", params: s });
})).result?.();
},
popStep: () => {
const s = j.getState().status;
s !== "COMPLETED" && s !== "IDLE" || window.history.back();
}
};
}
function we() {
return pt(xt);
}
function Se({
name: n,
initial: e,
idle: t,
pushOnEnter: r,
pushOnExit: s,
replaceOnEnter: a,
replaceOnExit: o,
popOnEnter: c,
popOnExit: h,
completedOnExit: l,
completedOnEnter: m,
options: d
}) {
return {
name: n,
initial: e,
variants: {
"IDLE-true": t,
"IDLE-false": t,
"PUSHING-false": s,
"PUSHING-true": r,
"REPLACING-false": o,
"REPLACING-true": a,
"POPPING-false": h,
"POPPING-true": c,
"COMPLETED-false": l,
"COMPLETED-true": m
},
...d
};
}
function Pe({
name: n,
initial: e,
idle: t,
pushOnEnter: r,
pushOnExit: s,
replaceOnEnter: a,
replaceOnExit: o,
popOnEnter: c,
popOnExit: h,
completedOnEnter: l,
completedOnExit: m,
options: d
}) {
return {
name: n,
initial: e,
variants: {
"IDLE-true": t,
"IDLE-false": t,
"PUSHING-false": s,
"PUSHING-true": r,
"REPLACING-false": o,
"REPLACING-true": a,
"POPPING-false": h,
"POPPING-true": c,
"COMPLETED-false": m,
"COMPLETED-true": l
},
...d
};
}
const ce = { then() {
} };
function ue({
freeze: n,
children: e
}) {
if (n)
throw ce;
return e;
}
function Mt({ freeze: n, children: e, placeholder: t }) {
return /* @__PURE__ */ D(_t, { fallback: t, children: /* @__PURE__ */ D(ue, { freeze: n, children: e }) });
}
function vt(n, e) {
const {
direction: t = "x",
markerSelector: r = "[data-swipe-at-edge]",
depthLimit: s = 24,
verifyByScroll: a = !1
} = e ?? {}, o = le(n);
if (!o) return { element: null, hasMarker: !1 };
const c = o.closest?.(r);
if (c instanceof HTMLElement && lt(c, t) && (!a || Dt(c, t)))
return { element: c, hasMarker: !0 };
let h = o, l = 0;
for (; h && h !== document.body && l < s; ) {
if (lt(h, t) && (!a || Dt(h, t)))
return { element: h, hasMarker: !1 };
h = h.parentElement, l++;
}
return { element: null, hasMarker: !1 };
}
function le(n) {
if (!n) return null;
const e = n, t = typeof e.composedPath == "function" ? e.composedPath() : void 0;
if (t && t.length) {
for (const r of t)
if (r instanceof HTMLElement) return r;
}
return n;
}
function lt(n, e) {
return e === "y" ? n.scrollHeight - n.clientHeight > 1 : n.scrollWidth - n.clientWidth > 1;
}
function Dt(n, e) {
if (!lt(n, e)) return !1;
if (e === "y") {
const t = n.scrollTop;
if (n.scrollTop = t + 1, n.scrollTop !== t)
return n.scrollTop = t, !0;
n.scrollTop = t - 1;
const s = n.scrollTop !== t;
return n.scrollTop = t, s;
} else {
const t = n.scrollLeft;
if (n.scrollLeft = t + 1, n.scrollLeft !== t)
return n.scrollLeft = t, !0;
n.scrollLeft = t - 1;
const s = n.scrollLeft !== t;
return n.scrollLeft = t, s;
}
}
function de({ children: n, ref: e, ...t }) {
const { isActive: r, transitionName: s } = tt(), [a, o] = Lt();
jt(e, () => a.current);
const c = j((u) => u.status), h = et.get(s), { decoratorName: l } = h, { initial: m, variants: d } = ht.get(l);
return z(() => {
if (!a.current) return;
const { value: u, options: P } = d[`${c}-${r}`];
o(a.current, u, P);
}, [c, r, o, d, a]), /* @__PURE__ */ D(
J.div,
{
ref: a,
initial: m,
style: {
position: "absolute",
top: 0,
left: 0,
width: "100%",
height: "100%",
pointerEvents: "none",
...t.style
},
"data-decorator": !0
}
);
}
const Z = st((n) => ({
dragStatus: "IDLE",
replaceTransitionStatus: "IDLE",
setDragStatus: (e) => n({ dragStatus: e }),
setReplaceTransitionStatus: (e) => n({ replaceTransitionStatus: e })
}));
function Ct({
children: n,
statusBarHeight: e,
statusBarColor: t,
systemNavigationBarHeight: r,
systemNavigationBarColor: s,
appBar: a,
navigationBar: o,
hideStatusBar: c,
hideSystemNavigationBar: h,
...l
}) {
const [m, d] = Lt(), { id: u, isActive: P, isRoot: L, transitionName: N, prevTransitionName: w } = tt(), k = Ft(), F = j((v) => v.status), Q = Z((v) => v.dragStatus), U = Z.getState().setDragStatus, R = Z.getState().setReplaceTransitionStatus, A = et.get(N), { variants: i, initial: y, swipeDirection: g, decoratorName: E } = A, p = ht.get(E), [f, I] = mt(0), [T, O] = mt(0), S = H(null), M = H(null), x = H(null), C = H(null), b = H(!1), W = H(!1), B = H({
element: null,
hasMarker: !1
}), X = H({ element: null, hasMarker: !1 }), yt = H(0), gt = H(0), at = H(null), ot = H(null), bt = async (v, G) => {
if (!g)
return;
const $ = S.current?.previousSibling;
M.current = $?.querySelector("[data-screen]"), C.current = $?.querySelector("[data-decorator]");
const K = await A?.onSwipeStart(v, G, {
animate: d,
currentScreen: m.current,
prevScreen: M.current,
dragControls: k,
onStart: (it) => p?.onSwipeStart?.(it, {
animate: d,
currentDecorator: x.current,
prevDecorator: C.current
})
});
U(K ? "PENDING" : "IDLE");
}, At = (v, G) => {
!g || Q !== "PENDING" || A?.onSwipe(v, G, {
animate: d,
currentScreen: m.current,
prevScreen: M.current,
dragControls: k,
onProgress: ($, K) => p?.onSwipe?.($, K, {
animate: d,
currentDecorator: x.current,
prevDecorator: C.current
})
});
}, Rt = async (v, G) => {
if (!g || Q !== "PENDING")
return;
await A?.onSwipeEnd(v, G, {
animate: d,
currentScreen: m.current,
prevScreen: M.current,
onStart: (K) => p?.onSwipeEnd?.(K, {
animate: d,
currentDecorator: x.current,
prevDecorator: C.current
})
}) ? window.history.back() : U("IDLE");
}, Ot = (v) => {
if (!(!L && P && F === "COMPLETED" && Q === "IDLE" && !!g))
return;
B.current = vt(v.target, {
direction: "x",
verifyByScroll: !0
}), X.current = vt(v.target, {
direction: "y",
verifyByScroll: !0
}), yt.current = v.clientX, gt.current = v.clientY, (!B.current.element && !X.current.element || B.current.element || X.current.element) && (b.current = !0);
}, Gt = (v) => {
const G = !B.current.element && !X.current.element;
if (b.current && G)
b.current = !1, W.current = !0, k.start(v);
else if (b.current && !G) {
const $ = v.clientX - yt.current, K = v.clientY - gt.current, it = X.current.element && X.current.element.scrollTop <= 0 && X.current.hasMarker, Ut = B.current.element && B.current.element.scrollLeft <= 0 && B.current.hasMarker;
(g === "y" && (it || B.current.element) && K > 0 && Math.abs($) < 4 || g === "x" && (Ut || X.current.element) && $ > 0 && Math.abs(K) < 4) && (b.current = !1, W.current = !0, k.start(v));
}
}, $t = () => {
b.current = !1, W.current = !1;
};
return z(() => {
const v = m.current;
if (!v) return;
const G = ($) => {
W.current && $.preventDefault(), $.target?.dataset.swipeAtEdgeBar === "true" && $.preventDefault();
};
return v.addEventListener("touchmove", G, {
passive: !1
}), () => {
v.removeEventListener("touchmove", G);
};
}, [m]), z(() => {
m.current && (async () => {
const { value: v, options: G } = i[`${F}-${P}`];
!P && F === "REPLACING" && w !== N && (R("PENDING"), await d(m.current, ie, {
duration: 0.1
})), P && F === "COMPLETED" && (U("IDLE"), R("IDLE")), await d(m.current, v, G), await q.resolveTask(u);
})();
}, [
F,
P,
u,
w,
N,
d,
m,
i,
U,
R
]), Et(() => {
at.current && I(at.current.offsetHeight);
}, [a]), Et(() => {
ot.current && O(ot.current.offsetHeight);
}, [o]), /* @__PURE__ */ ct(
J.div,
{
ref: S,
style: {
position: "absolute",
top: 0,
left: 0,
width: "100%",
height: "100%",
display: "flex",
flexDirection: "column",
boxSizing: "border-box",
isolation: "isolate",
contain: "strict",
overscrollBehavior: "contain"
},
children: [
/* @__PURE__ */ D(
"div",
{
"data-swipe-at-edge-bar": !0,
style: {
position: "absolute",
top: 0,
left: 0,
width: 8,
height: "100%",
zIndex: 1
}
}
),
a && /* @__PURE__ */ D(
J.div,
{
ref: at,
style: {
position: "absolute",
top: c ? 0 : e,
left: 0,
width: "100%"
},
children: a
}
),
/* @__PURE__ */ ct(
J.div,
{
ref: m,
...l,
initial: y,
drag: g,
dragListener: !1,
dragControls: k,
onDragStart: bt,
onDrag: At,
onDragEnd: Rt,
onPointerDown: Ot,
onPointerMove: Gt,
onPointerUp: $t,
"data-screen": !0,
style: {
display: "flex",
flexDirection: "column",
height: "100%",
backgroundColor: "white",
touchAction: "none",
overflowY: "auto",
...l.style
},
children: [
!c && e && /* @__PURE__ */ D(
J.div,
{
animate: {
backgroundColor: t
},
style: {
width: "100%",
minHeight: e
}
}
),
a && /* @__PURE__ */ D(
"div",
{
style: {
width: "100%",
minHeight: f
}
}
),
/* @__PURE__ */ D("div", { style: { display: "flex", flexDirection: "column", flexGrow: 1 }, children: n }),
o && /* @__PURE__ */ D(
"div",
{
style: {
width: "100%",
minHeight: T
}
}
),
!h && r && /* @__PURE__ */ D(
J.div,
{
animate: {
backgroundColor: s
},
style: {
width: "100%",
minHeight: r
}
}
)
]
}
),
o && /* @__PURE__ */ D(
J.div,
{
ref: ot,
style: {
position: "absolute",
bottom: h ? 0 : r,
left: 0,
width: "100%"
},
children: o
}
),
p && /* @__PURE__ */ D(de, { ref: x }),
/* @__PURE__ */ D(
"div",
{
"data-swipe-at-edge-bar": !0,
style: {
position: "absolute",
top: 0,
right: 0,
width: 8,
height: "100%",
zIndex: 1
}
}
)
]
}
);
}
function Te({ children: n, ...e }) {
const { isActive: t, isPrev: r, zIndex: s } = tt(), a = Y((d) => d.index), o = j((d) => d.status), c = Z((d) => d.dragStatus), h = Z((d) => d.replaceTransitionStatus), m = !t && (o === "COMPLETED" && c === "IDLE") || r && a - 2 <= s && h === "IDLE" || r && a - 2 > s;
return /* @__PURE__ */ D(Mt, { freeze: m, children: /* @__PURE__ */ D(Ct, { ...e, children: n }) });
}
function ve({ children: n, ...e }) {
const { isActive: t, isPrev: r, zIndex: s } = tt(), a = Y((d) => d.index), o = j((d) => d.status), c = Z((d) => d.dragStatus), h = Z((d) => d.replaceTransitionStatus), m = !t && (o === "COMPLETED" && c === "IDLE") || r && a - 2 <= s && h === "IDLE" || r && a - 2 > s;
return /* @__PURE__ */ D(Mt, { freeze: m, children: /* @__PURE__ */ D(
Ct,
{
...e,
style: {
backgroundColor: "transparent",
...e.style
},
children: /* @__PURE__ */ D(Qt, { children: n })
}
) });
}
function De({ children: n, ...e }) {
const { isActive: t, transitionName: r } = tt(), s = j((o) => o.status), a = et.get(r);
return /* @__PURE__ */ D(
qt,
{
transition: a?.variants[`${s}-${t}`]?.options,
...e,
children: n
}
);
}
export {
De as LayoutConfig,
ve as LayoutScreen,
ge as Route,
ye as Router,
Te as Screen,
ee as createDecorator,
Pe as createRawDecorator,
Se as createRawTransition,
rt as createTransition,
me as useNavigate,
we as useParams,
tt as useScreen,
Ee as useStep
};