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.

103 lines (102 loc) 6.09 kB
import { H as i, i as o, n as h } from "./factory-WDxu11V0.js"; import { t as l } from "./events-Cqz3ramM.js"; import "./builder-EH76YCFS.js"; import { i as c, n as d, o as u, t as b } from "./utils-U-9uH7EX.js"; import { a as m, n as v } from "./ssr-BzykYefm.js"; import { i as p, n as g } from "./theme-DKH_E9Cp.js"; var w = ":host{display:var(--ran-theme-switch-display, inline-flex);box-sizing:border-box}:host([hidden]){display:none}.ran-theme-switch{display:inline-flex;align-items:center;gap:var(--ran-theme-switch-gap, var(--ran-space-1, 4px));padding:var(--ran-theme-switch-padding, var(--ran-space-1, 4px));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, var(--ran-size-5, 28px));height:var(--ran-theme-switch-button-size, var(--ran-size-5, 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-button-color, var(--ran-color-text-secondary, #4d4d4d));cursor:pointer;padding:0}.ran-theme-switch button:hover{color:var(--ran-theme-switch-button-hover-color, var(--ran-color-text, #171717))}.ran-theme-switch button[aria-pressed=true]{background:var(--ran-theme-switch-button-active-background, var(--ran-color-bg-hover, #ebebeb));color:var(--ran-theme-switch-button-active-color, var(--ran-color-text, #171717))}.ran-theme-switch button:focus-visible{outline:var(--ran-theme-switch-button-focus-outline, 2px solid var(--ran-color-primary, #006bff));outline-offset:var(--ran-theme-switch-button-focus-outline-offset, 2px)}.ran-theme-switch svg{width:var(--ran-theme-switch-icon-size, var(--ran-size-1, 16px));height:var(--ran-theme-switch-icon-size, var(--ran-size-1, 16px))}", s = [ "system", "light", "dark" ], f = { 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>' }, a = "ran-theme-switch-sync", _ = class extends v { static get observedAttributes() { return [ "label-system", "label-light", "label-dark", "sheet" ]; } _events = new l(); _shadowDom; _group; _buttons; constructor() { super(), this._shadowDom = b(this, w), this._buttons = s.map((t) => { const e = h().attr("type", "button").data("choice", t).attr("part", `button ${t}`).aria("pressed", "false").build(); return i || (e.innerHTML = f[t]), e; }), this._group = o().class("ran-theme-switch").attr("part", "switch").role("group").children(this._buttons).build(), this._shadowDom.appendChild(this._group); } get sheet() { return d(this, "sheet"); } set sheet(t) { c(this, "sheet", t); } get value() { return g() || "system"; } set value(t) { s.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._buttons) t.setAttribute("aria-label", this._label(t.dataset.choice)); } _reflect() { const t = this.value; for (const e of this._buttons) e.setAttribute("aria-pressed", e.dataset.choice === t ? "true" : "false"); } _select(t) { p(t), this._reflect(), this._syncMeta(t), document.dispatchEvent(new CustomEvent(a)), 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 && s.includes(e) && this._select(e); }; _handleSync = () => this._reflect(); handlerExternalCss = () => { u(this, this._shadowDom, "sheet", null, this.sheet); }; connectedCallback() { this.handlerExternalCss(), this._syncLabels(), this._reflect(), this._events.on(this._group, "click", this._handleClick), document.addEventListener(a, this._handleSync), typeof window < "u" && window.addEventListener("storage", this._handleSync); } disconnectedCallback() { this._events.abort(), document.removeEventListener(a, 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()); } }; m("r-theme-switch", _); export { _ as t };