Files
easy-png-tools2/web/src/lib/theme.svelte.ts
T

47 lines
1.3 KiB
TypeScript

export type ThemeChoice = "light" | "dark";
const STORAGE_KEY = "theme";
let theme = $state<ThemeChoice>("light");
function storage(): Storage | null {
return typeof localStorage === "undefined" ? null : localStorage;
}
function systemTheme(): ThemeChoice {
if (typeof window === "undefined" || !window.matchMedia) return "light";
return window.matchMedia("(prefers-color-scheme: dark)").matches
? "dark"
: "light";
}
function apply(): void {
if (typeof document === "undefined") return;
document.documentElement.dataset.theme = theme;
}
export function getTheme(): ThemeChoice {
return theme;
}
export function setTheme(next: ThemeChoice): void {
theme = next;
storage()?.setItem(STORAGE_KEY, next);
apply();
}
/**
* Догоняет состояние после гидрации: фактический атрибут уже выставлен
* инлайн-скриптом в app.html; здесь он читается и синхронизируется с runes,
* чтобы кнопка в шапке отражала реальную тему.
*/
export function initTheme(): void {
if (typeof window === "undefined") return;
const attr =
typeof document !== "undefined"
? document.documentElement.dataset.theme
: undefined;
theme = attr === "dark" || attr === "light" ? attr : systemTheme();
apply();
}