Files

59 lines
1.8 KiB
JavaScript

/*
* 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 });
});