import { PersistedState, watch } from "runed"; import { themeStorageKey } from "./storage-keys.svelte.js"; import { isBrowser, noopStorage } from "./utils.js"; class CustomTheme { #storage = isBrowser ? localStorage : noopStorage; #initialValue = this.#storage.getItem(themeStorageKey.current); #value = this.#initialValue === null || this.#initialValue === undefined ? "" : this.#initialValue; #persisted = $state(this.#makePersisted()); #makePersisted(value = this.#value) { return new PersistedState(themeStorageKey.current, value, { serializer: { serialize: (v) => { if (typeof v !== "string") return ""; return v; }, deserialize: (v) => v, }, }); } constructor() { $effect.root(() => { return watch.pre(() => themeStorageKey.current, (_, prevStorageKey) => { const currModeValue = this.#persisted.current; this.#persisted = this.#makePersisted(currModeValue); if (prevStorageKey) { localStorage.removeItem(prevStorageKey); } }); }); } /** * The current theme. * @returns The current theme. */ get current() { return this.#persisted.current; } /** * Set the current theme. * @param newValue The new theme to set. */ set current(newValue) { this.#persisted.current = newValue; } } /** * A custom theme to apply and persist to the root `html` element. */ export const customTheme = new CustomTheme();