diff options
| author | kj_sh604 | 2026-03-15 16:19:35 -0400 |
|---|---|---|
| committer | kj_sh604 | 2026-03-15 16:19:35 -0400 |
| commit | bfc2cec7d43eb8eaa46dd3f91084932381257059 (patch) | |
| tree | 0857e3aac2cff922826d4871ff54536b26fad6fc /excalidraw-app/useHandleAppTheme.ts | |
| parent | 225db4a7805befe009fe055fc2ef5daedd6c04f9 (diff) | |
refactor: excalidraw-app/
Diffstat (limited to 'excalidraw-app/useHandleAppTheme.ts')
| -rw-r--r-- | excalidraw-app/useHandleAppTheme.ts | 69 |
1 files changed, 69 insertions, 0 deletions
diff --git a/excalidraw-app/useHandleAppTheme.ts b/excalidraw-app/useHandleAppTheme.ts new file mode 100644 index 0000000..e319611 --- /dev/null +++ b/excalidraw-app/useHandleAppTheme.ts @@ -0,0 +1,69 @@ +import { useEffect, useLayoutEffect, useState } from "react"; +import { THEME } from "@excalidraw/excalidraw"; +import { EVENT } from "@excalidraw/excalidraw/constants"; +import type { Theme } from "@excalidraw/excalidraw/element/types"; +import { CODES, KEYS } from "@excalidraw/excalidraw/keys"; +import { STORAGE_KEYS } from "./app_constants"; + +const getDarkThemeMediaQuery = (): MediaQueryList | undefined => + window.matchMedia?.("(prefers-color-scheme: dark)"); + +export const useHandleAppTheme = () => { + const [appTheme, setAppTheme] = useState<Theme | "system">(() => { + return ( + (localStorage.getItem(STORAGE_KEYS.LOCAL_STORAGE_THEME) as + | Theme + | "system" + | null) || THEME.LIGHT + ); + }); + const [editorTheme, setEditorTheme] = useState<Theme>(THEME.LIGHT); + + useEffect(() => { + const mediaQuery = getDarkThemeMediaQuery(); + + const handleChange = (e: MediaQueryListEvent) => { + setEditorTheme(e.matches ? THEME.DARK : THEME.LIGHT); + }; + + if (appTheme === "system") { + mediaQuery?.addEventListener("change", handleChange); + } + + const handleKeydown = (event: KeyboardEvent) => { + if ( + !event[KEYS.CTRL_OR_CMD] && + event.altKey && + event.shiftKey && + event.code === CODES.D + ) { + event.preventDefault(); + event.stopImmediatePropagation(); + setAppTheme(editorTheme === THEME.DARK ? THEME.LIGHT : THEME.DARK); + } + }; + + document.addEventListener(EVENT.KEYDOWN, handleKeydown, { capture: true }); + + return () => { + mediaQuery?.removeEventListener("change", handleChange); + document.removeEventListener(EVENT.KEYDOWN, handleKeydown, { + capture: true, + }); + }; + }, [appTheme, editorTheme, setAppTheme]); + + useLayoutEffect(() => { + localStorage.setItem(STORAGE_KEYS.LOCAL_STORAGE_THEME, appTheme); + + if (appTheme === "system") { + setEditorTheme( + getDarkThemeMediaQuery()?.matches ? THEME.DARK : THEME.LIGHT, + ); + } else { + setEditorTheme(appTheme); + } + }, [appTheme]); + + return { editorTheme, appTheme, setAppTheme }; +}; |
