UNPKG

@buildy-ui/theme

Version:

React theme state management library for utility and semantic CSS approaches

189 lines (184 loc) 4.56 kB
// src/constants.ts var THEME_TYPES = { SEMANTIC: "semantic", UI8KIT: "ui8kit" }; var DEFAULT_THEME = THEME_TYPES.UI8KIT; var STORAGE_KEYS = { THEME: "app-theme" }; var LOCAL_STORAGE_KEY = STORAGE_KEYS.THEME; // src/current.ts var currentTheme = DEFAULT_THEME; function getTheme() { return currentTheme; } function setTheme(theme) { if (Object.values(THEME_TYPES).includes(theme)) { currentTheme = theme; } else { console.warn(`Invalid theme: ${theme}. Using default: ${DEFAULT_THEME}`); currentTheme = DEFAULT_THEME; } } // src/utils.ts var getStoredTheme = () => { if (typeof window === "undefined") { return null; } try { const storedTheme = localStorage.getItem(LOCAL_STORAGE_KEY); if (storedTheme && Object.values(THEME_TYPES).includes(storedTheme)) { return storedTheme; } return null; } catch (error) { console.error("Failed to get theme from localStorage:", error); return null; } }; var storeTheme = (theme) => { if (typeof window === "undefined") { return; } try { localStorage.setItem(LOCAL_STORAGE_KEY, theme); } catch (error) { console.error("Failed to store theme in localStorage:", error); } }; var getThemeFromUrl = () => { if (typeof window === "undefined") { return null; } try { const url = new URL(window.location.href); const themeParam = url.searchParams.get("theme"); if (themeParam && Object.values(THEME_TYPES).includes(themeParam)) { return themeParam; } return null; } catch (error) { console.error("Failed to get theme from URL:", error); return null; } }; var removeThemeParamFromUrl = () => { if (typeof window === "undefined") { return; } try { const url = new URL(window.location.href); if (url.searchParams.has("theme")) { url.searchParams.delete("theme"); window.history.replaceState({}, "", url.toString()); } } catch (error) { console.error("Failed to remove theme param from URL:", error); } }; var getInitialTheme = () => { const urlTheme = getThemeFromUrl(); if (urlTheme) { storeTheme(urlTheme); removeThemeParamFromUrl(); return urlTheme; } const storedTheme = getStoredTheme(); if (storedTheme) { return storedTheme; } return DEFAULT_THEME; }; var toggleTheme = (currentTheme2) => { return currentTheme2 === THEME_TYPES.SEMANTIC ? THEME_TYPES.UI8KIT : THEME_TYPES.SEMANTIC; }; // src/context.tsx import { createContext, useContext, useEffect, useReducer } from "react"; // src/reducer.ts var initialThemeState = { current: DEFAULT_THEME, isLoading: false }; function themeReducer(state, action) { switch (action.type) { case "SET_THEME": return { ...state, current: action.payload }; case "TOGGLE_THEME": return { ...state, current: toggleTheme(state.current) }; case "SET_LOADING": return { ...state, isLoading: action.payload }; default: return state; } } // src/context.tsx import { jsx } from "react/jsx-runtime"; var ThemeContext = createContext(void 0); var ThemeProvider = ({ children, initialTheme }) => { const [state, dispatch] = useReducer(themeReducer, { ...initialThemeState, current: initialTheme || (typeof window !== "undefined" ? getInitialTheme() : initialThemeState.current) }); const setTheme2 = (theme) => { dispatch({ type: "SET_THEME", payload: theme }); }; const handleToggleTheme = () => { dispatch({ type: "TOGGLE_THEME" }); }; useEffect(() => { storeTheme(state.current); }, [state.current]); useEffect(() => { if (typeof window !== "undefined" && !initialTheme) { const clientInitialTheme = getInitialTheme(); if (clientInitialTheme !== state.current) { setTheme2(clientInitialTheme); } } }, []); const value = { ...state, setTheme: setTheme2, toggleTheme: handleToggleTheme }; return /* @__PURE__ */ jsx(ThemeContext.Provider, { value, children }); }; var useTheme = () => { const context = useContext(ThemeContext); if (context === void 0) { throw new Error("useTheme must be used within a ThemeProvider"); } return context; }; export { DEFAULT_THEME, LOCAL_STORAGE_KEY, STORAGE_KEYS, THEME_TYPES, ThemeProvider, getInitialTheme, getStoredTheme, getTheme, getThemeFromUrl, initialThemeState, removeThemeParamFromUrl, setTheme, storeTheme, themeReducer, toggleTheme, useTheme }; //# sourceMappingURL=index.js.map