UNPKG

theme-selector

Version:

A simple Svelte store library that lets you switch between light and dark themes, with support for system theme by default.

71 lines (70 loc) 2.09 kB
import { browser } from '$app/environment'; import { writable } from 'svelte/store'; class Theme { #themeOption; #themeCurrent; onThemeChange = (value) => { if (browser) { if (value === 'dark') { document.documentElement.classList.add('dark'); } else { document.documentElement.classList.remove('dark'); } } }; value; constructor(onThemeChange) { if (onThemeChange) { this.onThemeChange = onThemeChange; } this.#themeOption = writable('system'); this.#themeCurrent = writable('light'); this.value = 'light'; if (browser) { this.initialize(); } } initialize() { const theme = localStorage.getItem('theme'); if (theme) { this.#themeOption.set(theme); } else { this.#themeOption.set('system'); localStorage.setItem('theme', 'system'); } this.value = theme; this.#themeCurrent.set(this.get()); window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', () => { this.#themeCurrent.set(this.get()); }); this.#themeOption.subscribe((value) => { this.value = value; this.#themeCurrent.set(this.get()); }); this.#themeCurrent.subscribe((value) => { this.onThemeChange?.(value); }); this.onThemeChange?.(this.get()); } get() { if (this.value === 'system') { return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'; } else { return this.value; } } set(value) { this.#themeOption.set(value); localStorage.setItem('theme', value); } subscribe(run, invalidate) { return this.#themeCurrent.subscribe(run, invalidate); } } export const createThemeStore = (calledFunc) => { return new Theme(calledFunc); }; export const theme = new Theme();