Skip to content

Commit defcde1

Browse files
authored
Merge pull request #151 from ant-design/next
chore: master merge next
2 parents 92dce00 + b39ab51 commit defcde1

23 files changed

+1307
-246
lines changed

docs/demo/css-var.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
---
2+
title: CSS Variables
3+
nav:
4+
title: Demo
5+
path: /demo
6+
---
7+
8+
<code src="../examples/css-var.tsx"></code>

docs/examples/components/Button.tsx

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import type { CSSInterpolation, CSSObject } from '@ant-design/cssinjs';
2-
import { useStyleRegister } from '@ant-design/cssinjs';
2+
import { unit, useStyleRegister } from '@ant-design/cssinjs';
33
import classNames from 'classnames';
44
import React from 'react';
55
import type { DerivativeToken } from './theme';
@@ -14,6 +14,7 @@ const genSharedButtonStyle = (
1414
borderColor: token.borderColor,
1515
borderWidth: token.borderWidth,
1616
borderRadius: token.borderRadius,
17+
lineHeight: token.lineHeight,
1718

1819
cursor: 'pointer',
1920

@@ -65,7 +66,7 @@ const genPrimaryButtonStyle = (
6566
): CSSInterpolation =>
6667
genSolidButtonStyle(prefixCls, token, () => ({
6768
backgroundColor: token.primaryColor,
68-
border: `${token.borderWidth}px solid ${token.primaryColor}`,
69+
border: `${unit(token.borderWidth)} solid ${token.primaryColor}`,
6970
color: token.reverseTextColor,
7071

7172
'&:hover': {
@@ -83,7 +84,7 @@ const genGhostButtonStyle = (
8384
[`.${prefixCls}`]: {
8485
backgroundColor: 'transparent',
8586
color: token.primaryColor,
86-
border: `${token.borderWidth}px solid ${token.primaryColor}`,
87+
border: `${unit(token.borderWidth)} solid ${token.primaryColor}`,
8788

8889
'&:hover': {
8990
borderColor: token.primaryColor,
@@ -102,7 +103,7 @@ const Button = ({ className, type, ...restProps }: ButtonProps) => {
102103
const prefixCls = 'ant-btn';
103104

104105
// 【自定义】制造样式
105-
const [theme, token, hashId] = useToken();
106+
const [theme, token, hashId, cssVarKey] = useToken();
106107

107108
// default 添加默认样式选择器后可以省很多冲突解决问题
108109
const defaultCls = `${prefixCls}-default`;
@@ -129,7 +130,7 @@ const Button = ({ className, type, ...restProps }: ButtonProps) => {
129130

130131
return wrapSSR(
131132
<button
132-
className={classNames(prefixCls, typeCls, hashId, className)}
133+
className={classNames(prefixCls, typeCls, hashId, className, cssVarKey)}
133134
{...restProps}
134135
/>,
135136
);

docs/examples/components/theme.tsx

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
import React from 'react';
2-
import { TinyColor } from '@ctrl/tinycolor';
31
import type { CSSObject, Theme } from '@ant-design/cssinjs';
42
import { createTheme, useCacheToken } from '@ant-design/cssinjs';
3+
import { TinyColor } from '@ctrl/tinycolor';
4+
import React from 'react';
55

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

@@ -15,6 +15,9 @@ export interface DesignToken {
1515
borderRadius: number;
1616
borderColor: string;
1717
borderWidth: number;
18+
19+
lineHeight: number;
20+
lineHeightBase: number;
1821
}
1922

2023
export interface DerivativeToken extends DesignToken {
@@ -31,6 +34,9 @@ const defaultDesignToken: DesignToken = {
3134
borderRadius: 2,
3235
borderColor: 'black',
3336
borderWidth: 1,
37+
38+
lineHeight: 1.5,
39+
lineHeightBase: 1.5,
3440
};
3541

3642
// 模拟推导过程
@@ -48,21 +54,39 @@ export const ThemeContext = React.createContext(createTheme(derivative));
4854
export const DesignTokenContext = React.createContext<{
4955
token?: Partial<DesignToken>;
5056
hashed?: string | boolean;
57+
cssVar?: {
58+
key: string;
59+
};
5160
}>({
5261
token: defaultDesignToken,
5362
});
5463

55-
export function useToken(): [Theme<any, any>, DerivativeToken, string] {
56-
const { token: rootDesignToken = {}, hashed } =
57-
React.useContext(DesignTokenContext);
64+
export function useToken(): [
65+
Theme<any, any>,
66+
DerivativeToken,
67+
string,
68+
string | undefined,
69+
] {
70+
const {
71+
token: rootDesignToken = {},
72+
hashed,
73+
cssVar,
74+
} = React.useContext(DesignTokenContext);
5875
const theme = React.useContext(ThemeContext);
5976

6077
const [token, hashId] = useCacheToken<DerivativeToken, DesignToken>(
6178
theme,
6279
[defaultDesignToken, rootDesignToken],
6380
{
6481
salt: typeof hashed === 'string' ? hashed : '',
82+
cssVar: cssVar && {
83+
prefix: 'rc',
84+
key: cssVar.key,
85+
unitless: {
86+
lineHeight: true,
87+
},
88+
},
6589
},
6690
);
67-
return [theme, token, hashed ? hashId : ''];
91+
return [theme, token, hashed ? hashId : '', cssVar?.key];
6892
}

docs/examples/css-var.tsx

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import React from 'react';
2+
import './basic.less';
3+
import Button from './components/Button';
4+
import { DesignTokenContext } from './components/theme';
5+
6+
export default function App() {
7+
const [show, setShow] = React.useState(true);
8+
9+
const [, forceUpdate] = React.useState({});
10+
React.useEffect(() => {
11+
forceUpdate({});
12+
}, []);
13+
14+
return (
15+
<div style={{ background: 'rgba(0,0,0,0.1)', padding: 16 }}>
16+
<h3>默认情况下不会自动删除添加的样式</h3>
17+
18+
<label>
19+
<input type="checkbox" checked={show} onChange={() => setShow(!show)} />
20+
Show Components
21+
</label>
22+
23+
{show && (
24+
<div>
25+
<DesignTokenContext.Provider
26+
value={{ cssVar: { key: 'default' }, hashed: true }}
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>
34+
<br />
35+
<DesignTokenContext.Provider
36+
value={{
37+
token: { primaryColor: 'green' },
38+
cssVar: { key: 'default2' },
39+
hashed: true,
40+
}}
41+
>
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>
48+
</div>
49+
)}
50+
</div>
51+
);
52+
}

docs/examples/ssr-hydrate-file.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { createCache, StyleProvider } from '@ant-design/cssinjs';
22
import React from 'react';
33
import { hydrateRoot } from 'react-dom/client';
44
import { Demo } from './ssr-advanced';
5-
import './ssr-hydrate-file.css';
5+
// import './ssr-hydrate-file.css';
66

77
// Copy from `ssr-advanced-hydrate.tsx`
88
const HTML = `

package.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@ant-design/cssinjs",
3-
"version": "1.17.2",
3+
"version": "1.18.0-alpha.1",
44
"description": "Component level cssinjs resolution for antd",
55
"keywords": [
66
"react",
@@ -25,11 +25,12 @@
2525
"license": "MIT",
2626
"scripts": {
2727
"start": "dumi dev",
28+
"dev": "father dev",
2829
"docs:build": "dumi build",
2930
"docs:deploy": "gh-pages -d .doc",
3031
"compile": "father build",
3132
"gh-pages": "npm run docs:build && npm run docs:deploy",
32-
"prepublishOnly": "npm run compile && np --yolo --no-publish",
33+
"prepublishOnly": "npm run compile && np --yolo --no-publish --branch=next --tag=next",
3334
"postpublish": "npm run gh-pages",
3435
"lint": "eslint src/ --ext .ts,.tsx,.jsx,.js,.md",
3536
"prettier": "prettier --write \"**/*.{ts,tsx,js,jsx,json,md}\"",

src/extractStyle.ts

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
import type Cache from './Cache';
2+
import {
3+
extract as tokenExtractStyle,
4+
TOKEN_PREFIX,
5+
} from './hooks/useCacheToken';
6+
import {
7+
CSS_VAR_PREFIX,
8+
extract as cssVarExtractStyle,
9+
} from './hooks/useCSSVarRegister';
10+
import {
11+
extract as styleExtractStyle,
12+
STYLE_PREFIX,
13+
} from './hooks/useStyleRegister';
14+
import { toStyleStr } from './util';
15+
import {
16+
ATTR_CACHE_MAP,
17+
serialize as serializeCacheMap,
18+
} from './util/cacheMapUtil';
19+
20+
const ExtractStyleFns = {
21+
[STYLE_PREFIX]: styleExtractStyle,
22+
[TOKEN_PREFIX]: tokenExtractStyle,
23+
[CSS_VAR_PREFIX]: cssVarExtractStyle,
24+
};
25+
26+
function isNotNull<T>(value: T | null): value is T {
27+
return value !== null;
28+
}
29+
30+
export default function extractStyle(cache: Cache, plain = false) {
31+
const matchPrefixRegexp = new RegExp(
32+
`^(${Object.keys(ExtractStyleFns).join('|')})%`,
33+
);
34+
35+
// prefix with `style` is used for `useStyleRegister` to cache style context
36+
const styleKeys = Array.from(cache.cache.keys()).filter((key) =>
37+
matchPrefixRegexp.test(key),
38+
);
39+
40+
// Common effect styles like animation
41+
const effectStyles: Record<string, boolean> = {};
42+
43+
// Mapping of cachePath to style hash
44+
const cachePathMap: Record<string, string> = {};
45+
46+
let styleText = '';
47+
48+
styleKeys
49+
.map<[number, string] | null>((key) => {
50+
const cachePath = key.replace(matchPrefixRegexp, '').replace(/%/g, '|');
51+
const [prefix] = key.split('%');
52+
const extractFn = ExtractStyleFns[prefix as keyof typeof ExtractStyleFns];
53+
const extractedStyle = extractFn(cache.cache.get(key)![1], effectStyles, {
54+
plain,
55+
});
56+
if (!extractedStyle) {
57+
return null;
58+
}
59+
const [order, styleId, styleStr] = extractedStyle;
60+
if (key.startsWith('style')) {
61+
cachePathMap[cachePath] = styleId;
62+
}
63+
return [order, styleStr];
64+
})
65+
.filter(isNotNull)
66+
.sort(([o1], [o2]) => o1 - o2)
67+
.forEach(([, style]) => {
68+
styleText += style;
69+
});
70+
71+
// ==================== Fill Cache Path ====================
72+
styleText += toStyleStr(
73+
`.${ATTR_CACHE_MAP}{content:"${serializeCacheMap(cachePathMap)}";}`,
74+
undefined,
75+
undefined,
76+
{
77+
[ATTR_CACHE_MAP]: ATTR_CACHE_MAP,
78+
},
79+
plain,
80+
);
81+
82+
return styleText;
83+
}

0 commit comments

Comments
 (0)