61 lines
1.9 KiB
TypeScript
61 lines
1.9 KiB
TypeScript
import React, { createContext, useContext, useMemo, useState } from "react";
|
|
import { ThemeProvider, createTheme, PaletteMode } from "@mui/material/styles";
|
|
import useMediaQuery from "@mui/material/useMediaQuery";
|
|
import { getTheme } from "./theme";
|
|
|
|
// --- You can import your own makePaletteColor() here if needed ---
|
|
|
|
type ThemeMode = "light" | "dark" | "system";
|
|
|
|
interface ThemeModeContextType {
|
|
mode: ThemeMode;
|
|
resolvedMode: PaletteMode; // actual value used
|
|
toggleMode: () => void;
|
|
setMode: (mode: ThemeMode) => void;
|
|
}
|
|
|
|
const ThemeModeContext = createContext<ThemeModeContextType | undefined>(undefined);
|
|
|
|
export const useThemeMode = () => {
|
|
const context = useContext(ThemeModeContext);
|
|
if (!context) {
|
|
throw new Error("useThemeMode must be used within ThemeModeProvider");
|
|
}
|
|
return context;
|
|
};
|
|
|
|
export const AppThemeProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => {
|
|
|
|
const savedTheme = localStorage.getItem("theme");
|
|
const isValidTheme = (theme: string | null): theme is ThemeMode =>
|
|
theme === "light" || theme === "dark" || theme === "system";
|
|
const [mode, setMode] = useState<ThemeMode>(isValidTheme(savedTheme) ? savedTheme : "system");
|
|
|
|
const prefersDark = useMediaQuery("(prefers-color-scheme: dark)");
|
|
const resolvedMode: PaletteMode = mode === "system" ? (prefersDark ? "dark" : "light") : mode;
|
|
|
|
const theme = useMemo(() => getTheme(resolvedMode), [resolvedMode]);
|
|
|
|
const toggleMode = () => {
|
|
setMode(prev =>
|
|
prev === "light" ? "dark" :
|
|
prev === "dark" ? "system" :
|
|
"light"
|
|
);
|
|
};
|
|
|
|
const contextValue = useMemo(() => ({
|
|
mode,
|
|
resolvedMode,
|
|
toggleMode,
|
|
setMode,
|
|
}), [mode, resolvedMode]);
|
|
|
|
return (
|
|
<ThemeModeContext.Provider value={contextValue}>
|
|
<ThemeProvider theme={theme}>
|
|
{children}
|
|
</ThemeProvider>
|
|
</ThemeModeContext.Provider>
|
|
);
|
|
};
|