Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 | 3x 6x 6x 6x 4x 3x 3x 2x 3x 3x 3x 1x 6x 5x 6x 3x 3x | import { useEffect, useState } from 'react';
import { useLocalStorage } from './use-storage';
export function createThemeHook<T extends string[]>(options: createThemeHook.Options<T>) {
const hook = () => {
const [mode, setMode] = useLocalStorage<T[number] | 'auto'>('theme', 'auto');
const [theme, setTheme] = useState<T[number]>(createThemeHook.getTheme(mode, options));
useEffect(() => {
if (mode === 'auto') {
const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
const listener = (event: MediaQueryListEvent) => {
setTheme(event.matches ? options.dark : options.light);
};
mediaQuery.addEventListener('change', listener);
return () => {
mediaQuery.removeEventListener('change', listener);
};
} else {
setTheme(mode);
}
}, [mode, setTheme]);
useEffect(() => {
document.body.setAttribute('data-theme', theme);
}, [theme]);
return [mode, setMode, theme] as const;
};
hook.$modes = 'auto' as T[number] | 'auto';
return hook;
}
/* c8 ignore start */
export namespace createThemeHook {
/* c8 ignore end */
export type Options<T extends string[]> = {
/**
* A list of the available themes.
*/
themes: T;
/**
* This theme will be used when light mode is detected.
*/
light: T[number];
/**
* This theme will be used when dark mode is detected.
*/
dark: T[number];
};
export function getTheme<T extends string[]>(mode: T[number] | 'auto', options: Options<T>): T[number] {
if (mode === 'auto') {
return window.matchMedia('(prefers-color-scheme: dark)').matches ? options.dark : options.light;
}
return mode;
}
}
|