summaryrefslogtreecommitdiffstats
path: root/excalidraw-app/useHandleAppTheme.ts
diff options
context:
space:
mode:
authorkj_sh6042026-03-15 16:19:35 -0400
committerkj_sh6042026-03-15 16:19:35 -0400
commitbfc2cec7d43eb8eaa46dd3f91084932381257059 (patch)
tree0857e3aac2cff922826d4871ff54536b26fad6fc /excalidraw-app/useHandleAppTheme.ts
parent225db4a7805befe009fe055fc2ef5daedd6c04f9 (diff)
refactor: excalidraw-app/
Diffstat (limited to 'excalidraw-app/useHandleAppTheme.ts')
-rw-r--r--excalidraw-app/useHandleAppTheme.ts69
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 };
+};