UNPKG

@wener/console

Version:

Base console UI toolkit

170 lines (169 loc) 5.68 kB
import { useContext, useEffect } from "react"; import { deepEqual } from "@wener/utils"; import { z } from "zod"; import { useStore } from "zustand"; import { useShallow } from "zustand/react/shallow"; import { getPrefersColorSchema } from "../../utils/getPrefersColorSchema.js"; import { getSupportedThemes } from "./getSupportedThemes.js"; import { DaisyThemeStoreContext } from "./useTheme.js"; (function (DaisyTheme) { const Context = DaisyThemeStoreContext; DaisyTheme.Root = () => { return; }; function useThemeStore() { return useContext(Context); } DaisyTheme.useThemeStore = useThemeStore; function useThemeState() { let store = useThemeStore(); const state = useStore(store, useShallow((s) => s)); return [ state, (update) => { store.setState(update); } ]; } DaisyTheme.useThemeState = useThemeState; DaisyTheme.Sidecar = () => { const store = useContext(Context); useEffect(() => { const storage = globalThis.localStorage; if (!storage && typeof window === "undefined") { return; } const StateSchema = z.object({ light: z.string().optional(), dark: z.string().optional(), theme: z.string().optional(), custom: z.record(z.any()).optional() }); const closer = []; const loadState = (s) => { if (!s) { return; } try { const loaded = StateSchema.parse(JSON.parse(s)); store.setState(loaded, true); } catch (e) { console.warn("Failed to parse theme state", e); } }; const storageKey = "THEME_STATE"; // load previous loadState(storage.getItem(storageKey)); // watch storage change { const handleStorageChange = (e) => { if (e.key !== storageKey) { return; } loadState(e.newValue); }; window.addEventListener("storage", handleStorageChange); closer.push(() => { window.removeEventListener("storage", handleStorageChange); }); } // system { store.setState((s) => { s.system = getPrefersColorSchema(); }); closer.push(watchPrefersColorSchema(() => { store.setState((s) => { s.system = getPrefersColorSchema(); }); })); } // persist { let last = StateSchema.parse(store.getState()); const unsub = store.subscribe((s) => { const current = StateSchema.parse(s); if (deepEqual(last, current)) { return; } storage.setItem(storageKey, JSON.stringify(current)); last = current; }); // closer.push(unsub); } // active { // const element = document.documentElement; store.subscribe((s) => { let active = getActiveTheme(s); let schema = getThemeSchema(active); if (s.active === active && s.schema === schema) { return; } store.setState({ active, schema }); const el = globalThis.document?.documentElement; // setElementThemeAttribute(active, element); el?.setAttribute("data-theme", active); el?.setAttribute("data-color-mode", schema); }); } return () => { closer.forEach((c) => c()); }; }, [ store ]); /* data-color-mode="dark" */ return null; }; function useThemeSchema() { let store = useThemeStore(); return useStore(store, ({ theme }) => { return getThemeSchema(theme); }); } DaisyTheme.useThemeSchema = useThemeSchema; })(DaisyTheme || (DaisyTheme = {})); function getThemeSchema(theme) { switch (theme) { case "system": return getPrefersColorSchema(); case "dark": case "light": return theme; default: return getSupportedThemes().find((v) => v.value === theme)?.schema ?? "light"; } } function watchPrefersColorSchema(cb) { const listener = (event) => { cb(event.matches); }; const target = window.matchMedia("(prefers-color-scheme: light)"); cb(target.matches); target.addEventListener("change", listener); return () => { target.removeEventListener("change", listener); }; } function getActiveTheme(s) { let theme = s.theme || "system"; if (theme === "system") { theme = s.system || "light"; switch (theme) { case "dark": return s.dark || theme; case "light": return s.light || theme; } } return theme || "light"; } export var DaisyTheme; //# sourceMappingURL=DaisyTheme.js.map