import React, { createContext, useCallback, useEffect } from 'react'; import { Theme, ThemeProvider } from '@mui/material'; import useLocalStorage from 'use-local-storage'; import './index.scss'; import { TThemeKey, TThemeManager } from './types'; import { DEFAULT_THEME_MANAGER_VALUE } from './constant'; import useUserSystemTheme from './hooks/useUserSystemTheme'; // Менеджер темы выполняет задачу посредника между scss и material ui и обьеденяет их export const ThemeManagerContext = createContext( DEFAULT_THEME_MANAGER_VALUE, ); export default function ThemeManager({ children, materialThemes, useSystemTheme = true, useClientTheme = true, defaultTheme = 'light', defaultKey = 'app-theme-key', }: Props): JSX.Element { const userSystemKey = useUserSystemTheme(); // получаем цвет системы юзера const [userKey, setUserKey] = useLocalStorage( defaultKey, null, ); let key = defaultTheme; if (useClientTheme && userKey) key = userKey; else if (useSystemTheme && userSystemKey) key = userSystemKey; // Меняем тему и присваиваем класс элементу боди (не работает с SSR) const setTheme = useCallback((v: TThemeKey | null) => { setUserKey((prev) => { if (v === null) return v; document.body.classList.replace(prev ?? key, v); return v; }); }, []); useEffect(() => { document.body.classList.add(key); // Устанавливаем по умолчанию тему в боди }, []); const value = { setTheme, current: key, themes: Object.keys(materialThemes), }; return ( {children} ); } interface Props { children: React.ReactNode; defaultTheme?: TThemeKey;// Задать тему по умолчанию (по умолчанию light) defaultKey?: string; // Ключ для storage useSystemTheme?: boolean; // Установить системную тему (по умолчанию true) /* Установить тему, которую выбрал пользователь (по умолчанию true) имеет приоритет перед useSystemTheme */ useClientTheme?: boolean; // Обьект с темами где ключем является название, а значением является тема material materialThemes: { [key in TThemeKey]: Theme; }; }