11import type { ReactNode } from 'react' ;
22import React , { createContext , useCallback , useContext , useEffect , useMemo , useState } from 'react' ;
3- import { useCookie } from 'react-use' ;
4- import { wait } from '@bundle-stats/utils' ;
53
6- // classList required timeout to allow to disable motion during the switch
7- const CLASSLIST_UPDATE_TIMEOUT = 10 ;
8-
9- type ThemeName = 'light' | 'dark' ;
10-
11- const getCurrentTheme = ( ) : ThemeName => {
12- const { matches } = window . matchMedia ( '(prefers-color-scheme: dark)' ) ;
13- return matches ? 'dark' : 'light' ;
14- } ;
4+ import { getCurrentTheme , switchTheme , useCookieTheme , type ThemeName } from '../utils/theme' ;
155
166type ThemeContextProps = {
177 name : ThemeName ;
@@ -23,47 +13,35 @@ const ThemeContext = createContext<ThemeContextProps>({
2313 update : ( ) => { } ,
2414} ) ;
2515
26- export const ThemeProvider = ( { children } : { children : ReactNode } ) => {
27- const [ cookieValue , setCookieValue ] = useCookie ( 'theme' ) ;
28- const [ name , setName ] = useState < ThemeName > ( ( cookieValue as ThemeName ) || getCurrentTheme ( ) ) ;
29-
30- const updateClassList = useCallback ( async ( newTheme : ThemeName ) => {
31- const htmlElm = document . querySelector ( 'html' ) ;
32-
33- htmlElm ?. classList . add ( 'no-motion' ) ;
34-
35- await wait ( CLASSLIST_UPDATE_TIMEOUT ) ;
36-
37- if ( newTheme === 'dark' ) {
38- htmlElm ?. classList . remove ( 'light-theme' ) ;
39- htmlElm ?. classList . add ( 'dark-theme' ) ;
40- } else {
41- htmlElm ?. classList . remove ( 'dark-theme' ) ;
42- htmlElm ?. classList . add ( 'light-theme' ) ;
43- }
16+ export type ThemeProviderProps = {
17+ children : ReactNode ;
18+ } ;
4419
45- await wait ( CLASSLIST_UPDATE_TIMEOUT ) ;
20+ export const ThemeProvider = ( props : ThemeProviderProps ) => {
21+ const { children } = props ;
4622
47- htmlElm ?. classList . remove ( 'no-motion' ) ;
48- } , [ ] ) ;
23+ const [ cookieValue , setCookieValue ] = useCookieTheme ( ) ;
24+ const [ theme , setTheme ] = useState < ThemeName > ( ( cookieValue as ThemeName ) || getCurrentTheme ( ) ) ;
4925
50- const updateTheme = useCallback ( ( nextTheme : ThemeName ) => {
51- setName ( nextTheme ) ;
52- updateClassList ( nextTheme ) ;
53- setCookieValue ( nextTheme ) ;
54- } , [ ] ) ;
26+ const updateTheme = useCallback (
27+ ( nextTheme : ThemeName ) => {
28+ setCookieValue ( nextTheme ) ;
29+ switchTheme ( nextTheme ) ;
30+ } ,
31+ [ setTheme , setCookieValue ] ,
32+ ) ;
5533
56- // Sync classList
34+ // Sync classNames on load
5735 useEffect ( ( ) => {
58- updateClassList ( name ) ;
59- } , [ name ] ) ;
36+ switchTheme ( theme ) ;
37+ } , [ theme ] ) ;
6038
6139 const value = useMemo (
6240 ( ) => ( {
63- name,
41+ name : theme ,
6442 update : updateTheme ,
6543 } ) ,
66- [ name , updateTheme ] ,
44+ [ theme , updateTheme ] ,
6745 ) ;
6846
6947 return < ThemeContext . Provider value = { value } > { children } </ ThemeContext . Provider > ;
0 commit comments