import { useLocalStorage } from '@/hooks'; import { PropsWithChildren, createContext, useContext } from 'react'; type ThemeMode = 'light' | 'dark' | 'auto'; type ThemeOrientation = 'vertical' | 'horizontal'; type ThemeDirection = 'ltr' | 'rtl'; type ThemePresetColor = | 'default' | 'theme1' | 'theme2' | 'theme3' | 'theme4' | 'theme5' | 'theme6' | 'theme7' | 'theme8'; type ThemeFontFamily = | `'Inter', sans-serif` | `'Poppins', sans-serif` | `'Roboto', sans-serif` | `'Public Sans', sans-serif` | /** Any font family name as string */ string; type ThemeConfig = { /** * Default font family for the application. * @example * fontFamily: `'Inter', sans-serif` */ fontFamily: ThemeFontFamily; /** * Layout orientation: 'vertical' or 'horizontal'. * @example * themeOrientation: 'vertical' */ themeOrientation: ThemeOrientation; /** * Enables/disables mini mode for the drawer. * @example * miniDrawer: false */ miniDrawer: boolean; /** * If true, the main layout is wrapped in a centered container. * @example * container: true */ container: boolean; /** * Theme mode: 'light', 'dark', or 'auto'. * @example * mode: 'light' */ mode: ThemeMode; /** * Default theme color preset. * @example * presetColor: 'theme4' */ presetColor: ThemePresetColor; /** * Text direction: 'ltr' (left-to-right) or 'rtl' (right-to-left). * @example * themeDirection: 'ltr' */ themeDirection: ThemeDirection; /** * Default application path. * @example * appDefaultPath: '/dashboard' */ appDefaultPath: string; /** * Width of the side drawer in pixels. * @example * drawerWidth: 260 */ drawerWidth: number; /** * Maximum number of items shown horizontally in the menu. * @example * horizontalMaxItems: 6 */ horizontalMaxItems: number; /** * Base spacing for the layout (MUI units). * @example * spacing: 2 */ spacing: number; setFontFamily: (fontFamily: ThemeFontFamily) => void; setThemeOrientation: (themeOrientation: ThemeOrientation) => void; setMiniDrawer: (miniDrawer: boolean) => void; setContainer: (container: boolean) => void; setMode: (mode: ThemeMode) => void; setPresetColor: (presetColor: ThemePresetColor) => void; setThemeDirection: (themeDirection: ThemeDirection) => void; setAppDefaultPath: (appDefaultPath: string) => void; setDrawerWidth: (drawerWidth: number) => void; setHorizontalMaxItems: (horizontalMaxItems: number) => void; isVerticalLayout: (orientation: ThemeOrientation) => boolean; isHorizontalLayout: (orientation: ThemeOrientation) => boolean; }; type ThemeProvierProps = PropsWithChildren<{ initialConfig: ThemeConfig }>; function notImplemented(): void { throw new Error('Method must be implemented'); } const initialState: ThemeConfig = { fontFamily: `'Inter', sans-serif`, themeOrientation: 'vertical', miniDrawer: false, container: false, mode: 'light', presetColor: 'theme4', themeDirection: 'ltr', appDefaultPath: '/', drawerWidth: 260, horizontalMaxItems: 6, spacing: 2, setFontFamily: notImplemented, setThemeOrientation: notImplemented, setMiniDrawer: notImplemented, setContainer: notImplemented, setMode: notImplemented, setPresetColor: notImplemented, setThemeDirection: notImplemented, setAppDefaultPath: notImplemented, setDrawerWidth: notImplemented, setHorizontalMaxItems: notImplemented, isVerticalLayout: (_) => false, isHorizontalLayout: (_) => false }; function isVerticalLayout(layout: ThemeOrientation) { return layout === ('vertical' as ThemeOrientation); } function isHorizontalLayout(layout: ThemeOrientation) { return layout === ('horizontal' as ThemeOrientation); } const ThemeContext = createContext(initialState); function ThemeProvider({ initialConfig, children }: ThemeProvierProps): JSX.Element { const [config, setConfig] = useLocalStorage('theme-config', { ...initialState, ...initialConfig }); function setFontFamily(fontFamily: ThemeFontFamily) { setConfig((config: ThemeConfig) => ({ ...config, fontFamily })); } function setThemeOrientation(themeOrientation: ThemeOrientation) { setConfig((config: ThemeConfig) => ({ ...config, themeOrientation })); } function setMiniDrawer(miniDrawer: boolean) { setConfig((config: ThemeConfig) => ({ ...config, miniDrawer })); } function setContainer(container: boolean) { setConfig((config: ThemeConfig) => ({ ...config, container })); } function setMode(mode: ThemeMode) { setConfig((config: ThemeConfig) => ({ ...config, mode })); } function setPresetColor(presetColor: ThemePresetColor) { setConfig((config: ThemeConfig) => ({ ...config, presetColor })); } function setThemeDirection(themeDirection: ThemeDirection) { setConfig((config: ThemeConfig) => ({ ...config, themeDirection })); } function setAppDefaultPath(appDefaultPath: string) { setConfig((config: ThemeConfig) => ({ ...config, appDefaultPath })); } function setDrawerWidth(drawerWidth: number) { setConfig((config: ThemeConfig) => ({ ...config, drawerWidth })); } function setHorizontalMaxItems(horizontalMaxItems: number) { setConfig((config: ThemeConfig) => ({ ...config, horizontalMaxItems })); } return ( {children} ); } function useThemeContext(): ThemeConfig { return useContext(ThemeContext); } function useThemeConfig(): ThemeConfig { return useThemeContext(); } export type { ThemeConfig, ThemeDirection, ThemeFontFamily, ThemeMode, ThemeOrientation, ThemePresetColor }; export { ThemeContext, ThemeProvider, useThemeConfig, useThemeContext };