diff --git a/docs/api/create-styles.en-US.md b/docs/api/create-styles.en-US.md index 69e3d2c9..978770bf 100644 --- a/docs/api/create-styles.en-US.md +++ b/docs/api/create-styles.en-US.md @@ -192,19 +192,25 @@ Type: `string` The prefix marked on the ThemeProvider. By using this parameter, you can flexibly override the antd prefix. ```ts -const useStyles = createStyles(({ css, prefixCls }) => { - return { - primary: css` - .${prefixCls}-btn { - border: 12px; - } - `, - }; -}); +const useStyles = createStyles(({ css, prefixCls, iconPrefixCls }) => ({ + button: css` + &.${prefixCls}-btn { + background: lightsteelblue; + border: none; + color: royalblue; + } + + .${iconPrefixCls} { + color: darkblue; + } + `, +})); ``` The above style code can accurately override regardless of the value of the prefixCls wrapped by the outer ThemeProvider. + + ## ClassNameGeneratorOption The second parameter of `createStyles` can be used to control the generated className. diff --git a/docs/api/create-styles.zh-CN.md b/docs/api/create-styles.zh-CN.md index 758b7253..af91fad3 100644 --- a/docs/api/create-styles.zh-CN.md +++ b/docs/api/create-styles.zh-CN.md @@ -185,25 +185,31 @@ declare module 'antd-style' { 判断亮暗色主题的语法糖,实现上等价于 `appearance === 'dark'`,直接使用 isDarkMode 可以降低外观的判断成本。 -### prefixCls +### prefixCls 与 iconPrefixCls 类型:`string` -在 ThemeProvider 上标记的 prefixCls,利用该参数,可以实现灵活的 antd 前缀覆盖。 +在 ThemeProvider 上标记的 prefixCls/iconPrefixCls,利用该参数,可以实现灵活的 antd 前缀覆盖。 ```ts -const useStyles = createStyles(({ css, prefixCls }) => { - return { - primary: css` - .${prefixCls}-btn { - border: 12px; - } - `, - }; -}); +const useStyles = createStyles(({ css, prefixCls, iconPrefixCls }) => ({ + button: css` + &.${prefixCls}-btn { + background: lightsteelblue; + border: none; + color: royalblue; + } + + .${iconPrefixCls} { + color: darkblue; + } + `, +})); ``` -上述样式代码,无论外层包裹的 ThemeProvider prefixCls 改成什么值,均可准确覆盖到。 +上述样式代码,无论是包裹的 `ThemeProvider` / `ConfigProvider` prefixCls 改成什么值,均可准确覆盖到。 + + ## ClassNameGeneratorOption diff --git a/docs/demos/api/createStyles/with-antd-cp.tsx b/docs/demos/api/createStyles/with-antd-cp.tsx new file mode 100644 index 00000000..5c79d55a --- /dev/null +++ b/docs/demos/api/createStyles/with-antd-cp.tsx @@ -0,0 +1,32 @@ +import { SmileOutlined } from '@ant-design/icons'; +import { Button, ConfigProvider } from 'antd'; +import { createStyles } from 'antd-style'; + +const useStyles = createStyles(({ css, prefixCls, iconPrefixCls }) => ({ + button: css` + &.${prefixCls}-btn { + background: lightsteelblue; + border: none; + color: royalblue; + } + + .${iconPrefixCls} { + color: darkblue; + } + `, +})); + +const App = () => { + const { styles } = useStyles(); + + return ( + + ); +}; +export default () => ( + + + +); diff --git a/package.json b/package.json index 0ebcb9f7..a48159e3 100644 --- a/package.json +++ b/package.json @@ -96,7 +96,7 @@ "@types/react-dom": "^18", "@types/testing-library__jest-dom": "^5", "@umijs/lint": "^4", - "@vitest/coverage-v8": "latest", + "@vitest/coverage-v8": "0.34.6", "antd": "^5", "babel-plugin-antd-style": "^1", "chalk": "^4", @@ -133,7 +133,7 @@ "ts-node": "^10", "typescript": "^5", "vite": "^4.5.0", - "vitest": "latest", + "vitest": "0.34.6", "zustand": "^4" }, "peerDependencies": { diff --git a/src/factories/createStyles/index.ts b/src/factories/createStyles/index.ts index baba29ad..bc178f47 100644 --- a/src/factories/createStyles/index.ts +++ b/src/factories/createStyles/index.ts @@ -57,7 +57,7 @@ export const createStylesFactory = // 函数场景 if (styleOrGetStyle instanceof Function) { - const { stylish, appearance, isDarkMode, prefixCls, ...token } = theme; + const { stylish, appearance, isDarkMode, prefixCls, iconPrefixCls, ...token } = theme; // 创建响应式断点选择器的工具函数 // @ts-ignore @@ -73,6 +73,7 @@ export const createStylesFactory = appearance, isDarkMode, prefixCls, + iconPrefixCls, // 工具函数们 cx, css: serializeCSS, @@ -121,8 +122,8 @@ export const createStylesFactory = }, [props, theme]); return useMemo(() => { - const { prefixCls, ...res } = theme; - return { styles, cx, theme: res, prefixCls }; + const { prefixCls, iconPrefixCls, ...res } = theme; + return { styles, cx, theme: res, prefixCls, iconPrefixCls }; }, [styles, theme]); }; }; diff --git a/src/factories/createStyles/types.ts b/src/factories/createStyles/types.ts index 097031ff..1e3d380f 100644 --- a/src/factories/createStyles/types.ts +++ b/src/factories/createStyles/types.ts @@ -31,6 +31,7 @@ export interface CreateStylesUtils extends CommonStyleUtils { * @default ant */ prefixCls: string; + iconPrefixCls: string; } /** @@ -39,6 +40,7 @@ export interface CreateStylesUtils extends CommonStyleUtils { export interface ReturnStyles extends Pick { styles: ReturnStyleToUse; theme: Omit; + iconPrefixCls: string; prefixCls: string; } diff --git a/src/factories/createThemeProvider/TokenContainer.tsx b/src/factories/createThemeProvider/TokenContainer.tsx index 5fec2e92..4f8d329a 100644 --- a/src/factories/createThemeProvider/TokenContainer.tsx +++ b/src/factories/createThemeProvider/TokenContainer.tsx @@ -20,7 +20,7 @@ const TokenContainer: (props: TokenContainerProps) => ReactElement | customToken: customTokenOrFn, defaultCustomToken: defaultCustomTokenFn, customStylish: stylishOrGetStylish, - prefixCls = 'ant', + prefixCls, StyledThemeProvider, }) => { const themeState = useThemeMode(); diff --git a/src/factories/createThemeProvider/index.tsx b/src/factories/createThemeProvider/index.tsx index c5890f3f..fbfced13 100644 --- a/src/factories/createThemeProvider/index.tsx +++ b/src/factories/createThemeProvider/index.tsx @@ -63,6 +63,7 @@ export const createThemeProvider = ( onThemeModeChange, styled, }) => { + // 从上一层的 Context 中获取上下文信息,以实现嵌套继承的效果 const { prefixCls: defaultPrefixCls, StyledThemeContext, diff --git a/src/factories/createUseTheme.ts b/src/factories/createUseTheme.ts index 674ad215..e276bb54 100644 --- a/src/factories/createUseTheme.ts +++ b/src/factories/createUseTheme.ts @@ -4,6 +4,7 @@ import { Context, useContext, useMemo } from 'react'; import { DEFAULT_THEME_CONTEXT } from '@/functions/setupStyled'; import { useAntdTheme } from '@/hooks/useAntdTheme'; import { useThemeMode } from '@/hooks/useThemeMode'; +import { ConfigProvider } from 'antd'; interface CreateUseThemeOptions { StyleEngineContext: Context; @@ -11,7 +12,11 @@ interface CreateUseThemeOptions { export const createUseTheme = (options: CreateUseThemeOptions) => (): Theme => { const { StyleEngineContext } = options; - const { StyledThemeContext, CustomThemeContext, prefixCls } = useContext(StyleEngineContext); + const { + StyledThemeContext, + CustomThemeContext, + prefixCls: outPrefixCls, + } = useContext(StyleEngineContext); const antdTheme = useAntdTheme(); const themeState = useThemeMode(); @@ -19,14 +24,20 @@ export const createUseTheme = (options: CreateUseThemeOptions) => (): Theme => { const defaultCustomTheme = useContext(CustomThemeContext); const styledTheme = useContext(StyledThemeContext ?? DEFAULT_THEME_CONTEXT) || {}; + const { iconPrefixCls, getPrefixCls } = useContext(ConfigProvider.ConfigContext); + + const antdPrefixCls = getPrefixCls(); + const prefixCls = outPrefixCls ?? antdPrefixCls; + const initTheme = useMemo( () => ({ ...antdTheme, ...themeState, ...defaultCustomTheme, - prefixCls: prefixCls || 'ant', + prefixCls, + iconPrefixCls, }), - [antdTheme, themeState, prefixCls, defaultCustomTheme], + [antdTheme, themeState, defaultCustomTheme, prefixCls, iconPrefixCls], ); // 如果是个空值,说明没有套 Provider,返回 antdTheme 的默认值 @@ -34,5 +45,5 @@ export const createUseTheme = (options: CreateUseThemeOptions) => (): Theme => { return initTheme; } - return styledTheme as Theme; + return { ...styledTheme, prefixCls, iconPrefixCls } as Theme; }; diff --git a/src/functions/createInstance.ts b/src/functions/createInstance.ts index 6e991ab3..721ee7f9 100644 --- a/src/functions/createInstance.ts +++ b/src/functions/createInstance.ts @@ -34,6 +34,7 @@ export interface CreateOptions { * 默认的组件 prefixCls */ prefixCls?: string; + iconPrefixCls?: string; /** * 是否开启急速模式 * @@ -87,6 +88,7 @@ export const createInstance = (options: CreateOptions) => { CustomThemeContext, StyledThemeContext: styledThemeContext, prefixCls: internalOptions?.prefixCls, + iconPrefixCls: internalOptions?.iconPrefixCls, }); const useTheme = createUseTheme({ StyleEngineContext }); diff --git a/src/types/styled.ts b/src/types/styled.ts index 54f95021..8081f77b 100644 --- a/src/types/styled.ts +++ b/src/types/styled.ts @@ -35,4 +35,5 @@ export interface StyleEngine { * @description 当前组件的 CSS 类名前缀 */ prefixCls?: string; + iconPrefixCls?: string; } diff --git a/src/types/theme.ts b/src/types/theme.ts index 8b1005bd..79d8b4de 100644 --- a/src/types/theme.ts +++ b/src/types/theme.ts @@ -1,4 +1,4 @@ -import { ThemeConfig, MappingAlgorithm } from 'antd'; +import { MappingAlgorithm, ThemeConfig } from 'antd'; import { AliasToken } from 'antd/es/theme/interface'; import { BrowserPrefers, ThemeAppearance, ThemeMode } from './appearance'; @@ -76,4 +76,5 @@ export interface Theme extends FullToken, ThemeContextState { * antd 组件的 prefixCls */ prefixCls: string; + iconPrefixCls: string; } diff --git a/tests/functions/__snapshots__/createStyles.test.tsx.snap b/tests/functions/__snapshots__/createStyles.test.tsx.snap index 1950ae86..f633955c 100644 --- a/tests/functions/__snapshots__/createStyles.test.tsx.snap +++ b/tests/functions/__snapshots__/createStyles.test.tsx.snap @@ -13,6 +13,50 @@ exports[`createStyles > styles 对象的使用 > createStyleFn 通过函数方 `; +exports[`createStyles > styles 对象的使用 > createStyleFn 通过函数方式可以拿到 token 等信息 > 可以获取 prefixCls 与 iconPrefixCls 1`] = ` +.emotion-0.cp-btn { + background: lightsteelblue; + border: none; + color: royalblue; +} + +.emotion-0 .cpicon { + color: darkblue; +} + + +`; + exports[`createStyles > styles 对象的使用 > createStyleFn 通过函数方式可以拿到 token 等信息 > 字符串模板的对象模式用法 1`] = ` .emotion-0 { background-color: #f5f5f5; diff --git a/tests/functions/createStyles.test.tsx b/tests/functions/createStyles.test.tsx index 507058ae..9cfcf264 100644 --- a/tests/functions/createStyles.test.tsx +++ b/tests/functions/createStyles.test.tsx @@ -1,5 +1,7 @@ +import { SmileOutlined } from '@ant-design/icons'; import { render } from '@testing-library/react'; -import { createStyles, css, GetCustomToken, ThemeProvider } from 'antd-style'; +import { Button, ConfigProvider } from 'antd'; +import { GetCustomToken, ThemeProvider, createStyles, css } from 'antd-style'; import { FC, PropsWithChildren } from 'react'; describe('createStyles', () => { @@ -51,6 +53,43 @@ describe('createStyles', () => { expect(container.firstChild).toMatchSnapshot(); expect(container.firstChild).toHaveStyle({ backgroundColor: '#fff' }); }); + + it('可以获取 prefixCls 与 iconPrefixCls', () => { + const useStyles = createStyles(({ css, prefixCls, iconPrefixCls }) => { + return { + button: css` + &.${prefixCls}-btn { + background: lightsteelblue; + border: none; + color: royalblue; + } + + .${iconPrefixCls} { + color: darkblue; + } + `, + }; + }); + + const App = () => { + const { styles } = useStyles(); + + return ( + + ); + }; + const wrapper = ({ children }: PropsWithChildren) => ( + + {children} + + ); + + const { container } = render(, { wrapper }); + + expect(container.firstChild).toMatchSnapshot(); + }); }); describe('styleObject 方法', () => {