UNPKG

ranui

Version:

A framework-agnostic Web Components UI library built on native custom elements, with TypeScript types, light/dark theming, SSR and PWA support.

719 lines (718 loc) 18.2 kB
import { escapeHtml as p } from "ranuts/utils"; var f = typeof document > "u", g = 0, H = 1, w = 2, h = null, l = null, v = 0, y = /* @__PURE__ */ new Set(), A = !1; function I(t, e) { const r = e?.equals ?? Object.is, s = { value: t, observers: /* @__PURE__ */ new Set() }; return [() => (B(s), s.value), (o) => { const a = typeof o == "function" ? o(s.value) : o; if (!r(s.value, a)) { s.value = a; for (const c of s.observers) M(c, w); v === 0 && R(); } }]; } function T(t, e) { const r = _(t, !1, e?.equals); return k(r), () => (r.disposed || ($(r), B(r)), r.value); } function L(t) { const e = _(t, !0); return k(e), j(e), () => z(e); } function ct(t) { v++; try { t(); } finally { v--, v === 0 && R(); } } function ht(t) { const e = h; h = null; try { return t(); } finally { h = e; } } function N(t) { const e = { owned: [], cleanups: [], owner: l }, r = l, s = h; l = e, h = null; try { return t(() => V(e)); } finally { l = r, h = s; } } function x(t) { l && l.cleanups.push(t); } function ft() { return l; } function dt(t, e) { const r = l, s = h; l = t, h = null; try { return e(); } finally { l = r, h = s; } } function _(t, e, r) { return { fn: t, sources: /* @__PURE__ */ new Set(), isEffect: e, running: !1, disposed: !1, state: w, observers: /* @__PURE__ */ new Set(), value: void 0, equals: r ?? Object.is, owned: [], cleanups: [], owner: l }; } function k(t) { l && l.owned.push(t); } function B(t) { h && (h.sources.add(t), t.observers.add(h)); } function M(t, e) { if (t.disposed || t.state >= e) return; const r = t.state === g; if (t.state = e, t.isEffect) y.add(t); else if (r) for (const s of t.observers) M(s, H); } function R() { if (!(v > 0 || A)) { A = !0; try { for (; y.size > 0; ) { const t = [...y]; y.clear(); for (const e of t) e.disposed || $(e); } } finally { A = !1; } } } function $(t) { if (!(t.disposed || t.state === g)) { if (t.state === H) for (const e of t.sources) "fn" in e && $(e); t.state === w && j(t), t.state = g; } } function j(t) { if (t.running) throw new Error("ranui reactivity: cyclic dependency detected (a computation triggered itself)."); q(t); const e = h, r = l; h = t, l = t, t.running = !0, t.state = g; try { const s = t.fn(); if (t.isEffect) typeof s == "function" && t.cleanups.push(s); else { const i = t.value; if (t.value = s, t.observers.size > 0 && !t.equals(i, s)) for (const n of t.observers) M(n, w); } } finally { t.running = !1, h = e, l = r; } } function q(t) { for (const e of t.owned) z(e); t.owned.length = 0; for (const e of t.cleanups) e(); t.cleanups.length = 0; for (const e of t.sources) e.observers.delete(t); t.sources.clear(); } function z(t) { t.disposed || (t.disposed = !0, q(t), t.observers.clear()); } function V(t) { for (const e of t.owned) z(e); t.owned.length = 0; for (const e of t.cleanups) e(); t.cleanups.length = 0; } function O(t) { return p(t); } var K = (t) => typeof t == "string" ? !1 : "tagName" in t && "childrenList" in t, U = ".#["; function Y(t) { const e = []; let r = 0; const s = /^[a-zA-Z][\w-]*/.exec(t); for (s !== null && (e.push(s[0]), r = s[0].length); r < t.length; ) { const i = t[r]; if (i === "[") { const o = t.indexOf("]", r + 1); if (o === -1) return null; e.push(t.slice(r, o + 1)), r = o + 1; continue; } if (i !== "." && i !== "#") return null; let n = r + 1; for (; n < t.length && !U.includes(t[n]); ) n += 1; if (n === r + 1) return null; e.push(t.slice(r, n)), r = n; } return e.length > 0 ? e : null; } var Z = (t, e) => { const r = e; if (r.startsWith(".")) return t.classList.contains(r.slice(1)); if (r.startsWith("#")) return t.getAttribute("id") === r.slice(1); if (r.startsWith("[") && r.endsWith("]")) { const [s, i] = r.slice(1, -1).trim().split("="), n = (s || "").trim(); if (!n) return !1; if (i == null) return t.hasAttribute(n); const o = i.trim().replace(/^['"]|['"]$/g, ""); return t.getAttribute(n) === o; } return t.tagName === r.toLowerCase(); }, Q = (t, e) => { const r = e.trim(); if (!r) return !1; const s = Y(r); return s === null ? !1 : s.every((i) => Z(t, i)); }, C = (t, e, r) => { for (const s of t) K(s) && (Q(s, e) && r.push(s), C(s.childrenList, e, r)); }, E = class { childrenList = []; appendChild(t) { return this.childrenList.push(t), t; } serialize() { return this.childrenList.map((t) => typeof t == "string" ? p(t) : t.serialize()).join(""); } querySelector(t) { const e = this.querySelectorAll(t); return e.length > 0 ? e[0] : null; } querySelectorAll(t) { const e = []; return C(this.childrenList, t, e), e; } }, X = class { tagName; attributes = /* @__PURE__ */ new Map(); inlineStyles = /* @__PURE__ */ new Map(); childrenList = []; shadowRoot = null; textContent = null; content; eventListeners = /* @__PURE__ */ new Map(); style = { setProperty: (t, e) => { const r = t.startsWith("--") ? t : t.replace(/([A-Z])/g, "-$1").toLowerCase(); this.inlineStyles.set(r, e); }, removeProperty: (t) => this.inlineStyles.delete(t) }; classList = { add: (...t) => { const e = this.attributes.get("class") || "", r = /* @__PURE__ */ new Set([...e.split(" ").filter(Boolean), ...t]); this.attributes.set("class", Array.from(r).join(" ")); }, remove: (...t) => { const e = (this.attributes.get("class") || "").split(" ").filter((r) => !t.includes(r)); this.attributes.set("class", e.join(" ")); }, toggle: (t) => { this.classList.contains(t) ? this.classList.remove(t) : this.classList.add(t); }, contains: (t) => (this.attributes.get("class") || "").split(" ").includes(t) }; _innerHTML = ""; get innerHTML() { return this._innerHTML; } set innerHTML(t) { this._innerHTML = t, this.tagName === "template" && this.content && (this.content.childrenList = [t]); } constructor(t = "div") { this.tagName = t.toLowerCase(), this.tagName === "template" && (this.content = new E()); } get hidden() { return this.hasAttribute("hidden"); } set hidden(t) { t ? this.setAttribute("hidden", "") : this.removeAttribute("hidden"); } setAttribute(t, e) { this.attributes.set(t, e); } getAttribute(t) { return this.attributes.get(t) || null; } removeAttribute(t) { this.attributes.delete(t); } hasAttribute(t) { return this.attributes.has(t); } appendChild(t) { return this.childrenList.push(t), t; } attachShadow(t) { return this.shadowRoot = new J(this, t), this.shadowRoot; } querySelector(t) { const e = this.querySelectorAll(t); return e.length > 0 ? e[0] : null; } querySelectorAll(t) { const e = []; return C(this.childrenList, t, e), e; } addEventListener(t, e) { const r = this.eventListeners.get(t) || /* @__PURE__ */ new Set(); r.add(e), this.eventListeners.set(t, r); } removeEventListener(t, e) { const r = this.eventListeners.get(t); r && (r.delete(e), r.size === 0 && this.eventListeners.delete(t)); } dispatchEvent(t) { const e = this.eventListeners.get(t.type); if (!e || e.size === 0) return !0; for (const r of e) typeof r == "function" ? r.call(this, t) : r.handleEvent(t); return !t.defaultPrevented; } serialize(t) { typeof this._preSerialize == "function" && this._preSerialize(); const e = t || this._ssrTag || this.tagName, r = Array.from(this.attributes.entries()).map(([o, a]) => ` ${o}="${O(a)}"`).join(""), s = Array.from(this.inlineStyles.entries()).map(([o, a]) => `${o}:${a}`).join(";"), i = s ? ` style="${O(s)}"` : ""; let n = ""; return this.shadowRoot && (n += this.shadowRoot.serialize()), this.textContent !== null ? n += p(this.textContent) : this._innerHTML ? n += this._innerHTML : n += this.childrenList.map((o) => typeof o == "string" ? p(o) : (o instanceof E, o.serialize())).join(""), [ "area", "base", "br", "col", "embed", "hr", "img", "input", "link", "meta", "param", "source", "track", "wbr" ].includes(e) && !n ? `<${e}${r}${i} />` : `<${e}${r}${i}>${n}</${e}>`; } }, J = class { host; options; childrenList = []; adoptedStyleSheets = []; constructor(t, e) { this.host = t, this.options = e; } appendChild(t) { return this.childrenList.push(t), t; } querySelector(t) { const e = this.querySelectorAll(t); return e.length > 0 ? e[0] : null; } querySelectorAll(t) { const e = []; return C(this.childrenList, t, e), e; } serialize() { return `<template shadowrootmode="${this.options.mode}"${this.options.delegatesFocus ? " shadowrootdelegatesfocus" : ""}>${this.adoptedStyleSheets.map((t) => `<style>${p(t)}</style>`).join("")}${this.childrenList.map((t) => typeof t == "string" ? p(t) : (t instanceof E, t.serialize())).join("")}</template>`; } }, pt = () => ({ current: null }), D = (t) => t.reduce((e, r) => Array.isArray(r) ? e.concat(D(r)) : e.concat(r), []), m = (t) => t == null ? null : t instanceof G ? t.build() : typeof t == "string" ? f ? t : document.createTextNode(t) : t, tt = (t, e) => { if (f) { S(t, [e()]); return; } const r = document.createComment(""), s = document.createComment(""); t.appendChild(r), t.appendChild(s); let i = null; const n = () => { i?.(), i = null; let o = r.nextSibling; for (; o && o !== s; ) { const a = o.nextSibling; o.parentNode?.removeChild(o), o = a; } }; L(() => { const o = e(); n(); const a = document.createDocumentFragment(); i = N((c) => (S(a, [o]), c)), s.parentNode?.insertBefore(a, s); }), x(() => i?.()); }, F = "__ranFor"; function vt(t) { return { ...t, [F]: !0 }; } var et = (t) => typeof t == "object" && t !== null && t[F] === !0; function mt(t) { const e = T(() => !!t.when()), r = () => t.when(); return () => e() ? t.children(r) : t.fallback?.() ?? null; } function bt(t) { return t; } function yt(t) { const e = t.children, r = T(() => e.findIndex((s) => !!s.when())); return () => { const s = r(); if (s < 0) return t.fallback?.() ?? null; const i = e[s]; return i.children(() => i.when()); }; } var rt = (t, e, r) => { const [s, i] = I(e); let n = null; const o = N((a) => { const c = m(r(t, s)); return n = typeof c == "string" ? document.createTextNode(c) : c, a; }); return { node: n, index: i, dispose: o }; }, P = (t, e) => { const r = t.parentNode; if (!r) return; let s = t; for (const i of e) s.nextSibling !== i && r.insertBefore(i, s.nextSibling), s = i; }, st = (t, e) => { if (f) { (e.each() ?? []).forEach((i, n) => { const o = m(e.render(i, () => n)); o != null && t.appendChild(o); }); return; } const r = document.createComment(""); t.appendChild(r); let s = /* @__PURE__ */ new Map(); x(() => { for (const i of s.values()) i.dispose(); s.clear(); }), L(() => { const i = e.each() ?? [], n = /* @__PURE__ */ new Map(), o = []; i.forEach((a, c) => { const b = e.key(a, c); if (n.has(b)) return; let d = s.get(b); d ? (s.delete(b), d.index(c)) : d = rt(a, c, e.render), n.set(b, d), d.node && o.push(d.node); }); for (const a of s.values()) a.node?.parentNode?.removeChild(a.node), a.dispose(); P(r, o), s = n; }); }, W = "__ranIndex"; function gt(t) { return { ...t, [W]: !0 }; } var nt = (t) => typeof t == "object" && t !== null && t[W] === !0, it = (t, e, r) => { const [s, i] = I(t); let n = null; const o = N((a) => { const c = m(r(s, e)); return n = typeof c == "string" ? document.createTextNode(c) : c, a; }); return { node: n, setItem: i, dispose: o }; }, ot = (t, e) => { if (f) { (e.each() ?? []).forEach((i, n) => { const o = m(e.render(() => i, n)); o != null && t.appendChild(o); }); return; } const r = document.createComment(""); t.appendChild(r); let s = []; x(() => { for (const i of s) i.dispose(); s = []; }), L(() => { const i = e.each() ?? []; for (let n = 0; n < i.length; n++) n < s.length ? s[n].setItem(i[n]) : s.push(it(i[n], n, e.render)); for (let n = s.length - 1; n >= i.length; n--) { const { node: o } = s[n]; o?.parentNode?.removeChild(o), s[n].dispose(), s.pop(); } P(r, s.map((n) => n.node).filter((n) => n != null)); }); }, S = (t, e) => { D(e).forEach((r) => { if (et(r)) { st(t, r); return; } if (nt(r)) { ot(t, r); return; } if (typeof r == "function") { tt(t, r); return; } const s = m(r); s != null && t.appendChild(s); }); }; var at = /* @__PURE__ */ new Set([ "svg", "circle", "clipPath", "defs", "desc", "ellipse", "feBlend", "feColorMatrix", "feComposite", "feDropShadow", "feFlood", "feGaussianBlur", "feMerge", "feMergeNode", "feOffset", "filter", "foreignObject", "g", "image", "line", "linearGradient", "marker", "mask", "path", "pattern", "polygon", "polyline", "radialGradient", "rect", "stop", "switch", "symbol", "text", "textPath", "tspan", "use" ]), G = class { el; constructor(t, e) { const r = e ?? (at.has(t) ? "http://www.w3.org/2000/svg" : void 0); this.el = f ? new X(t) : r ? document.createElementNS(r, t) : document.createElement(t); } id(t) { return this.el.setAttribute("id", t), this; } bind(t, e) { typeof t == "function" ? L(() => e(t())) : e(t); } class(t) { return this.bind(t, (e) => { f ? this.el.attributes.set("class", e) : this.el.className = e; }), this; } addClass(...t) { return t.forEach((e) => this.el.classList.add(e)), this; } removeClass(...t) { return t.forEach((e) => this.el.classList.remove(e)), this; } attr(t, e) { return this.bind(e, (r) => this.el.setAttribute(t, r)), this; } attrs(t) { return Object.entries(t).forEach(([e, r]) => { r != null && this.el.setAttribute(e, String(r)); }), this; } boolAttr(t, e, r = "") { return this.bind(e, (s) => { s ? this.el.setAttribute(t, r) : this.el.removeAttribute(t); }), this; } part(t) { return this.attr("part", t); } data(t, e) { return this.attr(`data-${t}`, e); } style(t, e) { return typeof t == "string" ? this.bind(e ?? "", (r) => this.el.style.setProperty(t, r)) : Object.entries(t).forEach(([r, s]) => this.el.style.setProperty(r, s)), this; } cssVar(t, e) { const r = t.startsWith("--") ? t : `--${t}`; return this.style(r, e); } aria(t, e) { return this.attr(`aria-${t}`, e); } role(t) { return this.attr("role", t); } tabIndex(t) { return this.attr("tabindex", String(t)); } label(t) { return this.aria("label", t); } labelledBy(t) { return this.aria("labelledby", t); } describedBy(t) { return this.aria("describedby", t); } ariaHidden(t = !0) { return this.aria("hidden", String(t)); } on(t, e, r) { return this.el.addEventListener(t, e, r), this; } listen(t, e, r, s) { return t.on(this.el, e, r, s), this; } delegate(t, e, r, s, i) { return t.delegate(this.el, e, r, s, i), this; } children(...t) { return S(this.el, t), this; } replaceChildren(...t) { if (f) { const e = this.el; e.childrenList = []; } else this.el.replaceChildren(); return this.children(...t); } text(t) { return this.bind(t, (e) => { this.el.textContent = e; }), this; } ref(t) { return t.current = this.el, this; } shadow(t = { mode: "closed" }) { const e = this.el.attachShadow(t); return new lt(this.el, e, t); } build() { return this.el; } serialize() { if (f) return this.el.serialize(); const t = document.createElement("div"); return t.appendChild(this.el.cloneNode(!0)), t.innerHTML; } }, lt = class { root; hostEl; options; constructor(t, e, r) { this.hostEl = t, this.root = e, this.options = r; } children(...t) { return S(this.root, t), this; } adoptSheet(...t) { return this.root.adoptedStyleSheets = [...this.root.adoptedStyleSheets, ...t], this; } css(t) { if (f) return this.root.adoptedStyleSheets.push(t), this; if (typeof CSSStyleSheet < "u") try { const r = new CSSStyleSheet(); return r.replaceSync(t), this.root.adoptedStyleSheets = [...this.root.adoptedStyleSheets, r], this; } catch { } const e = document.createElement("style"); return e.textContent = t, this.root.appendChild(e), this; } done() { return { host: this.hostEl, shadow: this.root }; } serialize() { return f ? this.root.serialize() : this.root.innerHTML; } }, u = (t) => new G(t), St = () => u("div"), wt = () => u("span"), Lt = () => u("slot"), Ct = () => u("button"), At = () => u("input"), Et = () => u("style"), Nt = () => u("label"), xt = () => u("ul"), Mt = () => u("li"), $t = () => u("section"), zt = () => u("article"), Ot = () => u("nav"), Ht = () => u("header"), It = () => u("footer"), Tt = () => u("main"), _t = (t = "open", e = !1) => { const r = u("template"); return r.attr("shadowrootmode", t), e && r.attr("shadowrootdelegatesfocus", ""), r; }; export { Q as A, I as B, mt as C, X as D, E, L as F, f as H, N as I, ft as L, O as M, ct as N, J as O, T as P, x as R, lt as S, pt as T, ht as V, u as _, It as a, gt as b, Nt as c, Ot as d, $t as f, xt as g, Et as h, St as i, p as j, C as k, Mt as l, wt as m, Ct as n, Ht as o, Lt as p, _t as r, At as s, zt as t, Tt as u, G as v, yt as w, bt as x, vt as y, dt as z };