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.

105 lines (104 loc) 6.12 kB
import { a as i, n as o, o as h, r as l, t as c } from "./utils-D1iZnChu.js"; import { c as d } from "./mocks-CMGoftIc.js"; import { t as u } from "./events-C59wGdni.js"; import { i as m, n as b } from "./factory-ZNhcQ4tf.js"; import { a as v, n as p } from "./ssr-DSGwPtEd.js"; import { i as g, n as w } from "./theme-kOWZbKCq.js"; var f = ".remove-wap-active-focus{outline:0;-webkit-tap-highlight-color:transparent}.remove-wap-active-focus:active,.remove-wap-active-focus:focus{outline:0;-webkit-tap-highlight-color:transparent}:host{display:var(--ran-theme-switch-display, inline-flex);box-sizing:border-box}.ran-theme-switch{display:inline-flex;align-items:center;gap:var(--ran-theme-switch-gap, 2px);padding:var(--ran-theme-switch-padding, 2px);border-width:var(--ran-skin-border-width, 1px);border-style:var(--ran-skin-border-style, solid);border-color:var(--ran-theme-switch-border-color, var(--ran-color-border, #eaeaea));border-radius:var(--ran-theme-switch-radius, var(--ran-radius-full, 9999px));background:var(--ran-theme-switch-background, transparent);box-sizing:border-box}.ran-theme-switch button{width:var(--ran-theme-switch-button-size, 28px);height:var(--ran-theme-switch-button-size, 28px);display:grid;place-items:center;border:none;border-radius:var(--ran-theme-switch-radius, var(--ran-radius-full, 9999px));background:transparent;color:var(--ran-theme-switch-color, var(--ran-color-text-secondary, #4d4d4d));cursor:pointer;padding:0}.ran-theme-switch button:hover{color:var(--ran-theme-switch-hover-color, var(--ran-color-text, #171717))}.ran-theme-switch button[aria-pressed=true]{background:var(--ran-theme-switch-active-background, var(--ran-color-bg-hover, #ebebeb));color:var(--ran-theme-switch-active-color, var(--ran-color-text, #171717))}.ran-theme-switch button:focus-visible{outline:var(--ran-theme-switch-focus-outline, 2px solid var(--ran-color-primary, #006bff));outline-offset:2px}.ran-theme-switch svg{width:var(--ran-theme-switch-icon-size, 16px);height:var(--ran-theme-switch-icon-size, 16px)}", a = [ "system", "light", "dark" ], y = { system: '<svg viewBox="0 0 16 16" aria-hidden="true"><rect x="1.5" y="2.5" width="13" height="9" rx="1.5" fill="none" stroke="currentColor" stroke-width="1.5"/><path d="M5.5 14h5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg>', light: '<svg viewBox="0 0 16 16" aria-hidden="true"><circle cx="8" cy="8" r="3" fill="none" stroke="currentColor" stroke-width="1.5"/><path d="M8 1v1.8M8 13.2V15M15 8h-1.8M2.8 8H1m11.4-4.4-1.3 1.3M4.9 11.1l-1.3 1.3m9.8 0-1.3-1.3M4.9 4.9 3.6 3.6" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg>', dark: '<svg viewBox="0 0 16 16" aria-hidden="true"><path d="M13.5 9.5A6 6 0 0 1 6.5 2.5a6 6 0 1 0 7 7z" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linejoin="round"/></svg>' }, s = "ran-theme-switch-sync", _ = class extends p { static get observedAttributes() { return [ "label-system", "label-light", "label-dark", "sheet" ]; } _events = new u(); _shadowDom; _group; constructor() { super(), this._shadowDom = o(this, f), this._group = c(this._shadowDom, ".ran-theme-switch", () => { const t = a.map((e) => { const r = b().attr("type", "button").data("choice", e).attr("part", `button ${e}`).aria("pressed", "false").build(); return d || (r.innerHTML = y[e]), r; }); return m().class("ran-theme-switch").attr("part", "switch").role("group").children(t).build(); }); } get sheet() { return l(this, "sheet"); } set sheet(t) { i(this, "sheet", t); } get value() { return w() || "system"; } set value(t) { a.includes(t) && this._select(t); } _label(t) { const e = { system: "System theme", light: "Light theme", dark: "Dark theme" }[t]; return this.getAttribute(`label-${t}`) || e; } _syncLabels() { this._group.setAttribute("aria-label", this.getAttribute("label") || "Theme"); for (const t of this._group.querySelectorAll("button")) t.setAttribute("aria-label", this._label(t.dataset.choice)); } _reflect() { const t = this.value; for (const e of this._group.querySelectorAll("button")) e.setAttribute("aria-pressed", e.dataset.choice === t ? "true" : "false"); } _select(t) { g(t), this._reflect(), this._syncMeta(t), document.dispatchEvent(new CustomEvent(s)), this.dispatchEvent(new CustomEvent("change", { detail: { theme: t }, bubbles: !0, composed: !0 })); } _syncMeta(t) { if (typeof requestAnimationFrame > "u") return; const e = document.querySelectorAll('meta[name="theme-color"]'); e.length && requestAnimationFrame(() => { for (const r of e) if (r.dataset.ranOriginalContent === void 0 && (r.dataset.ranOriginalContent = r.getAttribute("content") || ""), t === "system") r.setAttribute("content", r.dataset.ranOriginalContent); else { const n = getComputedStyle(document.documentElement).getPropertyValue("--ran-color-bg").trim() || getComputedStyle(document.body).backgroundColor; r.setAttribute("content", n); } }); } _handleClick = (t) => { const e = t.target.closest?.("button")?.dataset.choice; e && a.includes(e) && this._select(e); }; _handleSync = () => this._reflect(); handlerExternalCss = () => { h(this, this._shadowDom, "sheet", null, this.sheet); }; connectedCallback() { this.handlerExternalCss(), this._syncLabels(), this._reflect(), this._events.on(this._group, "click", this._handleClick), document.addEventListener(s, this._handleSync), typeof window < "u" && window.addEventListener("storage", this._handleSync); } disconnectedCallback() { this._events.abort(), document.removeEventListener(s, this._handleSync), typeof window < "u" && window.removeEventListener("storage", this._handleSync); } attributeChangedCallback(t, e, r) { e !== r && (t === "sheet" && this.handlerExternalCss(), t.startsWith("label") && this._syncLabels()); } }; v("r-theme-switch", _); export { _ as t };