import React, { useContext, useMemo } from 'react'; import merge from 'lodash/merge'; import { defaultTheme, Theme } from './utils/theme'; export type DeepPartial = { [P in keyof T]?: DeepPartial; }; export type ThemeProviderInputValue = { mergedStyle?: Theme; style?: DeepPartial; }; export type MergedThemesParams = { style?: DeepPartial; theme?: Theme; }; export const mergeThemes = (params: MergedThemesParams) => { const { style, theme } = params; const finalTheme = ( !theme || Object.keys(theme).length === 0 ? JSON.parse(JSON.stringify(defaultTheme)) : JSON.parse(JSON.stringify(theme)) ) as Theme; if (style) { merge(finalTheme, style); } return finalTheme; }; export const ThemeContext = React.createContext({} as Theme); export const ThemeProvider: React.FC = (props) => { const { children, mergedStyle, style } = props; const { theme } = useTheme(); const modifiedTheme = useMemo(() => { if (mergedStyle) { return mergedStyle; } return mergeThemes({ style, theme }); }, [mergedStyle, style, theme]); return {children}; }; export const useTheme = () => { const theme = useContext(ThemeContext); return { theme }; };