import React, { useMemo, useState, useCallback } from 'react'; import type { FC, PropsWithChildren } from 'react'; import { extendTheme, ChakraProvider, useColorMode, theme as baseTheme, type ThemeConfig, type Colors, type Theme, type StyleFunctionProps } from '@chakra-ui/react'; import { ThemeProvider } from '../../hooks/useTheme'; import { isObject } from '../../factory/tools'; import markdown from './markdown'; export { baseTheme }; export type DocProviderProps = { /** * @description custom or use inner color scheme of chakra * @default baseTheme.colors.purple */ brand?: Colors; /** * @description total control of chakra theme config */ config?: Partial; }; const DocProvider: FC> = ({ children, config, brand = baseTheme.colors.purple }) => { const { colorMode } = useColorMode(); const [themeBrand, setThemeBrand] = useState(brand); const theme = useMemo(() => { return extendTheme({ initialColorMode: colorMode ?? 'system', useSystemColorMode: false, styles: { ...baseTheme.styles, ...(config?.styles ?? {}), global: (props: StyleFunctionProps) => ({ ...(baseTheme.styles.global ?? {}), ...(config?.styles?.global ?? {}), body: { p: 0 }, ...markdown(props) }) }, ...(config ?? {}), fonts: Object.entries(baseTheme.fonts).reduce( (fonts, [key, value]) => ({ ...fonts, [key]: 'Inter Variable, ' + (config?.fonts?.[key as keyof typeof baseTheme.fonts] ?? value) }), baseTheme.fonts ), colors: { brand: themeBrand, ...(config?.colors ?? {}) }, space: { ...baseTheme.space, ...(config?.space ?? {}), 18: '4.5rem' }, sizes: { ...baseTheme.sizes, ...(config?.sizes ?? {}), 18: '4.5rem', screenW: '100vw', screenH: '100vh', container: { ...baseTheme.sizes.container, ...(config?.sizes?.container ?? {}), xxl: '1392px' } }, breakpoints: { ...baseTheme.breakpoints, ...(config?.breakpoints ?? {}), xxl: '1392px' } } as ThemeConfig); }, [config, colorMode, themeBrand]); const changeBrand = useCallback( (manualBrand: Colors | string) => { if (isObject(manualBrand)) { setThemeBrand(manualBrand); } if (typeof manualBrand === 'string' && manualBrand in theme.colors) { // @ts-ignore setThemeBrand(theme.colors[manualBrand]); } }, [config] ); return ( {children} ); }; export default DocProvider;