/* * Copyright (C) 2026 Mateusz GruszczyƄski @linuxiarz.pl * Source-Available Code / Dual-Licensed. * * Free for non-commercial and evaluation use under terms of BSL/GPLv3. * Commercial or production use requires a valid paid license. * See LICENSE file in repository root for details. */ const STORAGE_KEY = "rustpad:theme"; const THEMES = new Set(["dark", "light"]); const systemThemeQuery = window.matchMedia("(prefers-color-scheme: light)"); function systemTheme() { return systemThemeQuery.matches ? "light" : "dark"; } function normalizeTheme(value) { return THEMES.has(value) ? value : systemTheme(); } function updateBrowserChrome(theme) { document.documentElement.dataset.theme = theme; document.documentElement.style.colorScheme = theme; document.querySelector('meta[name="color-scheme"]')?.setAttribute("content", theme); } export function getTheme() { return normalizeTheme(document.documentElement.dataset.theme); } export function applyTheme(value, { persist = true } = {}) { const theme = normalizeTheme(value); const previousTheme = getTheme(); updateBrowserChrome(theme); if (persist) { try { localStorage.setItem(STORAGE_KEY, theme); } catch { } } if (theme !== previousTheme) { window.dispatchEvent(new CustomEvent("rustpad:theme-change", { detail: { theme } })); } return theme; } export function applySessionTheme(session) { if (session?.theme) applyTheme(session.theme); } window.addEventListener("storage", event => { if (event.key !== STORAGE_KEY) return; applyTheme(THEMES.has(event.newValue) ? event.newValue : systemTheme(), { persist: false }); }); systemThemeQuery.addEventListener("change", () => { try { if (THEMES.has(localStorage.getItem(STORAGE_KEY))) return; } catch { } applyTheme(systemTheme(), { persist: false }); });