Skip to content

Commit 69d2e54

Browse files
committed
feat: css var support hash
1 parent fcb0e28 commit 69d2e54

File tree

14 files changed

+389
-283
lines changed

14 files changed

+389
-283
lines changed

docs/examples/components/Button.tsx

Lines changed: 39 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
1-
import type { CSSInterpolation, CSSObject } from '@ant-design/cssinjs';
2-
import { unit, useStyleRegister } from '@ant-design/cssinjs';
1+
import {
2+
CSSInterpolation,
3+
CSSObject,
4+
unit,
5+
useCSSVarRegister,
6+
useStyleRegister,
7+
} from '@ant-design/cssinjs';
38
import classNames from 'classnames';
49
import React from 'react';
510
import type { DerivativeToken } from './theme';
@@ -15,6 +20,7 @@ const genSharedButtonStyle = (
1520
borderWidth: token.borderWidth,
1621
borderRadius: token.borderRadius,
1722
lineHeight: token.lineHeight,
23+
padding: token.buttonPadding,
1824

1925
cursor: 'pointer',
2026

@@ -103,23 +109,45 @@ const Button = ({ className, type, ...restProps }: ButtonProps) => {
103109
const prefixCls = 'ant-btn';
104110

105111
// 【自定义】制造样式
106-
const [theme, token, hashId, cssVarKey] = useToken();
112+
const [theme, token, hashId, cssVarKey, realToken] = useToken();
107113

108114
// default 添加默认样式选择器后可以省很多冲突解决问题
109115
const defaultCls = `${prefixCls}-default`;
110116
const primaryCls = `${prefixCls}-primary`;
111117
const ghostCls = `${prefixCls}-ghost`;
112118

113-
// 全局注册,内部会做缓存优化
114-
useStyleRegister(
115-
{ theme, token, hashId, path: [prefixCls] },
116-
() => [
117-
genDefaultButtonStyle(defaultCls, token),
118-
genPrimaryButtonStyle(primaryCls, token),
119-
genGhostButtonStyle(ghostCls, token),
120-
],
119+
const [cssVarToken] = useCSSVarRegister(
120+
{
121+
path: [prefixCls],
122+
key: cssVarKey,
123+
token: realToken,
124+
prefix: prefixCls,
125+
unitless: {
126+
lineHeight: true,
127+
},
128+
ignore: {
129+
lineHeightBase: true,
130+
},
131+
scope: prefixCls,
132+
hashId,
133+
},
134+
() => ({
135+
buttonPadding: '4px 8px',
136+
}),
121137
);
122138

139+
const mergedToken: any = {
140+
...token,
141+
...cssVarToken,
142+
};
143+
144+
// 全局注册,内部会做缓存优化
145+
useStyleRegister({ theme, token, hashId, path: [prefixCls] }, () => [
146+
genDefaultButtonStyle(defaultCls, mergedToken),
147+
genPrimaryButtonStyle(primaryCls, mergedToken),
148+
genGhostButtonStyle(ghostCls, mergedToken),
149+
]);
150+
123151
const typeCls =
124152
(
125153
{

docs/examples/components/theme.tsx

Lines changed: 53 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import type { CSSObject, Theme } from '@ant-design/cssinjs';
22
import { createTheme, useCacheToken } from '@ant-design/cssinjs';
33
import { TinyColor } from '@ctrl/tinycolor';
4-
import React from 'react';
4+
import React, { PropsWithChildren } from 'react';
55

66
export type GetStyle = (prefixCls: string, token: DerivativeToken) => CSSObject;
77

@@ -22,6 +22,7 @@ export interface DesignToken {
2222

2323
export interface DerivativeToken extends DesignToken {
2424
primaryColorDisabled: string;
25+
buttonPadding: string;
2526
}
2627

2728
const defaultDesignToken: DesignToken = {
@@ -61,32 +62,68 @@ export const DesignTokenContext = React.createContext<{
6162
token: defaultDesignToken,
6263
});
6364

65+
export const DesignTokenProvider: React.FC<
66+
PropsWithChildren<{
67+
value?: {
68+
token?: Partial<DesignToken>;
69+
hashed?: string | boolean;
70+
cssVar?: {
71+
key?: string;
72+
prefix?: string;
73+
};
74+
};
75+
}>
76+
> = ({ children, value }) => {
77+
const { token, hashed, cssVar } = value || {};
78+
const themeKey = React.useId();
79+
const cssVarKey = `css-var-${themeKey.replace(/:/g, '')}`;
80+
return (
81+
<DesignTokenContext.Provider
82+
value={{
83+
token,
84+
hashed,
85+
cssVar: {
86+
...cssVar,
87+
key: cssVar?.key || cssVarKey,
88+
},
89+
}}
90+
>
91+
{children}
92+
</DesignTokenContext.Provider>
93+
);
94+
};
95+
6496
export function useToken(): [
6597
Theme<any, any>,
6698
DerivativeToken,
6799
string,
68-
string | undefined,
100+
string,
101+
DerivativeToken,
69102
] {
70103
const {
71104
token: rootDesignToken = {},
72105
hashed,
73-
cssVar,
106+
cssVar: ctxCssVar,
74107
} = React.useContext(DesignTokenContext);
75108
const theme = React.useContext(ThemeContext);
76109

77-
const [token, hashId] = useCacheToken<DerivativeToken, DesignToken>(
78-
theme,
79-
[defaultDesignToken, rootDesignToken],
80-
{
81-
salt: typeof hashed === 'string' ? hashed : '',
82-
cssVar: {
83-
prefix: 'rc',
84-
key: cssVar?.key || 'css-var-root',
85-
unitless: {
86-
lineHeight: true,
87-
},
110+
const cssVar = {
111+
key: ctxCssVar?.key || 'css-var-root',
112+
};
113+
114+
const [token, hashId, actualToken] = useCacheToken<
115+
DerivativeToken,
116+
DesignToken
117+
>(theme, [defaultDesignToken, rootDesignToken], {
118+
salt: typeof hashed === 'string' ? hashed : '',
119+
cssVar: {
120+
prefix: 'rc',
121+
key: cssVar?.key || 'css-var-root',
122+
unitless: {
123+
lineHeight: true,
88124
},
125+
hashed: !!hashed,
89126
},
90-
);
91-
return [theme, token, hashed ? hashId : '', cssVar?.key];
127+
});
128+
return [theme, token, hashed ? hashId : '', cssVar.key, actualToken];
92129
}

docs/examples/css-var.tsx

Lines changed: 24 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,17 @@
11
import React from 'react';
22
import './basic.less';
33
import Button from './components/Button';
4-
import { DesignTokenContext } from './components/theme';
4+
import { DesignTokenProvider } from './components/theme';
5+
6+
const Demo = () => (
7+
<>
8+
<Button>Default</Button>
9+
<Button type="primary">Primary</Button>
10+
<Button type="ghost">Ghost</Button>
11+
12+
<Button className="btn-override">Override By ClassName</Button>
13+
</>
14+
);
515

616
export default function App() {
717
const [show, setShow] = React.useState(true);
@@ -22,29 +32,24 @@ export default function App() {
2232

2333
{show && (
2434
<div>
25-
<DesignTokenContext.Provider
26-
value={{ cssVar: { key: 'default' }, hashed: false }}
27-
>
28-
<Button>Default</Button>
29-
<Button type="primary">Primary</Button>
30-
<Button type="ghost">Ghost</Button>
31-
32-
<Button className="btn-override">Override By ClassName</Button>
33-
</DesignTokenContext.Provider>
35+
<Demo />
3436
<br />
35-
<DesignTokenContext.Provider
37+
<DesignTokenProvider
3638
value={{
3739
token: { primaryColor: 'green' },
38-
cssVar: { key: 'default2' },
39-
hashed: false,
4040
}}
4141
>
42-
<Button>Default</Button>
43-
<Button type="primary">Primary</Button>
44-
<Button type="ghost">Ghost</Button>
45-
46-
<Button className="btn-override">Override By ClassName</Button>
47-
</DesignTokenContext.Provider>
42+
<Demo />
43+
</DesignTokenProvider>
44+
<br />
45+
<DesignTokenProvider
46+
value={{
47+
token: { primaryColor: 'orange' },
48+
hashed: true,
49+
}}
50+
>
51+
<Demo />
52+
</DesignTokenProvider>
4853
</div>
4954
)}
5055
</div>

src/hooks/useCSSVarRegister.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,13 +30,15 @@ const useCSSVarRegister = <V, T extends Record<string, V>>(
3030
ignore?: Record<string, boolean>;
3131
scope?: string;
3232
token: any;
33+
hashId?: string;
3334
},
3435
fn: () => T,
3536
) => {
36-
const { key, prefix, unitless, ignore, token, scope = '' } = config;
37+
const { key, prefix, unitless, ignore, token, hashId, scope = '' } = config;
3738
const {
3839
cache: { instanceId },
3940
container,
41+
hashPriority,
4042
} = useContext(StyleContext);
4143
const { _tokenKey: tokenKey } = token;
4244

@@ -52,6 +54,8 @@ const useCSSVarRegister = <V, T extends Record<string, V>>(
5254
unitless,
5355
ignore,
5456
scope,
57+
hashPriority,
58+
hashCls: hashId,
5559
});
5660
const styleId = uniqueHash(stylePath, cssVarsStr);
5761
return [mergedToken, cssVarsStr, styleId, key];

src/hooks/useCacheToken.tsx

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ export interface Option<DerivativeToken, DesignToken> {
5656
* Transform token to css variables.
5757
*/
5858
cssVar: {
59+
hashed?: boolean;
5960
/** Prefix for css variables */
6061
prefix?: string;
6162
/** Tokens that should not be appended with unit */
@@ -161,6 +162,7 @@ export default function useCacheToken<
161162
const {
162163
cache: { instanceId },
163164
container,
165+
hashPriority,
164166
} = useContext(StyleContext);
165167
const {
166168
salt = '',
@@ -176,7 +178,7 @@ export default function useCacheToken<
176178
const tokenStr = flattenToken(mergedToken);
177179
const overrideTokenStr = flattenToken(override);
178180

179-
const cssVarStr = cssVar ? flattenToken(cssVar) : '';
181+
const cssVarStr = flattenToken(cssVar);
180182

181183
const cachedToken = useGlobalCache<TokenCacheValue<DerivativeToken>>(
182184
TOKEN_PREFIX,
@@ -185,9 +187,15 @@ export default function useCacheToken<
185187
const mergedDerivativeToken = compute
186188
? compute(mergedToken, override, theme)
187189
: getComputedToken(mergedToken, override, theme, formatToken);
190+
const actualToken = { ...mergedDerivativeToken };
191+
192+
// Optimize for `useStyleRegister` performance
193+
const mergedSalt = `${salt}_${cssVar.prefix}`;
194+
const hashId = hash(mergedSalt);
195+
const hashCls = `${hashPrefix}-${hash(mergedSalt)}`;
196+
actualToken._tokenKey = token2key(actualToken, mergedSalt);
188197

189198
// Replace token value with css variables
190-
const actualToken = { ...mergedDerivativeToken };
191199
const [tokenWithCssVar, cssVarsStr] = transformToken(
192200
mergedDerivativeToken,
193201
cssVar.key,
@@ -196,19 +204,14 @@ export default function useCacheToken<
196204
ignore: cssVar.ignore,
197205
unitless: cssVar.unitless,
198206
preserve: cssVar.preserve,
207+
hashPriority,
208+
hashCls: cssVar.hashed ? hashCls : undefined,
199209
},
200210
) as [any, string];
211+
tokenWithCssVar._hashId = hashId;
201212

202-
// Optimize for `useStyleRegister` performance
203-
const mergedSalt = `${salt}_${cssVar.prefix || ''}`;
204-
actualToken._tokenKey = token2key(actualToken, mergedSalt);
205-
206-
const themeKey = cssVar.key;
207-
recordCleanToken(themeKey);
208-
209-
const hashId = `${hashPrefix}-${hash(mergedSalt)}`;
210-
211-
return [tokenWithCssVar, hashId, actualToken, cssVarsStr, cssVar.key];
213+
recordCleanToken(hashId);
214+
return [tokenWithCssVar, hashCls, actualToken, cssVarsStr, cssVar.key];
212215
},
213216
([, , , , themeKey]) => {
214217
// Remove token will remove all related style

0 commit comments

Comments
 (0)