diff --git a/src/factories/createStyledThemeProvider.tsx b/src/factories/createStyledThemeProvider.tsx
new file mode 100644
index 00000000..18741d2a
--- /dev/null
+++ b/src/factories/createStyledThemeProvider.tsx
@@ -0,0 +1,15 @@
+import { StyledConfig, StyledThemeProvider } from '@/types';
+
+/**
+ * 创建一个 styled api 的 ThemeProvider
+ * 如果用户有设定 ThemeProvider,就使用用户的,否则使用 ThemeContext.Provider
+ * @param styledConfig
+ */
+export const createStyledThemeProvider = (styledConfig: StyledConfig): StyledThemeProvider => {
+ if (styledConfig.ThemeProvider) return styledConfig.ThemeProvider;
+
+ const { ThemeContext } = styledConfig;
+ return (props) => (
+ {props.children}
+ );
+};
diff --git a/src/factories/createThemeProvider/index.tsx b/src/factories/createThemeProvider/index.tsx
index 364aa553..afd91af7 100644
--- a/src/factories/createThemeProvider/index.tsx
+++ b/src/factories/createThemeProvider/index.tsx
@@ -1,9 +1,10 @@
import { Context, memo, ReactElement } from 'react';
import { createUseTheme } from '@/factories/createUseTheme';
-import { DEFAULT_THEME_PROVIDER, DEFAULT_USE_THEME } from '@/functions/setupStyled';
+import { DEFAULT_THEME_CONTEXT, DEFAULT_THEME_PROVIDER } from '@/functions/setupStyled';
import { StyledConfig } from '@/types';
+import { createStyledThemeProvider } from '@/factories/createStyledThemeProvider';
import AntdProvider from './AntdProvider';
import ThemeSwitcher from './ThemeSwitcher';
import TokenContainer from './TokenContainer';
@@ -20,8 +21,13 @@ interface CreateThemeProviderOptions {
export const createThemeProvider = (
option: CreateThemeProviderOptions,
-): ((props: ThemeProviderProps) => ReactElement | null) =>
- memo(
+): ((props: ThemeProviderProps) => ReactElement | null) => {
+ // 如果有全局配置 styledConfig,那么 ThemeProvider
+ const DefaultStyledThemeProvider = option.styledConfig
+ ? createStyledThemeProvider(option.styledConfig)
+ : undefined;
+
+ return memo(
({
children,
@@ -38,36 +44,44 @@ export const createThemeProvider = (
onAppearanceChange,
themeMode,
styled,
- }) => (
-
- {
+ const useTheme = createUseTheme({
+ prefixCls: prefixCls || option.prefixCls,
+ styledThemeContext:
+ styled?.ThemeContext || option.styledConfig?.ThemeContext || DEFAULT_THEME_CONTEXT,
+ CustomThemeContext: option.CustomThemeContext,
+ });
+
+ const StyledThemeProvider = styled
+ ? createStyledThemeProvider(styled)
+ : DefaultStyledThemeProvider || DEFAULT_THEME_PROVIDER;
+
+ return (
+
-
- {children}
-
-
-
- ),
+
+ {children}
+
+
+
+ );
+ },
);
+};
diff --git a/src/factories/createUseTheme.ts b/src/factories/createUseTheme.ts
index a9caffb9..d6ff3ebd 100644
--- a/src/factories/createUseTheme.ts
+++ b/src/factories/createUseTheme.ts
@@ -1,24 +1,24 @@
-import { Theme, UseTheme } from '@/types';
+import { Theme } from '@/types';
import { Context, useContext, useMemo } from 'react';
-import { DEFAULT_USE_THEME } from '@/functions/setupStyled';
+import { DEFAULT_THEME_CONTEXT } from '@/functions/setupStyled';
import { useAntdTheme } from '@/hooks/useAntdTheme';
import { useThemeMode } from '@/hooks/useThemeMode';
interface CreateUseThemeOptions {
prefixCls?: string;
CustomThemeContext: Context;
- styledUseTheme?: UseTheme;
+ styledThemeContext?: Context;
}
export const createUseTheme = (options: CreateUseThemeOptions) => (): Theme => {
- const { prefixCls, styledUseTheme, CustomThemeContext } = options;
+ const { prefixCls, styledThemeContext, CustomThemeContext } = options;
const antdTheme = useAntdTheme();
const themeState = useThemeMode();
const defaultCustomTheme = useContext(CustomThemeContext);
- const styledTheme = styledUseTheme ? styledUseTheme() : DEFAULT_USE_THEME() || {};
+ const styledTheme = useContext(styledThemeContext ?? DEFAULT_THEME_CONTEXT) || {};
const initTheme = useMemo(
() => ({
diff --git a/src/functions/createInstance.ts b/src/functions/createInstance.ts
index 2c09e381..466a929c 100644
--- a/src/functions/createInstance.ts
+++ b/src/functions/createInstance.ts
@@ -10,7 +10,7 @@ import { createStylesFactory } from '@/factories/createStyles';
import { createThemeProvider, ThemeProviderProps } from '@/factories/createThemeProvider';
import { createUseTheme } from '@/factories/createUseTheme';
-import { HashPriority, StyledConfig, StyleManager, Theme } from '@/types';
+import { HashPriority, StyledConfig, StyleManager } from '@/types';
// 为 SSR 添加一个全局的 cacheManager,用于统一抽取 ssr 样式
declare global {
@@ -70,12 +70,12 @@ export const createInstance = (options: CreateOptions) => {
(options.customToken ? options.customToken : {}) as T,
);
- const styledUseTheme = options.styled?.useTheme as () => Theme;
+ const styledThemeContext = options.styled?.ThemeContext;
const useTheme = createUseTheme({
prefixCls: options?.prefixCls,
CustomThemeContext,
- styledUseTheme,
+ styledThemeContext,
});
const createStyles = createStylesFactory({
diff --git a/src/functions/setupStyled.ts b/src/functions/setupStyled.ts
index d932baea..3ea73dbc 100644
--- a/src/functions/setupStyled.ts
+++ b/src/functions/setupStyled.ts
@@ -1,15 +1,17 @@
-import { ThemeProvider, useTheme } from '@emotion/react';
+import { ThemeContext, ThemeProvider } from '@emotion/react';
+import { Context } from 'react';
+import { createStyledThemeProvider } from '@/factories/createStyledThemeProvider';
import { StyledConfig, StyledThemeProvider, Theme } from '@/types';
export let DEFAULT_THEME_PROVIDER = ThemeProvider as StyledThemeProvider;
-export let DEFAULT_USE_THEME = useTheme as () => Theme;
+export let DEFAULT_THEME_CONTEXT = ThemeContext as Context;
export const setupStyled = (config: StyledConfig) => {
- if (config?.ThemeProvider) {
- DEFAULT_THEME_PROVIDER = config.ThemeProvider;
- }
- if (config.useTheme) {
- DEFAULT_USE_THEME = config.useTheme;
+ if (!config.ThemeContext) {
+ throw 'ThemeContext is required. Please check your config.';
}
+
+ DEFAULT_THEME_CONTEXT = config.ThemeContext;
+ DEFAULT_THEME_PROVIDER = createStyledThemeProvider(config);
};
diff --git a/src/types/styled.ts b/src/types/styled.ts
index 2955d182..09df11ab 100644
--- a/src/types/styled.ts
+++ b/src/types/styled.ts
@@ -1,9 +1,16 @@
-import { Theme } from 'antd-style/src';
-import { FC, ReactNode } from 'react';
+import { Context, FC, ReactNode } from 'react';
+import { Theme } from './theme';
export interface StyledConfig {
+ /**
+ * styled 对象所对应的 ThemeContext
+ * @requires
+ */
+ ThemeContext: Context;
+ /**
+ * 可以注入相应 styled 方法的 ThemeProvider,或其他自己定义的ThemeProvider
+ */
ThemeProvider?: StyledThemeProvider;
- useTheme?: () => any;
}
export type StyledThemeProvider = FC<{ theme: Theme; children: ReactNode }>;
diff --git a/tests/functions/styled.test.tsx b/tests/functions/styled.test.tsx
index ad288100..afdcfa11 100644
--- a/tests/functions/styled.test.tsx
+++ b/tests/functions/styled.test.tsx
@@ -1,6 +1,12 @@
import styled from '@emotion/styled';
import { render } from '@testing-library/react';
-import { ThemeProvider } from 'antd-style';
+import { Theme as AntdStyleTheme, ThemeProvider } from 'antd-style';
+
+// 为 emotion 的 styled 注入 antd-style 的主题类型
+declare module '@emotion/react' {
+ // eslint-disable-next-line @typescript-eslint/no-empty-interface
+ interface Theme extends AntdStyleTheme {}
+}
describe('styled', () => {
it('类型定义正常', () => {