diff --git a/package.json b/package.json index 864af24..d53e5dc 100644 --- a/package.json +++ b/package.json @@ -57,7 +57,7 @@ "typescript": "^5.1.6" }, "dependencies": { - "@ant-design/cssinjs": "^2.0.1", + "@ant-design/cssinjs": "^2.1.0", "@babel/runtime": "^7.23.2", "@rc-component/util": "^1.4.0" }, @@ -65,4 +65,4 @@ "react": ">=18", "react-dom": ">=18" } -} +} \ No newline at end of file diff --git a/src/util/genStyleUtils.ts b/src/util/genStyleUtils.ts index 578c2bd..06df8e2 100644 --- a/src/util/genStyleUtils.ts +++ b/src/util/genStyleUtils.ts @@ -92,10 +92,13 @@ export type CSSVarRegisterProps = { type GetResetStylesConfig = { prefix: ReturnType; - csp: ReturnType + csp: ReturnType; }; -export type GetResetStyles = (token: AliasToken, config?: GetResetStylesConfig) => CSSInterpolation; +export type GetResetStyles = ( + token: AliasToken, + config?: GetResetStylesConfig, +) => CSSInterpolation; export type GetCompUnitless = < C extends TokenMapKey, @@ -160,6 +163,18 @@ function genStyleUtils< * @default true */ injectStyle?: boolean; + /** + * Extra prefixCls to inject CSS variables. + * 为额外的 prefixCls 注入 CSS 变量(不注入样式)。 + * + * @example + * ```typescript + * { + * extraCssVarPrefixCls: ['my-comp-compact', 'my-comp-large'] + * } + * ``` + */ + extraCssVarPrefixCls?: string[]; }, ) { const componentName = Array.isArray(component) ? component[0] : component; @@ -197,7 +212,9 @@ function genStyleUtils< return (prefixCls: string, rootCls: string = prefixCls) => { const hashId = useStyle(prefixCls, rootCls); - const cssVarCls = useCSSVar(rootCls); + const cssVarCls = useCSSVar( + options?.extraCssVarPrefixCls?.length ? [rootCls, ...options.extraCssVarPrefixCls] : rootCls, + ); return [hashId, cssVarCls] as const; }; @@ -208,7 +225,7 @@ function genStyleUtils< getDefaultToken: GetDefaultToken | undefined, options: { unitless?: Partial, boolean>>; - ignore?: Partial> + ignore?: Partial>; deprecatedTokens?: [ ComponentTokenKey, ComponentTokenKey, @@ -219,7 +236,7 @@ function genStyleUtils< ) { const { unitless: compUnitless, prefixToken, ignore } = options; - return (rootCls: string) => { + return (rootCls: string | string[]) => { const { cssVar, realToken } = useToken(); useCSSVarRegister( diff --git a/tests/extraCssVarPrefixCls.test.tsx b/tests/extraCssVarPrefixCls.test.tsx new file mode 100644 index 0000000..b80cfd2 --- /dev/null +++ b/tests/extraCssVarPrefixCls.test.tsx @@ -0,0 +1,96 @@ +import React from 'react'; +import { render } from '@testing-library/react'; +import { createCache, StyleProvider } from '@ant-design/cssinjs'; +import { genStyleUtils } from '../src'; + +interface TestTokenMap { + TestComponent: { + colorPrimary?: string; + fontSize?: number; + }; +} + +describe('extraCssVarPrefixCls', () => { + const mockConfig = { + usePrefix: jest.fn().mockReturnValue({ + rootPrefixCls: 'ant', + iconPrefixCls: 'anticon', + }), + useToken: jest.fn().mockReturnValue({ + theme: { + id: 'test', + } as any, + realToken: { + colorPrimary: '#1890ff', + fontSize: 14, + TestComponent: { + colorPrimary: '#ff0000', + fontSize: 16, + }, + }, + hashId: 'css-dev-only-do-not-override-abc123', + token: { + colorPrimary: '#1890ff', + fontSize: 14, + TestComponent: { + colorPrimary: '#ff0000', + fontSize: 16, + }, + }, + cssVar: { + prefix: 'ant', + key: 'test', + }, + }), + useCSP: jest.fn().mockReturnValue({ nonce: 'nonce' }), + getResetStyles: jest.fn().mockReturnValue([]), + layer: { + name: 'test', + dependencies: ['parent'], + }, + }; + + const { genStyleHooks } = genStyleUtils(mockConfig); + + beforeEach(() => { + document.head.innerHTML = ''; + }); + + it('should inject CSS vars for extraCssVarPrefixCls', () => { + const hooks = genStyleHooks( + 'TestComponent', + (token) => ({ + [`${token.componentCls}`]: { + color: token.colorPrimary, + fontSize: token.fontSize, + }, + }), + () => ({ + colorPrimary: '#ff0000', + fontSize: 16, + }), + { + extraCssVarPrefixCls: ['custom-a', 'custom-b'], + }, + ); + + const TestComponent = () => { + const [hashId, cssVarCls] = hooks('test-prefix'); + const className = [hashId, cssVarCls].filter(Boolean).join(' '); + return
{hashId}
; + }; + + render( + + + , + ); + + const totalStyle = Array.from(document.querySelectorAll('style')) + .map((el) => el.textContent) + .join('\n'); + + expect(totalStyle).toContain('.custom-a'); + expect(totalStyle).toContain('.custom-b'); + }); +}); diff --git a/tests/genStyleUtils.test.tsx b/tests/genStyleUtils.test.tsx index 0404648..c3e089e 100644 --- a/tests/genStyleUtils.test.tsx +++ b/tests/genStyleUtils.test.tsx @@ -47,7 +47,7 @@ describe('genStyleUtils', () => { const component = 'TestComponent'; const styleFn = jest.fn(); const getDefaultToken = { - mockCompToken: 'mock' + mockCompToken: 'mock', }; const hooks = genStyleHooks(component, styleFn, getDefaultToken); @@ -158,16 +158,14 @@ describe('genStyleUtils', () => { zeroRuntime: true, }), usePrefix, - } - const { genComponentStyleHook: gen } = genStyleUtils< - TestCompTokenMap, - object, - object - >(config); + }; + const { genComponentStyleHook: gen } = genStyleUtils( + config, + ); const styleFn = jest.fn(); const getDefaultToken = jest.fn(); - const useStyle = gen('TestComponent', styleFn, getDefaultToken) + const useStyle = gen('TestComponent', styleFn, getDefaultToken); const TestComponent: React.FC = ({ prefixCls, rootCls }) => { useStyle(prefixCls, rootCls); @@ -177,6 +175,6 @@ describe('genStyleUtils', () => { const { getByTestId } = render(); expect(getByTestId('test-component')).toHaveTextContent('Test'); expect(usePrefix).not.toHaveBeenCalled(); - }) - }) + }); + }); });