chore: auto merge branches (#51236)

chore: auto merge branches
This commit is contained in:
github-actions[bot] 2024-10-15 07:18:22 +00:00 committed by GitHub
commit d52de7145e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
56 changed files with 791 additions and 262 deletions

View File

@ -36,6 +36,7 @@ const useStyle = createStyles(({ token, css, cx }) => {
cardItem: css`
&:hover {
box-shadow: ${token.boxShadowCard};
border-color: transparent;
}
`,
sliderItem: css`

View File

@ -1,13 +1,48 @@
import React from 'react';
import { SoundOutlined } from '@ant-design/icons';
import { createStyles } from 'antd-style';
const Audio: React.FC<React.PropsWithChildren<{ domId: string }>> = ({ domId, children }) => {
const useStyle = createStyles(({ css, token }) => {
const { paddingXXS, fontSizeXL, motionDurationSlow, colorLink, colorLinkHover, colorLinkActive } =
token;
return {
playBtn: css`
display: inline-flex;
justify-content: center;
align-items: center;
column-gap: ${paddingXXS}px;
margin: 0;
`,
icon: css`
font-size: ${fontSizeXL}px;
color: ${colorLink};
transition: all ${motionDurationSlow};
&:hover {
color: ${colorLinkHover};
}
&:active {
color: ${colorLinkActive};
}
`,
};
});
interface AudioProps {
id?: string;
}
const AudioControl: React.FC<React.PropsWithChildren<AudioProps>> = ({ id, children }) => {
const { styles } = useStyle();
const onClick: React.MouseEventHandler<HTMLAnchorElement> = () => {
const audio = document.querySelector<HTMLAudioElement>(`#${id}`);
audio?.play();
};
return (
<a onClick={() => document.querySelector<HTMLAudioElement>(`#${domId}`)?.play()}>
<a className={styles.playBtn} onClick={onClick}>
{children}
<SoundOutlined style={{ fontSize: 20, color: 'black' }} />
<SoundOutlined className={styles.icon} />
</a>
);
};
export default Audio;
export default AudioControl;

View File

@ -123,7 +123,7 @@ const ComponentMeta: React.FC<ComponentMetaProps> = (props) => {
}, [component, source]);
const transformComponentName = (componentName: string) => {
if (componentName === 'Notifiction' || componentName === 'Message') {
if (componentName === 'Notification' || componentName === 'Message') {
return componentName.toLowerCase();
}
return componentName;

View File

@ -1,13 +1,6 @@
import React, { useContext } from 'react';
import {
BugFilled,
BugOutlined,
CodeFilled,
CodeOutlined,
ExperimentFilled,
ExperimentOutlined,
} from '@ant-design/icons';
import { ConfigProvider, Tooltip } from 'antd';
import { BugOutlined, CodeOutlined, ExperimentOutlined } from '@ant-design/icons';
import { ConfigProvider, Tooltip, Button } from 'antd';
import classNames from 'classnames';
import { DumiDemoGrid, FormattedMessage } from 'dumi';
@ -33,10 +26,6 @@ const DemoWrapper: typeof DumiDemoGrid = ({ items }) => {
const [expandAll, setExpandAll] = useLayoutState(false);
const [enableCssVar, setEnableCssVar] = useLayoutState(true);
const expandTriggerClass = classNames('code-box-expand-trigger', {
'code-box-expand-trigger-active': expandAll,
});
const handleVisibleToggle = () => {
setShowDebug?.(!showDebug);
};
@ -84,29 +73,35 @@ const DemoWrapper: typeof DumiDemoGrid = ({ items }) => {
<FormattedMessage id={`app.component.examples.${expandAll ? 'collapse' : 'expand'}`} />
}
>
{expandAll ? (
<CodeFilled className={expandTriggerClass} onClick={handleExpandToggle} />
) : (
<CodeOutlined className={expandTriggerClass} onClick={handleExpandToggle} />
)}
<Button
type="text"
size="small"
icon={<CodeOutlined />}
onClick={handleExpandToggle}
className={expandAll ? 'icon-enabled' : ''}
/>
</Tooltip>
<Tooltip
title={
<FormattedMessage id={`app.component.examples.${showDebug ? 'hide' : 'visible'}`} />
}
>
{showDebug ? (
<BugFilled className={expandTriggerClass} onClick={handleVisibleToggle} />
) : (
<BugOutlined className={expandTriggerClass} onClick={handleVisibleToggle} />
)}
<Button
type="text"
size="small"
icon={<BugOutlined />}
onClick={handleVisibleToggle}
className={showDebug ? 'icon-enabled' : ''}
/>
</Tooltip>
<Tooltip title={enableCssVar ? locale.disableCssVar : locale.enableCssVar}>
{enableCssVar ? (
<ExperimentFilled className={expandTriggerClass} onClick={handleCssVarToggle} />
) : (
<ExperimentOutlined className={expandTriggerClass} onClick={handleCssVarToggle} />
)}
<Button
type="text"
size="small"
icon={<ExperimentOutlined />}
onClick={handleCssVarToggle}
className={enableCssVar ? 'icon-enabled' : ''}
/>
</Tooltip>
</span>
<ConfigProvider theme={{ cssVar: enableCssVar, hashed: !enableCssVar }}>

View File

@ -108,7 +108,7 @@ const CodePreviewer: React.FC<AntdPreviewerProps> = (props) => {
clientOnly,
pkgDependencyList,
} = props;
const { showDebug, codeType } = useContext(DemoContext);
const { codeType } = useContext(DemoContext);
const { pkg } = useSiteData();
const location = useLocation();
@ -420,6 +420,26 @@ createRoot(document.getElementById('container')).render(<Demo />);
</a>
</Tooltip>
)}
<form
className="code-box-code-action"
action="https://codesandbox.io/api/v1/sandboxes/define"
method="POST"
target="_blank"
ref={codeSandboxIconRef}
onClick={() => {
track({ type: 'codesandbox', demo: asset.id });
codeSandboxIconRef.current?.submit();
}}
>
<input
type="hidden"
name="parameters"
value={compress(JSON.stringify(codesanboxPrefillConfig))}
/>
<Tooltip title={<FormattedMessage id="app.demo.codesandbox" />}>
<CodeSandboxIcon className="code-box-codesandbox" />
</Tooltip>
</form>
{showRiddleButton ? (
<form
className="code-box-code-action"
@ -472,28 +492,6 @@ createRoot(document.getElementById('container')).render(<Demo />);
<CodePenIcon className="code-box-codepen" />
</Tooltip>
</form>
{showDebug && (
<form
className="code-box-code-action"
action="https://codesandbox.io/api/v1/sandboxes/define"
method="POST"
target="_blank"
ref={codeSandboxIconRef}
onClick={() => {
track({ type: 'codesandbox', demo: asset.id });
codeSandboxIconRef.current?.submit();
}}
>
<input
type="hidden"
name="parameters"
value={compress(JSON.stringify(codesanboxPrefillConfig))}
/>
<Tooltip title={<FormattedMessage id="app.demo.codesandbox" />}>
<CodeSandboxIcon className="code-box-codesandbox" />
</Tooltip>
</form>
)}
<Tooltip title={<FormattedMessage id="app.demo.separate" />}>
<a
className="code-box-code-action"

View File

@ -1,6 +1,6 @@
import React, { cloneElement, isValidElement } from 'react';
import { BugOutlined } from '@ant-design/icons';
import { Drawer, Flex, Grid, Popover, Tag, Timeline, Typography } from 'antd';
import { Drawer, Flex, Grid, Popover, Tag, Timeline, Typography, Button } from 'antd';
import type { TimelineItemProps } from 'antd';
import { createStyles } from 'antd-style';
import semver from 'semver';
@ -83,6 +83,10 @@ const useStyle = createStyles(({ token, css }) => ({
margin-bottom: 1em;
`,
versionTitle: css`
height: 28px;
line-height: 28px;
font-weight: 600;
font-size: 20px;
margin: 0 !important;
`,
versionTag: css`
@ -155,6 +159,19 @@ const ParseChangelog: React.FC<{ changelog: string }> = (props) => {
return <span>{parsedChangelog}</span>;
};
const RefLinks: React.FC<{ refs: string[] }> = ({ refs }) => {
const { styles } = useStyle();
return (
<>
{refs?.map((ref) => (
<a className={styles.linkRef} key={ref} href={ref} target="_blank" rel="noreferrer">
#{ref.match(/^.*\/(\d+)$/)?.[1]}
</a>
))}
</>
);
};
const RenderChangelogList: React.FC<{ changelogList: ChangelogInfo[] }> = ({ changelogList }) => {
const elements: React.ReactNode[] = [];
const { styles } = useStyle();
@ -168,11 +185,7 @@ const RenderChangelogList: React.FC<{ changelogList: ChangelogInfo[] }> = ({ cha
elements.push(
<li key={i}>
<ParseChangelog changelog={changelog} />
{refs?.map<React.ReactNode>((ref) => (
<a className={styles.linkRef} key={ref} href={ref} target="_blank" rel="noreferrer">
#{ref.match(/^.*\/(\d+)$/)?.[1]}
</a>
))}
<RefLinks refs={refs} />
<br />
<img
src={imgElement?.getAttribute('src') || ''}
@ -186,6 +199,7 @@ const RenderChangelogList: React.FC<{ changelogList: ChangelogInfo[] }> = ({ cha
elements.push(
<li key={i}>
<ParseChangelog changelog={changelog} />
<RefLinks refs={refs} />
</li>,
);
}
@ -236,7 +250,12 @@ const ComponentChangelog: React.FC<Readonly<React.PropsWithChildren>> = (props)
children: (
<Typography>
<Flex className={styles.versionWrap} justify="flex-start" align="center" gap="middle">
<Typography.Title className={styles.versionTitle} level={4}>
<Button
color="default"
className={styles.versionTitle}
variant="link"
href={`/changelog${lang === 'cn' ? '-cn' : ''}/#${version.replace(/\./g, '').replace(/\s.*/g, '-')}`}
>
{version}
{bugVersionInfo.match && (
<Popover
@ -264,7 +283,7 @@ const ComponentChangelog: React.FC<Readonly<React.PropsWithChildren>> = (props)
<BugOutlined className={styles.bug} />
</Popover>
)}
</Typography.Title>
</Button>
<Tag className={styles.versionTag} bordered={false} color="blue">
{changelogList[0]?.releaseDate}
</Tag>

View File

@ -71,18 +71,6 @@ const GlobalDemoStyles: React.FC = () => {
border: 1px solid ${token.colorPrimary};
}
&-expand-trigger {
position: relative;
color: #3b4357;
font-size: ${token.fontSizeXL}px;
cursor: pointer;
opacity: 0.75;
transition: all ${token.motionDurationSlow};
&:hover {
opacity: 1;
}
}
&-title {
position: absolute;
top: -14px;
@ -358,7 +346,18 @@ const GlobalDemoStyles: React.FC = () => {
inset-inline-end: 0;
display: flex;
align-items: center;
column-gap: ${token.marginSM}px;
column-gap: ${token.marginXS}px;
${antCls}-btn {
opacity: 0.6;
&.icon-enabled {
background: ${token.colorFillSecondary};
opacity: 1;
${iconCls} {
color: ${token.colorTextBase};
font-weight: bold;
}
}
}
${antCls}-row-rtl {

View File

@ -38,9 +38,9 @@ jobs:
token: ${{ secrets.GITHUB_TOKEN }}
issue-number: ${{ github.event.issue.number }}
body: |
Hello @${{ github.event.issue.user.login }}. Please provide a online reproduction by forking [this one](https://u.ant.design/repro) or provide a minimal GitHub repository like [create-react-app-antd](https://github.com/ant-design/create-react-app-antd). Issues labeled by `Need Reproduce` will be closed if no activities in 3 days.
Hello @${{ github.event.issue.user.login }}. Please provide a online reproduction by forking [this one](https://u.ant.design/reproduce) or provide a minimal GitHub repository like [create-react-app-antd](https://github.com/ant-design/create-react-app-antd). Issues labeled by `Need Reproduce` will be closed if no activities in 3 days.
你好 @${{ github.event.issue.user.login }},我们需要你提供一个在线的重现实例以便于我们帮你排查问题。你可以通过 fork 这个[在线重现案例](https://u.ant.design/repro) ,或者提供一个最小化的 GitHub 仓库(类似 [create-react-app-antd](https://github.com/ant-design/create-react-app-antd)。3 天内未跟进此 issue 将会被自动关闭。
你好 @${{ github.event.issue.user.login }},我们需要你提供一个在线的重现实例以便于我们帮你排查问题。你可以通过 fork 这个[在线重现案例](https://u.ant.design/reproduce) ,或者提供一个最小化的 GitHub 仓库(类似 [create-react-app-antd](https://github.com/ant-design/create-react-app-antd)。3 天内未跟进此 issue 将会被自动关闭。
> [什么是最小化重现,为什么这是必需的?](https://github.com/ant-design/ant-design/wiki/%E4%BB%80%E4%B9%88%E6%98%AF%E6%9C%80%E5%B0%8F%E5%8C%96%E9%87%8D%E7%8E%B0%EF%BC%8C%E4%B8%BA%E4%BB%80%E4%B9%88%E8%BF%99%E6%98%AF%E5%BF%85%E9%9C%80%E7%9A%84%EF%BC%9F)

View File

@ -1,4 +1,4 @@
{
"*.{ts,tsx,js,jsx,css,mjs,json}": ["biome check --write --no-errors-on-unmatched"],
"*.{ts,tsx,js,jsx,css,mjs,json}": ["biome check --write --no-errors-on-unmatched", "eslint"],
"*.{md,yml}": ["prettier --ignore-unknown --write"]
}

View File

@ -1,7 +1,6 @@
---
order: 6
title: Changelog
toc: false
timeline: true
tag: vVERSION
---
@ -16,6 +15,33 @@ tag: vVERSION
---
## 5.21.4
`2024-10-14`
- 🐞 Fixed Input.Search not applying the `hoverBorderColor/activeBorderColor` token for hover/active states. [#51226](https://github.com/ant-design/ant-design/pull/51226) [@iqingting](https://github.com/iqingting)
- 🐞 Fix Tree icon align issue. [#51181](https://github.com/ant-design/ant-design/pull/51181) [@Meowu](https://github.com/Meowu)
- 🐞 Fix Splitter occasionally shows unnecessary scrollbars in nested combinations. [#51169](https://github.com/ant-design/ant-design/pull/51169) [@zombieJ](https://github.com/zombieJ)
- 💄 Modify Button `textHoverBg` hover background to `colorFillTertiary`. [#51187](https://github.com/ant-design/ant-design/pull/51187) [@coding-ice](https://github.com/coding-ice)
- TypeScript
- 🤖 Improve type of Switch `eventHandler`. [#51165](https://github.com/ant-design/ant-design/pull/51165) [@thinkasany](https://github.com/thinkasany)
## 5.21.3
`2024-10-09`
- 💄 Added a scroll bar to Dropdown when having many items. [#51112](https://github.com/ant-design/ant-design/pull/51112) [@Cameron-Asdf](https://github.com/Cameron-Asdf)
- Slider [#51150](https://github.com/ant-design/ant-design/pull/51150) [@yoyo837](https://github.com/yoyo837)
- 🐞 Fix Slider issue where the `id` prop is not supported.
- 🐞 Fix Slider to address the issue causing `useLayoutEffect does nothing on the server` warning when `extractStyle` is invoked.
- 🐞 Fix ColorPicker with gradient mode, sometimes handle color will be force sync back to first handle color issue. [#51161](https://github.com/ant-design/ant-design/pull/51161) [@zombieJ](https://github.com/zombieJ)
- 🐞 Fix Table `onChange` function receiving incorrect sorter value. [#51114](https://github.com/ant-design/ant-design/pull/51114) [@nathanlao](https://github.com/nathanlao)
- Splitter
- 🐞 Fix the issue about throw a warning when Splitter nested in a hidden tab panel. [#51109](https://github.com/ant-design/ant-design/pull/51109) [@kiner-tang](https://github.com/kiner-tang)
- 🐞 Fix the issue about Splitter had unexpected gaps in Flex. [#51096](https://github.com/ant-design/ant-design/pull/51096) [@kiner-tang](https://github.com/kiner-tang)
- 🐞 MISC: Restore `react` and `react-dom` peerDependencies. [#51079](https://github.com/ant-design/ant-design/pull/51079) [@chentsulin](https://github.com/chentsulin)
- TypeScript
- 🤖 Improve type of Slider `eventName`. [#51156](https://github.com/ant-design/ant-design/pull/51156) [@thinkasany](https://github.com/thinkasany)
## 5.21.2
`2024-10-01`

View File

@ -15,6 +15,33 @@ tag: vVERSION
---
## 5.21.4
`2024-10-14`
- 🐞 修复 Input.Search 无法使用 Input Token `hoverBorderColor/activeBorderColor` 修改边框颜色的问题。[#51226](https://github.com/ant-design/ant-design/pull/51226) [@iqingting](https://github.com/iqingting)
- 🐞 修复 Tree 的图标不对齐的问题。[#51181](https://github.com/ant-design/ant-design/pull/51181) [@Meowu](https://github.com/Meowu)
- 🐞 修复 Splitter 在嵌套组合时,偶尔会出现多余滚动条的问题。[#51169](https://github.com/ant-design/ant-design/pull/51169) [@zombieJ](https://github.com/zombieJ)
- 💄 修改 Button `textHoverBg` 在悬浮状态下的背景色为 `colorFillTertiary`。[#51187](https://github.com/ant-design/ant-design/pull/51187) [@coding-ice](https://github.com/coding-ice)
- TypeScript
- 🤖 优化 Switch `eventHandler` 类型。[#51165](https://github.com/ant-design/ant-design/pull/51165) [@thinkasany](https://github.com/thinkasany)
## 5.21.3
`2024-10-09`
- 💄 优化 Dropdown 列表较长时的滚动条样式。[#51112](https://github.com/ant-design/ant-design/pull/51112) [@Cameron-Asdf](https://github.com/Cameron-Asdf)
- Slider [#51150](https://github.com/ant-design/ant-design/pull/51150) [@yoyo837](https://github.com/yoyo837)
- 🐞 修复 Slider 不支持 `id` 属性的问题。
- 🐞 修复 Slider 导致 `extractStyle` 时抛出 `useLayoutEffect does nothing on the server` 警告信息的问题。
- 🐞 修复 ColorPicker 渐变色时,部分节点颜色拖拽会被强制重置为第一个节点颜色的问题。[#51161](https://github.com/ant-design/ant-design/pull/51161) [@zombieJ](https://github.com/zombieJ)
- 🐞 修复 Table 组件在切换页面时 `onChange` 函数接收到错误的 sorter 值的问题。[#51114](https://github.com/ant-design/ant-design/pull/51114) [@nathanlao](https://github.com/nathanlao)
- Splitter
- 🐞 修复 Splitter 嵌套在一个隐藏的 Tabs 面板中时抛出警告的问题。[#51109](https://github.com/ant-design/ant-design/pull/51109) [@kiner-tang](https://github.com/kiner-tang)
- 🐞 修复 Splitter 组件在 Flex 组件下时出现异常间距的问题。[#51096](https://github.com/ant-design/ant-design/pull/51096) [@kiner-tang](https://github.com/kiner-tang)
- 🐞 杂项:重新将 `react``react-dom` 添加进 peerDependencies。[#51079](https://github.com/ant-design/ant-design/pull/51079) [@chentsulin](https://github.com/chentsulin)
- TypeScript
- 🤖 优化 Slider `eventName` 类型。[#51156](https://github.com/ant-design/ant-design/pull/51156) [@thinkasany](https://github.com/thinkasany)
## 5.21.2
`2024-10-01`

View File

@ -131,7 +131,7 @@ export default App;
- [开发者说明](https://github.com/ant-design/ant-design/wiki/Development)
- [版本发布规则](https://github.com/ant-design/ant-design/wiki/%E8%BD%AE%E5%80%BC%E8%A7%84%E5%88%99%E5%92%8C%E7%89%88%E6%9C%AC%E5%8F%91%E5%B8%83%E6%B5%81%E7%A8%8B)
- [常见问题](https://ant.design/docs/react/faq-cn)
- [Stackblitz 在线演示](https://u.ant.design/reproduce),用于报告 bug
- [在线演示](https://u.ant.design/reproduce),用于报告 bug
- [定制主题](https://ant.design/docs/react/customize-theme-cn)
- [国际化](https://ant.design/docs/react/i18n-cn)
- [成为社区协作成员](https://github.com/ant-design/ant-design/wiki/Collaborators#how-to-apply-for-being-a-collaborator)

View File

@ -113,7 +113,7 @@ export default () => (
- [Developer Instruction](https://github.com/ant-design/ant-design/wiki/Development)
- [Versioning Release Note](https://github.com/ant-design/ant-design/wiki/%E8%BD%AE%E5%80%BC%E8%A7%84%E5%88%99%E5%92%8C%E7%89%88%E6%9C%AC%E5%8F%91%E5%B8%83%E6%B5%81%E7%A8%8B)
- [FAQ](https://ant.design/docs/react/faq)
- [Stackblitz Demo](https://u.ant.design/reproduce) for bug reports
- [Online Playground](https://u.ant.design/reproduce) for bug reports
- [Customize Theme](https://ant.design/docs/react/customize-theme)
- [How to Apply for Being A Collaborator](https://github.com/ant-design/ant-design/wiki/Collaborators#how-to-apply-for-being-a-collaborator)

View File

@ -283,7 +283,7 @@ export const prepareComponentToken: GetDefaultToken<'Button'> = (token) => {
textTextColor: token.colorText,
textTextHoverColor: token.colorText,
textTextActiveColor: token.colorText,
textHoverBg: token.colorBgTextHover,
textHoverBg: token.colorFillTertiary,
defaultColor: token.colorText,
defaultBg: token.colorBgContainer,
defaultBorderColor: token.colorBorder,

View File

@ -34,17 +34,11 @@ Common props ref[Common props](/docs/react/common-props)
// import 'dayjs/locale/zh-cn';
// dayjs.locale('zh-cn');
<Calendar
dateCellRender={dateCellRender}
monthCellRender={monthCellRender}
onPanelChange={onPanelChange}
onSelect={onSelect}
/>
<Calendar cellRender={cellRender} onPanelChange={onPanelChange} onSelect={onSelect} />
```
| Property | Description | Type | Default | Version |
| --- | --- | --- | --- | --- |
| dateCellRender | Customize the display of the date cell, the returned content will be appended to the cell | function(date: Dayjs): ReactNode | - | |
| cellRender | Customize cell content | function(current: dayjs, today: dayjs, info: { originNode: React.ReactElement,today: DateType, range?: 'start' \| 'end', type: PanelMode, locale?: Locale, subType?: 'hour' \| 'minute' \| 'second' \| 'meridiem' }) => React.ReactNode | - | 5.4.0 |
| dateFullCellRender | Customize the display of the date cell, the returned content will override the cell | function(date: Dayjs): ReactNode | - | |
| fullCellRender | Customize cell content | function(current: dayjs, today: dayjs, info: { originNode: React.ReactElement,today: DateType, range?: 'start' \| 'end', type: PanelMode, locale?: Locale, subType?: 'hour' \| 'minute' \| 'second' \| 'meridiem' }) => React.ReactNode | - | 5.4.0 |
@ -54,8 +48,6 @@ Common props ref[Common props](/docs/react/common-props)
| headerRender | Render custom header in panel | function(object:{value: Dayjs, type: string, onChange: f(), onTypeChange: f()}) | - | |
| locale | The calendar's locale | object | [(default)](https://github.com/ant-design/ant-design/blob/master/components/date-picker/locale/example.json) | |
| mode | The display mode of the calendar | `month` \| `year` | `month` | |
| monthCellRender | Customize the display of the month cell, the returned content will be appended to the cell | function(date: Dayjs): ReactNode | - | |
| monthFullCellRender | Customize the display of the month cell, the returned content will override the cell | function(date: Dayjs): ReactNode | - | |
| validRange | To set valid range | \[[dayjs](https://day.js.org/), [dayjs](https://day.js.org/)] | - | |
| value | The current selected date | [dayjs](https://day.js.org/) | - | |
| onChange | Callback for when date changes | function(date: Dayjs) | - | |

View File

@ -35,17 +35,11 @@ coverDark: https://mdn.alipayobjects.com/huamei_7uahnr/afts/img/A*-p-wQLik200AAA
// import 'dayjs/locale/zh-cn';
// dayjs.locale('zh-cn');
<Calendar
dateCellRender={dateCellRender}
monthCellRender={monthCellRender}
onPanelChange={onPanelChange}
onSelect={onSelect}
/>
<Calendar cellRender={cellRender} onPanelChange={onPanelChange} onSelect={onSelect} />
```
| 参数 | 说明 | 类型 | 默认值 | 版本 |
| --- | --- | --- | --- | --- |
| dateCellRender | 自定义渲染日期单元格,返回内容会被追加到单元格,>= 5.4.0 请用 `cellRender` | function(date: Dayjs): ReactNode | - | < 5.4.0 |
| cellRender | 自定义单元格的内容 | function(current: dayjs, today: dayjs, info: { originNode: React.ReactElement,today: DateType, range?: 'start' \| 'end', type: PanelMode, locale?: Locale, subType?: 'hour' \| 'minute' \| 'second' \| 'meridiem' }) => React.ReactNode | - | 5.4.0 |
| dateFullCellRender | 自定义渲染日期单元格,返回内容覆盖单元格,>= 5.4.0 请用 `fullCellRender` | function(date: Dayjs): ReactNode | - | < 5.4.0 |
| fullCellRender | 自定义单元格的内容 | function(current: dayjs, today: dayjs, info: { originNode: React.ReactElement,today: DateType, range?: 'start' \| 'end', type: PanelMode, locale?: Locale, subType?: 'hour' \| 'minute' \| 'second' \| 'meridiem' }) => React.ReactNode | - | 5.4.0 |
@ -55,8 +49,6 @@ coverDark: https://mdn.alipayobjects.com/huamei_7uahnr/afts/img/A*-p-wQLik200AAA
| headerRender | 自定义头部内容 | function(object:{value: Dayjs, type: string, onChange: f(), onTypeChange: f()}) | - | |
| locale | 国际化配置 | object | [(默认配置)](https://github.com/ant-design/ant-design/blob/master/components/date-picker/locale/example.json) | |
| mode | 初始模式 | `month` \| `year` | `month` | |
| monthCellRender | 自定义渲染月单元格,返回内容会被追加到单元格,>= 5.4.0 请用 `cellRender` | function(date: Dayjs): ReactNode | - | < 5.4.0 |
| monthFullCellRender | 自定义渲染月单元格,返回内容覆盖单元格,>= 5.4.0 请用 `fullCellRender` | function(date: Dayjs): ReactNode | - | < 5.4.0 |
| validRange | 设置可以显示的日期 | \[[dayjs](https://day.js.org/), [dayjs](https://day.js.org/)] | - | |
| value | 展示日期 | [dayjs](https://day.js.org/) | - | |
| onChange | 日期变化回调 | function(date: Dayjs) | - | |

View File

@ -81,7 +81,7 @@ Common props ref[Common props](/docs/react/common-props)
| accordion | If true, Collapse renders as Accordion | boolean | false | |
| activeKey | Key of the active panel | string\[] \| string <br/> number\[] \| number | No default value. In [accordion mode](#collapse-demo-accordion), it's the key of the first panel | |
| bordered | Toggles rendering of the border around the collapse block | boolean | true | |
| collapsible | Specify whether the panels of children be collapsible or the trigger area of collapsible | `header` \| `icon` \| `disabled` | - | 4.9.0 |
| collapsible | Specify how to trigger Collapse. Either by clicking icon or by clicking any area in header or disable collapse functionality itself | `header` \| `icon` \| `disabled` | - | 4.9.0 |
| defaultActiveKey | Key of the initial active panel | string\[] \| string <br/> number\[] \| number | - | |
| destroyInactivePanel | Destroy Inactive Panel | boolean | false | |
| expandIcon | Allow to customize collapse icon | (panelProps) => ReactNode | - | |

View File

@ -306,4 +306,38 @@ describe('ColorPicker.gradient', () => {
expect(container.querySelector('.ant-color-picker-gradient-slider')).toBeTruthy();
});
// This test case may easily break by jsdom update
// https://github.com/ant-design/ant-design/issues/51159
it('change color 2 should not be color 1', () => {
const { container } = render(
<ColorPicker
mode={['gradient']}
open
defaultValue={[
{
color: '#FF0000',
percent: 0,
},
{
color: '#0000FF',
percent: 100,
},
]}
/>,
);
// Select second one
const handle2 = container.querySelector<HTMLElement>('.ant-slider-handle-2')!;
doDrag(container, 0, 0, handle2, true);
// Drag in the color panel
const panelHandle = container.querySelector('.ant-color-picker-saturation')!;
const mouseDown = createEvent.mouseDown(panelHandle);
fireEvent(panelHandle, mouseDown);
expect(handle2).not.toHaveStyle({
backgroundColor: 'rgb(255,0,0)',
});
});
});

View File

@ -137,7 +137,7 @@ const PanelPicker: FC = () => {
info?: Info,
) => {
const nextColor = fillColor(colorValue, info);
setPickerColor(nextColor);
setPickerColor(nextColor.isGradient() ? nextColor.getColors()[activeIndex].color : nextColor);
onChange(nextColor, fromPicker);
};

View File

@ -96,6 +96,12 @@ const genBaseStyle: GenerateStyle<DropdownToken> = (token) => {
content: '""',
},
// Makes vertical dropdowns have a scrollbar once they become taller than the viewport.
'&-menu-vertical': {
maxHeight: '100vh',
overflowY: 'auto',
},
[`&-trigger${antCls}-btn`]: {
[`& > ${iconCls}-down, & > ${antCls}-btn-icon > ${iconCls}-down`]: {
fontSize: fontSizeIcon,

View File

@ -22005,6 +22005,7 @@ exports[`renders components/form/demo/validate-other.tsx extend context correctl
>
<div
class="ant-slider ant-slider-horizontal ant-slider-with-marks"
id="validate_other_slider"
>
<div
class="ant-slider-rail"

View File

@ -9428,6 +9428,7 @@ exports[`renders components/form/demo/validate-other.tsx correctly 1`] = `
>
<div
class="ant-slider ant-slider-horizontal ant-slider-with-marks"
id="validate_other_slider"
>
<div
class="ant-slider-rail"

View File

@ -650,8 +650,6 @@ const genSearchInputStyle: GenerateStyle<InputToken> = (token: InputToken) => {
[searchPrefixCls]: {
[componentCls]: {
'&:hover, &:focus': {
borderColor: token.colorPrimaryHover,
[`+ ${componentCls}-group-addon ${searchPrefixCls}-button:not(${antCls}-btn-primary)`]: {
borderInlineStartColor: token.colorPrimaryHover,
},

View File

@ -57,10 +57,13 @@ Consult [Tooltip's documentation](/components/tooltip/#api) to find more APIs.
## FAQ
### Why does the warning findDOMNode is deprecated some times appear in strict mode?
### Why does the warning `findDOMNode is deprecated` sometimes appear in strict mode?
This is due to the implementation of `rc-trigger`. `rc-trigger` forces children to accept ref, otherwise it will fall back to findDOMNode, so children need to be native html tags. If not, you need to use `React.forwardRef` transparently passes `ref` to native html tags.
- `findDOMNode is deprecated` reproduce: <https://codesandbox.io/p/sandbox/finddomnode-c5hy96>
- Using `forwardRef` to fix: <https://codesandbox.io/p/sandbox/no-finddomnode-warning-forked-gdxczs>
## Note
Please ensure that the child node of `Popconfirm` accepts `onMouseEnter`, `onMouseLeave`, `onFocus`, `onClick` events.

View File

@ -58,10 +58,13 @@ demo:
## FAQ
### 为何在严格模式中有时候会出现 findDOMNode is deprecated 这个警告?
### 为何在严格模式中有时候会出现 `findDOMNode is deprecated` 这个警告?
这是由于 `rc-trigger` 的实现方式导致的,`rc-trigger` 强制要求 children 能够接受 ref否则就会 fallback 到 findDOMNode所以 children 需要是原生 html 标签,如果不是,则需要使用 `React.forwardRef``ref` 透传到原生 html 标签。
- `findDOMNode is deprecated` 重现:<https://codesandbox.io/p/sandbox/finddomnode-c5hy96>
- 使用 `forwardRef` 消除警告:<https://codesandbox.io/p/sandbox/no-finddomnode-warning-forked-gdxczs>
## 注意
请确保 `Popconfirm` 的子元素能接受 `onMouseEnter`、`onMouseLeave`、`onFocus`、`onClick` 事件。

View File

@ -51,10 +51,13 @@ Please ensure that the child node of `Popover` accepts `onMouseEnter`, `onMouseL
## FAQ
### Why does the warning findDOMNode is deprecated some times appear in strict mode?
### Why does the warning `findDOMNode is deprecated` sometimes appear in strict mode?
This is due to the implementation of `rc-trigger`. `rc-trigger` forces children to accept ref, otherwise it will fall back to findDOMNode, so children need to be native html tags. If not, you need to use `React.forwardRef` transparently passes `ref` to native html tags.
- `findDOMNode is deprecated` reproduce: <https://codesandbox.io/p/sandbox/finddomnode-c5hy96>
- Using `forwardRef` to fix: <https://codesandbox.io/p/sandbox/no-finddomnode-warning-forked-gdxczs>
### Why sometime not work on HOC?
Please ensure that the child node of `Tooltip` accepts `onMouseEnter`, `onMouseLeave`, `onPointerEnter`, `onPointerLeave`, `onFocus`, `onClick` events.

View File

@ -52,10 +52,13 @@ demo:
## FAQ
### 为何在严格模式中有时候会出现 findDOMNode is deprecated 这个警告?
### 为何在严格模式中有时候会出现 `findDOMNode is deprecated` 这个警告?
这是由于 `rc-trigger` 的实现方式导致的,`rc-trigger` 强制要求 children 能够接受 ref否则就会 fallback 到 findDOMNode所以 children 需要是原生 html 标签,如果不是,则需要使用 `React.forwardRef``ref` 透传到原生 html 标签。
- `findDOMNode is deprecated` 重现:<https://codesandbox.io/p/sandbox/finddomnode-c5hy96>
- 使用 `forwardRef` 消除警告:<https://codesandbox.io/p/sandbox/no-finddomnode-warning-forked-gdxczs>
### 为何有时候 HOC 组件无法生效?
请确保 `Popover` 的子元素能接受 `onMouseEnter`、`onMouseLeave`、`onPointerEnter`、`onPointerLeave`、`onFocus`、`onClick` 事件。

View File

@ -267,7 +267,7 @@ const Slider = React.forwardRef<SliderRef, SliderSingleProps | SliderRangeProps>
const nodeProps = node.props;
function proxyEvent(
eventName: string,
eventName: keyof React.DOMAttributes<HTMLElement>,
event: React.SyntheticEvent,
triggerRestPropsEvent?: boolean,
) {

View File

@ -71,7 +71,14 @@ const Splitter: React.FC<React.PropsWithChildren<SplitterProps>> = (props) => {
const [containerSize, setContainerSize] = useState<number>(100);
const onContainerResize: GetProp<typeof ResizeObserver, 'onResize'> = (size) => {
setContainerSize(isVertical ? size.offsetHeight : size.offsetWidth);
const { offsetWidth, offsetHeight } = size;
const containerSize = isVertical ? offsetHeight : offsetWidth;
// Skip when container has no size, Such as nested in a hidden tab panel
// to fix: https://github.com/ant-design/ant-design/issues/51106
if (containerSize === 0) {
return;
}
setContainerSize(containerSize);
};
// ========================= Size =========================
@ -146,65 +153,62 @@ const Splitter: React.FC<React.PropsWithChildren<SplitterProps>> = (props) => {
const mergedStyle: React.CSSProperties = { ...splitter?.style, ...style };
return wrapCSSVar(
<>
<ResizeObserver onResize={onContainerResize}>
<div style={mergedStyle} className={containerClassName}>
{items.map((item, idx) => {
// Panel
const panel = <InternalPanel {...item} prefixCls={prefixCls} size={itemPxSizes[idx]} />;
<ResizeObserver onResize={onContainerResize}>
<div style={mergedStyle} className={containerClassName}>
{items.map((item, idx) => {
// Panel
const panel = <InternalPanel {...item} prefixCls={prefixCls} size={itemPxSizes[idx]} />;
// Split Bar
let splitBar: React.ReactElement | null = null;
// Split Bar
let splitBar: React.ReactElement | null = null;
const resizableInfo = resizableInfos[idx];
if (resizableInfo) {
const ariaMinStart = (stackSizes[idx - 1] || 0) + itemPtgMinSizes[idx];
const ariaMinEnd = (stackSizes[idx + 1] || 100) - itemPtgMaxSizes[idx + 1];
const resizableInfo = resizableInfos[idx];
if (resizableInfo) {
const ariaMinStart = (stackSizes[idx - 1] || 0) + itemPtgMinSizes[idx];
const ariaMinEnd = (stackSizes[idx + 1] || 100) - itemPtgMaxSizes[idx + 1];
const ariaMaxStart = (stackSizes[idx - 1] || 0) + itemPtgMaxSizes[idx];
const ariaMaxEnd = (stackSizes[idx + 1] || 100) - itemPtgMinSizes[idx + 1];
const ariaMaxStart = (stackSizes[idx - 1] || 0) + itemPtgMaxSizes[idx];
const ariaMaxEnd = (stackSizes[idx + 1] || 100) - itemPtgMinSizes[idx + 1];
splitBar = (
<SplitBar
index={idx}
active={movingIndex === idx}
prefixCls={prefixCls}
vertical={isVertical}
resizable={resizableInfo.resizable}
ariaNow={stackSizes[idx] * 100}
ariaMin={Math.max(ariaMinStart, ariaMinEnd) * 100}
ariaMax={Math.min(ariaMaxStart, ariaMaxEnd) * 100}
startCollapsible={resizableInfo.startCollapsible}
endCollapsible={resizableInfo.endCollapsible}
onOffsetStart={onInternalResizeStart}
onOffsetUpdate={(index, offsetX, offsetY) => {
let offset = isVertical ? offsetY : offsetX;
if (reverse) {
offset = -offset;
}
onInternalResizeUpdate(index, offset);
}}
onOffsetEnd={onInternalResizeEnd}
onCollapse={onInternalCollapse}
/>
);
}
return (
<React.Fragment key={`split-panel-${idx}`}>
{panel}
{splitBar}
</React.Fragment>
splitBar = (
<SplitBar
index={idx}
active={movingIndex === idx}
prefixCls={prefixCls}
vertical={isVertical}
resizable={resizableInfo.resizable}
ariaNow={stackSizes[idx] * 100}
ariaMin={Math.max(ariaMinStart, ariaMinEnd) * 100}
ariaMax={Math.min(ariaMaxStart, ariaMaxEnd) * 100}
startCollapsible={resizableInfo.startCollapsible}
endCollapsible={resizableInfo.endCollapsible}
onOffsetStart={onInternalResizeStart}
onOffsetUpdate={(index, offsetX, offsetY) => {
let offset = isVertical ? offsetY : offsetX;
if (reverse) {
offset = -offset;
}
onInternalResizeUpdate(index, offset);
}}
onOffsetEnd={onInternalResizeEnd}
onCollapse={onInternalCollapse}
/>
);
})}
</div>
</ResizeObserver>
}
{/* Fake mask for cursor */}
{typeof movingIndex === 'number' && (
<div aria-hidden className={classNames(maskCls, `${maskCls}-${layout}`)} />
)}
</>,
return (
<React.Fragment key={`split-panel-${idx}`}>
{panel}
{splitBar}
</React.Fragment>
);
})}
{/* Fake mask for cursor */}
{typeof movingIndex === 'number' && (
<div aria-hidden className={classNames(maskCls, `${maskCls}-${layout}`)} />
)}
</div>
</ResizeObserver>,
);
};

View File

@ -810,6 +810,132 @@ exports[`renders components/splitter/demo/multiple.tsx extend context correctly
exports[`renders components/splitter/demo/multiple.tsx extend context correctly 2`] = `[]`;
exports[`renders components/splitter/demo/nested-in-tabs.tsx extend context correctly 1`] = `
<div
class="ant-tabs ant-tabs-top"
>
<div
class="ant-tabs-nav"
role="tablist"
>
<div
class="ant-tabs-nav-wrap"
>
<div
class="ant-tabs-nav-list"
style="transform: translate(0px, 0px);"
>
<div
class="ant-tabs-tab ant-tabs-tab-active"
data-node-key="1"
>
<div
aria-controls="rc-tabs-test-panel-1"
aria-selected="true"
class="ant-tabs-tab-btn"
id="rc-tabs-test-tab-1"
role="tab"
tabindex="0"
>
General
</div>
</div>
<div
class="ant-tabs-tab"
data-node-key="2"
>
<div
aria-controls="rc-tabs-test-panel-2"
aria-selected="false"
class="ant-tabs-tab-btn"
id="rc-tabs-test-tab-2"
role="tab"
tabindex="0"
>
Splitter Tab
</div>
</div>
<div
class="ant-tabs-ink-bar ant-tabs-ink-bar-animated"
/>
</div>
</div>
<div
class="ant-tabs-nav-operations ant-tabs-nav-operations-hidden"
>
<button
aria-controls="rc-tabs-test-more-popup"
aria-expanded="false"
aria-haspopup="listbox"
aria-hidden="true"
class="ant-tabs-nav-more"
id="rc-tabs-test-more"
style="visibility: hidden; order: 1;"
tabindex="-1"
type="button"
>
<span
aria-label="ellipsis"
class="anticon anticon-ellipsis"
role="img"
>
<svg
aria-hidden="true"
data-icon="ellipsis"
fill="currentColor"
focusable="false"
height="1em"
viewBox="64 64 896 896"
width="1em"
>
<path
d="M176 511a56 56 0 10112 0 56 56 0 10-112 0zm280 0a56 56 0 10112 0 56 56 0 10-112 0zm280 0a56 56 0 10112 0 56 56 0 10-112 0z"
/>
</svg>
</span>
</button>
<div
class="ant-tabs-dropdown ant-slide-up-appear ant-slide-up-appear-prepare ant-slide-up ant-tabs-dropdown-placement-bottomLeft"
style="--arrow-x: 0px; --arrow-y: 0px; left: -1000vw; top: -1000vh; box-sizing: border-box;"
>
<ul
aria-label="expanded dropdown"
class="ant-tabs-dropdown-menu ant-tabs-dropdown-menu-root ant-tabs-dropdown-menu-vertical"
data-menu-list="true"
id="rc-tabs-test-more-popup"
role="listbox"
tabindex="-1"
/>
<div
aria-hidden="true"
style="display: none;"
/>
</div>
</div>
</div>
<div
class="ant-tabs-content-holder"
>
<div
class="ant-tabs-content ant-tabs-content-top"
>
<div
aria-hidden="false"
aria-labelledby="rc-tabs-test-tab-1"
class="ant-tabs-tabpane ant-tabs-tabpane-active"
id="rc-tabs-test-panel-1"
role="tabpanel"
tabindex="0"
>
Content of Tab Pane 1
</div>
</div>
</div>
</div>
`;
exports[`renders components/splitter/demo/nested-in-tabs.tsx extend context correctly 2`] = `[]`;
exports[`renders components/splitter/demo/size.tsx extend context correctly 1`] = `
<div
class="ant-splitter ant-splitter-horizontal"

View File

@ -826,6 +826,107 @@ exports[`renders components/splitter/demo/multiple.tsx correctly 1`] = `
</div>
`;
exports[`renders components/splitter/demo/nested-in-tabs.tsx correctly 1`] = `
<div
class="ant-tabs ant-tabs-top"
>
<div
class="ant-tabs-nav"
role="tablist"
>
<div
class="ant-tabs-nav-wrap"
>
<div
class="ant-tabs-nav-list"
style="transform:translate(0px, 0px)"
>
<div
class="ant-tabs-tab ant-tabs-tab-active"
data-node-key="1"
>
<div
aria-selected="true"
class="ant-tabs-tab-btn"
role="tab"
tabindex="0"
>
General
</div>
</div>
<div
class="ant-tabs-tab"
data-node-key="2"
>
<div
aria-selected="false"
class="ant-tabs-tab-btn"
role="tab"
tabindex="0"
>
Splitter Tab
</div>
</div>
<div
class="ant-tabs-ink-bar ant-tabs-ink-bar-animated"
/>
</div>
</div>
<div
class="ant-tabs-nav-operations ant-tabs-nav-operations-hidden"
>
<button
aria-controls="null-more-popup"
aria-expanded="false"
aria-haspopup="listbox"
aria-hidden="true"
class="ant-tabs-nav-more"
id="null-more"
style="visibility:hidden;order:1"
tabindex="-1"
type="button"
>
<span
aria-label="ellipsis"
class="anticon anticon-ellipsis"
role="img"
>
<svg
aria-hidden="true"
data-icon="ellipsis"
fill="currentColor"
focusable="false"
height="1em"
viewBox="64 64 896 896"
width="1em"
>
<path
d="M176 511a56 56 0 10112 0 56 56 0 10-112 0zm280 0a56 56 0 10112 0 56 56 0 10-112 0zm280 0a56 56 0 10112 0 56 56 0 10-112 0z"
/>
</svg>
</span>
</button>
</div>
</div>
<div
class="ant-tabs-content-holder"
>
<div
class="ant-tabs-content ant-tabs-content-top"
>
<div
aria-hidden="false"
class="ant-tabs-tabpane ant-tabs-tabpane-active"
role="tabpanel"
tabindex="0"
>
Content of Tab Pane 1
</div>
</div>
</div>
</div>
`;
exports[`renders components/splitter/demo/size.tsx correctly 1`] = `
<div
class="ant-splitter ant-splitter-horizontal"

View File

@ -270,6 +270,27 @@ describe('Splitter', () => {
expect(onResize).toHaveBeenCalledWith([50, 0, 50]);
expect(onResizeEnd).toHaveBeenCalledWith([50, 0, 50]);
});
it("aria-valuemin/aria-valuemax should not set NaN When container's width be setting zero", async () => {
containerSize = 0;
const App: React.FC = () => {
return <SplitterDemo items={[{}, {}, {}]} />;
};
const { container } = render(<App />);
mockDrag(container.querySelectorAll<HTMLDivElement>('.ant-splitter-bar-dragger')[1], -100);
triggerResize(container.querySelector('.ant-splitter')!);
await act(async () => {
await waitFakeTimer();
});
expect(errSpy).not.toHaveBeenCalled();
expect(container.querySelector('[aria-valuemin]')?.getAttribute('aria-valuemin')).not.toBe(
'NaN',
);
expect(container.querySelector('[aria-valuemax]')?.getAttribute('aria-valuemax')).not.toBe(
'NaN',
);
});
});
// ============================= Collapsible =============================

View File

@ -0,0 +1,7 @@
## zh-CN
嵌套在标签页中。
## en-US
Nested in tabs.

View File

@ -0,0 +1,54 @@
import React from 'react';
import { Flex, Splitter, Tabs, Typography } from 'antd';
const Desc: React.FC<Readonly<{ text?: string | number }>> = (props) => (
<Flex justify="center" align="center" style={{ height: '100%' }}>
<Typography.Title type="secondary" level={5} style={{ whiteSpace: 'nowrap' }}>
{props.text}
</Typography.Title>
</Flex>
);
const App: React.FC = () => {
const SplitterContent = (
<Splitter
style={{
height: 200,
boxShadow: '0 0 10px rgba(0, 0, 0, 0.1)',
}}
>
<Splitter.Panel collapsible>
<Desc text={1} />
</Splitter.Panel>
<Splitter.Panel
collapsible={{
start: true,
}}
>
<Desc text={2} />
</Splitter.Panel>
<Splitter.Panel>
<Desc text={3} />
</Splitter.Panel>
</Splitter>
);
return (
<Tabs
defaultActiveKey="1"
items={[
{
key: '1',
label: 'General',
children: 'Content of Tab Pane 1',
},
{
key: '2',
label: 'Splitter Tab',
children: SplitterContent,
},
]}
/>
);
};
export default App;

View File

@ -23,6 +23,7 @@ Can be used to separate areas horizontally or vertically. When you need to freel
<code src="./demo/collapsible.tsx">Collapsible</code>
<code src="./demo/multiple.tsx">Multiple panels</code>
<code src="./demo/group.tsx">Complex combination</code>
<code src="./demo/nested-in-tabs.tsx" debug>Nested in tabs</code>
<code src="./demo/debug.tsx" debug>Debug</code>
## API

View File

@ -26,6 +26,7 @@ tag: 5.21.0
<code src="./demo/collapsible.tsx">可折叠</code>
<code src="./demo/multiple.tsx">多面板</code>
<code src="./demo/group.tsx">复杂组合</code>
<code src="./demo/nested-in-tabs.tsx" debug>标签页中嵌套</code>
<code src="./demo/debug.tsx" debug>调试</code>
## API

View File

@ -6,12 +6,18 @@ import { genStyleHooks } from '../../theme/internal';
export interface ComponentToken {
/**
* @desc
* @descEN Height of content area
* @desc
* @descEN Drag and drop the identity element size
* @deprecated Please use `splitBarDraggableSize` instead.
*/
resizeSpinnerSize: number;
/**
* @desc
* @descEN Drag and drop the identity element size
*/
splitBarDraggableSize: number;
/**
* @desc
* @descEN Drag the element size
*/
splitBarSize: number;
@ -71,7 +77,7 @@ const genSplitterStyle: GenerateStyle<SplitterToken> = (token: SplitterToken): C
const {
componentCls,
colorFill,
resizeSpinnerSize,
splitBarDraggableSize,
splitBarSize,
splitTriggerSize,
controlItemBgHover,
@ -223,7 +229,7 @@ const genSplitterStyle: GenerateStyle<SplitterToken> = (token: SplitterToken): C
},
'&:after': {
height: resizeSpinnerSize,
height: splitBarDraggableSize,
width: splitBarSize,
},
},
@ -278,7 +284,7 @@ const genSplitterStyle: GenerateStyle<SplitterToken> = (token: SplitterToken): C
},
'&:after': {
width: resizeSpinnerSize,
width: splitBarDraggableSize,
height: splitBarSize,
},
},
@ -309,9 +315,15 @@ const genSplitterStyle: GenerateStyle<SplitterToken> = (token: SplitterToken): C
padding: '0 1px',
scrollbarWidth: 'thin',
boxSizing: 'border-box',
},
[`${splitPanelCls}-hidden`]: {
padding: 0,
'&-hidden': {
padding: 0,
overflow: 'hidden',
},
[`&:has(${componentCls}:only-child)`]: {
overflow: 'hidden',
},
},
...genRtlStyle(token),
@ -323,11 +335,14 @@ export const prepareComponentToken: GetDefaultToken<'Splitter'> = (token) => {
const splitBarSize = token.splitBarSize || 2;
const splitTriggerSize = token.splitTriggerSize || 6;
// https://github.com/ant-design/ant-design/pull/51223
const resizeSpinnerSize = token.resizeSpinnerSize || 20;
const splitBarDraggableSize = token.splitBarDraggableSize ?? resizeSpinnerSize;
return {
splitBarSize,
splitTriggerSize,
splitBarDraggableSize,
resizeSpinnerSize,
};
};

View File

@ -2,6 +2,7 @@ import * as React from 'react';
import LoadingOutlined from '@ant-design/icons/LoadingOutlined';
import classNames from 'classnames';
import RcSwitch from 'rc-switch';
import type { SwitchChangeEventHandler, SwitchClickEventHandler } from 'rc-switch';
import useMergedState from 'rc-util/lib/hooks/useMergedState';
import Wave from '../_util/wave';
@ -11,11 +12,7 @@ import useSize from '../config-provider/hooks/useSize';
import useStyle from './style';
export type SwitchSize = 'small' | 'default';
export type SwitchChangeEventHandler = (
checked: boolean,
event: React.MouseEvent<HTMLButtonElement>,
) => void;
export type SwitchClickEventHandler = SwitchChangeEventHandler;
export type { SwitchChangeEventHandler, SwitchClickEventHandler };
export interface SwitchProps {
prefixCls?: string;
@ -110,11 +107,10 @@ const InternalSwitch = React.forwardRef<HTMLButtonElement, SwitchProps>((props,
return wrapCSSVar(
<Wave component="Switch">
{/* @ts-ignore */}
<RcSwitch
{...restProps}
checked={checked}
onChange={changeHandler as any}
onChange={changeHandler}
prefixCls={prefixCls}
className={classes}
style={mergedStyle}

View File

@ -306,8 +306,55 @@ describe('Table.sorter', () => {
const sorter3 = handleChange.mock.calls[2][2];
expect(sorter3.column).toBe(undefined);
expect(sorter3.order).toBe(undefined);
expect(sorter3.field).toBe('name');
expect(sorter3.columnKey).toBe('name');
expect(sorter3.field).toBe(undefined);
expect(sorter3.columnKey).toBe(undefined);
});
it('should not retain sorter value when page changes after cancelling sort', () => {
const handleChange = jest.fn();
const { container } = render(
createTable({
onChange: handleChange,
pagination: { pageSize: 2 },
}),
);
// ascending sort
fireEvent.click(container.querySelector('.ant-table-column-sorters')!);
expect(handleChange).toHaveBeenCalledTimes(1);
let sorter = handleChange.mock.calls[0][2];
expect(sorter.column.dataIndex).toBe('name');
expect(sorter.order).toBe('ascend');
expect(sorter.field).toBe('name');
expect(sorter.columnKey).toBe('name');
// descending sort
fireEvent.click(container.querySelector('.ant-table-column-sorters')!);
expect(handleChange).toHaveBeenCalledTimes(2);
sorter = handleChange.mock.calls[1][2];
expect(sorter.column.dataIndex).toBe('name');
expect(sorter.order).toBe('descend');
expect(sorter.field).toBe('name');
expect(sorter.columnKey).toBe('name');
// cancel sort
fireEvent.click(container.querySelector('.ant-table-column-sorters')!);
expect(handleChange).toHaveBeenCalledTimes(3);
sorter = handleChange.mock.calls[2][2];
expect(sorter.column).toBe(undefined);
expect(sorter.order).toBe(undefined);
expect(sorter.field).toBe(undefined);
expect(sorter.columnKey).toBe(undefined);
// change page
fireEvent.click(container.querySelector('.ant-pagination-item-2')!);
expect(handleChange).toHaveBeenCalledTimes(4);
sorter = handleChange.mock.calls[3][2];
expect(sorter.column).toBe(undefined);
expect(sorter.order).toBe(undefined);
expect(sorter.field).toBe(undefined);
expect(sorter.columnKey).toBe(undefined);
});
it('hover header show sorter tooltip', () => {
@ -1141,7 +1188,10 @@ describe('Table.sorter', () => {
<Table columns={groupColumns} {...dataProp} onChange={onChange} />,
);
function clickToMatchExpect(index: number, sorter: { field: string; order: SortOrder }) {
function clickToMatchExpect(
index: number,
sorter: { field: string | undefined; order: SortOrder },
) {
fireEvent.click(container.querySelectorAll('.ant-table-column-sorters')[index]);
expect(onChange).toHaveBeenCalledWith(
@ -1157,12 +1207,12 @@ describe('Table.sorter', () => {
// First
clickToMatchExpect(0, { field: 'math', order: 'ascend' });
clickToMatchExpect(0, { field: 'math', order: 'descend' });
clickToMatchExpect(0, { field: 'math', order: undefined as unknown as SortOrder });
clickToMatchExpect(0, { field: undefined, order: undefined as unknown as SortOrder });
// Last
clickToMatchExpect(1, { field: 'english', order: 'ascend' });
clickToMatchExpect(1, { field: 'english', order: 'descend' });
clickToMatchExpect(1, { field: 'english', order: undefined as unknown as SortOrder });
clickToMatchExpect(1, { field: undefined, order: undefined as unknown as SortOrder });
});
// https://github.com/ant-design/ant-design/issues/37024

View File

@ -356,7 +356,7 @@ exports[`Table renders empty table with fixed columns should work 1`] = `
class="ant-spin-container"
>
<div
class="ant-table ant-table-empty ant-table-ping-right ant-table-fixed-column ant-table-scroll-horizontal ant-table-has-fix-left ant-table-has-fix-right"
class="ant-table ant-table-empty ant-table-fixed-column ant-table-scroll-horizontal ant-table-has-fix-left ant-table-has-fix-right"
>
<div
class="ant-table-container"

View File

@ -281,9 +281,9 @@ const injectSorter = <RecordType extends AnyObject = AnyObject>(
};
const stateToInfo = <RecordType extends AnyObject = AnyObject>(
sorterStates: SortState<RecordType>,
sorterState: SortState<RecordType>,
): SorterResult<RecordType> => {
const { column, sortOrder } = sorterStates;
const { column, sortOrder } = sorterState;
return {
column,
order: sortOrder,
@ -295,25 +295,28 @@ const stateToInfo = <RecordType extends AnyObject = AnyObject>(
const generateSorterInfo = <RecordType extends AnyObject = AnyObject>(
sorterStates: SortState<RecordType>[],
): SorterResult<RecordType> | SorterResult<RecordType>[] => {
const list = sorterStates
const activeSorters = sorterStates
.filter(({ sortOrder }) => sortOrder)
.map<SorterResult<RecordType>>(stateToInfo);
// =========== Legacy compatible support ===========
// https://github.com/ant-design/ant-design/pull/19226
if (list.length === 0 && sorterStates.length) {
if (activeSorters.length === 0 && sorterStates.length) {
const lastIndex = sorterStates.length - 1;
return {
...stateToInfo(sorterStates[lastIndex]),
column: undefined,
order: undefined,
field: undefined,
columnKey: undefined,
};
}
if (list.length <= 1) {
return list[0] || {};
if (activeSorters.length <= 1) {
return activeSorters[0] || {};
}
return list;
return activeSorters;
};
export const getSortData = <RecordType extends AnyObject = AnyObject>(

View File

@ -68,10 +68,13 @@ The following APIs are shared by Tooltip, Popconfirm, Popover.
## FAQ
### Why does the warning findDOMNode is deprecated some times appear in strict mode?
### Why does the warning `findDOMNode is deprecated` sometimes appear in strict mode?
This is due to the implementation of `rc-trigger`. `rc-trigger` forces children to accept ref, otherwise it will fall back to findDOMNode, so children need to be native html tags. If not, you need to use `React.forwardRef` transparently passes `ref` to native html tags.
- `findDOMNode is deprecated` reproduce: <https://codesandbox.io/p/sandbox/finddomnode-c5hy96>
- Using `forwardRef` to fix: <https://codesandbox.io/p/sandbox/no-finddomnode-warning-forked-gdxczs>
### Why sometime not work on HOC?
Please ensure that the child node of `Tooltip` accepts `onMouseEnter`, `onMouseLeave`, `onPointerEnter`, `onPointerLeave`, `onFocus`, `onClick` events.

View File

@ -70,10 +70,13 @@ demo:
## FAQ
### 为何在严格模式中有时候会出现 findDOMNode is deprecated 这个警告?
### 为何在严格模式中有时候会出现 `findDOMNode is deprecated` 这个警告?
这是由于 `rc-trigger` 的实现方式导致的,`rc-trigger` 强制要求 children 能够接受 ref否则就会 fallback 到 findDOMNode所以 children 需要是原生 html 标签,如果不是,则需要使用 `React.forwardRef``ref` 透传到原生 html 标签。
- `findDOMNode is deprecated` 重现:<https://codesandbox.io/p/sandbox/finddomnode-c5hy96>
- 使用 `forwardRef` 消除警告:<https://codesandbox.io/p/sandbox/no-finddomnode-warning-forked-gdxczs>
### 为何有时候 HOC 组件无法生效?
请确保 `Tooltip` 的子元素能接受 `onMouseEnter`、`onMouseLeave`、`onPointerEnter`、`onPointerLeave`、`onFocus`、`onClick` 事件。

View File

@ -258,6 +258,10 @@ export const genBaseStyle = (prefixCls: string, token: TreeToken): CSSObject =>
cursor: 'pointer',
userSelect: 'none',
transition: `all ${token.motionDurationSlow}`,
marginInlineEnd: token
.calc(token.calc(titleHeight).sub(token.controlInteractiveSize))
.div(2)
.equal(),
'&-noop': {
cursor: 'unset',

View File

@ -60,6 +60,7 @@ export const getLinkStyles: GenerateStyle<TypographyToken, CSSObject> = (token)
return {
'a&, a': {
...operationUnit(token),
userSelect: 'text',
[`&[disabled], &${componentCls}-disabled`]: {
color: token.colorTextDisabled,

View File

@ -534,6 +534,7 @@ exports[`renders components/watermark/demo/custom.tsx extend context correctly 1
>
<div
class="ant-slider ant-slider-horizontal"
id="fontSize"
>
<div
class="ant-slider-rail"
@ -609,6 +610,7 @@ exports[`renders components/watermark/demo/custom.tsx extend context correctly 1
>
<div
class="ant-slider ant-slider-horizontal"
id="zIndex"
>
<div
class="ant-slider-rail"
@ -684,6 +686,7 @@ exports[`renders components/watermark/demo/custom.tsx extend context correctly 1
>
<div
class="ant-slider ant-slider-horizontal"
id="rotate"
>
<div
class="ant-slider-rail"

View File

@ -158,6 +158,7 @@ exports[`renders components/watermark/demo/custom.tsx correctly 1`] = `
>
<div
class="ant-slider ant-slider-horizontal"
id="fontSize"
>
<div
class="ant-slider-rail"
@ -214,6 +215,7 @@ exports[`renders components/watermark/demo/custom.tsx correctly 1`] = `
>
<div
class="ant-slider ant-slider-horizontal"
id="zIndex"
>
<div
class="ant-slider-rail"
@ -270,6 +272,7 @@ exports[`renders components/watermark/demo/custom.tsx correctly 1`] = `
>
<div
class="ant-slider ant-slider-horizontal"
id="rotate"
>
<div
class="ant-slider-rail"

View File

@ -56,7 +56,7 @@ tag: 5.1.0
| fontWeight | 字体粗细 | `normal` \| `light` \| `weight` \| number | normal | |
| fontFamily | 字体类型 | string | sans-serif | |
| fontStyle | 字体样式 | `none` \| `normal` \| `italic` \| `oblique` | normal | |
| textAlign | 指定文本对齐方向 | [CanvasTextAlign](https://developer.mozilla.org/docs/Web/API/CanvasRenderingContext2D/textAlign) | 5.10.0 |
| textAlign | 指定文本对齐方向 | [CanvasTextAlign](https://developer.mozilla.org/docs/Web/API/CanvasRenderingContext2D/textAlign) | `center` | 5.10.0 |
## 主题变量Design Token

View File

@ -95,7 +95,7 @@ renderToString(
const styleText = extractStyle(cache);
```
Of course, this is a little cumbersome for developers. So we extracted a three-party package to achieve this requirement:
Of course, this is a little cumbersome for developers. So we extracted a third-party package to achieve this requirement:
```tsx
import { extractStyle } from '@ant-design/static-style-extract';

View File

@ -31,7 +31,7 @@ There is a special design interaction in Ant Design, which is the click wave eff
- <img alt="Radio" height="70" src="https://github.com/react-component/picker/assets/5378891/9f4edaa8-26f7-468c-bcf3-1ce80163bf0e" />
- <img alt="Switch" height="84" src="https://github.com/react-component/picker/assets/5378891/16abcee6-32d0-4075-bc4c-440d8aade067" />
In the past major versions, this wave effect could not be modified. If want to turn it off, developers even need to do some "magic code" to achieve it. So when the designer proposed a happy work theme, as a developer, we think this is a good time to make some changes.
In the past major versions, this wave effect could not be modified. If developers want to turn it off, they even need to do some "magic code" to achieve it. So when the designer proposed a happy work theme, as a developer, we think this is a good time to make some changes.
### Wave component

View File

@ -54,8 +54,6 @@ These code can run perfectly in React 17, and also run very well in React 18's S
The StrictMode of React 18 is different from [React 17](https://17.reactjs.org/docs/strict-mode.html) in that it will be called multiple times in each phase to ensure that developers clean up the Effect:
````tsx
```tsx
const My = () => {
console.log('render');
@ -85,7 +83,7 @@ const My = () => {
// - effect
// - effect cleanup
// - effect
````
```
With above sample, we can know that `counter` in StrictMode will be accumulated, but the final value will be correct (that is, each component will only be counted once):

View File

@ -7,7 +7,7 @@ title: Ant Design of React
<source src="https://mdn.alipayobjects.com/huamei_iwk9zp/afts/file/A*ChCdRJ0w8SUAAAAAAAAAAAAADgCCAQ" type="audio/mpeg">
</audio>
Following the Ant Design specification, we developed a React UI library `antd` (<Audio domId="antd-audio">Pronunciation </Audio>) that contains a set of high quality components and demos for building rich, interactive user interfaces.
Following the Ant Design specification, we developed a React UI library `antd` (<Audio id="antd-audio">Pronunciation</Audio>) that contains a set of high quality components and demos for building rich, interactive user interfaces.
<div class="pic-plus">
<img width="150" draggable="false" src="https://gw.alipayobjects.com/zos/rmsportal/KDpgvguMpGfqaHPjicRK.svg" />

View File

@ -7,7 +7,7 @@ title: Ant Design of React
<source src="https://mdn.alipayobjects.com/huamei_iwk9zp/afts/file/A*ChCdRJ0w8SUAAAAAAAAAAAAADgCCAQ" type="audio/mpeg">
</audio>
`antd`<Audio domId="antd-audio">如何发音?</Audio>)是基于 Ant Design 设计体系的 React UI 组件库,适合企业级中后台产品与前台桌面网站。
`antd`<Audio id="antd-audio">如何发音?</Audio>)是基于 Ant Design 设计体系的 React UI 组件库,适合企业级中后台产品与前台桌面网站。
<div class="pic-plus">
<img width="150" draggable="false" src="https://gw.alipayobjects.com/zos/rmsportal/KDpgvguMpGfqaHPjicRK.svg"/>

View File

@ -1,6 +1,6 @@
{
"name": "antd",
"version": "5.21.2",
"version": "5.21.4",
"description": "An enterprise-class UI design language and React components implementation",
"license": "MIT",
"funding": {
@ -107,7 +107,7 @@
"dependencies": {
"@ant-design/colors": "^7.1.0",
"@ant-design/cssinjs": "^1.21.1",
"@ant-design/cssinjs-utils": "^1.1.0",
"@ant-design/cssinjs-utils": "^1.1.1",
"@ant-design/icons": "^5.5.1",
"@ant-design/react-slick": "~1.1.2",
"@babel/runtime": "^7.25.6",
@ -141,7 +141,7 @@
"rc-resize-observer": "^1.4.0",
"rc-segmented": "~2.5.0",
"rc-select": "~14.15.2",
"rc-slider": "~11.1.6",
"rc-slider": "~11.1.7",
"rc-steps": "~6.0.1",
"rc-switch": "~4.1.0",
"rc-table": "~7.48.0",
@ -173,7 +173,7 @@
"@emotion/server": "^11.11.0",
"@eslint-react/eslint-plugin": "^1.14.3",
"@ianvs/prettier-plugin-sort-imports": "^4.3.1",
"@inquirer/prompts": "^6.0.1",
"@inquirer/prompts": "^7.0.0",
"@madccc/duplicate-package-checker-webpack-plugin": "^1.0.0",
"@microflash/rehype-figure": "^2.1.1",
"@npmcli/run-script": "^9.0.0",

View File

@ -7,86 +7,85 @@ const CircularDependencyPlugin = require('circular-dependency-plugin');
const DuplicatePackageCheckerPlugin = require('@madccc/duplicate-package-checker-webpack-plugin');
const path = require('path');
function addLocales(webpackConfig) {
function addLocales(config) {
const newConfig = { ...config }; // Avoid mutating the original config
let packageName = 'antd-with-locales';
if (webpackConfig.entry['antd.min']) {
if (newConfig.entry['antd.min']) {
packageName += '.min';
}
webpackConfig.entry[packageName] = './index-with-locales.js';
webpackConfig.output.filename = '[name].js';
newConfig.entry[packageName] = './index-with-locales.js';
newConfig.output.filename = '[name].js';
return newConfig;
}
function externalDayjs(config) {
config.externals.dayjs = {
const newConfig = { ...config }; // Shallow copy for safety
newConfig.externals.dayjs = {
root: 'dayjs',
commonjs2: 'dayjs',
commonjs: 'dayjs',
amd: 'dayjs',
};
return newConfig;
}
function externalCssinjs(config) {
config.resolve = config.resolve || {};
config.resolve.alias = config.resolve.alias || {};
const newConfig = { ...config }; // Shallow copy for safety
newConfig.resolve = newConfig.resolve || {};
newConfig.resolve.alias = newConfig.resolve.alias || {};
newConfig.resolve.alias['@ant-design/cssinjs'] = path.resolve(__dirname, 'alias/cssinjs');
return newConfig;
}
config.resolve.alias['@ant-design/cssinjs'] = path.resolve(__dirname, 'alias/cssinjs');
function addPluginsForProduction(config) {
const newConfig = { ...config }; // Shallow copy for safety
if (!process.env.CI || process.env.ANALYZER) {
newConfig.plugins.push(
new BundleAnalyzerPlugin({
analyzerMode: 'static',
openAnalyzer: false,
reportFilename: '../report.html',
})
);
}
if (newConfig.mode === 'production' && !process.env.PRODUCTION_ONLY) {
newConfig.plugins.push(
new DuplicatePackageCheckerPlugin({
verbose: true,
emitError: true,
})
);
}
newConfig.plugins.push(
codecovWebpackPlugin({
enableBundleAnalysis: process.env.CODECOV_TOKEN !== undefined,
bundleName: 'antd.min',
uploadToken: process.env.CODECOV_TOKEN,
}),
new CircularDependencyPlugin({
failOnError: true,
})
);
return newConfig;
}
let webpackConfig = getWebpackConfig(false);
// Used for `size-limit` ci which only need to check min files
if (process.env.PRODUCTION_ONLY) {
// eslint-disable-next-line no-console
console.log('🍐 Build production only');
webpackConfig = webpackConfig.filter((config) => config.mode === 'production');
}
// RUN_ENV: https://github.com/ant-design/antd-tools/blob/14ee166fc1f4ab5e87da45ee3b0643a8325f1bc3/lib/gulpfile.js#L48
if (process.env.RUN_ENV === 'PRODUCTION') {
webpackConfig.forEach((config) => {
addLocales(config);
externalDayjs(config);
externalCssinjs(config);
// Reduce non-minified dist files size
config.optimization.usedExports = true;
if (!process.env.CI || process.env.ANALYZER) {
config.plugins.push(
new BundleAnalyzerPlugin({
analyzerMode: 'static',
openAnalyzer: false,
reportFilename: '../report.html',
}),
);
}
if (config.mode !== 'production') {
return;
}
if (!process.env.PRODUCTION_ONLY) {
config.plugins.push(
new DuplicatePackageCheckerPlugin({
verbose: true,
emitError: true,
}),
);
}
config.plugins.push(
codecovWebpackPlugin({
enableBundleAnalysis: process.env.CODECOV_TOKEN !== undefined,
bundleName: 'antd.min',
uploadToken: process.env.CODECOV_TOKEN,
}),
);
config.plugins.push(
new CircularDependencyPlugin({
// add errors to webpack instead of warnings
failOnError: true,
}),
);
webpackConfig = webpackConfig.map((config) => {
let newConfig = addLocales(config);
newConfig = externalDayjs(newConfig);
newConfig = externalCssinjs(newConfig);
newConfig.optimization.usedExports = true;
newConfig = addPluginsForProduction(newConfig);
return newConfig;
});
}