UNPKG

@cerberus-design/react

Version:

The Cerberus Design React component library.

1 lines 4.32 kB
{"version":3,"sources":["../../../src/hooks/useTheme.ts"],"sourcesContent":["'use client'\n\nimport {\n useCallback,\n useEffect,\n useLayoutEffect,\n useMemo,\n useState,\n} from 'react'\nimport {\n type ColorModes,\n type CustomThemes,\n type DefaultThemes,\n type ThemeContextValue,\n} from '../context/theme'\n\n/**\n * This module provides a hook for using the theme.\n * @module\n */\n\nexport const THEME_KEY = 'cerberus-theme'\nexport const MODE_KEY = 'cerberus-mode'\n\nexport interface UseThemeOptions<T extends string = DefaultThemes> {\n /**\n * Whether to cache the theme in local storage.\n */\n cache?: boolean\n /**\n * Called when the theme is updated.\n */\n updateTheme?: (theme: T) => void\n /**\n * Called when the color mode is updated.\n */\n updateMode?: (mode: ColorModes) => void\n}\n\n/**\n * Provides a hook for using the theme for a single instance of the application.\n * @see https://cerberus.digitalu.design/react/use-theme\n * @param defaultTheme The default theme.\n * @param defaultColorMode The default color mode.\n * @param options Additional options.\n */\nexport function useTheme<C extends string = DefaultThemes>(\n defaultTheme: CustomThemes<C> = 'cerberus',\n defaultColorMode: ColorModes = 'light',\n options: UseThemeOptions<C> = {},\n): ThemeContextValue<C> {\n const { updateMode, updateTheme, cache } = options\n const [theme, setTheme] = useState<CustomThemes<C>>(defaultTheme)\n const [colorMode, setColorMode] = useState<ColorModes>(defaultColorMode)\n\n const handleThemeChange = useCallback(\n (newTheme: C) => {\n setTheme(newTheme)\n updateTheme?.(newTheme)\n },\n [updateTheme],\n )\n\n const handleColorModeChange = useCallback(\n (newMode: ColorModes) => {\n setColorMode(newMode)\n updateMode?.(newMode)\n },\n [updateMode],\n )\n\n useLayoutEffect(() => {\n const theme = localStorage.getItem(THEME_KEY)\n if (theme) {\n setTheme(theme as CustomThemes<C>)\n }\n }, [])\n\n useLayoutEffect(() => {\n const mode = localStorage.getItem(MODE_KEY)\n if (mode) {\n setColorMode(mode as ColorModes)\n }\n }, [])\n\n useEffect(() => {\n const root = document.documentElement\n root.dataset.pandaTheme = theme\n\n if (cache) {\n localStorage.setItem(THEME_KEY, theme)\n }\n }, [theme, cache])\n\n useEffect(() => {\n const root = document.documentElement\n\n if (colorMode === 'system') {\n root.dataset.colorMode = window.matchMedia('(prefers-color-scheme: dark)')\n .matches\n ? 'dark'\n : 'light'\n } else {\n root.dataset.colorMode = colorMode\n }\n\n if (cache) {\n localStorage.setItem(MODE_KEY, colorMode)\n }\n }, [colorMode, cache])\n\n return useMemo(\n () => ({\n theme,\n mode: colorMode,\n updateTheme: handleThemeChange,\n updateMode: handleColorModeChange,\n }),\n [theme, colorMode, handleThemeChange, handleColorModeChange],\n )\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAEA,mBAMO;AAaA,IAAM,YAAY;AAClB,IAAM,WAAW;AAwBjB,SAAS,SACd,eAAgC,YAChC,mBAA+B,SAC/B,UAA8B,CAAC,GACT;AACtB,QAAM,EAAE,YAAY,aAAa,MAAM,IAAI;AAC3C,QAAM,CAAC,OAAO,QAAQ,QAAI,uBAA0B,YAAY;AAChE,QAAM,CAAC,WAAW,YAAY,QAAI,uBAAqB,gBAAgB;AAEvE,QAAM,wBAAoB;AAAA,IACxB,CAAC,aAAgB;AACf,eAAS,QAAQ;AACjB,iDAAc;AAAA,IAChB;AAAA,IACA,CAAC,WAAW;AAAA,EACd;AAEA,QAAM,4BAAwB;AAAA,IAC5B,CAAC,YAAwB;AACvB,mBAAa,OAAO;AACpB,+CAAa;AAAA,IACf;AAAA,IACA,CAAC,UAAU;AAAA,EACb;AAEA,oCAAgB,MAAM;AACpB,UAAMA,SAAQ,aAAa,QAAQ,SAAS;AAC5C,QAAIA,QAAO;AACT,eAASA,MAAwB;AAAA,IACnC;AAAA,EACF,GAAG,CAAC,CAAC;AAEL,oCAAgB,MAAM;AACpB,UAAM,OAAO,aAAa,QAAQ,QAAQ;AAC1C,QAAI,MAAM;AACR,mBAAa,IAAkB;AAAA,IACjC;AAAA,EACF,GAAG,CAAC,CAAC;AAEL,8BAAU,MAAM;AACd,UAAM,OAAO,SAAS;AACtB,SAAK,QAAQ,aAAa;AAE1B,QAAI,OAAO;AACT,mBAAa,QAAQ,WAAW,KAAK;AAAA,IACvC;AAAA,EACF,GAAG,CAAC,OAAO,KAAK,CAAC;AAEjB,8BAAU,MAAM;AACd,UAAM,OAAO,SAAS;AAEtB,QAAI,cAAc,UAAU;AAC1B,WAAK,QAAQ,YAAY,OAAO,WAAW,8BAA8B,EACtE,UACC,SACA;AAAA,IACN,OAAO;AACL,WAAK,QAAQ,YAAY;AAAA,IAC3B;AAEA,QAAI,OAAO;AACT,mBAAa,QAAQ,UAAU,SAAS;AAAA,IAC1C;AAAA,EACF,GAAG,CAAC,WAAW,KAAK,CAAC;AAErB,aAAO;AAAA,IACL,OAAO;AAAA,MACL;AAAA,MACA,MAAM;AAAA,MACN,aAAa;AAAA,MACb,YAAY;AAAA,IACd;AAAA,IACA,CAAC,OAAO,WAAW,mBAAmB,qBAAqB;AAAA,EAC7D;AACF;","names":["theme"]}