UNPKG

mode-watcher

Version:

SSR-friendly light and dark mode for SvelteKit

67 lines (66 loc) 2.77 kB
import { userPrefersMode } from "./mode-states.svelte.js"; import { customTheme } from "./theme-state.svelte.js"; import { derivedMode } from "./states.svelte.js"; /** Toggle between light and dark mode */ export function toggleMode() { userPrefersMode.current = derivedMode.current === "dark" ? "light" : "dark"; } /** Set the mode to light or dark */ export function setMode(mode) { userPrefersMode.current = mode; } /** Reset the mode to operating system preference */ export function resetMode() { userPrefersMode.current = "system"; } /** Set the theme to a custom value */ export function setTheme(newTheme) { customTheme.current = newTheme; } export function defineConfig(config) { return config; } /** Used to set the mode on initial page load to prevent FOUC */ export function setInitialMode({ defaultMode = "system", themeColors, darkClassNames = ["dark"], lightClassNames = [], defaultTheme = "", modeStorageKey = "mode-watcher-mode", themeStorageKey = "mode-watcher-theme", }) { const rootEl = document.documentElement; const mode = localStorage.getItem(modeStorageKey) ?? defaultMode; const theme = localStorage.getItem(themeStorageKey) ?? defaultTheme; const light = mode === "light" || (mode === "system" && window.matchMedia("(prefers-color-scheme: light)").matches); if (light) { if (darkClassNames.length) rootEl.classList.remove(...darkClassNames.filter(Boolean)); if (lightClassNames.length) rootEl.classList.add(...lightClassNames.filter(Boolean)); } else { if (lightClassNames.length) rootEl.classList.remove(...lightClassNames.filter(Boolean)); if (darkClassNames.length) rootEl.classList.add(...darkClassNames.filter(Boolean)); } rootEl.style.colorScheme = light ? "light" : "dark"; if (themeColors) { const themeMetaEl = document.querySelector('meta[name="theme-color"]'); if (themeMetaEl) { themeMetaEl.setAttribute("content", mode === "light" ? themeColors.light : themeColors.dark); } } if (theme) { rootEl.setAttribute("data-theme", theme); localStorage.setItem(themeStorageKey, theme); } localStorage.setItem(modeStorageKey, mode); } /** * A type-safe way to generate the source expression used to set the initial mode and avoid FOUC. * * @deprecated Use `createInitialModeExpression` instead. */ export function generateSetInitialModeExpression(config = {}) { return `(${setInitialMode.toString()})(${JSON.stringify(config)});`; } /** * A type-safe way to generate the source expression used to set the initial mode and avoid FOUC. */ export const createInitialModeExpression = generateSetInitialModeExpression;