import { ConfigProvider as OldConfigProvider } from 'antd'; import { ConfigContext, ConfigProviderProps } from 'antd/lib/config-provider'; import { Theme } from 'antd/lib/config-provider/context'; import SizeContext from 'antd/lib/config-provider/SizeContext'; import React, { useEffect } from 'react'; import themeSwitcher, { SwitchConfig } from './utils/themeSwitcher'; import dark from './theme/dark'; import light from './theme/light'; type ThemeType = 'dark' | 'light'; interface ConfigProviderExtraProps { theme?: ThemeType; themeSrc?: { dark?: string; light?: string }; } type setGlobalConfig = ({ prefixCls, iconPrefixCls, theme, }: Pick & { theme?: Theme | undefined; }) => void; const ConfigProvider: React.FC< ConfigProviderProps & ConfigProviderExtraProps > & { ConfigContext: typeof ConfigContext; SizeContext: typeof SizeContext; config: setGlobalConfig; switchTheme: (config: SwitchConfig) => void; onThemeChange: ( themeFn: (theme, themeName: ThemeType) => void, ) => MutationObserver; getTheme: () => [any, string]; } = (props) => { const { themeSrc = {}, theme } = props; const { dark = `https://btri-dev.midea.com/btri-ui/dark.css`, light = `https://btri-dev.midea.com/btri-ui/light.css`, } = themeSrc; const themeMap = { dark, light, }; const themeConfig = { themeMap, }; const { switcher } = themeSwitcher(themeConfig); useEffect(() => { theme && switcher({ theme, }); }, [theme]); return {props.children}; }; ConfigProvider.ConfigContext = OldConfigProvider.ConfigContext; ConfigProvider.SizeContext = OldConfigProvider.SizeContext; ConfigProvider.config = OldConfigProvider.config; ConfigProvider.switchTheme = ( config: SwitchConfig & { themeSrc?: { dark?: string; light?: string } }, ) => { const { themeSrc = {} } = config; const { dark = `https://btri-dev.midea.com/btri-ui/dark.css`, light = `https://btri-dev.midea.com/btri-ui/light.css`, } = themeSrc; const themeMap = { dark, light, }; const themeConfig = { themeMap, }; const { switcher } = themeSwitcher(themeConfig); const styleElement = document.getElementById('theme-style'); const curTheme = styleElement?.className; // 如果没有指定主题,并且当前已经有主题了,不做处理 if (!config.theme && curTheme) { return; } switcher({ ...config, theme: config.theme || curTheme || 'light' }); }; ConfigProvider.onThemeChange = (themeFn) => { const styleElement = document.getElementById('theme-style'); const modes = { dark: dark, light: light, }; const callThemeFn = (themeName: ThemeType) => { const themeObj = modes[themeName]; const resTheme: any = {}; Object.keys(themeObj)?.forEach((key) => { let value: string = themeObj[key]; // 递归遍历 while (value.match(/@/g)) { value = value.replace(/(@)([\w|-]*)(,?.*)/g, (match, p1, p2, p3) => { return `${themeObj[p1 + p2]}${p3}`; }); } resTheme[key] = value; }); themeFn(resTheme, themeName); }; if (!styleElement) { const style = document.createElement('link'); style.type = 'text/css'; style.rel = 'stylesheet'; style.id = 'theme-style'; document.body.append(style); } if (styleElement?.className) { callThemeFn(styleElement.className as ThemeType); } const observer = new MutationObserver((mutationsList) => { // @ts-ignore const themeName = mutationsList[0].target.className; callThemeFn(themeName); }); observer.observe(document.getElementById('theme-style'), { attributes: true, attributeFilter: ['href'], }); return observer; }; ConfigProvider.getTheme = () => { const styleElement = document.getElementById('theme-style'); const themeName = styleElement?.className; const modes = { dark: dark, light: light, }; return [modes[themeName] || {}, themeName]; }; export { ConfigProvider };