@wener/console
Version:
Base console UI toolkit
170 lines (169 loc) • 5.68 kB
JavaScript
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