Skip to content

Commit

Permalink
Merge pull request #151 from ant-design/next
Browse files Browse the repository at this point in the history
chore: master merge next
  • Loading branch information
MadCcc authored Nov 21, 2023
2 parents 92dce00 + b39ab51 commit defcde1
Show file tree
Hide file tree
Showing 23 changed files with 1,307 additions and 246 deletions.
8 changes: 8 additions & 0 deletions docs/demo/css-var.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
title: CSS Variables
nav:
title: Demo
path: /demo
---

<code src="../examples/css-var.tsx"></code>
11 changes: 6 additions & 5 deletions docs/examples/components/Button.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { CSSInterpolation, CSSObject } from '@ant-design/cssinjs';
import { useStyleRegister } from '@ant-design/cssinjs';
import { unit, useStyleRegister } from '@ant-design/cssinjs';
import classNames from 'classnames';
import React from 'react';
import type { DerivativeToken } from './theme';
Expand All @@ -14,6 +14,7 @@ const genSharedButtonStyle = (
borderColor: token.borderColor,
borderWidth: token.borderWidth,
borderRadius: token.borderRadius,
lineHeight: token.lineHeight,

cursor: 'pointer',

Expand Down Expand Up @@ -65,7 +66,7 @@ const genPrimaryButtonStyle = (
): CSSInterpolation =>
genSolidButtonStyle(prefixCls, token, () => ({
backgroundColor: token.primaryColor,
border: `${token.borderWidth}px solid ${token.primaryColor}`,
border: `${unit(token.borderWidth)} solid ${token.primaryColor}`,
color: token.reverseTextColor,

'&:hover': {
Expand All @@ -83,7 +84,7 @@ const genGhostButtonStyle = (
[`.${prefixCls}`]: {
backgroundColor: 'transparent',
color: token.primaryColor,
border: `${token.borderWidth}px solid ${token.primaryColor}`,
border: `${unit(token.borderWidth)} solid ${token.primaryColor}`,

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

// 【自定义】制造样式
const [theme, token, hashId] = useToken();
const [theme, token, hashId, cssVarKey] = useToken();

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

return wrapSSR(
<button
className={classNames(prefixCls, typeCls, hashId, className)}
className={classNames(prefixCls, typeCls, hashId, className, cssVarKey)}
{...restProps}
/>,
);
Expand Down
36 changes: 30 additions & 6 deletions docs/examples/components/theme.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React from 'react';
import { TinyColor } from '@ctrl/tinycolor';
import type { CSSObject, Theme } from '@ant-design/cssinjs';
import { createTheme, useCacheToken } from '@ant-design/cssinjs';
import { TinyColor } from '@ctrl/tinycolor';
import React from 'react';

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

Expand All @@ -15,6 +15,9 @@ export interface DesignToken {
borderRadius: number;
borderColor: string;
borderWidth: number;

lineHeight: number;
lineHeightBase: number;
}

export interface DerivativeToken extends DesignToken {
Expand All @@ -31,6 +34,9 @@ const defaultDesignToken: DesignToken = {
borderRadius: 2,
borderColor: 'black',
borderWidth: 1,

lineHeight: 1.5,
lineHeightBase: 1.5,
};

// 模拟推导过程
Expand All @@ -48,21 +54,39 @@ export const ThemeContext = React.createContext(createTheme(derivative));
export const DesignTokenContext = React.createContext<{
token?: Partial<DesignToken>;
hashed?: string | boolean;
cssVar?: {
key: string;
};
}>({
token: defaultDesignToken,
});

export function useToken(): [Theme<any, any>, DerivativeToken, string] {
const { token: rootDesignToken = {}, hashed } =
React.useContext(DesignTokenContext);
export function useToken(): [
Theme<any, any>,
DerivativeToken,
string,
string | undefined,
] {
const {
token: rootDesignToken = {},
hashed,
cssVar,
} = React.useContext(DesignTokenContext);
const theme = React.useContext(ThemeContext);

const [token, hashId] = useCacheToken<DerivativeToken, DesignToken>(
theme,
[defaultDesignToken, rootDesignToken],
{
salt: typeof hashed === 'string' ? hashed : '',
cssVar: cssVar && {
prefix: 'rc',
key: cssVar.key,
unitless: {
lineHeight: true,
},
},
},
);
return [theme, token, hashed ? hashId : ''];
return [theme, token, hashed ? hashId : '', cssVar?.key];
}
52 changes: 52 additions & 0 deletions docs/examples/css-var.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import React from 'react';
import './basic.less';
import Button from './components/Button';
import { DesignTokenContext } from './components/theme';

export default function App() {
const [show, setShow] = React.useState(true);

const [, forceUpdate] = React.useState({});
React.useEffect(() => {
forceUpdate({});
}, []);

return (
<div style={{ background: 'rgba(0,0,0,0.1)', padding: 16 }}>
<h3>默认情况下不会自动删除添加的样式</h3>

<label>
<input type="checkbox" checked={show} onChange={() => setShow(!show)} />
Show Components
</label>

{show && (
<div>
<DesignTokenContext.Provider
value={{ cssVar: { key: 'default' }, hashed: true }}
>
<Button>Default</Button>
<Button type="primary">Primary</Button>
<Button type="ghost">Ghost</Button>

<Button className="btn-override">Override By ClassName</Button>
</DesignTokenContext.Provider>
<br />
<DesignTokenContext.Provider
value={{
token: { primaryColor: 'green' },
cssVar: { key: 'default2' },
hashed: true,
}}
>
<Button>Default</Button>
<Button type="primary">Primary</Button>
<Button type="ghost">Ghost</Button>

<Button className="btn-override">Override By ClassName</Button>
</DesignTokenContext.Provider>
</div>
)}
</div>
);
}
2 changes: 1 addition & 1 deletion docs/examples/ssr-hydrate-file.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { createCache, StyleProvider } from '@ant-design/cssinjs';
import React from 'react';
import { hydrateRoot } from 'react-dom/client';
import { Demo } from './ssr-advanced';
import './ssr-hydrate-file.css';
// import './ssr-hydrate-file.css';

// Copy from `ssr-advanced-hydrate.tsx`
const HTML = `
Expand Down
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@ant-design/cssinjs",
"version": "1.17.2",
"version": "1.18.0-alpha.1",
"description": "Component level cssinjs resolution for antd",
"keywords": [
"react",
Expand All @@ -25,11 +25,12 @@
"license": "MIT",
"scripts": {
"start": "dumi dev",
"dev": "father dev",
"docs:build": "dumi build",
"docs:deploy": "gh-pages -d .doc",
"compile": "father build",
"gh-pages": "npm run docs:build && npm run docs:deploy",
"prepublishOnly": "npm run compile && np --yolo --no-publish",
"prepublishOnly": "npm run compile && np --yolo --no-publish --branch=next --tag=next",
"postpublish": "npm run gh-pages",
"lint": "eslint src/ --ext .ts,.tsx,.jsx,.js,.md",
"prettier": "prettier --write \"**/*.{ts,tsx,js,jsx,json,md}\"",
Expand Down
83 changes: 83 additions & 0 deletions src/extractStyle.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import type Cache from './Cache';
import {
extract as tokenExtractStyle,
TOKEN_PREFIX,
} from './hooks/useCacheToken';
import {
CSS_VAR_PREFIX,
extract as cssVarExtractStyle,
} from './hooks/useCSSVarRegister';
import {
extract as styleExtractStyle,
STYLE_PREFIX,
} from './hooks/useStyleRegister';
import { toStyleStr } from './util';
import {
ATTR_CACHE_MAP,
serialize as serializeCacheMap,
} from './util/cacheMapUtil';

const ExtractStyleFns = {
[STYLE_PREFIX]: styleExtractStyle,
[TOKEN_PREFIX]: tokenExtractStyle,
[CSS_VAR_PREFIX]: cssVarExtractStyle,
};

function isNotNull<T>(value: T | null): value is T {
return value !== null;
}

export default function extractStyle(cache: Cache, plain = false) {
const matchPrefixRegexp = new RegExp(
`^(${Object.keys(ExtractStyleFns).join('|')})%`,
);

// prefix with `style` is used for `useStyleRegister` to cache style context
const styleKeys = Array.from(cache.cache.keys()).filter((key) =>
matchPrefixRegexp.test(key),
);

// Common effect styles like animation
const effectStyles: Record<string, boolean> = {};

// Mapping of cachePath to style hash
const cachePathMap: Record<string, string> = {};

let styleText = '';

styleKeys
.map<[number, string] | null>((key) => {
const cachePath = key.replace(matchPrefixRegexp, '').replace(/%/g, '|');
const [prefix] = key.split('%');
const extractFn = ExtractStyleFns[prefix as keyof typeof ExtractStyleFns];
const extractedStyle = extractFn(cache.cache.get(key)![1], effectStyles, {
plain,
});
if (!extractedStyle) {
return null;
}
const [order, styleId, styleStr] = extractedStyle;
if (key.startsWith('style')) {
cachePathMap[cachePath] = styleId;
}
return [order, styleStr];
})
.filter(isNotNull)
.sort(([o1], [o2]) => o1 - o2)
.forEach(([, style]) => {
styleText += style;
});

// ==================== Fill Cache Path ====================
styleText += toStyleStr(
`.${ATTR_CACHE_MAP}{content:"${serializeCacheMap(cachePathMap)}";}`,
undefined,
undefined,
{
[ATTR_CACHE_MAP]: ATTR_CACHE_MAP,
},
plain,
);

return styleText;
}
Loading

0 comments on commit defcde1

Please sign in to comment.