Last active
February 8, 2023 17:26
-
-
Save luooooob/902b4bb4962c9affb1e2cce5084c48ee to your computer and use it in GitHub Desktop.
Revisions
-
luooooob revised this gist
Feb 8, 2023 . 1 changed file with 100 additions and 0 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,100 @@ /* eslint-disable react-hooks/rules-of-hooks */ import { createContext, ReactNode, useContext, useEffect, useMemo, useState } from "react" import type { Dispatch, FC } from "react" const LOCALSTORAGE_KEY = "diandiandian-user-perfers-color-scheme" type ColorScheme = string | null type ColorSchemeDispatch = Dispatch<ColorScheme> const useSysColorScheme = () => { if (typeof window === 'undefined') { return { sysColorScheme: null } } const avaliableSysColorScheme = ["dark", "light"] as const const mediasMap = { ["dark"]: window.matchMedia(`(prefers-color-scheme: dark`), ["light"]: window.matchMedia(`(prefers-color-scheme: light`) } satisfies Record<typeof avaliableSysColorScheme[number], MediaQueryList> const findSysColorScheme = (): ColorScheme => { return avaliableSysColorScheme.find(key => mediasMap[key].matches ) || null } const [sysColorScheme, setSysColorScheme] = useState(findSysColorScheme()) useEffect(() => { const onMediaChange = () => { const newColorScheme = findSysColorScheme() if (sysColorScheme !== newColorScheme) { setSysColorScheme(newColorScheme) } } const medias = avaliableSysColorScheme.map(key => mediasMap[key]) medias.forEach(media => media.addEventListener('change', onMediaChange)) return () => medias.forEach(media => media.removeEventListener('change', onMediaChange)) }) return { sysColorScheme } } const useUserColorScheme = () => { if (typeof window === 'undefined') { return { userColorScheme: null, setUserColorSchemeAndSave: () => { }, } } const [userColorScheme, setUserColorScheme] = useState<ColorScheme>( window.localStorage.getItem(LOCALSTORAGE_KEY) ) const setUserColorSchemeAndSave: ColorSchemeDispatch = (colorScheme: ColorScheme) => { setUserColorScheme(colorScheme) if(colorScheme) { window.localStorage.setItem(LOCALSTORAGE_KEY, colorScheme) } window.localStorage.removeItem(LOCALSTORAGE_KEY) } return { userColorScheme, setUserColorSchemeAndSave } } const ColorSchemeContext = createContext<ColorScheme>(null) const ColorSchemeDispatchContext = createContext<ColorSchemeDispatch | null>(null) type ColorSchemeProps = { children: ReactNode } export const ColorScheme:FC<ColorSchemeProps> = ({ children }) => { const { sysColorScheme } = useSysColorScheme() const { userColorScheme, setUserColorSchemeAndSave } = useUserColorScheme() const colorScheme = userColorScheme ?? sysColorScheme return ( <ColorSchemeContext.Provider value={colorScheme}> <ColorSchemeDispatchContext.Provider value={setUserColorSchemeAndSave}> {children} </ColorSchemeDispatchContext.Provider> </ColorSchemeContext.Provider> ) } export const useColorScheme = () => { const colorScheme = useContext(ColorSchemeContext) const setColorScheme = useContext(ColorSchemeDispatchContext) if (!setColorScheme) { throw new Error("") } return { colorScheme, setColorScheme } } -
luooooob created this gist
Aug 15, 2021 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,25 @@ const systemColorSchemeRange = ['light', 'dark'] as const const getMediaByColorScheme = (colorScheme: string): MediaQueryList => { return matchMedia(`(prefers-color-scheme: ${colorScheme})`) } export const getSystemColorScheme = (): (typeof systemColorSchemeRange)[number] | null => { return systemColorSchemeRange.find(colorScheme => getMediaByColorScheme(colorScheme).matches) || null } export const getSystemColorSchemeMedias = (): MediaQueryList[] => { return systemColorSchemeRange.map(colorScheme => getMediaByColorScheme(colorScheme)) } export const getColorSchemeFromLocalStorage = (localStorageKey: string): string | null => { return localStorage.getItem(localStorageKey) } export const setColorSchemeToLocalStorage = (localStorageKey: string, colorScheme: string): void => { colorScheme ? localStorage.setItem(localStorageKey, colorScheme) : localStorage.removeItem(localStorageKey) } This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,39 @@ import { useEffect, useState } from "react" import { getSystemColorScheme, getSystemColorSchemeMedias, getColorSchemeFromLocalStorage, setColorSchemeToLocalStorage } from "../tools/colorScheme" export const useSystemPrefersColorScheme = () => { const initialColorScheme = getSystemColorScheme() const [systemPrefersColorScheme, setSystemPrefersColorScheme] = useState(initialColorScheme) const onMediaChange = () => { const newColorScheme = getSystemColorScheme() if (systemPrefersColorScheme !== newColorScheme) { setSystemPrefersColorScheme(newColorScheme) } } useEffect(() => { const medias = getSystemColorSchemeMedias() medias.forEach(media => media.addEventListener('change', onMediaChange)) return () => medias.forEach(media => media.removeEventListener('change', onMediaChange)) }) return [systemPrefersColorScheme] } export const useUserPrefersColorScheme = (localStorageKey?: string) => { const initialColorScheme = localStorageKey ? getColorSchemeFromLocalStorage(localStorageKey) : null const [userPrefersColorScheme, _setUserPrefersColorScheme] = useState(initialColorScheme) const setUserPrefersColorScheme = (coloeScheme: string) => { _setUserPrefersColorScheme(coloeScheme) localStorageKey && setColorSchemeToLocalStorage(localStorageKey, coloeScheme) } return [userPrefersColorScheme, setUserPrefersColorScheme] } This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,13 @@ import { getSystemColorScheme, getColorSchemeFromLocalStorage } from "./tools/colorScheme" const backgroundColorScheme: string = getSystemColorScheme() || getColorSchemeFromLocalStorage('user-prefers-background-color-scheme') || 'light' const themeColorScheme: string = getColorSchemeFromLocalStorage('user-prefers-theme-color-scheme') || 'jiaran' document.documentElement.setAttribute('data-background-color-scheme', backgroundColorScheme) document.documentElement.setAttribute('data-theme-color-scheme', themeColorScheme)