mirror of
https://gitee.com/ant-design/ant-design.git
synced 2024-12-01 19:49:59 +08:00
docs: Support semantic preview (#47332)
* docs: init * docs: semantic block * docs: part of demo * docs: modal * docs: slider * docs: space * docs: all sementic * docs: clean up * chore: fix lint * chore: clean up * chore: update script * test: fix test case * test: update testcase
This commit is contained in:
parent
e197751d01
commit
7104513a84
171
.dumi/components/SemanticPreview.tsx
Normal file
171
.dumi/components/SemanticPreview.tsx
Normal file
@ -0,0 +1,171 @@
|
||||
import * as React from 'react';
|
||||
import { Col, ConfigProvider, Flex, Row, Tag, theme, Typography } from 'antd';
|
||||
|
||||
export interface SemanticPreviewProps {
|
||||
semantics: { name: string; desc: string; version?: string }[];
|
||||
children: React.ReactElement;
|
||||
height?: number;
|
||||
}
|
||||
|
||||
const SemanticPreview = (props: SemanticPreviewProps) => {
|
||||
const { semantics = [], children, height } = props;
|
||||
const { token } = theme.useToken();
|
||||
|
||||
// ======================= Semantic =======================
|
||||
const getMarkClassName = React.useCallback(
|
||||
(semanticKey: string) => `semantic-mark-${semanticKey}`,
|
||||
[],
|
||||
);
|
||||
|
||||
const semanticClassNames = React.useMemo(() => {
|
||||
const classNames: Record<string, string> = {};
|
||||
|
||||
semantics.forEach((semantic) => {
|
||||
classNames[semantic.name] = getMarkClassName(semantic.name);
|
||||
});
|
||||
|
||||
return classNames;
|
||||
}, [semantics]);
|
||||
|
||||
const cloneNode = React.cloneElement(children, {
|
||||
classNames: semanticClassNames,
|
||||
});
|
||||
|
||||
// ======================== Hover =========================
|
||||
const MARK_BORDER_SIZE = 2;
|
||||
const containerRef = React.useRef<HTMLDivElement>(null);
|
||||
|
||||
const [positionMotion, setPositionMotion] = React.useState(false);
|
||||
|
||||
const [hoverSemantic, setHoverSemantic] = React.useState<string | null>(null);
|
||||
const [markPos, setMarkPos] = React.useState<
|
||||
[left: number, top: number, width: number, height: number]
|
||||
>([0, 0, 0, 0]);
|
||||
|
||||
React.useEffect(() => {
|
||||
if (hoverSemantic) {
|
||||
const targetClassName = getMarkClassName(hoverSemantic);
|
||||
const targetElement = containerRef.current?.querySelector(`.${targetClassName}`);
|
||||
|
||||
const containerRect = containerRef.current?.getBoundingClientRect();
|
||||
const targetRect = targetElement?.getBoundingClientRect();
|
||||
|
||||
setMarkPos([
|
||||
(targetRect?.left || 0) - (containerRect?.left || 0),
|
||||
(targetRect?.top || 0) - (containerRect?.top || 0),
|
||||
targetRect?.width || 0,
|
||||
targetRect?.height || 0,
|
||||
]);
|
||||
|
||||
setTimeout(() => {
|
||||
setPositionMotion(true);
|
||||
}, 10);
|
||||
} else {
|
||||
const timeout = setTimeout(() => {
|
||||
setPositionMotion(false);
|
||||
}, 500);
|
||||
|
||||
return () => {
|
||||
clearTimeout(timeout);
|
||||
};
|
||||
}
|
||||
}, [hoverSemantic]);
|
||||
|
||||
// ======================== Render ========================
|
||||
return (
|
||||
<div style={{ position: 'relative' }} ref={containerRef}>
|
||||
<Row style={{ minHeight: height }}>
|
||||
<Col
|
||||
span={16}
|
||||
style={{
|
||||
borderRight: `1px solid ${token.colorBorderSecondary}`,
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
padding: token.paddingMD,
|
||||
overflow: 'hidden',
|
||||
}}
|
||||
>
|
||||
<ConfigProvider
|
||||
theme={{
|
||||
token: {
|
||||
motion: false,
|
||||
},
|
||||
}}
|
||||
>
|
||||
{cloneNode}
|
||||
</ConfigProvider>
|
||||
</Col>
|
||||
<Col span={8}>
|
||||
<ul
|
||||
style={{
|
||||
rowGap: token.paddingXS,
|
||||
listStyle: 'none',
|
||||
margin: 0,
|
||||
padding: 0,
|
||||
flexDirection: 'column',
|
||||
overflow: 'hidden',
|
||||
}}
|
||||
>
|
||||
{semantics.map((semantic, index) => (
|
||||
<li
|
||||
key={semantic.name}
|
||||
style={{
|
||||
paddingBlock: token.paddingXS,
|
||||
paddingInline: token.paddingSM,
|
||||
cursor: 'pointer',
|
||||
borderTop: index === 0 ? 'none' : `1px solid ${token.colorBorderSecondary}`,
|
||||
background:
|
||||
hoverSemantic === semantic.name ? token.controlItemBgHover : 'transparent',
|
||||
transition: `background ${token.motionDurationFast} ease`,
|
||||
}}
|
||||
onMouseEnter={() => {
|
||||
setHoverSemantic(semantic.name);
|
||||
}}
|
||||
onMouseLeave={() => {
|
||||
setHoverSemantic(null);
|
||||
}}
|
||||
>
|
||||
<Flex vertical gap={token.paddingXS}>
|
||||
<Flex gap={token.paddingXS} align="center">
|
||||
<Typography.Title level={5} style={{ margin: 0 }}>
|
||||
{semantic.name}
|
||||
</Typography.Title>
|
||||
{semantic.version && <Tag color="blue">{semantic.version}</Tag>}
|
||||
</Flex>
|
||||
<Typography.Paragraph style={{ margin: 0, fontSize: token.fontSizeSM }}>
|
||||
{semantic.desc}
|
||||
</Typography.Paragraph>{' '}
|
||||
</Flex>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
<div
|
||||
style={{
|
||||
position: 'absolute',
|
||||
border: `${MARK_BORDER_SIZE}px solid ${token.colorWarning}`,
|
||||
boxSizing: 'border-box',
|
||||
zIndex: 999999,
|
||||
left: markPos[0] - MARK_BORDER_SIZE,
|
||||
top: markPos[1] - MARK_BORDER_SIZE,
|
||||
width: markPos[2] + MARK_BORDER_SIZE * 2,
|
||||
height: markPos[3] + MARK_BORDER_SIZE * 2,
|
||||
boxShadow: '0 0 0 1px #FFF',
|
||||
pointerEvents: 'none',
|
||||
transition: [
|
||||
`opacity ${token.motionDurationSlow} ease`,
|
||||
positionMotion ? `all ${token.motionDurationSlow} ease` : null,
|
||||
]
|
||||
.filter(Boolean)
|
||||
.join(','),
|
||||
opacity: hoverSemantic ? 1 : 0,
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default SemanticPreview;
|
@ -5,8 +5,9 @@ import stackblitzSdk from '@stackblitz/sdk';
|
||||
import { Alert, Badge, Flex, Tooltip } from 'antd';
|
||||
import { createStyles, css } from 'antd-style';
|
||||
import classNames from 'classnames';
|
||||
import { FormattedMessage, useSiteData, useLiveDemo } from 'dumi';
|
||||
import { FormattedMessage, useLiveDemo, useSiteData } from 'dumi';
|
||||
import LZString from 'lz-string';
|
||||
|
||||
import useLocation from '../../../hooks/useLocation';
|
||||
import BrowserFrame from '../../common/BrowserFrame';
|
||||
import ClientOnly from '../../common/ClientOnly';
|
||||
@ -99,6 +100,7 @@ const CodePreviewer: React.FC<AntdPreviewerProps> = (props) => {
|
||||
background,
|
||||
filename,
|
||||
version,
|
||||
simplify,
|
||||
clientOnly,
|
||||
pkgDependencyList,
|
||||
} = props;
|
||||
@ -177,6 +179,7 @@ const CodePreviewer: React.FC<AntdPreviewerProps> = (props) => {
|
||||
const codeBoxClass = classNames('code-box', {
|
||||
expand: codeExpand,
|
||||
'code-box-debug': originDebug,
|
||||
'code-box-simplify': simplify,
|
||||
});
|
||||
|
||||
const localizedTitle = title;
|
||||
@ -378,6 +381,7 @@ createRoot(document.getElementById('container')).render(<Demo />);
|
||||
</ErrorBoundary>
|
||||
)}
|
||||
</section>
|
||||
{!simplify && (
|
||||
<section className="code-box-meta markdown">
|
||||
<div className="code-box-title">
|
||||
<Tooltip title={originDebug ? <FormattedMessage id="app.demo.debug" /> : ''}>
|
||||
@ -385,11 +389,18 @@ createRoot(document.getElementById('container')).render(<Demo />);
|
||||
{localizedTitle}
|
||||
</a>
|
||||
</Tooltip>
|
||||
<EditButton title={<FormattedMessage id="app.content.edit-demo" />} filename={filename} />
|
||||
<EditButton
|
||||
title={<FormattedMessage id="app.content.edit-demo" />}
|
||||
filename={filename}
|
||||
/>
|
||||
</div>
|
||||
{description && (
|
||||
<div className="code-box-description" dangerouslySetInnerHTML={{ __html: description }} />
|
||||
<div
|
||||
className="code-box-description"
|
||||
dangerouslySetInnerHTML={{ __html: description }}
|
||||
/>
|
||||
)}
|
||||
|
||||
<Flex wrap="wrap" gap="middle" className="code-box-actions">
|
||||
{showOnlineUrl && (
|
||||
<Tooltip title={<FormattedMessage id="app.demo.online" />}>
|
||||
@ -511,6 +522,7 @@ createRoot(document.getElementById('container')).render(<Demo />);
|
||||
</Tooltip>
|
||||
</Flex>
|
||||
</section>
|
||||
)}
|
||||
{codeExpand && (
|
||||
<section className={highlightClass} key="code">
|
||||
<CodePreview
|
||||
|
@ -29,6 +29,16 @@ const GlobalDemoStyles: React.FC = () => {
|
||||
border-radius: ${token.borderRadiusLG}px;
|
||||
transition: all 0.2s;
|
||||
|
||||
&.code-box-simplify {
|
||||
border-radius: 0;
|
||||
margin-bottom: 0;
|
||||
|
||||
.code-box-demo {
|
||||
padding: 0;
|
||||
border-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.code-box-title {
|
||||
&,
|
||||
a {
|
||||
|
@ -1,6 +1,7 @@
|
||||
import { globSync } from 'glob';
|
||||
import * as React from 'react';
|
||||
import { globSync } from 'glob';
|
||||
import { renderToString } from 'react-dom/server';
|
||||
|
||||
import type { Options } from '../../tests/shared/demoTest';
|
||||
|
||||
(global as any).testConfig = {};
|
||||
@ -28,7 +29,9 @@ describe('node', () => {
|
||||
|
||||
// Test for ssr
|
||||
describe(componentName, () => {
|
||||
const demoList = globSync(`./components/${componentName}/demo/*.tsx`);
|
||||
const demoList = globSync(`./components/${componentName}/demo/*.tsx`).filter(
|
||||
(file) => !file.includes('_semantic'),
|
||||
);
|
||||
|
||||
// Use mock to get config
|
||||
require(`../../${componentTestFile}`); // eslint-disable-line global-require, import/no-dynamic-require
|
||||
|
43
components/badge/demo/_semantic.tsx
Normal file
43
components/badge/demo/_semantic.tsx
Normal file
@ -0,0 +1,43 @@
|
||||
import React from 'react';
|
||||
import { Avatar, Badge } from 'antd';
|
||||
|
||||
import SemanticPreview from '../../../.dumi/components/SemanticPreview';
|
||||
import useLocale from '../../../.dumi/hooks/useLocale';
|
||||
|
||||
const locales = {
|
||||
cn: {
|
||||
root: '根节点',
|
||||
indicator: '指示器节点',
|
||||
},
|
||||
en: {
|
||||
root: 'Root element',
|
||||
indicator: 'Indicator element',
|
||||
},
|
||||
};
|
||||
|
||||
const App: React.FC = () => {
|
||||
const [locale] = useLocale(locales);
|
||||
|
||||
return (
|
||||
<SemanticPreview
|
||||
semantics={[
|
||||
{
|
||||
name: 'root',
|
||||
desc: locale.root,
|
||||
version: '5.7.0',
|
||||
},
|
||||
{
|
||||
name: 'indicator',
|
||||
desc: locale.indicator,
|
||||
version: '5.7.0',
|
||||
},
|
||||
]}
|
||||
>
|
||||
<Badge count={5}>
|
||||
<Avatar shape="square" size="large" />
|
||||
</Badge>
|
||||
</SemanticPreview>
|
||||
);
|
||||
};
|
||||
|
||||
export default App;
|
@ -44,14 +44,14 @@ Common props ref:[Common props](/docs/react/common-props)
|
||||
| --- | --- | --- | --- | --- |
|
||||
| color | Customize Badge dot color | string | - | |
|
||||
| count | Number to show in badge | ReactNode | - | |
|
||||
| classNames | Semantic DOM class | Record<SemanticDOM, string> | - | 5.7.0 |
|
||||
| classNames | Semantic DOM class | [Record<SemanticDOM, string>](#semantic-dom) | - | 5.7.0 |
|
||||
| dot | Whether to display a red dot instead of `count` | boolean | false | |
|
||||
| offset | Set offset of the badge dot | \[number, number] | - | |
|
||||
| overflowCount | Max count to show | number | 99 | |
|
||||
| showZero | Whether to show badge when `count` is zero | boolean | false | |
|
||||
| size | If `count` is set, `size` sets the size of badge | `default` \| `small` | - | - |
|
||||
| status | Set Badge as a status dot | `success` \| `processing` \| `default` \| `error` \| `warning` | - | |
|
||||
| styles | Semantic DOM style | Record<SemanticDOM, CSSProperties> | - | 5.7.0 |
|
||||
| styles | Semantic DOM style | [Record<SemanticDOM, CSSProperties>](#semantic-dom) | - | 5.7.0 |
|
||||
| text | If `status` is set, `text` sets the display text of the status `dot` | ReactNode | - | |
|
||||
| title | Text to show when hovering over the badge | string | - | |
|
||||
|
||||
@ -63,12 +63,9 @@ Common props ref:[Common props](/docs/react/common-props)
|
||||
| placement | The placement of the Ribbon, `start` and `end` follow text direction (RTL or LTR) | `start` \| `end` | `end` | |
|
||||
| text | Content inside the Ribbon | ReactNode | - | |
|
||||
|
||||
### `styles` and `classNames` attribute
|
||||
## Semantic DOM
|
||||
|
||||
| Property | Description | Version |
|
||||
| --------- | ------------------- | ------- |
|
||||
| root | set `root` element | 5.7.0 |
|
||||
| indicator | set `badge` element | 5.7.0 |
|
||||
<code src="./demo/_semantic.tsx" simplify="true"></code>
|
||||
|
||||
## Design Token
|
||||
|
||||
|
@ -45,14 +45,14 @@ group: 数据展示
|
||||
| --- | --- | --- | --- | --- |
|
||||
| color | 自定义小圆点的颜色 | string | - | |
|
||||
| count | 展示的数字,大于 overflowCount 时显示为 `${overflowCount}+`,为 0 时隐藏 | ReactNode | - | |
|
||||
| classNames | 语义化结构 class | Record<SemanticDOM, string> | - | 5.7.0 |
|
||||
| classNames | 语义化结构 class | [Record<SemanticDOM, string>](#semantic-dom) | - | 5.7.0 |
|
||||
| dot | 不展示数字,只有一个小红点 | boolean | false | |
|
||||
| offset | 设置状态点的位置偏移 | \[number, number] | - | |
|
||||
| overflowCount | 展示封顶的数字值 | number | 99 | |
|
||||
| showZero | 当数值为 0 时,是否展示 Badge | boolean | false | |
|
||||
| size | 在设置了 `count` 的前提下有效,设置小圆点的大小 | `default` \| `small` | - | - |
|
||||
| status | 设置 Badge 为状态点 | `success` \| `processing` \| `default` \| `error` \| `warning` | - | |
|
||||
| styles | 语义化结构 style | Record<SemanticDOM, CSSProperties> | - | 5.7.0 |
|
||||
| styles | 语义化结构 style | [Record<SemanticDOM, CSSProperties>](#semantic-dom) | - | 5.7.0 |
|
||||
| text | 在设置了 `status` 的前提下有效,设置状态点的文本 | ReactNode | - | |
|
||||
| title | 设置鼠标放在状态点上时显示的文字 | string | - | |
|
||||
|
||||
@ -64,12 +64,9 @@ group: 数据展示
|
||||
| placement | 缎带的位置,`start` 和 `end` 随文字方向(RTL 或 LTR)变动 | `start` \| `end` | `end` | |
|
||||
| text | 缎带中填入的内容 | ReactNode | - | |
|
||||
|
||||
### `styles` 和 `classNames` 属性
|
||||
## Semantic DOM
|
||||
|
||||
| 名称 | 说明 | 版本 |
|
||||
| --------- | ------------ | ----- |
|
||||
| root | 设置根元素 | 5.7.0 |
|
||||
| indicator | 设置徽标元素 | 5.7.0 |
|
||||
<code src="./demo/_semantic.tsx" simplify="true"></code>
|
||||
|
||||
## 主题变量(Design Token)
|
||||
|
||||
|
37
components/button/demo/_semantic.tsx
Normal file
37
components/button/demo/_semantic.tsx
Normal file
@ -0,0 +1,37 @@
|
||||
import React from 'react';
|
||||
import { AntDesignOutlined } from '@ant-design/icons';
|
||||
import { Button } from 'antd';
|
||||
|
||||
import SemanticPreview from '../../../.dumi/components/SemanticPreview';
|
||||
import useLocale from '../../../.dumi/hooks/useLocale';
|
||||
|
||||
const locales = {
|
||||
cn: {
|
||||
icon: '图标元素',
|
||||
},
|
||||
en: {
|
||||
icon: 'Icon element',
|
||||
},
|
||||
};
|
||||
|
||||
const App: React.FC = () => {
|
||||
const [locale] = useLocale(locales);
|
||||
|
||||
return (
|
||||
<SemanticPreview
|
||||
semantics={[
|
||||
{
|
||||
name: 'icon',
|
||||
desc: locale.icon,
|
||||
version: '5.5.0',
|
||||
},
|
||||
]}
|
||||
>
|
||||
<Button type="primary" icon={<AntDesignOutlined />}>
|
||||
Ant Design
|
||||
</Button>
|
||||
</SemanticPreview>
|
||||
);
|
||||
};
|
||||
|
||||
export default App;
|
@ -59,7 +59,7 @@ Different button styles can be generated by setting Button properties. The recom
|
||||
| Property | Description | Type | Default | Version |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| block | Option to fit button width to its parent width | boolean | false | |
|
||||
| classNames | Semantic DOM class | Record<SemanticDOM, string> | - | 5.4.0 |
|
||||
| classNames | Semantic DOM class | [Record<SemanticDOM, string>](#semantic-dom) | - | 5.4.0 |
|
||||
| danger | Set the danger status of button | boolean | false | |
|
||||
| disabled | Disabled state of button | boolean | false | |
|
||||
| ghost | Make background transparent and invert text and border colors | boolean | false | |
|
||||
@ -69,18 +69,16 @@ Different button styles can be generated by setting Button properties. The recom
|
||||
| loading | Set the loading status of button | boolean \| { delay: number } | false | |
|
||||
| shape | Can be set button shape | `default` \| `circle` \| `round` | `default` | |
|
||||
| size | Set the size of button | `large` \| `middle` \| `small` | `middle` | |
|
||||
| styles | Semantic DOM style | Record<SemanticDOM, CSSProperties> | - | 5.4.0 |
|
||||
| styles | Semantic DOM style | [Record<SemanticDOM, CSSProperties>](#semantic-dom) | - | 5.4.0 |
|
||||
| target | Same as target attribute of a, works when href is specified | string | - | |
|
||||
| type | Set button type | `primary` \| `dashed` \| `link` \| `text` \| `default` | `default` | |
|
||||
| onClick | Set the handler to handle `click` event | (event: MouseEvent) => void | - | |
|
||||
|
||||
It accepts all props which native buttons support.
|
||||
|
||||
### `styles` and `classNames` attribute
|
||||
## Semantic DOM
|
||||
|
||||
| Property | Description | Version |
|
||||
| -------- | ----------------- | ------- |
|
||||
| icon | set `icon`element | 5.5.0 |
|
||||
<code src="./demo/_semantic.tsx" simplify="true"></code>
|
||||
|
||||
## Design Token
|
||||
|
||||
|
@ -64,7 +64,7 @@ group:
|
||||
| 属性 | 说明 | 类型 | 默认值 | 版本 |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| block | 将按钮宽度调整为其父宽度的选项 | boolean | false | |
|
||||
| classNames | 语义化结构 class | Record<SemanticDOM, string> | - | 5.4.0 |
|
||||
| classNames | 语义化结构 class | [Record<SemanticDOM, string>](#semantic-dom) | - | 5.4.0 |
|
||||
| danger | 设置危险按钮 | boolean | false | |
|
||||
| disabled | 设置按钮失效状态 | boolean | false | |
|
||||
| ghost | 幽灵属性,使按钮背景透明 | boolean | false | |
|
||||
@ -74,18 +74,16 @@ group:
|
||||
| loading | 设置按钮载入状态 | boolean \| { delay: number } | false | |
|
||||
| shape | 设置按钮形状 | `default` \| `circle` \| `round` | `default` | |
|
||||
| size | 设置按钮大小 | `large` \| `middle` \| `small` | `middle` | |
|
||||
| styles | 语义化结构 style | Record<SemanticDOM, CSSProperties> | - | 5.4.0 |
|
||||
| styles | 语义化结构 style | [Record<SemanticDOM, CSSProperties>](#semantic-dom) | - | 5.4.0 |
|
||||
| target | 相当于 a 链接的 target 属性,href 存在时生效 | string | - | |
|
||||
| type | 设置按钮类型 | `primary` \| `dashed` \| `link` \| `text` \| `default` | `default` | |
|
||||
| onClick | 点击按钮时的回调 | (event: MouseEvent) => void | - | |
|
||||
|
||||
支持原生 button 的其他所有属性。
|
||||
|
||||
### `styles` 和 `classNames` 属性
|
||||
## Semantic DOM
|
||||
|
||||
| 名称 | 说明 | 版本 |
|
||||
| ---- | ------------ | ----- |
|
||||
| icon | 设置图标元素 | 5.5.0 |
|
||||
<code src="./demo/_semantic.tsx" simplify="true"></code>
|
||||
|
||||
## 主题变量(Design Token)
|
||||
|
||||
|
72
components/drawer/demo/_semantic.tsx
Normal file
72
components/drawer/demo/_semantic.tsx
Normal file
@ -0,0 +1,72 @@
|
||||
import React from 'react';
|
||||
import { Drawer, Typography } from 'antd';
|
||||
|
||||
import SemanticPreview from '../../../.dumi/components/SemanticPreview';
|
||||
import useLocale from '../../../.dumi/hooks/useLocale';
|
||||
|
||||
const locales = {
|
||||
cn: {
|
||||
mask: '遮罩层元素',
|
||||
content: 'Drawer 容器元素',
|
||||
header: '头部元素',
|
||||
body: '内容元素',
|
||||
footer: '底部元素',
|
||||
},
|
||||
en: {
|
||||
mask: 'Mask element',
|
||||
content: 'Drawer container element',
|
||||
header: 'Header element',
|
||||
body: 'Body element',
|
||||
footer: 'Footer element',
|
||||
},
|
||||
};
|
||||
|
||||
const App: React.FC = () => {
|
||||
const [locale] = useLocale(locales);
|
||||
|
||||
return (
|
||||
<SemanticPreview
|
||||
semantics={[
|
||||
{
|
||||
name: 'mask',
|
||||
desc: locale.mask,
|
||||
version: '5.13.0',
|
||||
},
|
||||
{
|
||||
name: 'content',
|
||||
desc: locale.content,
|
||||
version: '5.13.0',
|
||||
},
|
||||
{
|
||||
name: 'header',
|
||||
desc: locale.header,
|
||||
version: '5.13.0',
|
||||
},
|
||||
{
|
||||
name: 'body',
|
||||
desc: locale.body,
|
||||
version: '5.13.0',
|
||||
},
|
||||
{
|
||||
name: 'footer',
|
||||
desc: locale.footer,
|
||||
version: '5.13.0',
|
||||
},
|
||||
]}
|
||||
height={300}
|
||||
>
|
||||
<Drawer
|
||||
title="Title"
|
||||
placement="right"
|
||||
footer={<Typography.Link>Footer</Typography.Link>}
|
||||
closable={false}
|
||||
open
|
||||
getContainer={false}
|
||||
>
|
||||
<p>Some contents...</p>
|
||||
</Drawer>
|
||||
</SemanticPreview>
|
||||
);
|
||||
};
|
||||
|
||||
export default App;
|
@ -51,8 +51,7 @@ v5 use `rootClassName` & `rootStyle` to config wrapper style instead of `classNa
|
||||
| autoFocus | Whether Drawer should get focused after open | boolean | true | 4.17.0 |
|
||||
| afterOpenChange | Callback after the animation ends when switching drawers | function(open) | - | |
|
||||
| className | Config Drawer Panel className. Use `rootClassName` if want to config top dom style | string | - | |
|
||||
| classNames | Config Drawer build-in module's className | `header?: string; body?: string; footer?: string; mask?: string; content?: string; wrapper?: string;` | - | |
|
||||
| styles | Config Drawer build-in module's style | `header?: CSSProperties; body?: CSSProperties; footer?: CSSProperties; mask?: CSSProperties; content?: CSSProperties; wrapper?: CSSProperties;` | - | 5.10.0 |
|
||||
| classNames | Semantic structure className | [Record<SemanticDOM, string>](#semantic-dom) | - | 5.10.0 |
|
||||
| closeIcon | Custom close icon. 5.7.0: close button will be hidden when setting to `null` or `false` | ReactNode | <CloseOutlined /> | |
|
||||
| destroyOnClose | Whether to unmount child components on closing drawer or not | boolean | false | |
|
||||
| extra | Extra actions area at corner | ReactNode | - | 4.17.0 |
|
||||
@ -68,6 +67,7 @@ v5 use `rootClassName` & `rootStyle` to config wrapper style instead of `classNa
|
||||
| push | Nested drawers push behavior | boolean \| { distance: string \| number } | { distance: 180 } | 4.5.0+ |
|
||||
| rootStyle | Style of wrapper element which **contains mask** compare to `style` | CSSProperties | - | |
|
||||
| style | Style of Drawer panel. Use `bodyStyle` if want to config body only | CSSProperties | - | |
|
||||
| styles | Semantic structure style | [Record<SemanticDOM, CSSProperties>](#semantic-dom) | - | 5.10.0 |
|
||||
| size | preset size of drawer, default `378px` and large `736px` | 'default' \| 'large' | 'default' | 4.17.0 |
|
||||
| title | The title for Drawer | ReactNode | - | |
|
||||
| open | Whether the Drawer dialog is visible or not | boolean | false | |
|
||||
@ -75,6 +75,10 @@ v5 use `rootClassName` & `rootStyle` to config wrapper style instead of `classNa
|
||||
| zIndex | The `z-index` of the Drawer | number | 1000 | |
|
||||
| onClose | Specify a callback that will be called when a user clicks mask, close button or Cancel button | function(e) | - | |
|
||||
|
||||
## Semantic DOM
|
||||
|
||||
<code src="./demo/_semantic.tsx" simplify="true"></code>
|
||||
|
||||
## Design Token
|
||||
|
||||
<ComponentTokenTable component="Drawer"></ComponentTokenTable>
|
||||
|
@ -157,6 +157,9 @@ const Drawer: React.FC<DrawerProps> & {
|
||||
const [zIndex, contextZIndex] = useZIndex('Drawer', rest.zIndex);
|
||||
|
||||
// =========================== Render ===========================
|
||||
const { classNames: propClassNames = {}, styles: propStyles = {} } = rest;
|
||||
const { classNames: contextClassNames = {}, styles: contextStyles = {} } = drawer || {};
|
||||
|
||||
return wrapCSSVar(
|
||||
<NoCompactStyle>
|
||||
<NoFormStyle status override>
|
||||
@ -168,24 +171,24 @@ const Drawer: React.FC<DrawerProps> & {
|
||||
motion={panelMotion}
|
||||
{...rest}
|
||||
classNames={{
|
||||
mask: classNames(rest.classNames?.mask, drawer?.classNames?.mask),
|
||||
content: classNames(rest.classNames?.content, drawer?.classNames?.content),
|
||||
mask: classNames(propClassNames.mask, contextClassNames.mask),
|
||||
content: classNames(propClassNames.content, contextClassNames.content),
|
||||
}}
|
||||
styles={{
|
||||
mask: {
|
||||
...rest.styles?.mask,
|
||||
...propStyles.mask,
|
||||
...maskStyle,
|
||||
...drawer?.styles?.mask,
|
||||
...contextStyles.mask,
|
||||
},
|
||||
content: {
|
||||
...rest.styles?.content,
|
||||
...propStyles.content,
|
||||
...drawerStyle,
|
||||
...drawer?.styles?.content,
|
||||
...contextStyles.content,
|
||||
},
|
||||
wrapper: {
|
||||
...rest.styles?.wrapper,
|
||||
...propStyles.wrapper,
|
||||
...contentWrapperStyle,
|
||||
...drawer?.styles?.wrapper,
|
||||
...contextStyles.wrapper,
|
||||
},
|
||||
}}
|
||||
open={open ?? visible}
|
||||
|
@ -50,8 +50,7 @@ v5 使用 `rootClassName` 与 `rootStyle` 来配置最外层元素样式。原 v
|
||||
| autoFocus | 抽屉展开后是否将焦点切换至其 Dom 节点 | boolean | true | 4.17.0 |
|
||||
| afterOpenChange | 切换抽屉时动画结束后的回调 | function(open) | - | |
|
||||
| className | Drawer 容器外层 className 设置,如果需要设置最外层,请使用 rootClassName | string | - | |
|
||||
| classNames | 配置抽屉内置模块的 className | `header?: string; body?: string; footer?: string; mask?: string; content?: string; wrapper?: string;` | - | |
|
||||
| styles | 配置抽屉内置模块的 style | `header?: CSSProperties; body?: CSSProperties; footer?: CSSProperties; mask?: CSSProperties; content?: CSSProperties; wrapper?: CSSProperties;` | - | 5.10.0 |
|
||||
| classNames | 语义化结构 className | [Record<SemanticDOM, string>](#semantic-dom) | - | 5.10.0 |
|
||||
| closeIcon | 自定义关闭图标。5.7.0:设置为 `null` 或 `false` 时隐藏关闭按钮 | ReactNode | <CloseOutlined /> | |
|
||||
| destroyOnClose | 关闭时销毁 Drawer 里的子元素 | boolean | false | |
|
||||
| extra | 抽屉右上角的操作区域 | ReactNode | - | 4.17.0 |
|
||||
@ -67,12 +66,17 @@ v5 使用 `rootClassName` 与 `rootStyle` 来配置最外层元素样式。原 v
|
||||
| rootStyle | 可用于设置 Drawer 最外层容器的样式,和 `style` 的区别是作用节点包括 `mask` | CSSProperties | - | |
|
||||
| size | 预设抽屉宽度(或高度),default `378px` 和 large `736px` | 'default' \| 'large' | 'default' | 4.17.0 |
|
||||
| style | 设计 Drawer 容器样式,如果你只需要设置内容部分请使用 `bodyStyle` | CSSProperties | - | |
|
||||
| styles | 语义化结构 style | [Record<SemanticDOM, CSSProperties>](#semantic-dom) | - | 5.10.0 |
|
||||
| title | 标题 | ReactNode | - | |
|
||||
| open | Drawer 是否可见 | boolean | - |
|
||||
| width | 宽度 | string \| number | 378 | |
|
||||
| zIndex | 设置 Drawer 的 `z-index` | number | 1000 | |
|
||||
| onClose | 点击遮罩层或左上角叉或取消按钮的回调 | function(e) | - | |
|
||||
|
||||
## Semantic DOM
|
||||
|
||||
<code src="./demo/_semantic.tsx" simplify="true"></code>
|
||||
|
||||
## 主题变量(Design Token)
|
||||
|
||||
<ComponentTokenTable component="Drawer"></ComponentTokenTable>
|
||||
|
61
components/input/demo/_semantic_input.tsx
Normal file
61
components/input/demo/_semantic_input.tsx
Normal file
@ -0,0 +1,61 @@
|
||||
import React from 'react';
|
||||
import { EditOutlined, UserOutlined } from '@ant-design/icons';
|
||||
import { Input } from 'antd';
|
||||
|
||||
import SemanticPreview from '../../../.dumi/components/SemanticPreview';
|
||||
import useLocale from '../../../.dumi/hooks/useLocale';
|
||||
|
||||
const locales = {
|
||||
cn: {
|
||||
input: '输入框元素',
|
||||
prefix: '前缀的包裹元素',
|
||||
suffix: '后缀的包裹元素',
|
||||
count: '文字计数元素',
|
||||
},
|
||||
en: {
|
||||
input: 'input element',
|
||||
prefix: 'prefix element',
|
||||
suffix: 'suffix element',
|
||||
count: 'count element',
|
||||
},
|
||||
};
|
||||
|
||||
const App: React.FC = () => {
|
||||
const [locale] = useLocale(locales);
|
||||
|
||||
return (
|
||||
<SemanticPreview
|
||||
semantics={[
|
||||
{
|
||||
name: 'input',
|
||||
desc: locale.input,
|
||||
version: '5.4.0',
|
||||
},
|
||||
{
|
||||
name: 'prefix',
|
||||
desc: locale.prefix,
|
||||
version: '5.4.0',
|
||||
},
|
||||
{
|
||||
name: 'suffix',
|
||||
desc: locale.suffix,
|
||||
version: '5.4.0',
|
||||
},
|
||||
{
|
||||
name: 'count',
|
||||
desc: locale.count,
|
||||
version: '5.4.0',
|
||||
},
|
||||
]}
|
||||
>
|
||||
<Input
|
||||
prefix={<UserOutlined />}
|
||||
suffix={<EditOutlined />}
|
||||
showCount
|
||||
defaultValue="Hello, Ant Design"
|
||||
/>
|
||||
</SemanticPreview>
|
||||
);
|
||||
};
|
||||
|
||||
export default App;
|
48
components/input/demo/_semantic_textarea.tsx
Normal file
48
components/input/demo/_semantic_textarea.tsx
Normal file
@ -0,0 +1,48 @@
|
||||
import React from 'react';
|
||||
import { Input } from 'antd';
|
||||
|
||||
import SemanticPreview from '../../../.dumi/components/SemanticPreview';
|
||||
import useLocale from '../../../.dumi/hooks/useLocale';
|
||||
|
||||
const locales = {
|
||||
cn: {
|
||||
textarea: '输入框元素',
|
||||
count: '文字计数元素',
|
||||
},
|
||||
en: {
|
||||
textarea: 'textarea element',
|
||||
count: 'count element',
|
||||
},
|
||||
};
|
||||
|
||||
const App: React.FC = () => {
|
||||
const [locale] = useLocale(locales);
|
||||
|
||||
return (
|
||||
<SemanticPreview
|
||||
semantics={[
|
||||
{
|
||||
name: 'textarea',
|
||||
desc: locale.textarea,
|
||||
version: '5.4.0',
|
||||
},
|
||||
{
|
||||
name: 'count',
|
||||
desc: locale.count,
|
||||
version: '5.4.0',
|
||||
},
|
||||
]}
|
||||
>
|
||||
<Input.TextArea
|
||||
defaultValue="Hello, Ant Design"
|
||||
rows={3}
|
||||
count={{
|
||||
max: 100,
|
||||
show: true,
|
||||
}}
|
||||
/>
|
||||
</SemanticPreview>
|
||||
);
|
||||
};
|
||||
|
||||
export default App;
|
@ -138,21 +138,11 @@ Supports all props of `Input`.
|
||||
|
||||
#### Input
|
||||
|
||||
<!-- prettier-ignore -->
|
||||
| Property | Description | Version |
|
||||
| --- | --- | --- |
|
||||
| input | `input` element | 5.4.0 |
|
||||
| prefix | Wrapper of prefix | 5.4.0 |
|
||||
| suffix | Wrapper of suffix | 5.4.0 |
|
||||
| count | Text count element | 5.4.0 |
|
||||
<code src="./demo/_semantic_input.tsx" simplify="true"></code>
|
||||
|
||||
#### Input.TextArea
|
||||
|
||||
<!-- prettier-ignore -->
|
||||
| Property | Description | Version |
|
||||
| --- | --- | --- |
|
||||
| textarea | `textarea` element | 5.4.0 |
|
||||
| count | Text count element | 5.4.0 |
|
||||
<code src="./demo/_semantic_textarea.tsx" simplify="true"></code>
|
||||
|
||||
## Design Token
|
||||
|
||||
|
@ -139,19 +139,11 @@ interface CountConfig {
|
||||
|
||||
#### Input
|
||||
|
||||
| 名称 | 说明 | 版本 |
|
||||
| ------ | ------------------ | ----- |
|
||||
| input | `input` 元素 | 5.4.0 |
|
||||
| prefix | 所有前缀的包裹元素 | 5.4.0 |
|
||||
| suffix | 所有后缀的包裹元素 | 5.4.0 |
|
||||
| count | 文字计数元素 | 5.4.0 |
|
||||
<code src="./demo/_semantic_input.tsx" simplify="true"></code>
|
||||
|
||||
#### Input.TextArea
|
||||
|
||||
| 名称 | 说明 | 版本 |
|
||||
| -------- | --------------- | ----- |
|
||||
| textarea | `textarea` 元素 | 5.4.0 |
|
||||
| count | 文字计数元素 | 5.4.0 |
|
||||
<code src="./demo/_semantic_textarea.tsx" simplify="true"></code>
|
||||
|
||||
## 主题变量(Design Token)
|
||||
|
||||
|
90
components/modal/demo/_semantic.tsx
Normal file
90
components/modal/demo/_semantic.tsx
Normal file
@ -0,0 +1,90 @@
|
||||
import React from 'react';
|
||||
import { Modal, type ModalProps } from 'antd';
|
||||
|
||||
import SemanticPreview from '../../../.dumi/components/SemanticPreview';
|
||||
import useLocale from '../../../.dumi/hooks/useLocale';
|
||||
|
||||
const locales = {
|
||||
cn: {
|
||||
mask: '遮罩层元素',
|
||||
wrapper: '包裹层元素,一般用于动画容器',
|
||||
content: 'Drawer 容器元素',
|
||||
header: '头部元素',
|
||||
body: '内容元素',
|
||||
footer: '底部元素',
|
||||
},
|
||||
en: {
|
||||
mask: 'Mask element',
|
||||
wrapper: 'Wrapper element. Used for motion container',
|
||||
content: 'Drawer container element',
|
||||
header: 'Header element',
|
||||
body: 'Body element',
|
||||
footer: 'Footer element',
|
||||
},
|
||||
};
|
||||
|
||||
const BlockModal = (props: ModalProps) => {
|
||||
const divRef = React.useRef<HTMLDivElement>(null);
|
||||
|
||||
return (
|
||||
<div ref={divRef} style={{ position: 'absolute', inset: 0 }}>
|
||||
<Modal
|
||||
getContainer={() => divRef.current!}
|
||||
{...props}
|
||||
styles={
|
||||
{
|
||||
mask: {
|
||||
position: 'absolute',
|
||||
},
|
||||
wrapper: {
|
||||
position: 'absolute',
|
||||
},
|
||||
} as any
|
||||
}
|
||||
style={{
|
||||
top: '50%',
|
||||
transform: 'translateY(-50%)',
|
||||
marginBottom: 0,
|
||||
paddingBottom: 0,
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const App: React.FC = () => {
|
||||
const [locale] = useLocale(locales);
|
||||
|
||||
return (
|
||||
<SemanticPreview
|
||||
semantics={[
|
||||
{
|
||||
name: 'mask',
|
||||
desc: locale.mask,
|
||||
version: '5.13.0',
|
||||
},
|
||||
{
|
||||
name: 'header',
|
||||
desc: locale.header,
|
||||
version: '5.13.0',
|
||||
},
|
||||
{
|
||||
name: 'body',
|
||||
desc: locale.body,
|
||||
version: '5.13.0',
|
||||
},
|
||||
{
|
||||
name: 'footer',
|
||||
desc: locale.footer,
|
||||
version: '5.13.0',
|
||||
},
|
||||
]}
|
||||
>
|
||||
<BlockModal title="Title" closable={false} open getContainer={false} width={400}>
|
||||
<p>Some contents...</p>
|
||||
</BlockModal>
|
||||
</SemanticPreview>
|
||||
);
|
||||
};
|
||||
|
||||
export default App;
|
@ -190,6 +190,10 @@ const confirmed = await modal.confirm({ ... });
|
||||
| originNode | default node | React.ReactNode | - |
|
||||
| extra | extended options | { OkBtn: FC; CancelBtn: FC } | - |
|
||||
|
||||
### `styles` and `classNames` attribute
|
||||
|
||||
<code src="./demo/_semantic.tsx" simplify="true"></code>
|
||||
|
||||
## Design Token
|
||||
|
||||
<ComponentTokenTable component="Modal"></ComponentTokenTable>
|
||||
|
@ -191,6 +191,10 @@ const confirmed = await modal.confirm({ ... });
|
||||
| originNode | 默认节点 | React.ReactNode | - |
|
||||
| extra | 扩展选项 | { OkBtn: FC; CancelBtn: FC } | - |
|
||||
|
||||
### `styles` and `classNames` 属性
|
||||
|
||||
<code src="./demo/_semantic.tsx" simplify="true"></code>
|
||||
|
||||
## 主题变量(Design Token)
|
||||
|
||||
<ComponentTokenTable component="Modal"></ComponentTokenTable>
|
||||
|
55
components/slider/demo/_semantic.tsx
Normal file
55
components/slider/demo/_semantic.tsx
Normal file
@ -0,0 +1,55 @@
|
||||
import React from 'react';
|
||||
import { Slider } from 'antd';
|
||||
|
||||
import SemanticPreview from '../../../.dumi/components/SemanticPreview';
|
||||
import useLocale from '../../../.dumi/hooks/useLocale';
|
||||
|
||||
const locales = {
|
||||
cn: {
|
||||
track: '范围选择下,点和点之间单个选取条',
|
||||
tracks: '范围选择下,整个范围选取条',
|
||||
rail: '背景条元素',
|
||||
handle: '抓取点元素',
|
||||
},
|
||||
en: {
|
||||
track: 'The selection bar between points and points under the range selection',
|
||||
tracks: 'The entire range selection bar under the range selection',
|
||||
rail: 'Background rail element',
|
||||
handle: 'Grab handle element',
|
||||
},
|
||||
};
|
||||
|
||||
const App: React.FC = () => {
|
||||
const [locale] = useLocale(locales);
|
||||
|
||||
return (
|
||||
<SemanticPreview
|
||||
semantics={[
|
||||
{
|
||||
name: 'track',
|
||||
desc: locale.track,
|
||||
version: '5.10.0',
|
||||
},
|
||||
{
|
||||
name: 'tracks',
|
||||
desc: locale.tracks,
|
||||
version: '5.10.0',
|
||||
},
|
||||
{
|
||||
name: 'rail',
|
||||
desc: locale.rail,
|
||||
version: '5.10.0',
|
||||
},
|
||||
{
|
||||
name: 'handle',
|
||||
desc: locale.handle,
|
||||
version: '5.10.0',
|
||||
},
|
||||
]}
|
||||
>
|
||||
<Slider range defaultValue={[20, 30, 50]} style={{ width: '100%' }} />
|
||||
</SemanticPreview>
|
||||
);
|
||||
};
|
||||
|
||||
export default App;
|
@ -38,6 +38,7 @@ Common props ref:[Common props](/docs/react/common-props)
|
||||
| --- | --- | --- | --- | --- |
|
||||
| autoAdjustOverflow | Whether to automatically adjust the popup position | boolean | true | 5.8.0 |
|
||||
| autoFocus | Whether get focus when component mounted | boolean | false | |
|
||||
| classNames | Semantic structure className | [Record<SemanticDOM, string>](#semantic-dom) | - | 5.10.0 |
|
||||
| defaultValue | The default value of slider. When `range` is false, use number, otherwise, use \[number, number] | number \| \[number, number] | 0 \| \[0, 0] | |
|
||||
| disabled | If true, the slider will not be intractable | boolean | false | |
|
||||
| keyboard | Support using keyboard to move handlers | boolean | true | 5.2.0+ |
|
||||
@ -49,21 +50,13 @@ Common props ref:[Common props](/docs/react/common-props)
|
||||
| range | Dual thumb mode | boolean | false | |
|
||||
| reverse | Reverse the component | boolean | false | |
|
||||
| step | The granularity the slider can step through values. Must greater than 0, and be divided by (max - min) . When `marks` no null, `step` can be null | number \| null | 1 | |
|
||||
| styles | Semantic structure style | [Record<SemanticDOM, React.CSSProperties>](#semantic-dom) | - | 5.10.0 |
|
||||
| tooltip | The tooltip relate props | [tooltip](#tooltip) | - | 4.23.0 |
|
||||
| value | The value of slider. When `range` is false, use number, otherwise, use \[number, number] | number \| \[number, number] | - | |
|
||||
| vertical | If true, the slider will be vertical | boolean | false | |
|
||||
| onChangeComplete | Fire when `mouseup` or `keyup` is fired | (value) => void | - | |
|
||||
| onChange | Callback function that is fired when the user changes the slider's value | (value) => void | - | |
|
||||
|
||||
### `styles` 和 `classNames` 属性
|
||||
|
||||
| Property | Description | Version |
|
||||
| -------- | ------------------------------------------- | ------- |
|
||||
| track | The track between handle to handle in range | 5.10.0 |
|
||||
| tracks | Who track in range | 5.10.0 |
|
||||
| rail | Background rail | 5.10.0 |
|
||||
| handle | The handle pointer | 5.10.0 |
|
||||
|
||||
### range
|
||||
|
||||
| Property | Description | Type | Default | Version |
|
||||
@ -86,6 +79,10 @@ Common props ref:[Common props](/docs/react/common-props)
|
||||
| blur() | Remove focus | |
|
||||
| focus() | Get focus | |
|
||||
|
||||
## Semantic DOM
|
||||
|
||||
<code src="./demo/_semantic.tsx" simplify="true"></code>
|
||||
|
||||
## Design Token
|
||||
|
||||
<ComponentTokenTable component="Slider"></ComponentTokenTable>
|
||||
|
@ -38,7 +38,7 @@ demo:
|
||||
| 参数 | 说明 | 类型 | 默认值 | 版本 |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| autoFocus | 自动获取焦点 | boolean | false | |
|
||||
| classNames | 语义化结构 className | Record<SemanticDOM, string> | - | 5.10.0 |
|
||||
| classNames | 语义化结构 className | [Record<SemanticDOM, string>](#semantic-dom) | - | 5.10.0 |
|
||||
| defaultValue | 设置初始取值。当 `range` 为 false 时,使用 number,否则用 \[number, number] | number \| \[number, number] | 0 \| \[0, 0] | |
|
||||
| disabled | 值为 true 时,滑块为禁用状态 | boolean | false | |
|
||||
| keyboard | 支持使用键盘操作 handler | boolean | true | 5.2.0+ |
|
||||
@ -50,22 +50,13 @@ demo:
|
||||
| range | 双滑块模式 | boolean \| [range](#range) | false | |
|
||||
| reverse | 反向坐标轴 | boolean | false | |
|
||||
| step | 步长,取值必须大于 0,并且可被 (max - min) 整除。当 `marks` 不为空对象时,可以设置 `step` 为 null,此时 Slider 的可选值仅有 marks 标出来的部分 | number \| null | 1 | |
|
||||
| styles | 语义化结构 className | Record<SemanticDOM, React.CSSProperties> | - | 5.10.0 |
|
||||
| styles | 语义化结构 styles | [Record<SemanticDOM, React.CSSProperties>](#semantic-dom) | - | 5.10.0 |
|
||||
| tooltip | 设置 Tooltip 相关属性 | [tooltip](#tooltip) | - | 4.23.0 |
|
||||
| value | 设置当前取值。当 `range` 为 false 时,使用 number,否则用 \[number, number] | number \| \[number, number] | - | |
|
||||
| vertical | 值为 true 时,Slider 为垂直方向 | boolean | false | |
|
||||
| onChangeComplete | 与 `mouseup` 和 `keyup` 触发时机一致,把当前值作为参数传入 | (value) => void | - | |
|
||||
| onChange | 当 Slider 的值发生改变时,会触发 onChange 事件,并把改变后的值作为参数传入 | (value) => void | - | |
|
||||
|
||||
### `styles` 和 `classNames` 属性
|
||||
|
||||
| 名称 | 说明 | 版本 |
|
||||
| ------ | -------------------------------- | ------ |
|
||||
| track | 范围选择下,点和点之间单个选取条 | 5.10.0 |
|
||||
| tracks | 范围选择下,整个范围选取条 | 5.10.0 |
|
||||
| rail | 背景条 | 5.10.0 |
|
||||
| handle | 抓取点 | 5.10.0 |
|
||||
|
||||
### range
|
||||
|
||||
| 参数 | 说明 | 类型 | 默认值 | 版本 |
|
||||
@ -89,6 +80,10 @@ demo:
|
||||
| blur() | 移除焦点 | |
|
||||
| focus() | 获取焦点 | |
|
||||
|
||||
## Semantic DOM
|
||||
|
||||
<code src="./demo/_semantic.tsx" simplify="true"></code>
|
||||
|
||||
## 主题变量(Design Token)
|
||||
|
||||
<ComponentTokenTable component="Slider"></ComponentTokenTable>
|
||||
|
38
components/space/demo/_semantic.tsx
Normal file
38
components/space/demo/_semantic.tsx
Normal file
@ -0,0 +1,38 @@
|
||||
import React from 'react';
|
||||
import { Button, Space } from 'antd';
|
||||
|
||||
import SemanticPreview from '../../../.dumi/components/SemanticPreview';
|
||||
import useLocale from '../../../.dumi/hooks/useLocale';
|
||||
|
||||
const locales = {
|
||||
cn: {
|
||||
item: '包裹的子组件',
|
||||
},
|
||||
en: {
|
||||
item: 'Wrapped item element',
|
||||
},
|
||||
};
|
||||
|
||||
const App: React.FC = () => {
|
||||
const [locale] = useLocale(locales);
|
||||
|
||||
return (
|
||||
<SemanticPreview
|
||||
semantics={[
|
||||
{
|
||||
name: 'item',
|
||||
desc: locale.item,
|
||||
version: '5.6.0',
|
||||
},
|
||||
]}
|
||||
>
|
||||
<Space>
|
||||
<Button type="primary">Primary</Button>
|
||||
<Button>Default</Button>
|
||||
<Button type="dashed">Dashed</Button>
|
||||
</Space>
|
||||
</SemanticPreview>
|
||||
);
|
||||
};
|
||||
|
||||
export default App;
|
@ -42,9 +42,11 @@ Common props ref:[Common props](/docs/react/common-props)
|
||||
| Property | Description | Type | Default | Version |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| align | Align items | `start` \| `end` \|`center` \|`baseline` | - | 4.2.0 |
|
||||
| classNames | Semantic className | [Record<SemanticDOM, string>](#semantic-dom) | - | |
|
||||
| direction | The space direction | `vertical` \| `horizontal` | `horizontal` | 4.1.0 |
|
||||
| size | The space size | [Size](#size) \| [Size\[\]](#size) | `small` | 4.1.0 \| Array: 4.9.0 |
|
||||
| split | Set split | ReactNode | - | 4.7.0 |
|
||||
| styles | Semantic style | [Record<SemanticDOM, CSSProperties>](#semantic-dom) | - | |
|
||||
| wrap | Auto wrap line, when `horizontal` effective | boolean | false | 4.9.0 |
|
||||
|
||||
### Size
|
||||
@ -71,12 +73,9 @@ Use Space.Compact when child form components are compactly connected and the bor
|
||||
| direction | Set direction of layout | `vertical` \| `horizontal` | `horizontal` | 4.24.0 |
|
||||
| size | Set child component size | `large` \| `middle` \| `small` | `middle` | 4.24.0 |
|
||||
|
||||
### `styles` and `classNames` attribute
|
||||
## Semantic DOM
|
||||
|
||||
<!-- prettier-ignore -->
|
||||
| Property | Description | Version |
|
||||
| -------- | ------------------------- | ------- |
|
||||
| item | set `Space` child element | 5.6.0 |
|
||||
<code src="./demo/_semantic.tsx" simplify="true"></code>
|
||||
|
||||
## Design Token
|
||||
|
||||
|
@ -48,9 +48,11 @@ coverDark: https://mdn.alipayobjects.com/huamei_7uahnr/afts/img/A*37T2R6O9oi0AAA
|
||||
| 参数 | 说明 | 类型 | 默认值 | 版本 |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| align | 对齐方式 | `start` \| `end` \|`center` \|`baseline` | - | 4.2.0 |
|
||||
| classNames | 语义化 className | [Record<SemanticDOM, string>](#semantic-dom) | - | |
|
||||
| direction | 间距方向 | `vertical` \| `horizontal` | `horizontal` | 4.1.0 |
|
||||
| size | 间距大小 | [Size](#size) \| [Size\[\]](#size) | `small` | 4.1.0 \| Array: 4.9.0 |
|
||||
| split | 设置拆分 | ReactNode | - | 4.7.0 |
|
||||
| styles | 语义化 style | [Record<SemanticDOM, CSSProperties>](#semantic-dom) | - | |
|
||||
| wrap | 是否自动换行,仅在 `horizontal` 时有效 | boolean | false | 4.9.0 |
|
||||
|
||||
### Size
|
||||
@ -79,12 +81,9 @@ coverDark: https://mdn.alipayobjects.com/huamei_7uahnr/afts/img/A*37T2R6O9oi0AAA
|
||||
| direction | 指定排列方向 | `vertical` \| `horizontal` | `horizontal` | 4.24.0 |
|
||||
| size | 子组件大小 | `large` \| `middle` \| `small` | `middle` | 4.24.0 |
|
||||
|
||||
### `styles` 和 `classNames` 属性
|
||||
## Semantic DOM
|
||||
|
||||
<!-- prettier-ignore -->
|
||||
| 名称 | 说明 | 版本 |
|
||||
| ---- | --------------------- | ----- |
|
||||
| item | 设置 `Space` 包裹的子组件 | 5.6.0 |
|
||||
<code src="./demo/_semantic.tsx" simplify="true"></code>
|
||||
|
||||
## 主题变量(Design Token)
|
||||
|
||||
|
@ -50,7 +50,6 @@
|
||||
"build": "npm run compile && NODE_OPTIONS='--max-old-space-size=4096' npm run dist",
|
||||
"changelog": "git fetch origin && tsx scripts/print-changelog.ts",
|
||||
"check-commit": "tsx scripts/check-commit.ts",
|
||||
"check-ts-demo": "tsx scripts/check-ts-demo.ts",
|
||||
"clean": "antd-tools run clean && rm -rf es lib coverage dist report.html",
|
||||
"clean-lockfiles": "rm -rf package-lock.json yarn.lock",
|
||||
"collect-token-statistic": "tsx scripts/collect-token-statistic.ts",
|
||||
|
@ -24,17 +24,17 @@ exports[`site test Component components/avatar en Page 1`] = `2`;
|
||||
|
||||
exports[`site test Component components/avatar zh Page 1`] = `2`;
|
||||
|
||||
exports[`site test Component components/badge en Page 1`] = `3`;
|
||||
exports[`site test Component components/badge en Page 1`] = `2`;
|
||||
|
||||
exports[`site test Component components/badge zh Page 1`] = `3`;
|
||||
exports[`site test Component components/badge zh Page 1`] = `2`;
|
||||
|
||||
exports[`site test Component components/breadcrumb en Page 1`] = `3`;
|
||||
|
||||
exports[`site test Component components/breadcrumb zh Page 1`] = `3`;
|
||||
|
||||
exports[`site test Component components/button en Page 1`] = `2`;
|
||||
exports[`site test Component components/button en Page 1`] = `1`;
|
||||
|
||||
exports[`site test Component components/button zh Page 1`] = `2`;
|
||||
exports[`site test Component components/button zh Page 1`] = `1`;
|
||||
|
||||
exports[`site test Component components/calendar en Page 1`] = `1`;
|
||||
|
||||
@ -116,9 +116,9 @@ exports[`site test Component components/image en Page 1`] = `4`;
|
||||
|
||||
exports[`site test Component components/image zh Page 1`] = `4`;
|
||||
|
||||
exports[`site test Component components/input en Page 1`] = `8`;
|
||||
exports[`site test Component components/input en Page 1`] = `6`;
|
||||
|
||||
exports[`site test Component components/input zh Page 1`] = `8`;
|
||||
exports[`site test Component components/input zh Page 1`] = `6`;
|
||||
|
||||
exports[`site test Component components/input-number en Page 1`] = `2`;
|
||||
|
||||
@ -196,13 +196,13 @@ exports[`site test Component components/skeleton en Page 1`] = `6`;
|
||||
|
||||
exports[`site test Component components/skeleton zh Page 1`] = `6`;
|
||||
|
||||
exports[`site test Component components/slider en Page 1`] = `5`;
|
||||
exports[`site test Component components/slider en Page 1`] = `4`;
|
||||
|
||||
exports[`site test Component components/slider zh Page 1`] = `5`;
|
||||
exports[`site test Component components/slider zh Page 1`] = `4`;
|
||||
|
||||
exports[`site test Component components/space en Page 1`] = `3`;
|
||||
exports[`site test Component components/space en Page 1`] = `2`;
|
||||
|
||||
exports[`site test Component components/space zh Page 1`] = `3`;
|
||||
exports[`site test Component components/space zh Page 1`] = `2`;
|
||||
|
||||
exports[`site test Component components/spin en Page 1`] = `1`;
|
||||
|
||||
|
@ -1,86 +0,0 @@
|
||||
/* eslint-disable no-await-in-loop, no-console */
|
||||
import { spawn } from 'child_process';
|
||||
import path from 'path';
|
||||
import chalk from 'chalk';
|
||||
import fs from 'fs-extra';
|
||||
import { globSync } from 'glob';
|
||||
|
||||
(async () => {
|
||||
console.time('Execution...');
|
||||
|
||||
const demoFiles = globSync(path.join(process.cwd(), 'components/**/demo/*.md'));
|
||||
|
||||
const tmpFolder = path.resolve('components', '~tmp');
|
||||
await fs.remove(tmpFolder);
|
||||
await fs.ensureDir(tmpFolder);
|
||||
|
||||
function getTypescriptDemo(content: string, demoPath: string) {
|
||||
const lines = content.split(/[\n\r]/);
|
||||
|
||||
const tsxStartLine = lines.findIndex((line) =>
|
||||
line.replace(/\s/g, '').toLowerCase().includes('```tsx'),
|
||||
);
|
||||
|
||||
if (tsxStartLine < 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const tsxEndLine = lines.findIndex(
|
||||
(line, index) => index > tsxStartLine && line.trim() === '```',
|
||||
);
|
||||
|
||||
let script = lines.slice(tsxStartLine + 1, tsxEndLine).join('\n');
|
||||
|
||||
// insert React
|
||||
if (!script.includes('import React') && !script.includes('import * as React')) {
|
||||
script = `import React from 'react';\n${script}`;
|
||||
}
|
||||
|
||||
// Replace mountNode
|
||||
script = script.replace('mountNode', `document.getElementById('#root')`);
|
||||
|
||||
// Replace antd
|
||||
script = script.replace(`from 'antd'`, `from '..'`);
|
||||
|
||||
// Add path
|
||||
script = `/* eslint-disabled */\n// ${demoPath}\n${script}`;
|
||||
|
||||
return script;
|
||||
}
|
||||
|
||||
for (let i = 0; i < demoFiles.length; i += 1) {
|
||||
const demoPath = demoFiles[i];
|
||||
|
||||
const content = await fs.readFile(demoPath, 'utf8');
|
||||
const script = getTypescriptDemo(content, demoPath);
|
||||
|
||||
const dirs = path.dirname(demoPath).split(path.sep);
|
||||
|
||||
// Parse TSX
|
||||
if (script) {
|
||||
const tmpFile = path.join(
|
||||
tmpFolder,
|
||||
`${dirs[dirs.length - 2]}-${path.basename(demoPath).replace(/\..*/, '')}.tsx`,
|
||||
);
|
||||
await fs.writeFile(tmpFile, script, 'utf8');
|
||||
}
|
||||
}
|
||||
|
||||
const child = spawn('npm', ['run', 'tsc']);
|
||||
|
||||
child.stdout.pipe(process.stdout);
|
||||
child.stderr.pipe(process.stderr);
|
||||
|
||||
child.on('exit', async (code: number) => {
|
||||
console.timeEnd('Execution...');
|
||||
|
||||
if (code) {
|
||||
console.log(chalk.red('💥 OPS! Seems some tsx demo not pass tsc...'));
|
||||
} else {
|
||||
await fs.remove(tmpFolder);
|
||||
console.log(chalk.green('🤪 All tsx demo passed. Congratulations!'));
|
||||
}
|
||||
|
||||
process.exit(code);
|
||||
});
|
||||
})();
|
@ -2,6 +2,7 @@
|
||||
import path from 'path';
|
||||
import * as React from 'react';
|
||||
import { createCache, StyleProvider } from '@ant-design/cssinjs';
|
||||
import { ConfigProvider } from 'antd';
|
||||
import { globSync } from 'glob';
|
||||
import kebabCase from 'lodash/kebabCase';
|
||||
import { renderToString } from 'react-dom/server';
|
||||
@ -11,7 +12,6 @@ import { render } from '../utils';
|
||||
import { TriggerMockContext } from './demoTestContext';
|
||||
import { excludeWarning, isSafeWarning } from './excludeWarning';
|
||||
import rootPropsTest from './rootPropsTest';
|
||||
import { ConfigProvider } from 'antd';
|
||||
|
||||
export { rootPropsTest };
|
||||
|
||||
@ -28,7 +28,9 @@ export type Options = {
|
||||
};
|
||||
|
||||
function baseText(doInject: boolean, component: string, options: Options = {}) {
|
||||
const files = globSync(`./components/${component}/demo/*.tsx`);
|
||||
const files = globSync(`./components/${component}/demo/*.tsx`).filter(
|
||||
(file) => !file.includes('_semantic'),
|
||||
);
|
||||
files.forEach((file) => {
|
||||
// to compatible windows path
|
||||
file = file.split(path.sep).join('/');
|
||||
|
@ -251,7 +251,9 @@ type Options = {
|
||||
// eslint-disable-next-line jest/no-export
|
||||
export function imageDemoTest(component: string, options: Options = {}) {
|
||||
let describeMethod = options.skip === true ? describe.skip : describe;
|
||||
const files = globSync(`./components/${component}/demo/*.tsx`);
|
||||
const files = globSync(`./components/${component}/demo/*.tsx`).filter(
|
||||
(file) => !file.includes('_semantic'),
|
||||
);
|
||||
|
||||
files.forEach((file) => {
|
||||
if (Array.isArray(options.skip) && options.skip.some((c) => file.endsWith(c))) {
|
||||
|
@ -8,5 +8,6 @@
|
||||
"antd/locale/*": ["locale/*"]
|
||||
}
|
||||
},
|
||||
"include": ["components/*/demo/*.tsx"]
|
||||
"include": ["components/*/demo/*.tsx"],
|
||||
"exclude": ["components/*/demo/_semantic*"]
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user