From aa648d2cd80847054b86907890f6977c4425f45f Mon Sep 17 00:00:00 2001
From: losgif
Date: Sat, 30 Jul 2022 17:13:20 +0800
Subject: [PATCH 01/22] feat(table): add column title attribute in expandable
props. (#36794)
* chore: rc-table's version up to 7.26.0
* docs(table): add column title attribute in expandable
* docs(table): add column title attribute in expandable
---
components/table/index.en-US.md | 1 +
components/table/index.zh-CN.md | 1 +
package.json | 2 +-
3 files changed, 3 insertions(+), 1 deletion(-)
diff --git a/components/table/index.en-US.md b/components/table/index.en-US.md
index b1964d0899..c2de4149ee 100644
--- a/components/table/index.en-US.md
+++ b/components/table/index.en-US.md
@@ -177,6 +177,7 @@ Properties for expandable.
| Property | Description | Type | Default | Version |
| --- | --- | --- | --- | --- |
| childrenColumnName | The column contains children to display | string | children | |
+| columnTitle | Set the title of the expand column | ReactNode | - | 4.23.0 |
| columnWidth | Set the width of the expand column | string \| number | - | |
| defaultExpandAllRows | Expand all rows initially | boolean | false | |
| defaultExpandedRowKeys | Initial expanded row keys | string\[] | - | |
diff --git a/components/table/index.zh-CN.md b/components/table/index.zh-CN.md
index b5d8017063..902b874e5d 100644
--- a/components/table/index.zh-CN.md
+++ b/components/table/index.zh-CN.md
@@ -178,6 +178,7 @@ const columns = [
| 参数 | 说明 | 类型 | 默认值 | 版本 |
| --- | --- | --- | --- | --- |
| childrenColumnName | 指定树形结构的列名 | string | children | |
+| columnTitle | 自定义展开列表头 | ReactNode | - | 4.23.0 |
| columnWidth | 自定义展开列宽度 | string \| number | - | |
| defaultExpandAllRows | 初始时,是否展开所有行 | boolean | false | |
| defaultExpandedRowKeys | 默认展开的行 | string\[] | - | |
diff --git a/package.json b/package.json
index e7737114a5..921aa7f36f 100644
--- a/package.json
+++ b/package.json
@@ -148,7 +148,7 @@
"rc-slider": "~10.0.0",
"rc-steps": "~4.1.0",
"rc-switch": "~3.2.0",
- "rc-table": "~7.25.3",
+ "rc-table": "~7.26.0",
"rc-tabs": "~11.16.0",
"rc-textarea": "~0.3.0",
"rc-tooltip": "~5.2.0",
From 549a2f956f1e5c414457ef315ea321ce9e5d5275 Mon Sep 17 00:00:00 2001
From: JarvisArt <38420763+JarvisArt@users.noreply.github.com>
Date: Mon, 1 Aug 2022 17:39:57 +0800
Subject: [PATCH 02/22] feat: add value parameter to textarea
showCount.formatter (#36793)
---
components/input/TextArea.tsx | 4 ++--
components/input/__tests__/index.test.tsx | 6 ++++--
components/input/__tests__/textarea.test.js | 6 ++++--
components/input/index.en-US.md | 4 ++--
components/input/index.zh-CN.md | 4 ++--
package.json | 2 +-
6 files changed, 15 insertions(+), 11 deletions(-)
diff --git a/components/input/TextArea.tsx b/components/input/TextArea.tsx
index 82dde308a2..2be7514256 100644
--- a/components/input/TextArea.tsx
+++ b/components/input/TextArea.tsx
@@ -17,7 +17,7 @@ import type { InputFocusOptions } from './Input';
import { fixControlledValue, resolveOnChange, triggerFocus } from './Input';
interface ShowCountProps {
- formatter: (args: { count: number; maxLength?: number }) => string;
+ formatter: (args: { value: string; count: number; maxLength?: number }) => string;
}
function fixEmojiLength(value: string, maxLength: number) {
@@ -233,7 +233,7 @@ const TextArea = React.forwardRef(
let dataCount = '';
if (typeof showCount === 'object') {
- dataCount = showCount.formatter({ count: valueLength, maxLength });
+ dataCount = showCount.formatter({ value: val, count: valueLength, maxLength });
} else {
dataCount = `${valueLength}${hasMaxLength ? ` / ${maxLength}` : ''}`;
}
diff --git a/components/input/__tests__/index.test.tsx b/components/input/__tests__/index.test.tsx
index c43759b7b7..833c682d16 100644
--- a/components/input/__tests__/index.test.tsx
+++ b/components/input/__tests__/index.test.tsx
@@ -272,12 +272,14 @@ describe('should support showCount', () => {
const { container } = render(
`${count}, ${maxLength}` }}
+ showCount={{
+ formatter: ({ value, count, maxLength }) => `${value}, ${count}, ${maxLength}`,
+ }}
value="12345"
/>,
);
expect(container.querySelector('input')?.getAttribute('value')).toBe('12345');
- expect(container.querySelector('.ant-input-show-count-suffix')?.innerHTML).toBe('5, 5');
+ expect(container.querySelector('.ant-input-show-count-suffix')?.innerHTML).toBe('12345, 5, 5');
});
});
diff --git a/components/input/__tests__/textarea.test.js b/components/input/__tests__/textarea.test.js
index 27a882c428..3e3744034c 100644
--- a/components/input/__tests__/textarea.test.js
+++ b/components/input/__tests__/textarea.test.js
@@ -304,13 +304,15 @@ describe('TextArea', () => {
const { container } = render(
-
-
@@ -569,20 +703,6 @@ exports[`renders ./components/tabs/demo/centered.md extend context correctly 1`]
>
Content of Tab Pane 1
-
-
@@ -766,13 +886,6 @@ exports[`renders ./components/tabs/demo/custom-add-trigger.md extend context cor
>
Content of Tab Pane 1
-
@@ -909,20 +1022,6 @@ exports[`renders ./components/tabs/demo/custom-tab-bar.md extend context correct
>
Content of Tab Pane 1
-
-
@@ -1069,20 +1168,6 @@ exports[`renders ./components/tabs/demo/custom-tab-bar-node.md extend context co
>
Content of Tab Pane 1
-
-
@@ -1213,20 +1298,6 @@ exports[`renders ./components/tabs/demo/deprecated.md extend context correctly 1
>
Content of Tab Pane 1
-
-
@@ -1357,20 +1428,6 @@ exports[`renders ./components/tabs/demo/disabled.md extend context correctly 1`]
>
Tab 1
-
-
@@ -1611,20 +1668,6 @@ exports[`renders ./components/tabs/demo/editable-card.md extend context correctl
>
Content of Tab 1
-
-
@@ -1768,20 +1811,6 @@ Array [
>
Content of tab 1
-
-
,
@@ -1989,20 +2018,6 @@ Array [
>
Content of tab 1
-
-
,
@@ -2156,13 +2171,6 @@ exports[`renders ./components/tabs/demo/icon.md extend context correctly 1`] = `
-
-
TTTT 1
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -3635,20 +3503,6 @@ Array [
>
Content of Tab 1
-
-
,
@@ -3845,20 +3699,6 @@ exports[`renders ./components/tabs/demo/size.md extend context correctly 1`] = `
>
Content of tab 1
-
-
@@ -3986,20 +3826,6 @@ exports[`renders ./components/tabs/demo/size.md extend context correctly 1`] = `
>
Content of card tab 1
-
-
@@ -4522,13 +4348,6 @@ exports[`renders ./components/tabs/demo/slide.md extend context correctly 1`] =
-
Content of tab 1
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/components/tabs/__tests__/__snapshots__/demo.test.js.snap b/components/tabs/__tests__/__snapshots__/demo.test.js.snap
index 7e17857307..11afc76dce 100644
--- a/components/tabs/__tests__/__snapshots__/demo.test.js.snap
+++ b/components/tabs/__tests__/__snapshots__/demo.test.js.snap
@@ -1,5 +1,162 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
+exports[`renders ./components/tabs/demo/animated.md correctly 1`] = `
+Array [
+ ,
+ ,
+]
+`;
+
exports[`renders ./components/tabs/demo/basic.md correctly 1`] = `
Content of Tab Pane 1
-
-
@@ -231,20 +374,6 @@ exports[`renders ./components/tabs/demo/card.md correctly 1`] = `
>
Content of Tab Pane 1
-
-
@@ -367,20 +496,6 @@ exports[`renders ./components/tabs/demo/card-top.md correctly 1`] = `
Content of Tab Pane 1
-
-
@@ -493,20 +608,6 @@ exports[`renders ./components/tabs/demo/centered.md correctly 1`] = `
>
Content of Tab Pane 1
-
-
@@ -671,13 +772,6 @@ exports[`renders ./components/tabs/demo/custom-add-trigger.md correctly 1`] = `
>
Content of Tab Pane 1
-
@@ -795,20 +889,6 @@ exports[`renders ./components/tabs/demo/custom-tab-bar.md correctly 1`] = `
>
Content of Tab Pane 1
-
-
@@ -936,20 +1016,6 @@ exports[`renders ./components/tabs/demo/custom-tab-bar-node.md correctly 1`] = `
>
Content of Tab Pane 1
-
-
@@ -1061,20 +1127,6 @@ exports[`renders ./components/tabs/demo/deprecated.md correctly 1`] = `
>
Content of Tab Pane 1
-
-
@@ -1186,20 +1238,6 @@ exports[`renders ./components/tabs/demo/disabled.md correctly 1`] = `
>
Tab 1
-
-
@@ -1421,20 +1459,6 @@ exports[`renders ./components/tabs/demo/editable-card.md correctly 1`] = `
>
Content of Tab 1
-
-
@@ -1559,20 +1583,6 @@ Array [
>
Content of tab 1
-
-
,
@@ -1761,20 +1771,6 @@ Array [
>
Content of tab 1
-
-
,
@@ -1909,13 +1905,6 @@ exports[`renders ./components/tabs/demo/icon.md correctly 1`] = `
-
-
TTTT 1
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -2913,20 +2762,6 @@ Array [
>
Content of Tab 1
-
-
,
@@ -3104,20 +2939,6 @@ exports[`renders ./components/tabs/demo/size.md correctly 1`] = `
>
Content of tab 1
-
-
@@ -3226,20 +3047,6 @@ exports[`renders ./components/tabs/demo/size.md correctly 1`] = `
>
Content of card tab 1
-
-
@@ -3743,13 +3550,6 @@ exports[`renders ./components/tabs/demo/slide.md correctly 1`] = `
-
Content of tab 1
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/components/tabs/__tests__/animated.test.tsx b/components/tabs/__tests__/animated.test.tsx
new file mode 100644
index 0000000000..30c51fbc8f
--- /dev/null
+++ b/components/tabs/__tests__/animated.test.tsx
@@ -0,0 +1,34 @@
+import { renderHook } from '../../../tests/utils';
+import useAnimateConfig from '../hooks/useAnimateConfig';
+
+describe('Tabs.Animated', () => {
+ it('boolean: false', () => {
+ const { result } = renderHook(() => useAnimateConfig('test', false));
+
+ expect(result.current).toEqual({
+ inkBar: false,
+ tabPane: false,
+ });
+ });
+
+ it('boolean: true', () => {
+ const { result } = renderHook(() => useAnimateConfig('test', true));
+
+ expect(result.current).toEqual({
+ inkBar: true,
+ tabPane: false,
+ });
+ });
+
+ it('config', () => {
+ const { result } = renderHook(() => useAnimateConfig('test', { inkBar: false, tabPane: true }));
+
+ expect(result.current).toEqual({
+ inkBar: false,
+ tabPane: true,
+ tabPaneMotion: expect.objectContaining({
+ motionName: 'test-switch',
+ }),
+ });
+ });
+});
diff --git a/components/tabs/demo/animated.md b/components/tabs/demo/animated.md
new file mode 100644
index 0000000000..cce0654290
--- /dev/null
+++ b/components/tabs/demo/animated.md
@@ -0,0 +1,79 @@
+---
+order: 99
+title:
+ zh-CN: 动画
+ en-US: Animated
+debug: true
+---
+
+## zh-CN
+
+动画切换。
+
+## en-US
+
+Animated of Tab Pane.
+
+```tsx
+import { Tabs, Switch, Space } from 'antd';
+import React from 'react';
+
+const App: React.FC = () => {
+ const [inkBar, setInkBar] = React.useState(true);
+ const [tabPane, setTabPane] = React.useState(true);
+
+ return (
+ <>
+
+ setInkBar(!inkBar)}
+ />
+ setTabPane(!tabPane)}
+ />
+
+
+
+ >
+ );
+};
+
+export default App;
+```
diff --git a/components/tabs/hooks/useAnimateConfig.ts b/components/tabs/hooks/useAnimateConfig.ts
new file mode 100644
index 0000000000..31695d9f3a
--- /dev/null
+++ b/components/tabs/hooks/useAnimateConfig.ts
@@ -0,0 +1,46 @@
+import type { CSSMotionProps } from 'rc-motion';
+import type { AnimatedConfig } from 'rc-tabs/lib/interface';
+import type { TabsProps } from '..';
+import { getTransitionName } from '../../_util/motion';
+
+const motion: CSSMotionProps = {
+ motionAppear: false,
+ motionEnter: true,
+ motionLeave: true,
+};
+
+export default function useAnimateConfig(
+ prefixCls: string,
+ animated: TabsProps['animated'] = {
+ inkBar: true,
+ tabPane: false,
+ },
+): AnimatedConfig {
+ let mergedAnimated: AnimatedConfig;
+
+ if (animated === false) {
+ mergedAnimated = {
+ inkBar: false,
+ tabPane: false,
+ };
+ } else if (animated === true) {
+ mergedAnimated = {
+ inkBar: true,
+ tabPane: false,
+ };
+ } else {
+ mergedAnimated = {
+ inkBar: true,
+ ...(typeof animated === 'object' ? animated : {}),
+ };
+ }
+
+ if (mergedAnimated.tabPane) {
+ mergedAnimated.tabPaneMotion = {
+ ...motion,
+ motionName: getTransitionName(prefixCls, 'switch'),
+ };
+ }
+
+ return mergedAnimated;
+}
diff --git a/components/tabs/index.tsx b/components/tabs/index.tsx
index e97ac6afaa..4f95f07e7b 100755
--- a/components/tabs/index.tsx
+++ b/components/tabs/index.tsx
@@ -11,6 +11,7 @@ import { ConfigContext } from '../config-provider';
import type { SizeType } from '../config-provider/SizeContext';
import SizeContext from '../config-provider/SizeContext';
import warning from '../_util/warning';
+import useAnimateConfig from './hooks/useAnimateConfig';
import useLegacyItems from './hooks/useLegacyItems';
import TabPane, { TabPaneProps } from './TabPane';
@@ -39,6 +40,7 @@ function Tabs({
addIcon,
children,
items,
+ animated,
...props
}: TabsProps) {
const { prefixCls: customizePrefixCls, moreIcon = } = props;
@@ -66,6 +68,8 @@ function Tabs({
const mergedItems = useLegacyItems(items, children);
+ const mergedAnimated = useAnimateConfig(prefixCls, animated);
+
return (
{contextSize => {
@@ -88,6 +92,7 @@ function Tabs({
editable={editable}
moreIcon={moreIcon}
prefixCls={prefixCls}
+ animated={mergedAnimated}
/>
);
}}
diff --git a/components/tabs/style/index.less b/components/tabs/style/index.less
index 0ff9cbc1ac..bb63bf4e2b 100644
--- a/components/tabs/style/index.less
+++ b/components/tabs/style/index.less
@@ -207,17 +207,45 @@
min-height: 0;
}
- display: flex;
+ position: relative;
width: 100%;
-
- &-animated {
- transition: margin @animation-duration-slow;
- }
}
&-tabpane {
- flex: none;
- width: 100%;
- outline: none;
+ &-hidden {
+ display: none;
+ }
+ }
+
+ // Motion
+ &-switch {
+ &-appear,
+ &-enter {
+ transition: none;
+
+ &-start {
+ opacity: 0;
+ }
+
+ &-active {
+ opacity: 1;
+ transition: opacity @animation-duration-slow;
+ }
+ }
+
+ &-leave {
+ position: absolute;
+ transition: none;
+ inset: 0;
+
+ &-start {
+ opacity: 1;
+ }
+
+ &-active {
+ opacity: 0;
+ transition: opacity @animation-duration-slow;
+ }
+ }
}
}
diff --git a/package.json b/package.json
index f302143413..03cdd72ff5 100644
--- a/package.json
+++ b/package.json
@@ -149,7 +149,7 @@
"rc-steps": "~4.1.0",
"rc-switch": "~3.2.0",
"rc-table": "~7.26.0",
- "rc-tabs": "~12.0.0-alpha.1",
+ "rc-tabs": "~12.1.0-alpha.0",
"rc-textarea": "~0.3.0",
"rc-tooltip": "~5.2.0",
"rc-tree": "~5.6.5",
diff --git a/tests/utils.ts b/tests/utils.tsx
similarity index 81%
rename from tests/utils.ts
rename to tests/utils.tsx
index 6a969070fc..435250f5bf 100644
--- a/tests/utils.ts
+++ b/tests/utils.tsx
@@ -1,6 +1,6 @@
import MockDate from 'mockdate';
import type { ReactElement } from 'react';
-import { StrictMode } from 'react';
+import React, { StrictMode } from 'react';
import type { RenderOptions } from '@testing-library/react';
import { render, act } from '@testing-library/react';
import { _rs as onLibResize } from 'rc-resize-observer/lib/utils/observerUtil';
@@ -27,6 +27,20 @@ export const sleep = async (timeout = 0) => {
const customRender = (ui: ReactElement, options?: Omit) =>
render(ui, { wrapper: StrictMode, ...options });
+export function renderHook(func: () => T): { result: React.RefObject } {
+ const result = React.createRef();
+
+ const Demo = () => {
+ (result as any).current = func();
+
+ return null;
+ };
+
+ customRender();
+
+ return { result };
+}
+
export { customRender as render };
export const triggerResize = (target: Element) => {
From ca73f6e3f17035319901aa038b042d2ec7534a21 Mon Sep 17 00:00:00 2001
From: yykoypj <601924094@qq.com>
Date: Mon, 15 Aug 2022 14:39:02 +0800
Subject: [PATCH 07/22] chore: Remove visible usage for tag (#36934)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
* feat: remove visible for Tag
* chore: adjust warning info
* test: back of doc
Co-authored-by: 二货机器人
---
components/tag/__tests__/index.test.js | 15 ++++++++++++++-
components/tag/demo/controlled.md | 9 +++++----
components/tag/index.en-US.md | 23 +++++++++++------------
components/tag/index.tsx | 8 ++++++++
components/tag/index.zh-CN.md | 9 ++++-----
5 files changed, 42 insertions(+), 22 deletions(-)
diff --git a/components/tag/__tests__/index.test.js b/components/tag/__tests__/index.test.js
index 4d9aa8f9e3..3d096fd194 100644
--- a/components/tag/__tests__/index.test.js
+++ b/components/tag/__tests__/index.test.js
@@ -2,8 +2,9 @@ import { mount } from 'enzyme';
import React from 'react';
import Tag from '..';
import mountTest from '../../../tests/shared/mountTest';
+import { render, act } from '../../../tests/utils';
import rtlTest from '../../../tests/shared/rtlTest';
-import { act } from '../../../tests/utils';
+import { resetWarned } from '../../_util/warning';
describe('Tag', () => {
mountTest(Tag);
@@ -81,6 +82,18 @@ describe('Tag', () => {
expect(onClick).not.toHaveBeenCalled();
});
+ it('deprecated warning', () => {
+ resetWarned();
+ const errSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
+
+ render();
+ expect(errSpy).toHaveBeenCalledWith(
+ 'Warning: [antd: Tag] `visible` will be removed in next major version, please use `visible && ` instead.',
+ );
+
+ errSpy.mockRestore();
+ });
+
describe('visibility', () => {
it('can be controlled by visible with visible as initial value', () => {
const wrapper = mount();
diff --git a/components/tag/demo/controlled.md b/components/tag/demo/controlled.md
index 28fa706d28..eb78e31622 100644
--- a/components/tag/demo/controlled.md
+++ b/components/tag/demo/controlled.md
@@ -1,17 +1,18 @@
---
order: 5
title:
- zh-CN: 控制关闭状态
- en-US: Controlled
+ zh-CN: 控制关闭状态(废弃)
+ en-US: Controlled (Deprecated)
+debug: true
---
## zh-CN
-通过 `visible` 属性控制关闭状态。
+废弃,通过 `visible` 属性控制关闭状态。
## en-US
-By using the `visible` prop, you can control the close state of Tag.
+Deprecated. By using the `visible` prop, you can control the close state of Tag.
```tsx
import { Button, Tag } from 'antd';
diff --git a/components/tag/index.en-US.md b/components/tag/index.en-US.md
index 17c5ee8c2b..585f01792c 100644
--- a/components/tag/index.en-US.md
+++ b/components/tag/index.en-US.md
@@ -17,18 +17,17 @@ Tag for categorizing or markup.
### Tag
-| Property | Description | Type | Default | Version |
-| --- | --- | --- | --- | --- |
-| closable | Whether the Tag can be closed | boolean | false | |
-| closeIcon | Custom close icon | ReactNode | - | 4.4.0 |
-| color | Color of the Tag | string | - | |
-| icon | Set the icon of tag | ReactNode | - | |
-| visible | Whether the Tag is closed or not | boolean | true | |
-| onClose | Callback executed when tag is closed | (e) => void | - | |
+| Property | Description | Type | Default | Version |
+| --------- | ------------------------------------ | ----------- | ------- | ------- |
+| closable | Whether the Tag can be closed | boolean | false | |
+| closeIcon | Custom close icon | ReactNode | - | 4.4.0 |
+| color | Color of the Tag | string | - | |
+| icon | Set the icon of tag | ReactNode | - | |
+| onClose | Callback executed when tag is closed | (e) => void | - | |
### Tag.CheckableTag
-| Property | Description | Type | Default |
-| --- | --- | --- | --- |
-| checked | Checked status of Tag | boolean | false |
-| onChange | Callback executed when Tag is checked/unchecked | (checked) => void | - |
+| Property | Description | Type | Default |
+| -------- | ----------------------------------------------- | ----------------- | ------- |
+| checked | Checked status of Tag | boolean | false |
+| onChange | Callback executed when Tag is checked/unchecked | (checked) => void | - |
diff --git a/components/tag/index.tsx b/components/tag/index.tsx
index f38177d10c..66fc0d6e87 100644
--- a/components/tag/index.tsx
+++ b/components/tag/index.tsx
@@ -8,6 +8,7 @@ import type { PresetColorType, PresetStatusColorType } from '../_util/colors';
import { PresetColorTypes, PresetStatusColorTypes } from '../_util/colors';
import type { LiteralUnion } from '../_util/type';
import Wave from '../_util/wave';
+import warning from '../_util/warning';
import CheckableTag from './CheckableTag';
export { CheckableTagProps } from './CheckableTag';
@@ -18,6 +19,7 @@ export interface TagProps extends React.HTMLAttributes {
color?: LiteralUnion;
closable?: boolean;
closeIcon?: React.ReactNode;
+ /** @deprecated `visible` will be removed in next major version. */
visible?: boolean;
onClose?: (e: React.MouseEvent) => void;
style?: React.CSSProperties;
@@ -50,6 +52,12 @@ const InternalTag: React.ForwardRefRenderFunction = (
const { getPrefixCls, direction } = React.useContext(ConfigContext);
const [visible, setVisible] = React.useState(true);
+ warning(
+ !('visible' in props),
+ 'Tag',
+ '`visible` will be removed in next major version, please use `visible && ` instead.',
+ );
+
React.useEffect(() => {
if ('visible' in props) {
setVisible(props.visible!);
diff --git a/components/tag/index.zh-CN.md b/components/tag/index.zh-CN.md
index 7611a029f8..16aaa2078d 100644
--- a/components/tag/index.zh-CN.md
+++ b/components/tag/index.zh-CN.md
@@ -23,12 +23,11 @@ cover: https://gw.alipayobjects.com/zos/alicdn/cH1BOLfxC/Tag.svg
| closeIcon | 自定义关闭按钮 | ReactNode | - | 4.4.0 |
| color | 标签色 | string | - | |
| icon | 设置图标 | ReactNode | - | |
-| visible | 是否显示标签 | boolean | true | |
| onClose | 关闭时的回调(可通过 `e.preventDefault()` 来阻止默认行为) | (e) => void | - | |
### Tag.CheckableTag
-| 参数 | 说明 | 类型 | 默认值 |
-| --- | --- | --- | --- |
-| checked | 设置标签的选中状态 | boolean | false |
-| onChange | 点击标签时触发的回调 | (checked) => void | - |
+| 参数 | 说明 | 类型 | 默认值 |
+| -------- | -------------------- | ----------------- | ------ |
+| checked | 设置标签的选中状态 | boolean | false |
+| onChange | 点击标签时触发的回调 | (checked) => void | - |
From 4b1b0e3d0049bee8e2d887705488c62034246e97 Mon Sep 17 00:00:00 2001
From: Alan Deng
Date: Mon, 15 Aug 2022 21:46:08 +0800
Subject: [PATCH 08/22] feat: custom slider handle margin left in the vertical
direction (#37001)
---
components/slider/style/index.less | 2 +-
components/style/themes/default.less | 1 +
components/style/themes/variable.less | 1 +
3 files changed, 3 insertions(+), 1 deletion(-)
diff --git a/components/slider/style/index.less b/components/slider/style/index.less
index 586f62fb67..87a57aa554 100644
--- a/components/slider/style/index.less
+++ b/components/slider/style/index.less
@@ -178,7 +178,7 @@
.@{slider-prefix-cls}-handle {
margin-top: -6px; // we chould consider border width as well: (10 + 2 ) / 2
- margin-left: -5px;
+ margin-left: @slider-handle-margin-left;
}
.@{slider-prefix-cls}-mark {
diff --git a/components/style/themes/default.less b/components/style/themes/default.less
index 299595ce1f..6bee9e1c3e 100644
--- a/components/style/themes/default.less
+++ b/components/style/themes/default.less
@@ -893,6 +893,7 @@
@slider-handle-color-tooltip-open: @primary-color;
@slider-handle-size: 14px;
@slider-handle-margin-top: -5px;
+@slider-handle-margin-left: -5px;
@slider-handle-shadow: 0;
@slider-dot-border-color: @border-color-split;
@slider-dot-border-color-active: tint(@primary-color, 50%);
diff --git a/components/style/themes/variable.less b/components/style/themes/variable.less
index cc86343c3c..43ee2646c2 100644
--- a/components/style/themes/variable.less
+++ b/components/style/themes/variable.less
@@ -948,6 +948,7 @@
@slider-handle-color-tooltip-open: @primary-color;
@slider-handle-size: 14px;
@slider-handle-margin-top: -5px;
+@slider-handle-margin-left: -5px;
@slider-handle-shadow: 0;
@slider-dot-border-color: @border-color-split;
@slider-dot-border-color-active: ~'var(--@{ant-prefix}-primary-color-deprecated-t-50)';
From c435eaad3f4414a88213c7d4f75f51acfd13ada2 Mon Sep 17 00:00:00 2001
From: Kyrielin
Date: Tue, 16 Aug 2022 09:59:27 +0800
Subject: [PATCH 09/22] feat(Tooltip): support React.Fragment as children
(#37045)
---
components/_util/reactNode.ts | 4 +++
components/tooltip/__tests__/tooltip.test.js | 31 ++++++++++++++++++++
components/tooltip/index.tsx | 4 +--
3 files changed, 37 insertions(+), 2 deletions(-)
diff --git a/components/_util/reactNode.ts b/components/_util/reactNode.ts
index ccdc8015be..759fd7a6c2 100644
--- a/components/_util/reactNode.ts
+++ b/components/_util/reactNode.ts
@@ -2,6 +2,10 @@ import * as React from 'react';
export const { isValidElement } = React;
+export function isFragment(child: React.ReactElement): boolean {
+ return child && child.type === React.Fragment;
+}
+
type AnyObject = Record;
type RenderProps = undefined | AnyObject | ((originProps: AnyObject) => AnyObject | undefined);
diff --git a/components/tooltip/__tests__/tooltip.test.js b/components/tooltip/__tests__/tooltip.test.js
index 62129cd42f..9ebdee5c50 100644
--- a/components/tooltip/__tests__/tooltip.test.js
+++ b/components/tooltip/__tests__/tooltip.test.js
@@ -422,4 +422,35 @@ describe('Tooltip', () => {
expect(onVisibleChange).toHaveBeenLastCalledWith(true);
expect(container.querySelector('.ant-tooltip-open')).not.toBeNull();
});
+
+ it('should work with Fragment children', () => {
+ const onVisibleChange = jest.fn();
+ const ref = React.createRef();
+
+ const { container } = render(
+
+ <>
+ Hello world!
+ Hello world!
+ >
+ ,
+ );
+
+ const divElement = container.querySelector('.hello');
+ fireEvent.mouseEnter(divElement);
+ expect(onVisibleChange).toHaveBeenLastCalledWith(true);
+ expect(ref.current.props.visible).toBe(true);
+ expect(container.querySelector('.ant-tooltip-open')).not.toBeNull();
+
+ fireEvent.mouseLeave(divElement);
+ expect(onVisibleChange).toHaveBeenLastCalledWith(false);
+ expect(ref.current.props.visible).toBe(false);
+ expect(container.querySelector('.ant-tooltip-open')).toBeNull();
+ });
});
diff --git a/components/tooltip/index.tsx b/components/tooltip/index.tsx
index c959af9f3a..badebb626f 100644
--- a/components/tooltip/index.tsx
+++ b/components/tooltip/index.tsx
@@ -9,7 +9,7 @@ import type { PresetColorType } from '../_util/colors';
import { PresetColorTypes } from '../_util/colors';
import { getTransitionName } from '../_util/motion';
import getPlacements, { AdjustOverflow, PlacementsConfig } from '../_util/placements';
-import { cloneElement, isValidElement } from '../_util/reactNode';
+import { cloneElement, isValidElement, isFragment } from '../_util/reactNode';
import type { LiteralUnion } from '../_util/type';
export { AdjustOverflow, PlacementsConfig };
@@ -224,7 +224,7 @@ const Tooltip = React.forwardRef((props, ref) => {
}
const child = getDisabledCompatibleChildren(
- isValidElement(children) ? children : {children},
+ isValidElement(children) && !isFragment(children) ? children : {children},
prefixCls,
);
const childProps = child.props;
From 38aaec1156ebbcf8e624e8969be7f2fb51fd1038 Mon Sep 17 00:00:00 2001
From: yykoypj <601924094@qq.com>
Date: Wed, 17 Aug 2022 10:29:16 +0800
Subject: [PATCH 10/22] chore: save prod perf (#37088)
---
components/tag/index.tsx | 13 ++++++++-----
1 file changed, 8 insertions(+), 5 deletions(-)
diff --git a/components/tag/index.tsx b/components/tag/index.tsx
index 66fc0d6e87..e71bb3444b 100644
--- a/components/tag/index.tsx
+++ b/components/tag/index.tsx
@@ -52,11 +52,14 @@ const InternalTag: React.ForwardRefRenderFunction = (
const { getPrefixCls, direction } = React.useContext(ConfigContext);
const [visible, setVisible] = React.useState(true);
- warning(
- !('visible' in props),
- 'Tag',
- '`visible` will be removed in next major version, please use `visible && ` instead.',
- );
+ // Warning for deprecated usage
+ if (process.env.NODE_ENV !== 'production') {
+ warning(
+ !('visible' in props),
+ 'Tag',
+ '`visible` will be removed in next major version, please use `visible && ` instead.',
+ );
+ }
React.useEffect(() => {
if ('visible' in props) {
From aa97494625a741cb83030fd4b9585c15039e1562 Mon Sep 17 00:00:00 2001
From: yykoypj <601924094@qq.com>
Date: Wed, 17 Aug 2022 15:47:22 +0800
Subject: [PATCH 11/22] feat: change slide tooltip api (#37000)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
* feat: change slide tooltip api
* fix: deprecated warning
* refactor: remove boolean type support for Slider tooltip
* feat: update warning text
* chore: fix typo
* chore: save prod perf
* test: back of test case
* chore: clean up
* chore: fix test require
Co-authored-by: 二货机器人
---
.../__tests__/components.test.js | 9 +-
components/grid/demo/playground.md | 6 +-
.../__snapshots__/index.test.tsx.snap | 50 -------
components/slider/__tests__/index.test.tsx | 140 ++++++++++++++----
components/slider/demo/show-tooltip.md | 6 +-
components/slider/demo/tip-formatter.md | 8 +-
components/slider/index.en-US.md | 26 ++--
components/slider/index.tsx | 106 +++++++++----
components/slider/index.zh-CN.md | 23 ++-
9 files changed, 240 insertions(+), 134 deletions(-)
diff --git a/components/config-provider/__tests__/components.test.js b/components/config-provider/__tests__/components.test.js
index fd34b92771..5c1732926e 100644
--- a/components/config-provider/__tests__/components.test.js
+++ b/components/config-provider/__tests__/components.test.js
@@ -470,9 +470,14 @@ describe('ConfigProvider', () => {
testPair('Slider', props => {
const myProps = { ...props };
if (myProps.prefixCls) {
- myProps.tooltipPrefixCls = `${myProps.prefixCls}-tooltip`;
+ return (
+
+ );
}
- return ;
+ return ;
});
// Spin
diff --git a/components/grid/demo/playground.md b/components/grid/demo/playground.md
index 9b5cb94952..0692c38572 100644
--- a/components/grid/demo/playground.md
+++ b/components/grid/demo/playground.md
@@ -59,7 +59,7 @@ const App: React.FC = () => {
onChange={setGutterKey}
marks={gutters}
step={null}
- tipFormatter={value => value && gutters[value]}
+ tooltip={{ formatter: value => value && gutters[value] }}
/>
Vertical Gutter (px):
@@ -71,7 +71,7 @@ const App: React.FC = () => {
onChange={setVgutterKey}
marks={vgutters}
step={null}
- tipFormatter={value => value && vgutters[value]}
+ tooltip={{ formatter: value => value && vgutters[value] }}
/>
Column Count:
@@ -83,7 +83,7 @@ const App: React.FC = () => {
onChange={setColCountKey}
marks={colCounts}
step={null}
- tipFormatter={value => value && colCounts[value]}
+ tooltip={{ formatter: value => value && colCounts[value] }}
/>
diff --git a/components/slider/__tests__/__snapshots__/index.test.tsx.snap b/components/slider/__tests__/__snapshots__/index.test.tsx.snap
index f9f8e49f7c..932db4dc6a 100644
--- a/components/slider/__tests__/__snapshots__/index.test.tsx.snap
+++ b/components/slider/__tests__/__snapshots__/index.test.tsx.snap
@@ -80,56 +80,6 @@ exports[`Slider should render in RTL direction 1`] = `
`;
-exports[`Slider should show correct placement tooltip when set tooltipPlacement 1`] = `
-
-`;
-
-exports[`Slider should show correct placement tooltip when set tooltipPlacement 2`] = `
-
-`;
-
exports[`Slider should show tooltip when hovering slider handler 1`] = `
diff --git a/components/locale-provider/__tests__/index.test.js b/components/locale-provider/__tests__/index.test.js
index 0114a0a4bd..29781a6672 100644
--- a/components/locale-provider/__tests__/index.test.js
+++ b/components/locale-provider/__tests__/index.test.js
@@ -191,7 +191,7 @@ const App = () => (
item.title} />
-
+
Locale Modal
diff --git a/components/modal/ConfirmDialog.tsx b/components/modal/ConfirmDialog.tsx
index 2af9d95b4e..3a8e5bb9fc 100644
--- a/components/modal/ConfirmDialog.tsx
+++ b/components/modal/ConfirmDialog.tsx
@@ -24,6 +24,7 @@ const ConfirmDialog = (props: ConfirmDialogProps) => {
zIndex,
afterClose,
visible,
+ open,
keyboard,
centered,
getContainer,
@@ -90,8 +91,8 @@ const ConfirmDialog = (props: ConfirmDialogProps) => {
{ [`${contentPrefixCls}-centered`]: !!props.centered },
wrapClassName,
)}
- onCancel={() => close({ triggerCancel: true })}
- visible={visible}
+ onCancel={() => close?.({ triggerCancel: true })}
+ open={open || visible}
title=""
footer=""
transitionName={getTransitionName(rootPrefixCls, 'zoom', props.transitionName)}
diff --git a/components/modal/Modal.tsx b/components/modal/Modal.tsx
index d2d1d950cc..8872686571 100644
--- a/components/modal/Modal.tsx
+++ b/components/modal/Modal.tsx
@@ -12,6 +12,7 @@ import { NoFormStyle } from '../form/context';
import LocaleReceiver from '../locale-provider/LocaleReceiver';
import { getTransitionName } from '../_util/motion';
import { canUseDocElement } from '../_util/styleChecker';
+import warning from '../_util/warning';
import { getConfirmLocale } from './locale';
let mousePosition: { x: number; y: number } | null;
@@ -37,7 +38,12 @@ if (canUseDocElement()) {
export interface ModalProps {
/** 对话框是否可见 */
+ /**
+ * @deprecated `visible` is deprecated which will be removed in next major version. Please use
+ * `open` instead.
+ */
visible?: boolean;
+ open?: boolean;
/** 确定按钮 loading */
confirmLoading?: boolean;
/** 标题 */
@@ -92,7 +98,12 @@ type getContainerFunc = () => HTMLElement;
export interface ModalFuncProps {
prefixCls?: string;
className?: string;
+ /**
+ * @deprecated `visible` is deprecated which will be removed in next major version. Please use
+ * `open` instead.
+ */
visible?: boolean;
+ open?: boolean;
title?: React.ReactNode;
closable?: boolean;
content?: React.ReactNode;
@@ -151,6 +162,12 @@ const Modal: React.FC = props => {
onOk?.(e);
};
+ warning(
+ !('visible' in props),
+ 'Modal',
+ `\`visible\` will be removed in next major version, please use \`open\` instead.`,
+ );
+
const renderFooter = (locale: ModalLocale) => {
const { okText, okType, cancelText, confirmLoading } = props;
return (
@@ -174,6 +191,7 @@ const Modal: React.FC = props => {
prefixCls: customizePrefixCls,
footer,
visible,
+ open,
wrapClassName,
centered,
getContainer,
@@ -211,7 +229,7 @@ const Modal: React.FC = props => {
prefixCls={prefixCls}
wrapClassName={wrapClassNameExtended}
footer={footer === undefined ? defaultFooter : footer}
- visible={visible}
+ visible={open || visible}
mousePosition={mousePosition}
onClose={handleCancel}
closeIcon={closeIconToRender}
@@ -226,7 +244,7 @@ const Modal: React.FC = props => {
Modal.defaultProps = {
width: 520,
confirmLoading: false,
- visible: false,
+ open: false,
okType: 'primary' as LegacyButtonType,
};
diff --git a/components/modal/__tests__/Modal.test.tsx b/components/modal/__tests__/Modal.test.tsx
index 177a5f131c..18a75da560 100644
--- a/components/modal/__tests__/Modal.test.tsx
+++ b/components/modal/__tests__/Modal.test.tsx
@@ -4,14 +4,15 @@ import Modal from '..';
import mountTest from '../../../tests/shared/mountTest';
import rtlTest from '../../../tests/shared/rtlTest';
import { fireEvent, render } from '../../../tests/utils';
+import { resetWarned } from '../../_util/warning';
jest.mock('rc-util/lib/Portal');
-class ModalTester extends React.Component {
- state = { visible: false };
+class ModalTester extends React.Component {
+ state = { open: false };
componentDidMount() {
- this.setState({ visible: true }); // eslint-disable-line react/no-did-mount-set-state
+ this.setState({ open: true }); // eslint-disable-line react/no-did-mount-set-state
}
container = React.createRef();
@@ -19,11 +20,11 @@ class ModalTester extends React.Component {
getContainer = () => this.container?.current!;
render() {
- const { visible } = this.state;
+ const { open } = this.state;
return (
-
+
Here is content of Modal
@@ -36,7 +37,7 @@ describe('Modal', () => {
rtlTest(Modal);
it('support closeIcon', () => {
- render(closeIcon} visible />);
+ render(closeIcon} open />);
expect(document.body.querySelectorAll('.ant-modal-root')[0]).toMatchSnapshot();
});
@@ -52,35 +53,35 @@ describe('Modal', () => {
it('onCancel should be called', () => {
const onCancel = jest.fn();
- render();
+ render();
fireEvent.click(document.body.querySelectorAll('.ant-btn')[0]);
expect(onCancel).toHaveBeenCalled();
});
it('onOk should be called', () => {
const onOk = jest.fn();
- render();
+ render();
const btns = document.body.querySelectorAll('.ant-btn');
fireEvent.click(btns[btns.length - 1]);
expect(onOk).toHaveBeenCalled();
});
it('danger type', () => {
- render();
+ render();
const btns = document.body.querySelectorAll('.ant-btn');
expect(btns[btns.length - 1].classList.contains('ant-btn-dangerous')).toBeTruthy();
});
it('mouse position', () => {
const Demo = () => {
- const [visible, setVisible] = React.useState(false);
+ const [open, setOpen] = React.useState(false);
const containerRef = React.useRef(null);
return (
-
setVisible(true)}>
+
setOpen(true)}>
click me
-
containerRef.current!} />
+ containerRef.current!} />
);
};
@@ -90,4 +91,18 @@ describe('Modal', () => {
(container.querySelectorAll('.ant-modal')[0] as HTMLDivElement).style.transformOrigin,
).toBeTruthy();
});
+
+ it('deprecated warning', () => {
+ resetWarned();
+ const errSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
+
+ render(
);
+ expect(errSpy).toHaveBeenCalledWith(
+ 'Warning: [antd: Modal] `visible` will be removed in next major version, please use `open` instead.',
+ );
+
+ expect(document.querySelector('.ant-modal')).toBeTruthy();
+
+ errSpy.mockRestore();
+ });
});
diff --git a/components/modal/confirm.tsx b/components/modal/confirm.tsx
index bfa807ff94..a8e05c9574 100644
--- a/components/modal/confirm.tsx
+++ b/components/modal/confirm.tsx
@@ -29,7 +29,7 @@ export type ModalStaticFunctions = Record
, M
export default function confirm(config: ModalFuncProps) {
const container = document.createDocumentFragment();
// eslint-disable-next-line @typescript-eslint/no-use-before-define
- let currentConfig = { ...config, close, visible: true } as any;
+ let currentConfig = { ...config, close, open: true } as any;
function destroy(...args: any[]) {
const triggerCancel = args.some(param => param && param.triggerCancel);
@@ -79,7 +79,7 @@ export default function confirm(config: ModalFuncProps) {
function close(...args: any[]) {
currentConfig = {
...currentConfig,
- visible: false,
+ open: false,
afterClose: () => {
if (typeof config.afterClose === 'function') {
config.afterClose();
diff --git a/components/modal/demo/async.md b/components/modal/demo/async.md
index 52dc80605d..e5dded5ac6 100644
--- a/components/modal/demo/async.md
+++ b/components/modal/demo/async.md
@@ -18,26 +18,26 @@ import { Button, Modal } from 'antd';
import React, { useState } from 'react';
const App: React.FC = () => {
- const [visible, setVisible] = useState(false);
+ const [open, setOpen] = useState(false);
const [confirmLoading, setConfirmLoading] = useState(false);
const [modalText, setModalText] = useState('Content of the modal');
const showModal = () => {
- setVisible(true);
+ setOpen(true);
};
const handleOk = () => {
setModalText('The modal will be closed after two seconds');
setConfirmLoading(true);
setTimeout(() => {
- setVisible(false);
+ setOpen(false);
setConfirmLoading(false);
}, 2000);
};
const handleCancel = () => {
console.log('Clicked cancel button');
- setVisible(false);
+ setOpen(false);
};
return (
@@ -47,7 +47,7 @@ const App: React.FC = () => {
{
- const [isModalVisible, setIsModalVisible] = useState(false);
+ const [isModalOpen, setIsModalOpen] = useState(false);
const showModal = () => {
- setIsModalVisible(true);
+ setIsModalOpen(true);
};
const handleOk = () => {
- setIsModalVisible(false);
+ setIsModalOpen(false);
};
const handleCancel = () => {
- setIsModalVisible(false);
+ setIsModalOpen(false);
};
return (
@@ -37,7 +37,7 @@ const App: React.FC = () => {
-
+
Some contents...
Some contents...
Some contents...
diff --git a/components/modal/demo/button-props.md b/components/modal/demo/button-props.md
index de6ec2d2af..da61638ae2 100644
--- a/components/modal/demo/button-props.md
+++ b/components/modal/demo/button-props.md
@@ -18,20 +18,20 @@ import { Button, Modal } from 'antd';
import React, { useState } from 'react';
const App: React.FC = () => {
- const [visible, setVisible] = useState(false);
+ const [open, setOpen] = useState(false);
const showModal = () => {
- setVisible(true);
+ setOpen(true);
};
const handleOk = (e: React.MouseEvent) => {
console.log(e);
- setVisible(false);
+ setOpen(false);
};
const handleCancel = (e: React.MouseEvent) => {
console.log(e);
- setVisible(false);
+ setOpen(false);
};
return (
@@ -41,7 +41,7 @@ const App: React.FC = () => {
(
);
export default () => {
- const [visible, setVisible] = useState(false);
+ const [open, setOpen] = useState(false);
const [targetKeys, setTargetKeys] = useState(oriTargetKeys);
const [selectedKeys, setSelectedKeys] = useState([]);
const [disabled, setDisabled] = useState(false);
@@ -329,17 +329,17 @@ export default () => {
};
const showModal = () => {
- setVisible(true);
+ setOpen(true);
};
const handleOk = e => {
console.log(e);
- setVisible(false);
+ setOpen(false);
};
const handleCancel = e => {
console.log(e);
- setVisible(false);
+ setOpen(false);
};
const columns = [
@@ -385,7 +385,7 @@ export default () => {
-
+
{
const [loading, setLoading] = useState(false);
- const [visible, setVisible] = useState(false);
+ const [open, setOpen] = useState(false);
const showModal = () => {
- setVisible(true);
+ setOpen(true);
};
const handleOk = () => {
setLoading(true);
setTimeout(() => {
setLoading(false);
- setVisible(false);
+ setOpen(false);
}, 3000);
};
const handleCancel = () => {
- setVisible(false);
+ setOpen(false);
};
return (
@@ -47,7 +47,7 @@ const App: React.FC = () => {
Open Modal with customized footer
{
- const [visible, setVisible] = useState(false);
+ const [open, setOpen] = useState(false);
const showModal = () => {
- setVisible(true);
+ setOpen(true);
};
const hideModal = () => {
- setVisible(false);
+ setOpen(false);
};
return (
@@ -36,7 +36,7 @@ const LocalizedModal = () => {
{
- const [visible, setVisible] = useState(false);
+ const [open, setOpen] = useState(false);
const [disabled, setDisabled] = useState(false);
const [bounds, setBounds] = useState({ left: 0, top: 0, bottom: 0, right: 0 });
const draggleRef = useRef(null);
const showModal = () => {
- setVisible(true);
+ setOpen(true);
};
const handleOk = (e: React.MouseEvent) => {
console.log(e);
- setVisible(false);
+ setOpen(false);
};
const handleCancel = (e: React.MouseEvent) => {
console.log(e);
- setVisible(false);
+ setOpen(false);
};
const onStart = (_event: DraggableEvent, uiData: DraggableData) => {
@@ -80,7 +80,7 @@ const App: React.FC = () => {
Draggable Modal
}
- visible={visible}
+ open={open}
onOk={handleOk}
onCancel={handleCancel}
modalRender={modal => (
diff --git a/components/modal/demo/position.md b/components/modal/demo/position.md
index 6f8e368ab9..636e6a6b4b 100644
--- a/components/modal/demo/position.md
+++ b/components/modal/demo/position.md
@@ -18,20 +18,20 @@ import { Button, Modal } from 'antd';
import React, { useState } from 'react';
const App: React.FC = () => {
- const [modal1Visible, setModal1Visible] = useState(false);
- const [modal2Visible, setModal2Visible] = useState(false);
+ const [modal1Open, setModal1Open] = useState(false);
+ const [modal2Open, setModal2Open] = useState(false);
return (
<>
-