ranui
Version:
A framework-agnostic Web Components UI library built on native custom elements, with TypeScript types, light/dark theming, SSR and PWA support.
239 lines (238 loc) • 6.43 kB
JavaScript
var c = null, r = null, h = null;
function P() {
return h;
}
function x(e) {
h = e;
}
function E() {
h = null;
}
function m(e) {
const t = {};
return e && new URLSearchParams(e.startsWith("?") ? e.slice(1) : e).forEach((n, a) => {
t[a] = n;
}), t;
}
function f(e, t, n) {
const a = [], s = e.split("/").map((i) => i.startsWith(":") ? (a.push(i.slice(1)), "([^/]+)") : i === "*" ? "(.*)" : i.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")).join("/"), o = t ? new RegExp(`^${s}$`) : new RegExp(`^${s}(?:/.*)?$`), u = n.match(o);
if (!u) return {
matched: !1,
params: {}
};
const d = {};
return a.forEach((i, w) => {
d[i] = decodeURIComponent(u[w + 1] ?? "");
}), {
matched: !0,
params: d
};
}
function g(e, t) {
return e ? `${e.replace(/\/$/, "")}/${t.replace(/^\//, "")}` : t;
}
function l(e, t = "") {
const n = [];
for (const a of e) {
const s = g(t, a.path);
n.push({
path: s,
exact: a.exact ?? !1,
meta: a.meta
}), a.children?.length && n.push(...l(a.children, s));
}
return n;
}
function v() {
return typeof document < "u" && "startViewTransition" in document;
}
function b(e) {
v() ? document.startViewTransition(e) : e();
}
function p() {
typeof document > "u" || r && document.head.contains(r) || (r = document.createElement("style"), r.textContent = "@view-transition { navigation: auto; }", document.head.appendChild(r));
}
function _() {
r?.remove(), r = null;
}
function y(e) {
return e === !0 || e === "spa" || e === "both";
}
function S(e) {
return e === "mpa" || e === "both";
}
var R = class {
_mode;
_base;
_routes;
_flatRoutes;
_vtMode;
_beforeGuards = [];
_afterGuards = [];
_changeHandlers = [];
_pageSwapHandlers = [];
_pageRevealHandlers = [];
_components = /* @__PURE__ */ new Set();
_current = null;
_mpaActive = !1;
constructor(e = {}) {
this._mode = e.mode ?? "history", this._base = e.base ?? "", this._routes = e.routes ?? [], this._flatRoutes = l(this._routes), this._vtMode = e.viewTransition, S(this._vtMode) && this._enableMpa();
}
get mode() {
return this._mode;
}
get base() {
return this._base;
}
get routes() {
return [...this._routes];
}
get currentRoute() {
return this._current;
}
matchRoute(e) {
const t = this._flatRoutes.find((n) => f(n.path, n.exact, e).matched);
return t ? {
path: t.path,
exact: t.exact,
meta: t.meta
} : null;
}
matchParams(e) {
for (const t of this._flatRoutes) {
const n = f(t.path, t.exact, e);
if (n.matched) return n.params;
}
return {};
}
getStaticPaths() {
return this._flatRoutes.map((e) => e.path);
}
_enableMpa() {
this._mpaActive || (this._mpaActive = !0, p(), typeof window < "u" && (window.addEventListener("pageswap", this._onPageSwap), window.addEventListener("pagereveal", this._onPageReveal)));
}
_disableMpa() {
this._mpaActive && (this._mpaActive = !1, _(), typeof window < "u" && (window.removeEventListener("pageswap", this._onPageSwap), window.removeEventListener("pagereveal", this._onPageReveal)));
}
_onPageSwap = (e) => {
this._pageSwapHandlers.forEach((t) => t(e));
};
_onPageReveal = (e) => {
this._pageRevealHandlers.forEach((t) => t(e));
};
_bind(e) {
this._components.add(e);
}
_unbind(e) {
this._components.delete(e);
}
_buildLocation(e) {
const t = e.indexOf("?"), n = t === -1 ? e : e.slice(0, t), a = t === -1 ? "" : e.slice(t + 1);
return {
path: n || "/",
params: {},
query: m(a),
fullPath: e || "/"
};
}
_getCurrentPath() {
if (typeof window > "u") return "/";
if (this._mode === "hash") return window.location.hash.slice(1) || "/";
const e = window.location.pathname, t = this._base;
return (t && e.startsWith(t) ? e.slice(t.length) || "/" : e) + (window.location.search || "");
}
_notify() {
const e = this._buildLocation(this._getCurrentPath());
e.params = this.matchParams(e.path);
const t = this._current;
this._current = e;
const n = () => {
this._components.forEach((a) => a._syncRoutes());
};
y(this._vtMode) ? b(n) : n(), this._afterGuards.forEach((a) => a(e, t)), this._changeHandlers.forEach((a) => a(e, t));
}
async _navigate(e, t) {
const n = this._buildLocation(e), a = this._current;
for (const s of this._beforeGuards) {
const o = await new Promise((u) => {
s(n, a, u);
});
if (o === !1) return;
if (typeof o == "string") return this._navigate(o, t);
}
if (typeof window < "u") {
const s = this._mode === "hash" ? `#${e}` : this._base + e;
t ? window.history.replaceState({ path: e }, "", s) : window.history.pushState({ path: e }, "", s);
}
this._notify();
}
push(e) {
return this._navigate(e, !1);
}
replace(e) {
return this._navigate(e, !0);
}
back() {
typeof window < "u" && window.history.back();
}
forward() {
typeof window < "u" && window.history.forward();
}
go(e) {
typeof window < "u" && window.history.go(e);
}
destroy() {
this._disableMpa(), this._components.clear();
}
beforeEach(e) {
return this._beforeGuards.push(e), () => {
const t = this._beforeGuards.indexOf(e);
t !== -1 && this._beforeGuards.splice(t, 1);
};
}
afterEach(e) {
return this._afterGuards.push(e), () => {
const t = this._afterGuards.indexOf(e);
t !== -1 && this._afterGuards.splice(t, 1);
};
}
onRouteChange(e) {
return this._changeHandlers.push(e), () => {
const t = this._changeHandlers.indexOf(e);
t !== -1 && this._changeHandlers.splice(t, 1);
};
}
onPageSwap(e) {
return this._pageSwapHandlers.push(e), () => {
const t = this._pageSwapHandlers.indexOf(e);
t !== -1 && this._pageSwapHandlers.splice(t, 1);
};
}
onPageReveal(e) {
return this._pageRevealHandlers.push(e), () => {
const t = this._pageRevealHandlers.indexOf(e);
t !== -1 && this._pageRevealHandlers.splice(t, 1);
};
}
};
function H(e) {
c?.destroy();
const t = new R(e);
return c = t, t;
}
function M() {
return c;
}
function G() {
return p(), () => _();
}
export {
R as RouterCore,
E as clearSSGPath,
H as createRouter,
G as enableMpaViewTransitions,
P as getSSGPath,
f as matchPath,
x as setSSGPath,
M as useRouter
};