()
| 53 | } |
| 54 | |
| 55 | export function useTheme() { |
| 56 | const defaultTheme: ValidTheme = |
| 57 | typeof window !== 'undefined' |
| 58 | ? window?.matchMedia('(prefers-color-scheme: dark)')?.matches |
| 59 | ? 'dark' |
| 60 | : 'light' |
| 61 | : 'light'; |
| 62 | const customTheme = window.localStorage.getItem(THEME_CONFIG); |
| 63 | const theme = isValidTheme(customTheme) ? customTheme : defaultTheme; |
| 64 | |
| 65 | const primaryColor = useMemo( |
| 66 | () => colord(THEME_COLORS[theme].primary), |
| 67 | [theme] |
| 68 | ); |
| 69 | const healthColor = useMemo( |
| 70 | () => colord(THEME_COLORS[theme].green400), |
| 71 | [theme] |
| 72 | ); |
| 73 | |
| 74 | const colors = useMemo( |
| 75 | () => ({ |
| 76 | theme: { |
| 77 | ...THEME_COLORS[theme], |
| 78 | }, |
| 79 | chart: { |
| 80 | error: twColors.red[500], |
| 81 | text: THEME_COLORS[theme].gray700, |
| 82 | line: THEME_COLORS[theme].gray200, |
| 83 | pv: primaryColor.alpha(0.4).toRgbString(), |
| 84 | uv: primaryColor.alpha(0.6).toRgbString(), |
| 85 | monitor: healthColor.alpha(0.8).toRgbString(), |
| 86 | default: primaryColor.alpha(0.8).toRgbString(), |
| 87 | }, |
| 88 | map: { |
| 89 | baseColor: THEME_COLORS[theme].primary, |
| 90 | fillColor: THEME_COLORS[theme].gray100, |
| 91 | strokeColor: THEME_COLORS[theme].primary, |
| 92 | hoverColor: THEME_COLORS[theme].primary, |
| 93 | }, |
| 94 | }), |
| 95 | [] |
| 96 | ); |
| 97 | |
| 98 | function saveTheme(value: string) { |
| 99 | window.localStorage.setItem(THEME_CONFIG, value); |
| 100 | } |
| 101 | |
| 102 | useEffect(() => { |
| 103 | document.body.setAttribute('data-theme', theme); |
| 104 | }, [theme]); |
| 105 | |
| 106 | useEffect(() => { |
| 107 | const url = new URL(window?.location?.href); |
| 108 | const theme = url.searchParams.get('theme'); |
| 109 | |
| 110 | if (theme && ['light', 'dark'].includes(theme)) { |
| 111 | saveTheme(theme); |
| 112 | } |
no test coverage detected