From c69604ad5f43b94b7184a7d0f8f7c55bfaba96f3 Mon Sep 17 00:00:00 2001 From: afc163 Date: Tue, 8 Mar 2022 21:06:06 +0800 Subject: [PATCH 01/18] chore: resposive.md => responsive.md (#34368) * chore: resposive.md => responsive.md * update snapshot --- .../list/__tests__/__snapshots__/demo-extend.test.ts.snap | 2 +- components/list/__tests__/__snapshots__/demo.test.js.snap | 2 +- components/list/demo/{resposive.md => responsive.md} | 0 3 files changed, 2 insertions(+), 2 deletions(-) rename components/list/demo/{resposive.md => responsive.md} (100%) diff --git a/components/list/__tests__/__snapshots__/demo-extend.test.ts.snap b/components/list/__tests__/__snapshots__/demo-extend.test.ts.snap index 372bebef66..6b2923044c 100644 --- a/components/list/__tests__/__snapshots__/demo-extend.test.ts.snap +++ b/components/list/__tests__/__snapshots__/demo-extend.test.ts.snap @@ -1162,7 +1162,7 @@ exports[`renders ./components/list/demo/loadmore.md extend context correctly 1`] `; -exports[`renders ./components/list/demo/resposive.md extend context correctly 1`] = ` +exports[`renders ./components/list/demo/responsive.md extend context correctly 1`] = `
diff --git a/components/list/__tests__/__snapshots__/demo.test.js.snap b/components/list/__tests__/__snapshots__/demo.test.js.snap index 56e0c6a1be..c226edf967 100644 --- a/components/list/__tests__/__snapshots__/demo.test.js.snap +++ b/components/list/__tests__/__snapshots__/demo.test.js.snap @@ -1162,7 +1162,7 @@ exports[`renders ./components/list/demo/loadmore.md correctly 1`] = `
`; -exports[`renders ./components/list/demo/resposive.md correctly 1`] = ` +exports[`renders ./components/list/demo/responsive.md correctly 1`] = `
diff --git a/components/list/demo/resposive.md b/components/list/demo/responsive.md similarity index 100% rename from components/list/demo/resposive.md rename to components/list/demo/responsive.md From d12614fdbba5f26d8a6247410af343aee62bad46 Mon Sep 17 00:00:00 2001 From: Dennis273 Date: Wed, 9 Mar 2022 16:46:52 +0800 Subject: [PATCH 02/18] docs(Spin): fix en-US description of `spinning` prop (#34382) Previous description indicates that Spin is visible but not spinning when `spinning === false`. According to ZH-CN doc, Spin is not visible when `spinning === false`. --- components/spin/index.en-US.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/spin/index.en-US.md b/components/spin/index.en-US.md index 30b1bc069b..5e54162d9c 100644 --- a/components/spin/index.en-US.md +++ b/components/spin/index.en-US.md @@ -18,7 +18,7 @@ When part of the page is waiting for asynchronous data or during a rendering pro | delay | Specifies a delay in milliseconds for loading state (prevent flush) | number (milliseconds) | - | | indicator | React node of the spinning indicator | ReactNode | - | | size | The size of Spin, options: `small`, `default` and `large` | string | `default` | -| spinning | Whether Spin is spinning | boolean | true | +| spinning | Whether Spin is visible | boolean | true | | tip | Customize description content when Spin has children | ReactNode | - | | wrapperClassName | The className of wrapper when Spin has children | string | - | From b199d9d2fa85a7993ec5372a2a4599d051ef93eb Mon Sep 17 00:00:00 2001 From: MadCcc <1075746765@qq.com> Date: Wed, 9 Mar 2022 17:08:29 +0800 Subject: [PATCH 03/18] fix: input lg font size (#34381) --- components/input/style/mixin.less | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/components/input/style/mixin.less b/components/input/style/mixin.less index 75b9afea78..b37b40930f 100644 --- a/components/input/style/mixin.less +++ b/components/input/style/mixin.less @@ -7,6 +7,10 @@ .input-lg() { padding: @input-padding-vertical-lg @input-padding-horizontal-lg; font-size: @font-size-lg; + + input { + font-size: @font-size-lg; + } } .input-sm() { From 235ab32f44d9594c59e00bff5bd114ad3e49d456 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BA=8C=E8=B4=A7=E6=9C=BA=E5=99=A8=E4=BA=BA?= Date: Wed, 9 Mar 2022 19:34:46 +0800 Subject: [PATCH 04/18] fix: Dropdown not auto adjust placement (#34390) --- components/dropdown/__tests__/index.test.js | 20 ++++++++++++++++++++ components/dropdown/dropdown.tsx | 1 + 2 files changed, 21 insertions(+) diff --git a/components/dropdown/__tests__/index.test.js b/components/dropdown/__tests__/index.test.js index dc97a9bb8f..a4009c40ae 100644 --- a/components/dropdown/__tests__/index.test.js +++ b/components/dropdown/__tests__/index.test.js @@ -79,4 +79,24 @@ describe('Dropdown', () => { expect.stringContaining("[antd: Dropdown] You are using 'topCenter'"), ); }); + + // zombieJ: when replaced with react test lib, it may be mock fully content + it('dropdown should support auto adjust placement', () => { + const wrapper = mount( + menu
} visible> + + , + ); + + expect(wrapper.find('Trigger').prop('builtinPlacements')).toEqual( + expect.objectContaining({ + bottomLeft: expect.objectContaining({ + overflow: { + adjustX: 1, + adjustY: 1, + }, + }), + }), + ); + }); }); diff --git a/components/dropdown/dropdown.tsx b/components/dropdown/dropdown.tsx index fd4e096893..20cf3a9356 100644 --- a/components/dropdown/dropdown.tsx +++ b/components/dropdown/dropdown.tsx @@ -189,6 +189,7 @@ const Dropdown: DropdownInterface = props => { const builtinPlacements = getPlacements({ arrowPointAtCenter: typeof arrow === 'object' && arrow.pointAtCenter, + autoAdjustOverflow: true, }); return ( From 0d2ee1d67fa61f174da15c80afb72a571be523c4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 10 Mar 2022 10:40:44 +0800 Subject: [PATCH 05/18] chore(deps-dev): bump jest-axe from 5.0.1 to 6.0.0 (#34392) Bumps [jest-axe](https://github.com/nickcolley/jest-axe) from 5.0.1 to 6.0.0. - [Release notes](https://github.com/nickcolley/jest-axe/releases) - [Changelog](https://github.com/nickcolley/jest-axe/blob/main/CHANGELOG.md) - [Commits](https://github.com/nickcolley/jest-axe/commits/v6.0.0) --- updated-dependencies: - dependency-name: jest-axe dependency-type: direct:development update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 0deebc8f90..a13057d22c 100644 --- a/package.json +++ b/package.json @@ -228,7 +228,7 @@ "intersection-observer": "^0.12.0", "isomorphic-fetch": "^3.0.0", "jest": "^27.0.3", - "jest-axe": "^5.0.1", + "jest-axe": "^6.0.0", "jest-environment-node": "^27.4.4", "jest-image-snapshot": "^4.5.1", "jest-puppeteer": "^6.0.0", From 793b61e9dbaa53e1534d441c401176335d3ffe34 Mon Sep 17 00:00:00 2001 From: Fisher <33776415+zomixi@users.noreply.github.com> Date: Thu, 10 Mar 2022 11:01:13 +0800 Subject: [PATCH 06/18] =?UTF-8?q?fix(transfer):=20footer=E7=B1=BB=E5=9E=8B?= =?UTF-8?q?=E5=AE=9A=E4=B9=89=E6=94=AF=E6=8C=81direction=20(#34337)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/transfer/index.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/components/transfer/index.tsx b/components/transfer/index.tsx index 27764b2fbc..009d18fd50 100644 --- a/components/transfer/index.tsx +++ b/components/transfer/index.tsx @@ -79,7 +79,9 @@ export interface TransferProps { showSearch?: boolean; filterOption?: (inputValue: string, item: RecordType) => boolean; locale?: Partial; - footer?: (props: TransferListProps) => React.ReactNode; + footer?: (props: TransferListProps, info?: { + direction: TransferDirection; + }) => React.ReactNode; rowKey?: (record: RecordType) => string; onSearch?: (direction: TransferDirection, value: string) => void; onScroll?: (direction: TransferDirection, e: React.SyntheticEvent) => void; From 75429d3b993e7b18ee4ade046c4f4fa4240a0b34 Mon Sep 17 00:00:00 2001 From: Jungzl <35426360+Jungzl@users.noreply.github.com> Date: Thu, 10 Mar 2022 12:11:26 +0800 Subject: [PATCH 07/18] docs: fix select fieldNames typo (#34399) --- components/select/index.en-US.md | 2 +- components/select/index.zh-CN.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/components/select/index.en-US.md b/components/select/index.en-US.md index 90c686ed49..71961722a0 100644 --- a/components/select/index.en-US.md +++ b/components/select/index.en-US.md @@ -37,7 +37,7 @@ Select component to select value from options. | dropdownMatchSelectWidth | Determine whether the dropdown menu and the select input are the same width. Default set `min-width` same as input. Will ignore when value less than select width. `false` will disable virtual scroll | boolean \| number | true | | | dropdownRender | Customize dropdown content | (originNode: ReactNode) => ReactNode | - | | | dropdownStyle | The style of dropdown menu | CSSProperties | - | | -| fieldNames | Customize node title, key, options field name | object | { label: `label`, key: `key`, options: `options` } | 4.17.0 | +| fieldNames | Customize node label, value, options field name | object | { label: `label`, value: `value`, options: `options` } | 4.17.0 | | filterOption | If true, filter options by input, if function, filter options against it. The function will receive two arguments, `inputValue` and `option`, if the function returns `true`, the option will be included in the filtered set; Otherwise, it will be excluded | boolean \| function(inputValue, option) | true | | | filterSort | Sort function for search options sorting, see [Array.sort](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort)'s compareFunction | (optionA: Option, optionB: Option) => number | - | 4.9.0 | | getPopupContainer | Parent Node which the selector should be rendered to. Default to `body`. When position issues happen, try to modify it into scrollable content and position it relative. [Example](https://codesandbox.io/s/4j168r7jw0) | function(triggerNode) | () => document.body | | diff --git a/components/select/index.zh-CN.md b/components/select/index.zh-CN.md index 280c7c5fd6..a441cf1297 100644 --- a/components/select/index.zh-CN.md +++ b/components/select/index.zh-CN.md @@ -38,7 +38,7 @@ cover: https://gw.alipayobjects.com/zos/alicdn/_0XzgOis7/Select.svg | dropdownMatchSelectWidth | 下拉菜单和选择器同宽。默认将设置 `min-width`,当值小于选择框宽度时会被忽略。false 时会关闭虚拟滚动 | boolean \| number | true | | | dropdownRender | 自定义下拉框内容 | (originNode: ReactNode) => ReactNode | - | | | dropdownStyle | 下拉菜单的 style 属性 | CSSProperties | - | | -| fieldNames | 自定义节点 label、key、options 的字段 | object | { label: `label`, key: `key`, options: `options` } | 4.17.0 | +| fieldNames | 自定义节点 label、value、options 的字段 | object | { label: `label`, value: `value`, options: `options` } | 4.17.0 | | filterOption | 是否根据输入项进行筛选。当其为一个函数时,会接收 `inputValue` `option` 两个参数,当 `option` 符合筛选条件时,应返回 true,反之则返回 false | boolean \| function(inputValue, option) | true | | | filterSort | 搜索时对筛选结果项的排序函数, 类似[Array.sort](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort)里的 compareFunction | (optionA: Option, optionB: Option) => number | - | 4.9.0 | | getPopupContainer | 菜单渲染父节点。默认渲染到 body 上,如果你遇到菜单滚动定位问题,试试修改为滚动的区域,并相对其定位。[示例](https://codesandbox.io/s/4j168r7jw0) | function(triggerNode) | () => document.body | | From 3d7ed0815b030ed2359da04ea8c5bf62c178f7a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BA=8C=E8=B4=A7=E6=9C=BA=E5=99=A8=E4=BA=BA?= Date: Thu, 10 Mar 2022 15:21:10 +0800 Subject: [PATCH 08/18] fix: not warning if Form.Item unmount (#34405) --- components/form/FormItem.tsx | 5 +-- components/form/__tests__/list.test.js | 50 ++++++++++++++++++++++++++ package.json | 4 +-- 3 files changed, 55 insertions(+), 4 deletions(-) diff --git a/components/form/FormItem.tsx b/components/form/FormItem.tsx index d8395ba358..2e64434ece 100644 --- a/components/form/FormItem.tsx +++ b/components/form/FormItem.tsx @@ -5,6 +5,7 @@ import { Field, FormInstance, FieldContext, ListContext } from 'rc-field-form'; import { FieldProps } from 'rc-field-form/lib/Field'; import { Meta, NamePath } from 'rc-field-form/lib/interface'; import { supportRef } from 'rc-util/lib/ref'; +import useState from 'rc-util/lib/hooks/useState'; import omit from 'rc-util/lib/omit'; import Row from '../grid/row'; import { ConfigContext } from '../config-provider'; @@ -132,7 +133,7 @@ function FormItem(props: FormItemProps): React.ReactElemen const [subFieldErrors, setSubFieldErrors] = useFrameState>({}); // >>>>> Current field errors - const [meta, setMeta] = React.useState(() => genEmptyMeta()); + const [meta, setMeta] = useState(() => genEmptyMeta()); const onMetaChange = (nextMeta: Meta & { destroy?: boolean }) => { // This keyInfo is not correct when field is removed @@ -141,7 +142,7 @@ function FormItem(props: FormItemProps): React.ReactElemen const keyInfo = listContext?.getKey(nextMeta.name); // Destroy will reset all the meta - setMeta(nextMeta.destroy ? genEmptyMeta() : nextMeta); + setMeta(nextMeta.destroy ? genEmptyMeta() : nextMeta, true); // Bump to parent since noStyle if (noStyle && notifyParentMetaChange) { diff --git a/components/form/__tests__/list.test.js b/components/form/__tests__/list.test.js index bcb3ad0006..8f7778b0c6 100644 --- a/components/form/__tests__/list.test.js +++ b/components/form/__tests__/list.test.js @@ -1,6 +1,8 @@ import React from 'react'; import { mount } from 'enzyme'; import { act } from 'react-dom/test-utils'; +import { render, fireEvent } from '@testing-library/react'; +import '@testing-library/jest-dom'; import Form from '..'; import Input from '../../input'; import Button from '../../button'; @@ -204,4 +206,52 @@ describe('Form.List', () => { const wrapper = mount(); expect(wrapper.render()).toMatchSnapshot(); }); + + it('no warning when reset in validate', async () => { + const errorSpy = jest.spyOn(console, 'error').mockImplementation(() => {}); + + const Demo = () => { + const [form] = Form.useForm(); + + React.useEffect(() => { + form.setFieldsValue({ + list: [1], + }); + }, []); + + return ( +
+ + {fields => + fields.map(field => ( + + + + )) + } + + +
+ ); + }; + + const { container } = render(); + fireEvent.click(container.querySelector('button')); + + await sleep(); + + expect(errorSpy).not.toHaveBeenCalled(); + + errorSpy.mockRestore(); + }); }); diff --git a/package.json b/package.json index a13057d22c..3f9bbbeb57 100644 --- a/package.json +++ b/package.json @@ -152,7 +152,7 @@ "rc-tree-select": "~5.1.1", "rc-trigger": "^5.2.10", "rc-upload": "~4.3.0", - "rc-util": "^5.14.0", + "rc-util": "^5.19.2", "scroll-into-view-if-needed": "^2.2.25" }, "devDependencies": { @@ -164,7 +164,7 @@ "@qixian.cs/github-contributors-list": "^1.0.3", "@stackblitz/sdk": "^1.3.0", "@testing-library/jest-dom": "^5.16.2", - "@testing-library/react": "^12.1.3", + "@testing-library/react": "^12.1.4", "@types/enzyme": "^3.10.5", "@types/gtag.js": "^0.0.8", "@types/jest": "^27.0.0", From 161f5623d53dc792426be86c53137cc1362388cd Mon Sep 17 00:00:00 2001 From: MadCcc <1075746765@qq.com> Date: Thu, 10 Mar 2022 15:31:19 +0800 Subject: [PATCH 09/18] fix: fix arrow size in default.less (#34407) * fix: fix arrow size in default.less * chore: code clean --- components/style/themes/default.less | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/components/style/themes/default.less b/components/style/themes/default.less index fce17ec46d..8f6dbfd01c 100644 --- a/components/style/themes/default.less +++ b/components/style/themes/default.less @@ -516,7 +516,7 @@ // Tooltip background color @tooltip-bg: rgba(0, 0, 0, 0.75); // Tooltip arrow width -@tooltip-arrow-width: 5px; +@tooltip-arrow-width: 8px * sqrt(2); // Tooltip distance with trigger @tooltip-distance: @tooltip-arrow-width - 1px + 4px; // Tooltip arrow color @@ -532,7 +532,7 @@ @popover-min-width: 177px; @popover-min-height: 32px; // Popover arrow width -@popover-arrow-width: 6px; +@popover-arrow-width: @tooltip-arrow-width; // Popover arrow color @popover-arrow-color: @popover-bg; // Popover outer arrow width From 78d2b3f063ac04bda22de54549a9f7d5005ba5fb Mon Sep 17 00:00:00 2001 From: MadCcc <1075746765@qq.com> Date: Thu, 10 Mar 2022 15:53:17 +0800 Subject: [PATCH 10/18] chore: update rc-field-form version (#34411) --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 3f9bbbeb57..8837001187 100644 --- a/package.json +++ b/package.json @@ -127,7 +127,7 @@ "rc-dialog": "~8.6.0", "rc-drawer": "~4.4.2", "rc-dropdown": "~3.3.2", - "rc-field-form": "~1.23.0", + "rc-field-form": "~1.24.0", "rc-image": "~5.2.5", "rc-input": "^0.0.1-alpha.5", "rc-input-number": "~7.3.0", From b51c90084792cfe4c093094861fc2fdd7d0e3b18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BA=8C=E8=B4=A7=E6=9C=BA=E5=99=A8=E4=BA=BA?= Date: Thu, 10 Mar 2022 18:54:32 +0800 Subject: [PATCH 11/18] refactor: rm useDestroy hook (#34418) --- components/_util/ActionButton.tsx | 13 ++++-------- .../_util/__tests__/useDestroyed.test.js | 20 ------------------- components/_util/hooks/useDestroyed.ts | 14 ------------- components/page-header/index.tsx | 9 +++------ components/popconfirm/index.tsx | 7 ++----- package.json | 2 +- 6 files changed, 10 insertions(+), 55 deletions(-) delete mode 100644 components/_util/__tests__/useDestroyed.test.js delete mode 100644 components/_util/hooks/useDestroyed.ts diff --git a/components/_util/ActionButton.tsx b/components/_util/ActionButton.tsx index 50540b3c55..45f209602c 100644 --- a/components/_util/ActionButton.tsx +++ b/components/_util/ActionButton.tsx @@ -1,7 +1,7 @@ import * as React from 'react'; +import useState from 'rc-util/lib/hooks/useState'; import Button from '../button'; import { LegacyButtonType, ButtonProps, convertLegacyProps } from '../button/button'; -import useDestroyed from './hooks/useDestroyed'; export interface ActionButtonProps { type?: LegacyButtonType; @@ -21,8 +21,7 @@ function isThenable(thing?: PromiseLike): boolean { const ActionButton: React.FC = props => { const clickedRef = React.useRef(false); const ref = React.useRef(); - const isDestroyed = useDestroyed(); - const [loading, setLoading] = React.useState(false); + const [loading, setLoading] = useState(false); React.useEffect(() => { let timeoutId: any; @@ -45,9 +44,7 @@ const ActionButton: React.FC = props => { setLoading(true); returnValueOfOnOk!.then( (...args: any[]) => { - if (!isDestroyed()) { - setLoading(false); - } + setLoading(false, true); close(...args); clickedRef.current = false; }, @@ -56,9 +53,7 @@ const ActionButton: React.FC = props => { // eslint-disable-next-line no-console console.error(e); // See: https://github.com/ant-design/ant-design/issues/6183 - if (!isDestroyed()) { - setLoading(false); - } + setLoading(false, true); clickedRef.current = false; }, ); diff --git a/components/_util/__tests__/useDestroyed.test.js b/components/_util/__tests__/useDestroyed.test.js deleted file mode 100644 index d98979e49f..0000000000 --- a/components/_util/__tests__/useDestroyed.test.js +++ /dev/null @@ -1,20 +0,0 @@ -import { mount } from 'enzyme'; -import React from 'react'; -import useDestroyed from '../hooks/useDestroyed'; - -describe('useMounted', () => { - it('should work properly', () => { - let isDestroyed = null; - - const AutoUnmounted = () => { - isDestroyed = useDestroyed(); - - return
Mounted
; - }; - - const wrapper = mount(); - expect(isDestroyed()).toBeFalsy(); - wrapper.unmount(); - expect(isDestroyed()).toBeTruthy(); - }); -}); diff --git a/components/_util/hooks/useDestroyed.ts b/components/_util/hooks/useDestroyed.ts deleted file mode 100644 index 4b361a78ae..0000000000 --- a/components/_util/hooks/useDestroyed.ts +++ /dev/null @@ -1,14 +0,0 @@ -import * as React from 'react'; - -export default function useDestroyed() { - const mountedRef = React.useRef(true); - - React.useEffect( - () => () => { - mountedRef.current = false; - }, - [], - ); - - return () => !mountedRef.current; -} diff --git a/components/page-header/index.tsx b/components/page-header/index.tsx index b6d7cc2be6..e68799d979 100644 --- a/components/page-header/index.tsx +++ b/components/page-header/index.tsx @@ -1,5 +1,6 @@ import * as React from 'react'; import classNames from 'classnames'; +import useState from 'rc-util/lib/hooks/useState'; import ArrowLeftOutlined from '@ant-design/icons/ArrowLeftOutlined'; import ArrowRightOutlined from '@ant-design/icons/ArrowRightOutlined'; import ResizeObserver from 'rc-resize-observer'; @@ -9,7 +10,6 @@ import Breadcrumb, { BreadcrumbProps } from '../breadcrumb'; import Avatar, { AvatarProps } from '../avatar'; import TransButton from '../_util/transButton'; import LocaleReceiver from '../locale-provider/LocaleReceiver'; -import useDestroyed from '../_util/hooks/useDestroyed'; export interface PageHeaderProps { backIcon?: React.ReactNode; @@ -121,12 +121,9 @@ const renderChildren = (prefixCls: string, children: React.ReactNode) => ( ); const PageHeader: React.FC = props => { - const [compact, updateCompact] = React.useState(false); - const isDestroyed = useDestroyed(); + const [compact, updateCompact] = useState(false); const onResize = ({ width }: { width: number }) => { - if (!isDestroyed()) { - updateCompact(width < 768); - } + updateCompact(width < 768, true); }; return ( diff --git a/components/popconfirm/index.tsx b/components/popconfirm/index.tsx index 24cffb7940..afc2ecc050 100644 --- a/components/popconfirm/index.tsx +++ b/components/popconfirm/index.tsx @@ -13,7 +13,6 @@ import { getRenderPropValue, RenderFunction } from '../_util/getRenderPropValue' import { cloneElement } from '../_util/reactNode'; import { getTransitionName } from '../_util/motion'; import ActionButton from '../_util/ActionButton'; -import useDestroyed from '../_util/hooks/useDestroyed'; export interface PopconfirmProps extends AbstractTooltipProps { title: React.ReactNode | RenderFunction; @@ -49,15 +48,13 @@ const Popconfirm = React.forwardRef((props, ref) => { defaultValue: props.defaultVisible, }); - const isDestroyed = useDestroyed(); + // const isDestroyed = useDestroyed(); const settingVisible = ( value: boolean, e?: React.MouseEvent | React.KeyboardEvent, ) => { - if (!isDestroyed()) { - setVisible(value); - } + setVisible(value, true); props.onVisibleChange?.(value, e); }; diff --git a/package.json b/package.json index 8837001187..ff5dc24e55 100644 --- a/package.json +++ b/package.json @@ -152,7 +152,7 @@ "rc-tree-select": "~5.1.1", "rc-trigger": "^5.2.10", "rc-upload": "~4.3.0", - "rc-util": "^5.19.2", + "rc-util": "^5.19.3", "scroll-into-view-if-needed": "^2.2.25" }, "devDependencies": { From 4c666f577561e285c7315652cb984cdba9dd3234 Mon Sep 17 00:00:00 2001 From: MadCcc <1075746765@qq.com> Date: Thu, 10 Mar 2022 19:04:51 +0800 Subject: [PATCH 12/18] fix: clear status in input addon (#34412) --- components/form/context.tsx | 9 +++++++++ components/input-number/index.tsx | 6 +++--- components/input/Input.tsx | 6 +++++- 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/components/form/context.tsx b/components/form/context.tsx index 8ba6d2ac6b..6ce2ac970d 100644 --- a/components/form/context.tsx +++ b/components/form/context.tsx @@ -3,6 +3,7 @@ import omit from 'rc-util/lib/omit'; import { Meta } from 'rc-field-form/lib/interface'; import { FormProvider as RcFormProvider } from 'rc-field-form'; import { FormProviderProps as RcFormProviderProps } from 'rc-field-form/lib/FormContext'; +import { FC, PropsWithChildren, useMemo } from 'react'; import { ColProps } from '../grid/col'; import { FormLabelAlign } from './interface'; import { RequiredMark } from './Form'; @@ -57,3 +58,11 @@ export interface FormItemStatusContextProps { } export const FormItemStatusContext = React.createContext({}); + +export const NoFormStatus: FC> = ({ children }: PropsWithChildren<{}>) => { + const emptyContext = useMemo(() => ({}), []); + + return ( + {children} + ); +}; diff --git a/components/input-number/index.tsx b/components/input-number/index.tsx index 64086960e6..798f0bfde3 100644 --- a/components/input-number/index.tsx +++ b/components/input-number/index.tsx @@ -6,7 +6,7 @@ import * as React from 'react'; import { useContext } from 'react'; import { ConfigContext } from '../config-provider'; import SizeContext, { SizeType } from '../config-provider/SizeContext'; -import { FormItemStatusContext } from '../form/context'; +import { FormItemStatusContext, NoFormStatus } from '../form/context'; import { cloneElement } from '../_util/reactNode'; import { getFeedbackIcon, @@ -168,9 +168,9 @@ const InputNumber = React.forwardRef((props, element = (
- {addonBeforeNode} + {addonBeforeNode && {addonBeforeNode}} {cloneElement(element, { style: null })} - {addonAfterNode} + {addonAfterNode && {addonAfterNode}}
); diff --git a/components/input/Input.tsx b/components/input/Input.tsx index f0265af2f6..e56b8697eb 100644 --- a/components/input/Input.tsx +++ b/components/input/Input.tsx @@ -11,7 +11,7 @@ import { InputStatus, } from '../_util/statusUtils'; import { ConfigContext } from '../config-provider'; -import { FormItemStatusContext } from '../form/context'; +import { FormItemStatusContext, NoFormStatus } from '../form/context'; import { hasPrefixSuffix } from './utils'; import devWarning from '../_util/devWarning'; @@ -130,6 +130,8 @@ const Input = forwardRef((props, ref) => { onFocus, suffix, allowClear, + addonAfter, + addonBefore, ...rest } = props; const { getPrefixCls, direction, input } = React.useContext(ConfigContext); @@ -217,6 +219,8 @@ const Input = forwardRef((props, ref) => { onFocus={handleFocus} suffix={suffixNode} allowClear={mergedAllowClear} + addonAfter={addonAfter && {addonAfter}} + addonBefore={addonBefore && {addonBefore}} inputClassName={classNames( !withPrefixSuffix && { [`${prefixCls}-sm`]: mergedSize === 'small', From fbb98f2b4f30de95989d2a75f4fa98c63f2b2dd7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=AB=98=E5=96=B5=E5=96=B5?= Date: Thu, 10 Mar 2022 19:26:01 +0800 Subject: [PATCH 13/18] Fix InputProps supports data attributes (#34410) * fix: add data-xx for inputProps and convert input/_tests/index.test.js to tsx file * fix: run tests --- components/input/Input.tsx | 1 + ...index.test.js.snap => index.test.tsx.snap} | 0 .../{index.test.js => index.test.tsx} | 89 ++++++++++++------- 3 files changed, 58 insertions(+), 32 deletions(-) rename components/input/__tests__/__snapshots__/{index.test.js.snap => index.test.tsx.snap} (100%) rename components/input/__tests__/{index.test.js => index.test.tsx} (79%) diff --git a/components/input/Input.tsx b/components/input/Input.tsx index e56b8697eb..4028eb6095 100644 --- a/components/input/Input.tsx +++ b/components/input/Input.tsx @@ -118,6 +118,7 @@ export interface InputProps size?: SizeType; status?: InputStatus; bordered?: boolean; + [key: `data-${string}`]: string; } const Input = forwardRef((props, ref) => { diff --git a/components/input/__tests__/__snapshots__/index.test.js.snap b/components/input/__tests__/__snapshots__/index.test.tsx.snap similarity index 100% rename from components/input/__tests__/__snapshots__/index.test.js.snap rename to components/input/__tests__/__snapshots__/index.test.tsx.snap diff --git a/components/input/__tests__/index.test.js b/components/input/__tests__/index.test.tsx similarity index 79% rename from components/input/__tests__/index.test.js rename to components/input/__tests__/index.test.tsx index b5e6c8c20b..edcdd4f99b 100644 --- a/components/input/__tests__/index.test.js +++ b/components/input/__tests__/index.test.tsx @@ -2,7 +2,7 @@ import React, { useState } from 'react'; import { mount } from 'enzyme'; // eslint-disable-next-line import/no-unresolved import Form from '../../form'; -import Input from '..'; +import Input, { InputProps, InputRef } from '..'; import mountTest from '../../../tests/shared/mountTest'; import rtlTest from '../../../tests/shared/rtlTest'; @@ -29,7 +29,7 @@ describe('Input', () => { }); it('select()', () => { - const ref = React.createRef(); + const ref = React.createRef(); mount(); ref.current?.select(); }); @@ -55,7 +55,7 @@ describe('Input', () => { describe('focus trigger warning', () => { it('not trigger', () => { const wrapper = mount(); - wrapper.find('input').instance().focus(); + (wrapper.find('input').instance() as any).focus(); wrapper.setProps({ suffix: 'light', }); @@ -63,7 +63,7 @@ describe('Input', () => { }); it('trigger warning', () => { const wrapper = mount(); - wrapper.find('input').first().getDOMNode().focus(); + wrapper.find('input').first().getDOMNode().focus(); wrapper.setProps({ suffix: 'light', }); @@ -77,11 +77,11 @@ describe('Input', () => { it('set mouse cursor position', () => { const defaultValue = '11111'; const valLength = defaultValue.length; - const ref = React.createRef(); + const ref = React.createRef(); const wrapper = mount(); ref.current?.setSelectionRange(valLength, valLength); - expect(wrapper.find('input').first().getDOMNode().selectionStart).toEqual(5); - expect(wrapper.find('input').first().getDOMNode().selectionEnd).toEqual(5); + expect(wrapper.find('input').first().getDOMNode().selectionStart).toEqual(5); + expect(wrapper.find('input').first().getDOMNode().selectionEnd).toEqual(5); }); }); @@ -106,8 +106,12 @@ describe('prefix and suffix', () => { , ); - expect(wrapper.find('.prefix-with-hidden').at(0).getDOMNode().hidden).toBe(true); - expect(wrapper.find('.suffix-with-hidden').at(0).getDOMNode().hidden).toBe(true); + expect(wrapper.find('.prefix-with-hidden').at(0).getDOMNode().hidden).toBe( + true, + ); + expect(wrapper.find('.suffix-with-hidden').at(0).getDOMNode().hidden).toBe( + true, + ); }); }); @@ -143,6 +147,7 @@ describe('Input setting hidden', () => { showCount allowClear prefix="11" + // @ts-ignore suffix="22" addonBefore="http://" addonAfter=".com" @@ -162,10 +167,10 @@ describe('Input setting hidden', () => { , ); - expect(wrapper.find('.input').at(0).getDOMNode().hidden).toBe(true); - expect(wrapper.find('.input-search').at(0).getDOMNode().hidden).toBe(true); - expect(wrapper.find('.input-textarea').at(0).getDOMNode().hidden).toBe(true); - expect(wrapper.find('.input-password').at(0).getDOMNode().hidden).toBe(true); + expect(wrapper.find('.input').at(0).getDOMNode().hidden).toBe(true); + expect(wrapper.find('.input-search').at(0).getDOMNode().hidden).toBe(true); + expect(wrapper.find('.input-textarea').at(0).getDOMNode().hidden).toBe(true); + expect(wrapper.find('.input-password').at(0).getDOMNode().hidden).toBe(true); }); }); @@ -250,17 +255,18 @@ describe('Input allowClear', () => { it('should change type when click', () => { const wrapper = mount(); wrapper.find('input').simulate('change', { target: { value: '111' } }); - expect(wrapper.find('input').getDOMNode().value).toEqual('111'); + expect(wrapper.find('input').getDOMNode().value).toEqual('111'); expect(wrapper.render()).toMatchSnapshot(); wrapper.find('.ant-input-clear-icon').at(0).simulate('click'); expect(wrapper.render()).toMatchSnapshot(); - expect(wrapper.find('input').getDOMNode().value).toEqual(''); + expect(wrapper.find('input').getDOMNode().value).toEqual(''); }); it('should not show icon if value is undefined, null or empty string', () => { + // @ts-ignore const wrappers = [null, undefined, ''].map(val => mount()); wrappers.forEach(wrapper => { - expect(wrapper.find('input').getDOMNode().value).toEqual(''); + expect(wrapper.find('input').getDOMNode().value).toEqual(''); expect(wrapper.find('.ant-input-clear-icon-hidden').exists()).toBeTruthy(); expect(wrapper.render()).toMatchSnapshot(); }); @@ -268,41 +274,43 @@ describe('Input allowClear', () => { it('should not show icon if defaultValue is undefined, null or empty string', () => { const wrappers = [null, undefined, ''].map(val => + // @ts-ignore mount(), ); wrappers.forEach(wrapper => { - expect(wrapper.find('input').getDOMNode().value).toEqual(''); + expect(wrapper.find('input').getDOMNode().value).toEqual(''); expect(wrapper.find('.ant-input-clear-icon-hidden').exists()).toBeTruthy(); expect(wrapper.render()).toMatchSnapshot(); }); }); it('should trigger event correctly', () => { - let argumentEventObject; + let argumentEventObject: React.ChangeEvent | undefined; + let argumentEventObjectValue; - const onChange = e => { + const onChange: InputProps['onChange'] = e => { argumentEventObject = e; argumentEventObjectValue = e.target.value; }; const wrapper = mount(); wrapper.find('.ant-input-clear-icon').at(0).simulate('click'); - expect(argumentEventObject.type).toBe('click'); + expect(argumentEventObject?.type).toBe('click'); expect(argumentEventObjectValue).toBe(''); - expect(wrapper.find('input').at(0).getDOMNode().value).toBe(''); + expect(wrapper.find('input').at(0).getDOMNode().value).toBe(''); }); it('should trigger event correctly on controlled mode', () => { - let argumentEventObject; + let argumentEventObject: React.ChangeEvent | undefined; let argumentEventObjectValue; - const onChange = e => { + const onChange: InputProps['onChange'] = e => { argumentEventObject = e; argumentEventObjectValue = e.target.value; }; const wrapper = mount(); wrapper.find('.ant-input-clear-icon').at(0).simulate('click'); - expect(argumentEventObject.type).toBe('click'); + expect(argumentEventObject?.type).toBe('click'); expect(argumentEventObjectValue).toBe(''); - expect(wrapper.find('input').at(0).getDOMNode().value).toBe('111'); + expect(wrapper.find('input').at(0).getDOMNode().value).toBe('111'); }); it('should focus input after clear', () => { @@ -332,12 +340,12 @@ describe('Input allowClear', () => { const wrapper = mount(, { attachTo: document.body, }); - wrapper.find('input').getDOMNode().focus(); + wrapper.find('input').getDOMNode().focus(); wrapper.find('.ant-input-clear-icon').at(0).simulate('mouseDown'); wrapper.find('.ant-input-clear-icon').at(0).simulate('click'); wrapper.find('.ant-input-clear-icon').at(0).simulate('mouseUp'); wrapper.find('.ant-input-clear-icon').at(0).simulate('focus'); - wrapper.find('.ant-input-clear-icon').at(0).getDOMNode().click(); + wrapper.find('.ant-input-clear-icon').at(0).getDOMNode().click(); expect(onBlur).not.toBeCalled(); wrapper.unmount(); }); @@ -359,12 +367,12 @@ describe('Input allowClear', () => { const wrapper = mount(); - wrapper.find('input').getDOMNode().focus(); + wrapper.find('input').getDOMNode().focus(); wrapper.find('input').simulate('change', { target: { value: '111' } }); - expect(wrapper.find('input').getDOMNode().value).toEqual('111'); + expect(wrapper.find('input').getDOMNode().value).toEqual('111'); wrapper.find('.ant-input-clear-icon').at(0).simulate('click'); - expect(wrapper.find('input').getDOMNode().value).toEqual(''); + expect(wrapper.find('input').getDOMNode().value).toEqual(''); wrapper.unmount(); }); @@ -375,10 +383,11 @@ describe('Input allowClear', () => { }); it('should display boolean value as string', () => { + // @ts-ignore const wrapper = mount(); - expect(wrapper.find('input').first().getDOMNode().value).toBe('true'); + expect(wrapper.find('input').first().getDOMNode().value).toBe('true'); wrapper.setProps({ value: false }); - expect(wrapper.find('input').first().getDOMNode().value).toBe('false'); + expect(wrapper.find('input').first().getDOMNode().value).toBe('false'); }); it('should support custom clearIcon', () => { @@ -386,3 +395,19 @@ describe('Input allowClear', () => { expect(wrapper.find('.ant-input-clear-icon').text()).toBe('clear'); }); }); + +describe('typescript types ', () => { + it('InputProps type should support data-* attributes', () => { + const props: InputProps = { + value: 123, + + // expect no ts error here + 'data-testid': 'test-id', + 'data-id': '12345', + }; + const wrapper = mount(); + const input = wrapper.find('input').first().getDOMNode(); + expect(input.getAttribute('data-testid')).toBe('test-id'); + expect(input.getAttribute('data-id')).toBe('12345'); + }); +}); From 362a99e9d4a1645db84e124fcfbbf30a2e59ccef Mon Sep 17 00:00:00 2001 From: PanStar Date: Thu, 10 Mar 2022 19:29:50 +0800 Subject: [PATCH 14/18] feat: hide the last border in borderless mode (#34366) --- components/collapse/style/index.less | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/components/collapse/style/index.less b/components/collapse/style/index.less index 6b10c990b8..b92378d523 100644 --- a/components/collapse/style/index.less +++ b/components/collapse/style/index.less @@ -120,6 +120,11 @@ border-radius: 0; } + // hide the last border-bottom in borderless mode + &-borderless > &-item:last-child { + border-bottom: 0; + } + &-borderless > &-item > &-content { background-color: transparent; border-top: 0; From fca721030904fe0bcbfdba8c16cb5c68b21f49c8 Mon Sep 17 00:00:00 2001 From: dujun Date: Thu, 10 Mar 2022 19:47:16 +0800 Subject: [PATCH 15/18] fix: Tooltip width in safari (#34415) --- components/tooltip/style/index.less | 1 + 1 file changed, 1 insertion(+) diff --git a/components/tooltip/style/index.less b/components/tooltip/style/index.less index 7b00fdea44..697f685574 100644 --- a/components/tooltip/style/index.less +++ b/components/tooltip/style/index.less @@ -19,6 +19,7 @@ z-index: @zindex-tooltip; display: block; width: max-content; + width: intrinsic; max-width: @tooltip-max-width; visibility: visible; From 86415ef8a2890da096c5fca77cf11d82537002a6 Mon Sep 17 00:00:00 2001 From: zqran Date: Fri, 11 Mar 2022 09:52:16 +0800 Subject: [PATCH 16/18] docs(Table): replace the link of `TableComponents` prop with `rc-table` type (#34423) --- components/table/index.en-US.md | 2 +- components/table/index.zh-CN.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/components/table/index.en-US.md b/components/table/index.en-US.md index c19fce6262..0858b4bc07 100644 --- a/components/table/index.en-US.md +++ b/components/table/index.en-US.md @@ -62,7 +62,7 @@ const columns = [ | --- | --- | --- | --- | --- | | bordered | Whether to show all table borders | boolean | false | | | columns | Columns of table | [ColumnsType](#Column)\[] | - | | -| components | Override default table elements | [TableComponents](https://git.io/fANxz) | - | | +| components | Override default table elements | [TableComponents](https://github.com/react-component/table/blob/75ee0064e54a4b3215694505870c9d6c817e9e4a/src/interface.ts#L129) | - | | | dataSource | Data record array to be displayed | object\[] | - | | | expandable | Config expandable content | [expandable](#expandable) | - | | | footer | Table footer renderer | function(currentPageData) | - | | diff --git a/components/table/index.zh-CN.md b/components/table/index.zh-CN.md index 6db807b71f..71489d98cf 100644 --- a/components/table/index.zh-CN.md +++ b/components/table/index.zh-CN.md @@ -69,7 +69,7 @@ const columns = [ | --- | --- | --- | --- | --- | | bordered | 是否展示外边框和列边框 | boolean | false | | | columns | 表格列的配置描述,具体项见下表 | [ColumnsType](#Column)\[] | - | | -| components | 覆盖默认的 table 元素 | [TableComponents](https://git.io/fANxz) | - | | +| components | 覆盖默认的 table 元素 | [TableComponents](https://github.com/react-component/table/blob/75ee0064e54a4b3215694505870c9d6c817e9e4a/src/interface.ts#L129) | - | | | dataSource | 数据数组 | object\[] | - | | | expandable | 配置展开属性 | [expandable](#expandable) | - | | | footer | 表格尾部 | function(currentPageData) | - | | From f987bd0479333b51391c0ae36415538f0874d620 Mon Sep 17 00:00:00 2001 From: afc163 Date: Fri, 11 Mar 2022 13:34:38 +0800 Subject: [PATCH 17/18] fix: PageHeader extra gutter (#34428) --- .../__snapshots__/demo-extend.test.ts.snap | 736 ++++++++++-------- .../__tests__/__snapshots__/demo.test.js.snap | 372 +++++---- components/page-header/demo/content.md | 18 +- components/page-header/index.tsx | 7 +- components/page-header/style/index.less | 5 - components/page-header/style/index.tsx | 1 + 6 files changed, 658 insertions(+), 481 deletions(-) diff --git a/components/page-header/__tests__/__snapshots__/demo-extend.test.ts.snap b/components/page-header/__tests__/__snapshots__/demo-extend.test.ts.snap index 23b5f206f9..0bbaec1ded 100644 --- a/components/page-header/__tests__/__snapshots__/demo-extend.test.ts.snap +++ b/components/page-header/__tests__/__snapshots__/demo-extend.test.ts.snap @@ -58,30 +58,48 @@ Array [ - - - +
+ +
+
+ +
+
+ +
+
- - - +
+ +
+
+ +
+
+ +
+
- - - - -
- - +
+ +
+
+ +
+
+ +
+
+
-
-
- -
-
-
- - - +
+ +
+
+ +
+
+ +
+
- - - - + + Operation + + +
+
+ +
+
+ +
+
+ +
+
- - - +
+ +
+
+ +
+
+ +
+
- - - +
+ +
+
+ +
+
+ +
+
( - - + +
)} - {extra && {extra}} + {extra && ( + + {extra} + + )}
); }; diff --git a/components/page-header/style/index.less b/components/page-header/style/index.less index 6eeedec96f..074145756c 100644 --- a/components/page-header/style/index.less +++ b/components/page-header/style/index.less @@ -87,13 +87,8 @@ white-space: nowrap; > * { - margin-left: @margin-sm; white-space: unset; } - - > *:first-child { - margin-left: 0; - } } } diff --git a/components/page-header/style/index.tsx b/components/page-header/style/index.tsx index 8ca5d47ad6..cd4e5ba32d 100644 --- a/components/page-header/style/index.tsx +++ b/components/page-header/style/index.tsx @@ -3,3 +3,4 @@ import './index.less'; // style dependencies import '../../breadcrumb/style'; import '../../avatar/style'; +import '../../space/style'; From c50bbe64bb349eec7c52c8a1ad83059570dbddf7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BA=8C=E8=B4=A7=E6=9C=BA=E5=99=A8=E4=BA=BA?= Date: Fri, 11 Mar 2022 15:26:29 +0800 Subject: [PATCH 18/18] chore: refactor internal menu with hooks (#34433) * chore: refactor menu with hooks * chore: clean up --- components/menu/index.tsx | 166 +++++++++++++++++--------------------- 1 file changed, 72 insertions(+), 94 deletions(-) diff --git a/components/menu/index.tsx b/components/menu/index.tsx index 1b436d79df..f02197a7ef 100644 --- a/components/menu/index.tsx +++ b/components/menu/index.tsx @@ -3,15 +3,14 @@ import RcMenu, { ItemGroup, MenuProps as RcMenuProps } from 'rc-menu'; import classNames from 'classnames'; import omit from 'rc-util/lib/omit'; import EllipsisOutlined from '@ant-design/icons/EllipsisOutlined'; -import memoize from 'memoize-one'; import SubMenu, { SubMenuProps } from './SubMenu'; import Item, { MenuItemProps } from './MenuItem'; -import { ConfigConsumer, ConfigConsumerProps, DirectionType } from '../config-provider'; +import { ConfigContext } from '../config-provider'; import devWarning from '../_util/devWarning'; import { SiderContext, SiderContextProps } from '../layout/Sider'; import collapseMotion from '../_util/motion'; import { cloneElement } from '../_util/reactNode'; -import MenuContext, { MenuTheme, MenuContextProps } from './MenuContext'; +import MenuContext, { MenuTheme } from './MenuContext'; import MenuDivider from './MenuDivider'; export { MenuDividerProps } from './MenuDivider'; @@ -37,108 +36,87 @@ type InternalMenuProps = MenuProps & collapsedWidth?: string | number; }; -class InternalMenu extends React.Component { - static defaultProps: Partial = { - theme: 'light', // or dark - }; +function InternalMenu(props: InternalMenuProps) { + const { getPrefixCls, getPopupContainer, direction } = React.useContext(ConfigContext); - constructor(props: InternalMenuProps) { - super(props); + const rootPrefixCls = getPrefixCls(); - devWarning( - !('inlineCollapsed' in props && props.mode !== 'inline'), - 'Menu', - '`inlineCollapsed` should only be used when `mode` is inline.', - ); + const { + prefixCls: customizePrefixCls, + className, + theme = 'light', + expandIcon, + _internalDisableMenuItemTitleTooltip, + inlineCollapsed, + siderCollapsed, + ...restProps + } = props; - devWarning( - !(props.siderCollapsed !== undefined && 'inlineCollapsed' in props), - 'Menu', - '`inlineCollapsed` not control Menu under Sider. Should set `collapsed` on Sider instead.', - ); - } + const passedProps = omit(restProps, ['collapsedWidth']); - getInlineCollapsed() { - const { inlineCollapsed, siderCollapsed } = this.props; + // ======================== Warning ========================== + devWarning( + !('inlineCollapsed' in props && props.mode !== 'inline'), + 'Menu', + '`inlineCollapsed` should only be used when `mode` is inline.', + ); + + devWarning( + !(props.siderCollapsed !== undefined && 'inlineCollapsed' in props), + 'Menu', + '`inlineCollapsed` not control Menu under Sider. Should set `collapsed` on Sider instead.', + ); + + // ======================== Collapsed ======================== + // Inline Collapsed + const mergedInlineCollapsed = React.useMemo(() => { if (siderCollapsed !== undefined) { return siderCollapsed; } return inlineCollapsed; - } + }, [inlineCollapsed, siderCollapsed]); - getMemoizedContextValue = memoize( - ( - cls: string, - collapsed: boolean | undefined, - the: MenuTheme | undefined, - dir: DirectionType, - disableMenuItemTitleTooltip: boolean | undefined, - ): MenuContextProps => ({ - prefixCls: cls, - inlineCollapsed: collapsed || false, - antdMenuTheme: the, - direction: dir, - firstLevel: true, - disableMenuItemTitleTooltip, - }), - ); - - renderMenu = ({ getPopupContainer, getPrefixCls, direction }: ConfigConsumerProps) => { - const rootPrefixCls = getPrefixCls(); - - const { - prefixCls: customizePrefixCls, - className, - theme, - expandIcon, - _internalDisableMenuItemTitleTooltip, - ...restProps - } = this.props; - - const passedProps = omit(restProps, ['siderCollapsed', 'collapsedWidth']); - const inlineCollapsed = this.getInlineCollapsed(); - - const defaultMotions = { - horizontal: { motionName: `${rootPrefixCls}-slide-up` }, - inline: collapseMotion, - other: { motionName: `${rootPrefixCls}-zoom-big` }, - }; - - const prefixCls = getPrefixCls('menu', customizePrefixCls); - const menuClassName = classNames(`${prefixCls}-${theme}`, className); - - // TODO: refactor menu with function component - const contextValue = this.getMemoizedContextValue( - prefixCls, - inlineCollapsed, - theme, - direction, - _internalDisableMenuItemTitleTooltip, - ); - - return ( - - } - overflowedIndicatorPopupClassName={`${prefixCls}-${theme}`} - {...passedProps} - inlineCollapsed={inlineCollapsed} - className={menuClassName} - prefixCls={prefixCls} - direction={direction} - defaultMotions={defaultMotions} - expandIcon={cloneElement(expandIcon, { - className: `${prefixCls}-submenu-expand-icon`, - })} - /> - - ); + const defaultMotions = { + horizontal: { motionName: `${rootPrefixCls}-slide-up` }, + inline: collapseMotion, + other: { motionName: `${rootPrefixCls}-zoom-big` }, }; - render() { - return {this.renderMenu}; - } + const prefixCls = getPrefixCls('menu', customizePrefixCls); + const menuClassName = classNames(`${prefixCls}-${theme}`, className); + + // ======================== Context ========================== + const contextValue = React.useMemo( + () => ({ + prefixCls, + inlineCollapsed: mergedInlineCollapsed || false, + antdMenuTheme: theme, + direction, + firstLevel: true, + disableMenuItemTitleTooltip: _internalDisableMenuItemTitleTooltip, + }), + [prefixCls, mergedInlineCollapsed, theme, direction, _internalDisableMenuItemTitleTooltip], + ); + + // ========================= Render ========================== + return ( + + } + overflowedIndicatorPopupClassName={`${prefixCls}-${theme}`} + {...passedProps} + inlineCollapsed={mergedInlineCollapsed} + className={menuClassName} + prefixCls={prefixCls} + direction={direction} + defaultMotions={defaultMotions} + expandIcon={cloneElement(expandIcon, { + className: `${prefixCls}-submenu-expand-icon`, + })} + /> + + ); } // We should keep this as ref-able