| 1 | // Reasonix — shared three-state theme switch (system / light / dark). |
| 2 | // The pre-paint inline script in each layout sets documentElement.dataset.theme |
| 3 | // before first paint; this module wires the toggle buttons and keeps the |
| 4 | // resolved theme in sync with OS changes while the preference is "system". |
| 5 | const THEME_KEY = "reasonix-theme"; |
| 6 | const META_LIGHT = "#ffffff"; |
| 7 | const META_DARK = "#1f232b"; |
| 8 | |
| 9 | export function currentThemePref() { |
| 10 | try { |
| 11 | const p = localStorage.getItem(THEME_KEY); |
| 12 | return p === "light" || p === "dark" ? p : "system"; |
| 13 | } catch (e) { |
| 14 | return "system"; |
| 15 | } |
| 16 | } |
| 17 | |
| 18 | export function resolveTheme(pref) { |
| 19 | return pref === "dark" || |
| 20 | (pref === "system" && window.matchMedia("(prefers-color-scheme: dark)").matches) |
| 21 | ? "dark" |
| 22 | : "light"; |
| 23 | } |
| 24 | |
| 25 | export function applyTheme(pref) { |
| 26 | const resolved = resolveTheme(pref); |
| 27 | document.documentElement.dataset.theme = resolved; |
| 28 | const meta = document.querySelector('meta[name="theme-color"]'); |
| 29 | if (meta) meta.content = resolved === "dark" ? META_DARK : META_LIGHT; |
| 30 | document.querySelectorAll(".theme-switch button").forEach((b) => { |
| 31 | const on = b.dataset.theme === pref; |
| 32 | b.classList.toggle("active", on); |
| 33 | if (on) b.setAttribute("aria-pressed", "true"); |
| 34 | else b.setAttribute("aria-pressed", "false"); |
| 35 | }); |
| 36 | } |
| 37 | |
| 38 | export function initTheme() { |
| 39 | applyTheme(currentThemePref()); |
| 40 | const mq = window.matchMedia("(prefers-color-scheme: dark)"); |
| 41 | const onOsChange = () => { |
| 42 | const pref = currentThemePref(); |
| 43 | if (pref === "system") applyTheme(pref); |
| 44 | }; |
| 45 | if (mq.addEventListener) mq.addEventListener("change", onOsChange); |
| 46 | document.querySelectorAll(".theme-switch button").forEach((b) => { |
| 47 | b.addEventListener("click", () => { |
| 48 | try { |
| 49 | localStorage.setItem(THEME_KEY, b.dataset.theme); |
| 50 | } catch (e) {} |
| 51 | applyTheme(b.dataset.theme); |
| 52 | }); |
| 53 | }); |
| 54 | } |
| 55 |