chore: next merge feature

This commit is contained in:
二货机器人 2022-08-18 17:24:39 +08:00
commit 25e001f8b5
59 changed files with 1059 additions and 638 deletions

View File

@ -15,6 +15,13 @@ timeline: true
---
## 4.22.6
`2022-08-17`
- 🐞 Revert [#36710](https://github.com/ant-design/ant-design/pull/36710) to fix Table `onChange` argument `sorter` error in multiple columns sort.
- 🐞 Fix Drawer can not close when config `opacity` on the `maskStyle`. [#37100](https://github.com/ant-design/ant-design/pull/37100)
## 4.22.5
`2022-08-15`

View File

@ -15,6 +15,13 @@ timeline: true
---
## 4.22.6
`2022-08-17`
- 🐞 回滚 [#36710](https://github.com/ant-design/ant-design/pull/36710) 以修复 Table 多列排序时 `onChange``sorter` 参数错误的问题。
- 🐞 修复 Drawer 的 `maskStyle` 配置 `opacity` 样式时无法关闭的问题。[#37100](https://github.com/ant-design/ant-design/pull/37100)
## 4.22.5
`2022-08-15`

View File

@ -457,9 +457,14 @@ describe('ConfigProvider', () => {
testPair('Slider', props => {
const myProps = { ...props };
if (myProps.prefixCls) {
myProps.tooltipPrefixCls = `${myProps.prefixCls}-tooltip`;
return (
<Slider
tooltip={{ open: true, prefixCls: `${myProps.prefixCls}-tooltip` }}
{...myProps}
/>
);
}
return <Slider tooltipVisible {...myProps} />;
return <Slider tooltip={{ open: true }} {...myProps} />;
});
// Spin

View File

@ -15,7 +15,7 @@ exports[`Drawer className is test_drawer 1`] = `
tabindex="0"
/>
<div
class="ant-drawer-content-wrapper ant-drawer-panel-motion-right-appear ant-drawer-panel-motion-right-appear-active ant-drawer-panel-motion-right"
class="ant-drawer-content-wrapper"
style="width: 378px;"
>
<div
@ -91,7 +91,7 @@ exports[`Drawer closable is false 1`] = `
tabindex="0"
/>
<div
class="ant-drawer-content-wrapper ant-drawer-panel-motion-right-appear ant-drawer-panel-motion-right-appear-active ant-drawer-panel-motion-right"
class="ant-drawer-content-wrapper"
style="width: 378px;"
>
<div
@ -139,7 +139,7 @@ exports[`Drawer getContainer return undefined 2`] = `
tabindex="0"
/>
<div
class="ant-drawer-content-wrapper ant-drawer-panel-motion-right-appear ant-drawer-panel-motion-right-appear-active ant-drawer-panel-motion-right"
class="ant-drawer-content-wrapper"
style="width: 400px;"
>
<div
@ -216,7 +216,7 @@ exports[`Drawer have a footer 1`] = `
tabindex="0"
/>
<div
class="ant-drawer-content-wrapper ant-drawer-panel-motion-right-appear ant-drawer-panel-motion-right-appear-active ant-drawer-panel-motion-right"
class="ant-drawer-content-wrapper"
style="width: 378px;"
>
<div
@ -297,7 +297,7 @@ exports[`Drawer have a title 1`] = `
tabindex="0"
/>
<div
class="ant-drawer-content-wrapper ant-drawer-panel-motion-right-appear ant-drawer-panel-motion-right-appear-active ant-drawer-panel-motion-right"
class="ant-drawer-content-wrapper"
style="width: 378px;"
>
<div
@ -378,7 +378,7 @@ exports[`Drawer render correctly 1`] = `
tabindex="0"
/>
<div
class="ant-drawer-content-wrapper ant-drawer-panel-motion-right-appear ant-drawer-panel-motion-right-appear-active ant-drawer-panel-motion-right"
class="ant-drawer-content-wrapper"
style="width: 400px;"
>
<div
@ -454,7 +454,7 @@ exports[`Drawer render top drawer 1`] = `
tabindex="0"
/>
<div
class="ant-drawer-content-wrapper ant-drawer-panel-motion-top-appear ant-drawer-panel-motion-top-appear-active ant-drawer-panel-motion-top"
class="ant-drawer-content-wrapper"
style="height: 400px;"
>
<div
@ -533,7 +533,7 @@ exports[`Drawer style/drawerStyle/headerStyle/bodyStyle should work 1`] = `
tabindex="0"
/>
<div
class="ant-drawer-content-wrapper ant-drawer-panel-motion-right-appear ant-drawer-panel-motion-right-appear-active ant-drawer-panel-motion-right"
class="ant-drawer-content-wrapper"
style="width: 378px;"
>
<div
@ -612,7 +612,7 @@ exports[`Drawer support closeIcon 1`] = `
tabindex="0"
/>
<div
class="ant-drawer-content-wrapper ant-drawer-panel-motion-right-appear ant-drawer-panel-motion-right-appear-active ant-drawer-panel-motion-right"
class="ant-drawer-content-wrapper"
style="width: 400px;"
>
<div

View File

@ -15,7 +15,7 @@ HTMLCollection [
tabindex="-1"
>
<div
class="ant-drawer-mask ant-drawer-mask-motion-appear ant-drawer-mask-motion-appear-active ant-drawer-mask-motion"
class="ant-drawer-mask"
/>
<div
aria-hidden="true"
@ -24,7 +24,7 @@ HTMLCollection [
tabindex="0"
/>
<div
class="ant-drawer-content-wrapper ant-drawer-panel-motion-right-appear ant-drawer-panel-motion-right-appear-active ant-drawer-panel-motion-right"
class="ant-drawer-content-wrapper"
style="width: 378px;"
>
<div
@ -117,7 +117,7 @@ exports[`renders ./components/drawer/demo/config-provider.md extend context corr
tabindex="-1"
>
<div
class="ant-drawer-mask ant-drawer-mask-motion-appear ant-drawer-mask-motion-appear-active ant-drawer-mask-motion"
class="ant-drawer-mask"
/>
<div
aria-hidden="true"
@ -126,7 +126,7 @@ exports[`renders ./components/drawer/demo/config-provider.md extend context corr
tabindex="0"
/>
<div
class="ant-drawer-content-wrapper ant-drawer-panel-motion-right-appear ant-drawer-panel-motion-right-appear-active ant-drawer-panel-motion-right"
class="ant-drawer-content-wrapper"
style="width: 378px;"
>
<div
@ -310,7 +310,7 @@ HTMLCollection [
tabindex="-1"
>
<div
class="ant-drawer-mask ant-drawer-mask-motion-appear ant-drawer-mask-motion-appear-active ant-drawer-mask-motion"
class="ant-drawer-mask"
/>
<div
aria-hidden="true"
@ -319,7 +319,7 @@ HTMLCollection [
tabindex="0"
/>
<div
class="ant-drawer-content-wrapper ant-drawer-panel-motion-right-appear ant-drawer-panel-motion-right-appear-active ant-drawer-panel-motion-right"
class="ant-drawer-content-wrapper"
style="width: 500px;"
>
<div
@ -467,7 +467,7 @@ HTMLCollection [
tabindex="-1"
>
<div
class="ant-drawer-mask ant-drawer-mask-motion-appear ant-drawer-mask-motion-appear-active ant-drawer-mask-motion"
class="ant-drawer-mask"
/>
<div
aria-hidden="true"
@ -476,7 +476,7 @@ HTMLCollection [
tabindex="0"
/>
<div
class="ant-drawer-content-wrapper ant-drawer-panel-motion-right-appear ant-drawer-panel-motion-right-appear-active ant-drawer-panel-motion-right"
class="ant-drawer-content-wrapper"
style="width: 720px;"
>
<div
@ -2512,7 +2512,7 @@ HTMLCollection [
tabindex="-1"
>
<div
class="ant-drawer-mask ant-drawer-mask-motion-appear ant-drawer-mask-motion-appear-active ant-drawer-mask-motion"
class="ant-drawer-mask"
/>
<div
aria-hidden="true"
@ -2521,7 +2521,7 @@ HTMLCollection [
tabindex="0"
/>
<div
class="ant-drawer-content-wrapper ant-drawer-panel-motion-right-appear ant-drawer-panel-motion-right-appear-active ant-drawer-panel-motion-right"
class="ant-drawer-content-wrapper"
style="width: 520px; transform: translateX(-180px);"
>
<div
@ -2561,7 +2561,7 @@ HTMLCollection [
tabindex="-1"
>
<div
class="ant-drawer-mask ant-drawer-mask-motion-appear ant-drawer-mask-motion-appear-active ant-drawer-mask-motion"
class="ant-drawer-mask"
/>
<div
aria-hidden="true"
@ -2570,7 +2570,7 @@ HTMLCollection [
tabindex="0"
/>
<div
class="ant-drawer-content-wrapper ant-drawer-panel-motion-right-appear ant-drawer-panel-motion-right-appear-active ant-drawer-panel-motion-right"
class="ant-drawer-content-wrapper"
style="width: 320px;"
>
<div
@ -2644,7 +2644,7 @@ HTMLCollection [
tabindex="0"
/>
<div
class="ant-drawer-content-wrapper ant-drawer-panel-motion-right-appear ant-drawer-panel-motion-right-appear-active ant-drawer-panel-motion-right"
class="ant-drawer-content-wrapper"
style="width: 333px; background: red; border-radius: 20px; box-shadow: -5px 0 5px green; overflow: hidden;"
>
<div
@ -2828,7 +2828,7 @@ HTMLCollection [
tabindex="-1"
>
<div
class="ant-drawer-mask ant-drawer-mask-motion-appear ant-drawer-mask-motion-appear-active ant-drawer-mask-motion"
class="ant-drawer-mask"
/>
<div
aria-hidden="true"
@ -2837,7 +2837,7 @@ HTMLCollection [
tabindex="0"
/>
<div
class="ant-drawer-content-wrapper ant-drawer-panel-motion-left-appear ant-drawer-panel-motion-left-appear-active ant-drawer-panel-motion-left"
class="ant-drawer-content-wrapper"
style="width: 378px;"
>
<div
@ -2909,7 +2909,7 @@ exports[`renders ./components/drawer/demo/render-in-current.md extend context co
tabindex="-1"
>
<div
class="ant-drawer-mask ant-drawer-mask-motion-appear ant-drawer-mask-motion-appear-active ant-drawer-mask-motion"
class="ant-drawer-mask"
/>
<div
aria-hidden="true"
@ -2918,7 +2918,7 @@ exports[`renders ./components/drawer/demo/render-in-current.md extend context co
tabindex="0"
/>
<div
class="ant-drawer-content-wrapper ant-drawer-panel-motion-right-appear ant-drawer-panel-motion-right-appear-active ant-drawer-panel-motion-right"
class="ant-drawer-content-wrapper"
style="width: 378px;"
>
<div
@ -3083,7 +3083,7 @@ HTMLCollection [
tabindex="-1"
>
<div
class="ant-drawer-mask ant-drawer-mask-motion-appear ant-drawer-mask-motion-appear-active ant-drawer-mask-motion"
class="ant-drawer-mask"
/>
<div
aria-hidden="true"
@ -3092,7 +3092,7 @@ HTMLCollection [
tabindex="0"
/>
<div
class="ant-drawer-content-wrapper ant-drawer-panel-motion-right-appear ant-drawer-panel-motion-right-appear-active ant-drawer-panel-motion-right"
class="ant-drawer-content-wrapper"
style="width: 378px;"
>
<div
@ -3315,7 +3315,7 @@ HTMLCollection [
tabindex="-1"
>
<div
class="ant-drawer-mask ant-drawer-mask-motion-appear ant-drawer-mask-motion-appear-active ant-drawer-mask-motion"
class="ant-drawer-mask"
/>
<div
aria-hidden="true"
@ -3324,7 +3324,7 @@ HTMLCollection [
tabindex="0"
/>
<div
class="ant-drawer-content-wrapper ant-drawer-panel-motion-right-appear ant-drawer-panel-motion-right-appear-active ant-drawer-panel-motion-right"
class="ant-drawer-content-wrapper"
style="width: 640px;"
>
<div

View File

@ -9,6 +9,8 @@ jest.mock('rc-drawer', () => {
...props,
open: true,
getContainer: false,
maskMotion: null,
motion: null,
};
return <MockDrawer {...newProps} />;
};

View File

@ -141,6 +141,7 @@ function Drawer({
motionAppear: true,
motionEnter: true,
motionLeave: true,
motionDeadline: 500,
};
const panelMotion: RcDrawerProps['motion'] = motionPlacement => ({
@ -148,6 +149,7 @@ function Drawer({
motionAppear: true,
motionEnter: true,
motionLeave: true,
motionDeadline: 500,
});
// =========================== Render ===========================

View File

@ -1,106 +0,0 @@
import { mount } from 'enzyme';
import React from 'react';
import Dropdown from '..';
import mountTest from '../../../tests/shared/mountTest';
import rtlTest from '../../../tests/shared/rtlTest';
import Menu from '../../menu';
describe('DropdownButton', () => {
mountTest(Dropdown.Button);
rtlTest(Dropdown.Button);
it('pass appropriate props to Dropdown', () => {
const props = {
align: {
offset: [10, 20],
},
overlay: (
<Menu>
<Menu.Item key="1">foo</Menu.Item>
</Menu>
),
disabled: false,
trigger: ['hover'],
visible: true,
onVisibleChange: () => {},
};
const wrapper = mount(<Dropdown.Button {...props} />);
const dropdownProps = wrapper.find(Dropdown).props();
Object.keys(props).forEach(key => {
expect(dropdownProps[key]).toBe(props[key]);
});
});
it("don't pass visible to Dropdown if it's not exits", () => {
const menu = (
<Menu>
<Menu.Item key="1">foo</Menu.Item>
</Menu>
);
const wrapper = mount(<Dropdown.Button overlay={menu} />);
const dropdownProps = wrapper.find(Dropdown).props();
expect('visible' in dropdownProps).toBe(false);
});
it('should support href like Button', () => {
const menu = (
<Menu>
<Menu.Item key="1">foo</Menu.Item>
</Menu>
);
const wrapper = mount(<Dropdown.Button overlay={menu} href="https://ant.design" />);
expect(wrapper.render()).toMatchSnapshot();
});
it('have static property for type detecting', () => {
const menu = (
<Menu>
<Menu.Item key="1">foo</Menu.Item>
</Menu>
);
const wrapper = mount(<Dropdown.Button overlay={menu} />);
expect(wrapper.find(Dropdown.Button).type().__ANT_BUTTON).toBe(true);
});
it('should pass mouseEnterDelay and mouseLeaveDelay to Dropdown', () => {
const menu = (
<Menu>
<Menu.Item key="1">foo</Menu.Item>
</Menu>
);
const wrapper = mount(
<Dropdown.Button mouseEnterDelay={1} mouseLeaveDelay={2} overlay={menu} />,
);
expect(wrapper.find('Dropdown').props().mouseEnterDelay).toBe(1);
expect(wrapper.find('Dropdown').props().mouseLeaveDelay).toBe(2);
});
it('should support overlayClassName and overlayStyle', () => {
const menu = (
<Menu>
<Menu.Item key="1">foo</Menu.Item>
</Menu>
);
const wrapper = mount(
<Dropdown.Button
overlayClassName="className"
overlayStyle={{ color: 'red' }}
overlay={menu}
visible
/>,
);
expect(wrapper.find('.ant-dropdown').getDOMNode().className).toContain('className');
expect(wrapper.find('.ant-dropdown').getDOMNode().style.color).toContain('red');
});
it('should support loading', () => {
const wrapper = mount(<Dropdown.Button loading />);
expect(wrapper.find('.ant-dropdown-button .ant-btn-loading').getDOMNode().className).toContain(
'ant-btn',
);
});
});

View File

@ -0,0 +1,117 @@
import React from 'react';
import DropdownButton from '../dropdown-button';
import mountTest from '../../../tests/shared/mountTest';
import rtlTest from '../../../tests/shared/rtlTest';
import Menu from '../../menu';
import type { DropdownProps } from '../dropdown';
import { render } from '../../../tests/utils';
let dropdownProps: DropdownProps;
jest.mock('../dropdown', () => {
const ActualDropdown = jest.requireActual('../dropdown');
const ActualDropdownComponent = ActualDropdown.default;
const h: typeof React = jest.requireActual('react');
const mockedDropdown = (props: DropdownProps) => {
dropdownProps = props;
const { children, ...restProps } = props;
return h.createElement(ActualDropdownComponent, { ...restProps }, children);
};
mockedDropdown.defaultProps = ActualDropdownComponent.defaultProps;
mockedDropdown.Button = ActualDropdownComponent.Button;
return {
...ActualDropdown,
__esModule: true,
default: mockedDropdown,
};
});
describe('DropdownButton', () => {
mountTest(DropdownButton);
rtlTest(DropdownButton);
it('pass appropriate props to Dropdown', () => {
const props: DropdownProps = {
align: {
offset: [10, 20],
},
overlay: (
<Menu>
<Menu.Item key="1">foo</Menu.Item>
</Menu>
),
disabled: false,
trigger: ['hover'],
visible: true,
onVisibleChange: () => {},
};
render(<DropdownButton {...props} />);
Object.keys(props).forEach((key: keyof DropdownProps) => {
expect(dropdownProps[key]).toBe(props[key]);
});
});
it("don't pass visible to Dropdown if it's not exits", () => {
const menu = (
<Menu>
<Menu.Item key="1">foo</Menu.Item>
</Menu>
);
render(<DropdownButton overlay={menu} />);
expect('visible' in dropdownProps).toBe(false);
});
it('should support href like Button', () => {
const menu = (
<Menu>
<Menu.Item key="1">foo</Menu.Item>
</Menu>
);
const { asFragment } = render(<DropdownButton overlay={menu} href="https://ant.design" />);
expect(asFragment().firstChild).toMatchSnapshot();
});
it('have static property for type detecting', () => {
expect(DropdownButton.__ANT_BUTTON).toBe(true);
});
it('should pass mouseEnterDelay and mouseLeaveDelay to Dropdown', () => {
const menu = (
<Menu>
<Menu.Item key="1">foo</Menu.Item>
</Menu>
);
render(<DropdownButton mouseEnterDelay={1} mouseLeaveDelay={2} overlay={menu} />);
expect(dropdownProps.mouseEnterDelay).toBe(1);
expect(dropdownProps.mouseLeaveDelay).toBe(2);
});
it('should support overlayClassName and overlayStyle', () => {
const menu = (
<Menu>
<Menu.Item key="1">foo</Menu.Item>
</Menu>
);
const { container } = render(
<DropdownButton
overlayClassName="className"
overlayStyle={{ color: 'red' }}
overlay={menu}
visible
/>,
);
expect(container.querySelector('.ant-dropdown')?.classList).toContain('className');
expect((container.querySelector('.ant-dropdown') as HTMLElement).style.color).toContain('red');
});
it('should support loading', () => {
const { container } = render(<DropdownButton overlay={<div />} loading />);
expect(container.querySelector('.ant-dropdown-button .ant-btn-loading')?.classList).toContain(
'ant-btn',
);
});
});

View File

@ -1,44 +1,61 @@
import { mount } from 'enzyme';
import React from 'react';
import type { TriggerProps } from 'rc-trigger';
import Dropdown from '..';
import type { DropDownProps } from '..';
import mountTest from '../../../tests/shared/mountTest';
import rtlTest from '../../../tests/shared/rtlTest';
import { act, fireEvent, render, sleep } from '../../../tests/utils';
import Menu from '../../menu';
let triggerProps: TriggerProps;
jest.mock('rc-trigger', () => {
let Trigger = jest.requireActual('rc-trigger/lib/mock');
Trigger = Trigger.default || Trigger;
const h: typeof React = jest.requireActual('react');
return {
default: h.forwardRef<unknown, TriggerProps>((props, ref) => {
triggerProps = props;
return h.createElement(Trigger, { ref, ...props });
}),
__esModule: true,
};
});
describe('Dropdown', () => {
mountTest(() => (
<Dropdown menu={<Menu />}>
<Dropdown overlay={<Menu />}>
<span />
</Dropdown>
));
rtlTest(() => (
<Dropdown menu={<Menu />}>
<Dropdown overlay={<Menu />}>
<span />
</Dropdown>
));
it('overlay is function and has custom transitionName', () => {
const wrapper = mount(
const { asFragment } = render(
<Dropdown overlay={() => <div>menu</div>} transitionName="move-up" visible>
<button type="button">button</button>
</Dropdown>,
);
expect(wrapper.render()).toMatchSnapshot();
expect(Array.from(asFragment().childNodes)).toMatchSnapshot();
});
it('overlay is string', () => {
const wrapper = mount(
<Dropdown overlay="string" visible>
const { asFragment } = render(
<Dropdown overlay={'string' as any} visible>
<button type="button">button</button>
</Dropdown>,
);
expect(wrapper.render()).toMatchSnapshot();
expect(Array.from(asFragment().childNodes)).toMatchSnapshot();
});
it('support Menu expandIcon', async () => {
const props = {
const props: DropDownProps = {
overlay: (
<Menu expandIcon={<span id="customExpandIcon" />}>
<Menu.Item key="1">foo</Menu.Item>
@ -51,23 +68,23 @@ describe('Dropdown', () => {
getPopupContainer: node => node,
};
const wrapper = mount(
const { container } = render(
<Dropdown {...props}>
<button type="button">button</button>
</Dropdown>,
);
await sleep(500);
expect(wrapper.find(Dropdown).find('#customExpandIcon').length).toBe(1);
expect(container.querySelectorAll('#customExpandIcon').length).toBe(1);
});
it('should warn if use topCenter or bottomCenter', () => {
const error = jest.spyOn(console, 'error');
mount(
render(
<div>
<Dropdown overlay="123" placement="bottomCenter">
<Dropdown overlay={'123' as any} placement="bottomCenter">
<button type="button">bottomCenter</button>
</Dropdown>
<Dropdown overlay="123" placement="topCenter">
<Dropdown overlay={'123' as any} placement="topCenter">
<button type="button">topCenter</button>
</Dropdown>
</div>,
@ -82,13 +99,13 @@ describe('Dropdown', () => {
// zombieJ: when replaced with react test lib, it may be mock fully content
it('dropdown should support auto adjust placement', () => {
const wrapper = mount(
render(
<Dropdown overlay={<div>menu</div>} visible>
<button type="button">button</button>
</Dropdown>,
);
expect(wrapper.find('Trigger').prop('builtinPlacements')).toEqual(
expect(triggerProps.builtinPlacements).toEqual(
expect.objectContaining({
bottomLeft: expect.objectContaining({
overflow: {
@ -104,7 +121,7 @@ describe('Dropdown', () => {
jest.useFakeTimers();
const { container } = render(
<Dropdown
trigger="click"
trigger={['click']}
overlay={
<Menu
items={[
@ -127,13 +144,13 @@ describe('Dropdown', () => {
);
// Open
fireEvent.click(container.querySelector('a'));
fireEvent.click(container.querySelector('a')!);
act(() => {
jest.runAllTimers();
});
// Close
fireEvent.click(container.querySelector('.ant-dropdown-menu-item'));
fireEvent.click(container.querySelector('.ant-dropdown-menu-item')!);
// Force Motion move on
for (let i = 0; i < 10; i += 1) {
@ -143,7 +160,7 @@ describe('Dropdown', () => {
}
// Motion End
fireEvent.animationEnd(container.querySelector('.ant-slide-up-leave-active'));
fireEvent.animationEnd(container.querySelector('.ant-slide-up-leave-active')!);
expect(container.querySelector('.ant-dropdown-hidden')).toBeTruthy();

View File

@ -3,17 +3,17 @@
exports[`Grid renders wrapped Col correctly 1`] = `
<div
class="ant-row"
style="margin-left:-10px;margin-right:-10px"
style="margin-left: -10px; margin-right: -10px;"
>
<div>
<div
class="ant-col ant-col-12"
style="padding-left:10px;padding-right:10px"
style="padding-left: 10px; padding-right: 10px;"
/>
</div>
<div
class="ant-col ant-col-12"
style="padding-left:10px;padding-right:10px"
style="padding-left: 10px; padding-right: 10px;"
/>
</div>
`;
@ -45,6 +45,6 @@ exports[`Grid should render Row 1`] = `
exports[`Grid when typeof gutter is object array in large screen 1`] = `
<div
class="ant-row"
style="margin-left:-20px;margin-right:-20px;margin-top:-200px;margin-bottom:-200px"
style="margin: -200px -20px -200px -20px;"
/>
`;

View File

@ -1,7 +1,7 @@
import { mount } from 'enzyme';
import React, { memo, useContext, useRef, useState } from 'react';
import Row from '../row';
import RowContext from '../RowContext';
import { render, fireEvent } from '../../../tests/utils';
const CacheInner = memo(() => {
const countRef = useRef(0);
@ -33,16 +33,16 @@ const CacheOuter = () => {
};
it('Cached RowContext is working', () => {
const wrapper = mount(<CacheOuter />);
const childCount = wrapper.find('#child_count').text();
const { container } = render(<CacheOuter />);
const childCount = container.querySelector('#child_count')?.textContent;
wrapper.find('#parent_btn').at(0).simulate('click');
expect(wrapper.find('#parent_count').text()).toBe('2');
fireEvent.click(container.querySelector('#parent_btn')!);
expect(container.querySelector('#parent_count')?.textContent).toBe('2');
// child component won't rerender
expect(wrapper.find('#child_count').text()).toBe(childCount);
expect(container.querySelector('#child_count')?.textContent).toBe(childCount);
wrapper.find('#parent_btn').at(0).simulate('click');
expect(wrapper.find('#parent_count').text()).toBe('3');
fireEvent.click(container.querySelector('#parent_btn')!);
expect(container.querySelector('#parent_count')?.textContent).toBe('3');
// child component won't rerender
expect(wrapper.find('#child_count').text()).toBe(childCount);
expect(container.querySelector('#child_count')?.textContent).toBe(childCount);
});

View File

@ -1,4 +1,3 @@
import { mount } from 'enzyme';
import React from 'react';
import ReactDOMServer from 'react-dom/server';
import { Col, Row } from '..';
@ -22,19 +21,15 @@ describe('Grid.Gap', () => {
});
it('should use gap', () => {
const wrapper = mount(
const { container } = render(
<Row gutter={[16, 8]}>
<Col />
</Row>,
);
expect(wrapper.find('.ant-row').props().style).toEqual(
expect.objectContaining({
marginLeft: -8,
rowGap: 8,
marginRight: -8,
}),
);
expect((container.querySelector('.ant-row') as HTMLElement)!.style.marginLeft).toEqual('-8px');
expect((container.querySelector('.ant-row') as HTMLElement)!.style.marginRight).toEqual('-8px');
expect((container.querySelector('.ant-row') as HTMLElement)!.style.rowGap).toEqual('8px');
});
it('not break ssr', () => {

View File

@ -1,127 +0,0 @@
import { mount, render } from 'enzyme';
import React from 'react';
import { act } from 'react-dom/test-utils';
import { Col, Row } from '..';
import mountTest from '../../../tests/shared/mountTest';
import rtlTest from '../../../tests/shared/rtlTest';
import ResponsiveObserve from '../../_util/responsiveObserve';
import useBreakpoint from '../hooks/useBreakpoint';
describe('Grid', () => {
mountTest(Row);
mountTest(Col);
rtlTest(Row);
rtlTest(Col);
it('should render Col', () => {
const wrapper = render(<Col span={2} />);
expect(wrapper).toMatchSnapshot();
});
it('should render Row', () => {
const wrapper = render(<Row />);
expect(wrapper).toMatchSnapshot();
});
it('when typeof gutter is object', () => {
const wrapper = mount(<Row gutter={{ xs: 8, sm: 16, md: 24 }} />);
expect(wrapper.find('div').first().props().style).toEqual(
expect.objectContaining({
marginLeft: -4,
marginRight: -4,
}),
);
});
it('when typeof gutter is object array', () => {
const wrapper = mount(
<Row
gutter={[
{ xs: 8, sm: 16, md: 24, lg: 32, xl: 40 },
{ xs: 8, sm: 16, md: 24, lg: 32, xl: 40 },
]}
/>,
);
expect(wrapper.find('div').first().props().style).toEqual(
expect.objectContaining({
marginLeft: -4,
marginRight: -4,
}),
);
});
it('when typeof gutter is object array in large screen', () => {
const wrapper = render(
<Row
gutter={[
{ xs: 8, sm: 16, md: 24, lg: 32, xl: 40 },
{ xs: 8, sm: 16, md: 24, lg: 100, xl: 400 },
]}
/>,
);
expect(wrapper).toMatchSnapshot();
});
it('renders wrapped Col correctly', () => {
const MyCol = () => <Col span={12} />;
const wrapper = render(
<Row gutter={20}>
<div>
<Col span={12} />
</div>
<MyCol />
</Row>,
);
expect(wrapper).toMatchSnapshot();
});
it('ResponsiveObserve.unsubscribe should be called when unmounted', () => {
const Unmount = jest.spyOn(ResponsiveObserve, 'unsubscribe');
const wrapper = mount(<Row gutter={{ xs: 20 }} />);
act(() => {
wrapper.unmount();
});
expect(Unmount).toHaveBeenCalled();
});
it('should work correct when gutter is object', () => {
const wrapper = mount(<Row gutter={{ xs: 20 }} />);
expect(wrapper.find('div').prop('style')).toEqual({
marginLeft: -10,
marginRight: -10,
});
});
it('should work current when gutter is array', () => {
const wrapper = mount(<Row gutter={[16, 20]} />);
expect(wrapper.find('div').prop('style')).toEqual({
marginLeft: -8,
marginRight: -8,
marginTop: -10,
marginBottom: -10,
});
});
// By jsdom mock, actual jsdom not implemented matchMedia
// https://jestjs.io/docs/en/manual-mocks#mocking-methods-which-are-not-implemented-in-jsdom
it('should work with useBreakpoint', () => {
function Demo() {
const screens = useBreakpoint();
return JSON.stringify(screens);
}
const wrapper = mount(<Demo />);
expect(wrapper.text()).toEqual(
JSON.stringify({
xs: true,
sm: false,
md: false,
lg: false,
xl: false,
xxl: false,
}),
);
});
});

View File

@ -0,0 +1,146 @@
import React from 'react';
import { Col, Row } from '..';
import mountTest from '../../../tests/shared/mountTest';
import rtlTest from '../../../tests/shared/rtlTest';
import ResponsiveObserve from '../../_util/responsiveObserve';
import useBreakpoint from '../hooks/useBreakpoint';
import { render, act } from '../../../tests/utils';
describe('Grid', () => {
mountTest(Row);
mountTest(Col);
rtlTest(Row);
rtlTest(Col);
afterEach(() => {
ResponsiveObserve.unregister();
});
it('should render Col', () => {
const { asFragment } = render(<Col span={2} />);
expect(asFragment().firstChild).toMatchSnapshot();
});
it('should render Row', () => {
const { asFragment } = render(<Row />);
expect(asFragment().firstChild).toMatchSnapshot();
});
it('when typeof gutter is object', () => {
const { container } = render(<Row gutter={{ xs: 8, sm: 16, md: 24 }} />);
expect(container.querySelector('div')!.style.marginLeft).toEqual('-4px');
expect(container.querySelector('div')!.style.marginRight).toEqual('-4px');
});
it('when typeof gutter is object array', () => {
const { container } = render(
<Row
gutter={[
{ xs: 8, sm: 16, md: 24, lg: 32, xl: 40 },
{ xs: 8, sm: 16, md: 24, lg: 32, xl: 40 },
]}
/>,
);
expect(container.querySelector('div')!.style.marginLeft).toEqual('-4px');
expect(container.querySelector('div')!.style.marginRight).toEqual('-4px');
});
it('when typeof gutter is object array in large screen', () => {
jest.spyOn(window, 'matchMedia').mockImplementation(
query =>
({
addListener: (cb: (e: { matches: boolean }) => void) => {
cb({ matches: query === '(min-width: 1200px)' });
},
removeListener: jest.fn(),
matches: query === '(min-width: 1200px)',
} as any),
);
const { container, asFragment } = render(
<Row
gutter={[
{ xs: 8, sm: 16, md: 24, lg: 32, xl: 40 },
{ xs: 8, sm: 16, md: 24, lg: 100, xl: 400 },
]}
/>,
);
expect(asFragment().firstChild).toMatchSnapshot();
expect(container.querySelector('div')!.style.marginLeft).toEqual('-20px');
expect(container.querySelector('div')!.style.marginRight).toEqual('-20px');
expect(container.querySelector('div')!.style.marginTop).toEqual('-200px');
expect(container.querySelector('div')!.style.marginBottom).toEqual('-200px');
});
it('renders wrapped Col correctly', () => {
const MyCol = () => <Col span={12} />;
const { asFragment } = render(
<Row gutter={20}>
<div>
<Col span={12} />
</div>
<MyCol />
</Row>,
);
expect(asFragment().firstChild).toMatchSnapshot();
});
it('ResponsiveObserve.unsubscribe should be called when unmounted', () => {
const Unmount = jest.spyOn(ResponsiveObserve, 'unsubscribe');
const { unmount } = render(<Row gutter={{ xs: 20 }} />);
act(() => {
unmount();
});
expect(Unmount).toHaveBeenCalled();
});
it('should work correct when gutter is object', () => {
const { container } = render(<Row gutter={{ xs: 20 }} />);
expect(container.querySelector('div')!.style.marginLeft).toEqual('-10px');
expect(container.querySelector('div')!.style.marginRight).toEqual('-10px');
});
it('should work current when gutter is array', () => {
const { container } = render(<Row gutter={[16, 20]} />);
expect(container.querySelector('div')!.style.marginLeft).toEqual('-8px');
expect(container.querySelector('div')!.style.marginRight).toEqual('-8px');
expect(container.querySelector('div')!.style.marginTop).toEqual('-10px');
expect(container.querySelector('div')!.style.marginBottom).toEqual('-10px');
});
// By jsdom mock, actual jsdom not implemented matchMedia
// https://jestjs.io/docs/en/manual-mocks#mocking-methods-which-are-not-implemented-in-jsdom
it('should work with useBreakpoint', () => {
const matchMediaSpy = jest.spyOn(window, 'matchMedia');
matchMediaSpy.mockImplementation(
query =>
({
addListener: (cb: (e: { matches: boolean }) => void) => {
cb({ matches: query === '(max-width: 575px)' });
},
removeListener: jest.fn(),
matches: query === '(max-width: 575px)',
} as any),
);
let screensVar;
function Demo() {
const screens = useBreakpoint();
screensVar = screens;
return <div />;
}
render(<Demo />);
expect(screensVar).toEqual({
xs: true,
sm: false,
md: false,
lg: false,
xl: false,
xxl: false,
});
});
});

View File

@ -1,34 +0,0 @@
import { mount } from 'enzyme';
import React from 'react';
// eslint-disable-next-line no-unused-vars
import { Col, Row } from '..';
jest.mock('rc-util/lib/Dom/canUseDom', () => () => false);
describe('Grid.Server', () => {
it('use compatible gap logic', () => {
const wrapper = mount(
<Row gutter={[8, 16]}>
<Col />
</Row>,
);
expect(wrapper.find('.ant-row').props().style).toEqual(
expect.objectContaining({
marginLeft: -4,
marginRight: -4,
marginTop: -8,
marginBottom: -8,
}),
);
expect(wrapper.find('.ant-col').props().style).toEqual(
expect.objectContaining({
paddingLeft: 4,
paddingRight: 4,
paddingTop: 8,
paddingBottom: 8,
}),
);
});
});

View File

@ -0,0 +1,30 @@
import React from 'react';
// eslint-disable-next-line no-unused-vars
import { Col, Row } from '..';
import { render } from '../../../tests/utils';
jest.mock('rc-util/lib/Dom/canUseDom', () => () => false);
describe('Grid.Server', () => {
it('use compatible gap logic', () => {
const { container } = render(
<Row gutter={[8, 16]}>
<Col />
</Row>,
);
expect((container.querySelector('.ant-row') as HTMLElement)!.style.marginLeft).toEqual('-4px');
expect((container.querySelector('.ant-row') as HTMLElement)!.style.marginRight).toEqual('-4px');
expect((container.querySelector('.ant-row') as HTMLElement)!.style.marginTop).toEqual('-8px');
expect((container.querySelector('.ant-row') as HTMLElement)!.style.marginBottom).toEqual(
'-8px',
);
expect((container.querySelector('.ant-col') as HTMLElement)!.style.paddingLeft).toEqual('4px');
expect((container.querySelector('.ant-col') as HTMLElement)!.style.paddingRight).toEqual('4px');
expect((container.querySelector('.ant-col') as HTMLElement)!.style.paddingTop).toEqual('8px');
expect((container.querySelector('.ant-col') as HTMLElement)!.style.paddingBottom).toEqual(
'8px',
);
});
});

View File

@ -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] }}
/>
</div>
<span>Vertical Gutter (px): </span>
@ -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] }}
/>
</div>
<span>Column Count:</span>
@ -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] }}
/>
</div>
<Row gutter={[gutters[gutterKey], vgutters[vgutterKey]]}>

View File

@ -1,7 +1,7 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Menu Menu.Item with icon children auto wrap span 1`] = `
Array [
<DocumentFragment>
<ul
class="ant-menu ant-menu-root ant-menu-vertical"
data-menu-list="true"
@ -154,16 +154,16 @@ Array [
/>
</div>
</li>
</ul>,
</ul>
<div
aria-hidden="true"
style="display: none;"
/>,
]
/>
</DocumentFragment>
`;
exports[`Menu all types must be available in the "items" syntax 1`] = `
Array [
<DocumentFragment>
<ul
class="ant-menu ant-menu-root ant-menu-inline"
data-menu-list="true"
@ -315,12 +315,12 @@ Array [
</li>
</ul>
</li>
</ul>,
</ul>
<div
aria-hidden="true"
style="display: none;"
/>,
]
/>
</DocumentFragment>
`;
exports[`Menu rtl render component should be rendered correctly in RTL direction 1`] = `
@ -381,7 +381,7 @@ Array [
`;
exports[`Menu should controlled collapse work 1`] = `
Array [
<DocumentFragment>
<ul
class="ant-menu ant-menu-root ant-menu-inline"
data-menu-list="true"
@ -420,16 +420,16 @@ Array [
Option 1
</span>
</li>
</ul>,
</ul>
<div
aria-hidden="true"
style="display: none;"
/>,
]
/>
</DocumentFragment>
`;
exports[`Menu should controlled collapse work 2`] = `
Array [
<DocumentFragment>
<ul
class="ant-menu ant-menu-root ant-menu-vertical ant-menu-inline-collapsed"
data-menu-list="true"
@ -468,10 +468,10 @@ Array [
Option 1
</span>
</li>
</ul>,
</ul>
<div
aria-hidden="true"
style="display: none;"
/>,
]
/>
</DocumentFragment>
`;

View File

@ -5,14 +5,12 @@ import {
PieChartOutlined,
UserOutlined,
} from '@ant-design/icons';
import { mount } from 'enzyme';
import React, { useState } from 'react';
import Menu from '..';
import mountTest from '../../../tests/shared/mountTest';
import rtlTest from '../../../tests/shared/rtlTest';
import { fireEvent, render, act } from '../../../tests/utils';
import Layout from '../../layout';
import Tooltip from '../../tooltip';
import initCollapseMotion from '../../_util/motion';
import { noop } from '../../_util/warning';
@ -137,7 +135,7 @@ describe('Menu', () => {
});
it('If has select nested submenu item ,the menu items on the grandfather level should be highlight', () => {
const wrapper = mount(
const { container } = render(
<Menu defaultSelectedKeys={['1-3-2']} mode="vertical">
<SubMenu key="1" title="submenu1">
<Menu.Item key="1-1">Option 1</Menu.Item>
@ -150,11 +148,11 @@ describe('Menu', () => {
<Menu.Item key="2">menu2</Menu.Item>
</Menu>,
);
expect(wrapper.find('li.ant-menu-submenu-selected').length).toBe(1);
expect(container.querySelectorAll('li.ant-menu-submenu-selected').length).toBe(1);
});
it('forceSubMenuRender', () => {
const wrapper = mount(
const { container, rerender } = render(
<Menu mode="horizontal">
<SubMenu key="1" title="submenu1">
<Menu.Item key="1-1">
@ -164,14 +162,22 @@ describe('Menu', () => {
</Menu>,
);
expect(wrapper.find('.bamboo').hostNodes()).toHaveLength(0);
expect(container.querySelector('.bamboo')).toBeFalsy();
wrapper.setProps({ forceSubMenuRender: true });
expect(wrapper.find('.bamboo').hostNodes()).toHaveLength(1);
rerender(
<Menu mode="horizontal" forceSubMenuRender>
<SubMenu key="1" title="submenu1">
<Menu.Item key="1-1">
<span className="bamboo" />
</Menu.Item>
</SubMenu>
</Menu>,
);
expect(container.querySelector('.bamboo')).toBeTruthy();
});
it('should accept defaultOpenKeys in mode horizontal', () => {
const wrapper = mount(
const { container } = render(
<Menu defaultOpenKeys={['1']} mode="horizontal">
<SubMenu key="1" title="submenu1">
<Menu.Item key="submenu1">Option 1</Menu.Item>
@ -180,11 +186,15 @@ describe('Menu', () => {
<Menu.Item key="2">menu2</Menu.Item>
</Menu>,
);
expect(wrapper.exists('.ant-menu-sub')).toBeFalsy();
expect(
container.querySelector('.ant-menu-submenu-open').querySelector('.ant-menu-submenu-title')
.textContent,
).toEqual('submenu1');
});
it('should accept defaultOpenKeys in mode inline', () => {
const wrapper = mount(
const { container } = render(
<Menu defaultOpenKeys={['1']} mode="inline">
<SubMenu key="1" title="submenu1">
<Menu.Item key="submenu1">Option 1</Menu.Item>
@ -193,11 +203,15 @@ describe('Menu', () => {
<Menu.Item key="2">menu2</Menu.Item>
</Menu>,
);
expect(wrapper.find('.ant-menu-sub').at(0).hasClass('ant-menu-hidden')).not.toBe(true);
expect(
container.querySelector('.ant-menu-submenu-open').querySelector('.ant-menu-submenu-title')
.textContent,
).toEqual('submenu1');
});
it('should accept defaultOpenKeys in mode vertical', () => {
const wrapper = mount(
const { container } = render(
<Menu defaultOpenKeys={['1']} mode="vertical">
<SubMenu key="1" title="submenu1">
<Menu.Item key="submenu1">Option 1</Menu.Item>
@ -206,11 +220,11 @@ describe('Menu', () => {
<Menu.Item key="2">menu2</Menu.Item>
</Menu>,
);
expect(wrapper.find('PopupTrigger').first().prop('visible')).toBeTruthy();
expect(container.querySelector('.ant-menu-sub')).toBeFalsy();
});
it('should accept openKeys in mode horizontal', () => {
const wrapper = mount(
const { container } = render(
<Menu openKeys={['1']} mode="horizontal">
<SubMenu key="1" title="submenu1">
<Menu.Item key="submenu1">Option 1</Menu.Item>
@ -219,11 +233,14 @@ describe('Menu', () => {
<Menu.Item key="2">menu2</Menu.Item>
</Menu>,
);
expect(wrapper.find('PopupTrigger').first().prop('visible')).toBeTruthy();
triggerAllTimer();
expect(container.querySelector('div.ant-menu-submenu-popup')).not.toHaveClass(
'ant-menu-submenu-hidden',
);
});
it('should accept openKeys in mode inline', () => {
const wrapper = mount(
const { container } = render(
<Menu openKeys={['1']} mode="inline">
<SubMenu key="1" title="submenu1">
<Menu.Item key="submenu1">Option 1</Menu.Item>
@ -232,11 +249,11 @@ describe('Menu', () => {
<Menu.Item key="2">menu2</Menu.Item>
</Menu>,
);
expect(wrapper.find('InlineSubMenuList').first().prop('open')).toBeTruthy();
expect(container.querySelector('ul.ant-menu-sub')).not.toHaveClass('ant-menu-hidden');
});
it('should accept openKeys in mode vertical', () => {
const wrapper = mount(
const { container } = render(
<Menu openKeys={['1']} mode="vertical">
<SubMenu key="1" title="submenu1">
<Menu.Item key="submenu1">Option 1</Menu.Item>
@ -245,7 +262,10 @@ describe('Menu', () => {
<Menu.Item key="2">menu2</Menu.Item>
</Menu>,
);
expect(wrapper.find('PopupTrigger').first().prop('visible')).toBeTruthy();
triggerAllTimer();
expect(container.querySelector('div.ant-menu-submenu-popup')).not.toHaveClass(
'ant-menu-submenu-hidden',
);
});
it('test submenu in mode horizontal', async () => {
@ -359,8 +379,8 @@ describe('Menu', () => {
});
it('should always follow openKeys when inlineCollapsed is switched', () => {
const wrapper = mount(
<Menu defaultOpenKeys={['1']} mode="inline">
const Demo = props => (
<Menu defaultOpenKeys={['1']} mode="inline" {...props}>
<Menu.Item key="menu1" icon={<InboxOutlined />}>
Option
</Menu.Item>
@ -368,30 +388,34 @@ describe('Menu', () => {
<Menu.Item key="submenu1">Option</Menu.Item>
<Menu.Item key="submenu2">Option</Menu.Item>
</SubMenu>
</Menu>,
</Menu>
);
const { container, rerender } = render(<Demo />);
expect(wrapper.find('InlineSubMenuList').prop('open')).toBeTruthy();
expect(container.querySelector('li.ant-menu-submenu-inline')).toHaveClass(
'ant-menu-submenu-open',
);
// inlineCollapsed
wrapper.setProps({ inlineCollapsed: true });
rerender(<Demo inlineCollapsed />);
act(() => {
jest.runAllTimers();
});
wrapper.update();
expect(wrapper.find('ul.ant-menu-root').hasClass('ant-menu-vertical')).toBeTruthy();
expect(wrapper.find('PopupTrigger').prop('visible')).toBeFalsy();
expect(container.querySelector('ul.ant-menu-root')).toHaveClass('ant-menu-vertical');
expect(container.querySelector('.ant-menu-submenu-popup')).toBeFalsy();
// !inlineCollapsed
wrapper.setProps({ inlineCollapsed: false });
rerender(<Demo inlineCollapsed={false} />);
act(() => {
jest.runAllTimers();
});
wrapper.update();
expect(wrapper.find('ul.ant-menu-sub').last().hasClass('ant-menu-inline')).toBeTruthy();
expect(wrapper.find('InlineSubMenuList').prop('open')).toBeTruthy();
expect(container.querySelector('ul.ant-menu-sub')).toHaveClass('ant-menu-inline');
expect(container.querySelector('li.ant-menu-submenu-inline')).toHaveClass(
'ant-menu-submenu-open',
);
});
it('inlineCollapsed should works well when specify a not existed default openKeys', () => {
@ -431,7 +455,7 @@ describe('Menu', () => {
});
it('inlineCollapsed Menu.Item Tooltip can be removed', () => {
const wrapper = mount(
const { container } = render(
<Menu
defaultOpenKeys={['not-existed']}
mode="inline"
@ -456,12 +480,19 @@ describe('Menu', () => {
</Menu.Item>
</Menu>,
);
expect(wrapper.find(Menu.Item).at(0).find(Tooltip).props().title).toBe('item');
expect(wrapper.find(Menu.Item).at(1).find(Tooltip).props().title).toBe('title');
expect(wrapper.find(Menu.Item).at(2).find(Tooltip).props().title).toBe('item');
expect(wrapper.find(Menu.Item).at(3).find(Tooltip).props().title).toBe(null);
expect(wrapper.find(Menu.Item).at(4).find(Tooltip).props().title).toBe('');
expect(wrapper.find(Menu.Item).at(4).find(Tooltip).props().title).toBe('');
fireEvent.mouseEnter(container.querySelectorAll('li.ant-menu-item')[0]);
fireEvent.mouseEnter(container.querySelectorAll('li.ant-menu-item')[1]);
fireEvent.mouseEnter(container.querySelectorAll('li.ant-menu-item')[2]);
fireEvent.mouseEnter(container.querySelectorAll('li.ant-menu-item')[3]);
fireEvent.mouseEnter(container.querySelectorAll('li.ant-menu-item')[4]);
fireEvent.mouseEnter(container.querySelectorAll('li.ant-menu-item')[5]);
triggerAllTimer();
// when title is null or '' and false, tooltip will not render.
expect(container.querySelectorAll('.ant-tooltip-inner').length).toBe(3);
expect(container.querySelectorAll('.ant-tooltip-inner')[0].textContent).toBe('item');
expect(container.querySelectorAll('.ant-tooltip-inner')[1].textContent).toBe('title');
expect(container.querySelectorAll('.ant-tooltip-inner')[2].textContent).toBe('item');
});
describe('open submenu when click submenu title', () => {
@ -612,7 +643,7 @@ describe('Menu', () => {
});
it('inline title', () => {
const wrapper = mount(
const { container } = render(
<Menu mode="inline" inlineCollapsed>
<Menu.Item key="1" title="bamboo lucky" icon={<PieChartOutlined />}>
Option 1
@ -624,13 +655,10 @@ describe('Menu', () => {
</Menu.Item>
</Menu>,
);
wrapper.find('.ant-menu-item').hostNodes().simulate('mouseenter');
fireEvent.mouseEnter(container.querySelector('.ant-menu-item'));
triggerAllTimer();
wrapper.update();
const text = wrapper.find('.ant-tooltip-inner').text();
expect(text).toBe('bamboo lucky');
expect(container.querySelector('.ant-tooltip-inner').textContent).toBe('bamboo lucky');
});
it('render correctly when using with Layout.Sider', () => {
@ -659,34 +687,34 @@ describe('Menu', () => {
);
}
}
const wrapper = mount(<Demo />);
expect(wrapper.find(Menu).at(0).getDOMNode().classList.contains('ant-menu-inline')).toBe(true);
wrapper.find('.ant-menu-submenu-title').simulate('click');
wrapper.find('.ant-layout-sider-trigger').simulate('click');
const { container } = render(<Demo />);
expect(container.querySelector('ul.ant-menu-root')).toHaveClass('ant-menu-inline');
fireEvent.click(container.querySelector('.ant-menu-submenu-title'));
fireEvent.click(container.querySelector('.ant-layout-sider-trigger'));
triggerAllTimer();
wrapper.update();
expect(wrapper.find(Menu).getDOMNode().classList.contains('ant-menu-inline-collapsed')).toBe(
true,
);
wrapper.find(Menu).simulate('mouseenter');
expect(wrapper.find(Menu).getDOMNode().classList.contains('ant-menu-inline')).toBe(false);
expect(wrapper.find(Menu).getDOMNode().classList.contains('ant-menu-vertical')).toBe(true);
expect(container.querySelector('ul.ant-menu-root')).toHaveClass('ant-menu-inline-collapsed');
fireEvent.mouseEnter(container.querySelector('ul.ant-menu-root'));
expect(container.querySelector('ul.ant-menu-root')).not.toHaveClass('ant-menu-inline');
expect(container.querySelector('ul.ant-menu-root')).toHaveClass('ant-menu-vertical');
});
it('onMouseEnter should work', () => {
const onMouseEnter = jest.fn();
const wrapper = mount(
const { container } = render(
<Menu onMouseEnter={onMouseEnter} defaultSelectedKeys={['test1']}>
<Menu.Item key="test1">Navigation One</Menu.Item>
<Menu.Item key="test2">Navigation Two</Menu.Item>
</Menu>,
);
wrapper.find('ul.ant-menu-root').simulate('mouseenter');
fireEvent.mouseEnter(container.querySelector('ul.ant-menu-root'));
expect(onMouseEnter).toHaveBeenCalled();
});
it('MenuItem should not render Tooltip when inlineCollapsed is false', () => {
const wrapper = mount(
const { container } = render(
<Menu defaultSelectedKeys={['mail']} defaultOpenKeys={['mail']} mode="horizontal">
<Menu.Item key="mail" icon={<MailOutlined />}>
Navigation One
@ -703,29 +731,27 @@ describe('Menu', () => {
{ attachTo: div },
);
wrapper.find('li.ant-menu-item').first().simulate('mouseenter');
fireEvent.mouseEnter(container.querySelector('li.ant-menu-item'));
act(() => {
jest.runAllTimers();
});
wrapper.update();
expect(wrapper.find('.ant-tooltip-inner').length).toBe(0);
expect(container.querySelectorAll('.ant-tooltip-inner').length).toBe(0);
});
it('MenuItem should render icon and icon should be the first child when icon exists', () => {
const wrapper = mount(
const { container } = render(
<Menu>
<Menu.Item key="mail" icon={<MailOutlined />}>
Navigation One
</Menu.Item>
</Menu>,
);
expect(wrapper.find('.ant-menu-item .anticon').hasClass('anticon-mail')).toBe(true);
expect(container.querySelector('.ant-menu-item .anticon')).toHaveClass('anticon-mail');
});
it('should controlled collapse work', () => {
const wrapper = mount(
const { asFragment, rerender } = render(
<Menu mode="inline" inlineCollapsed={false}>
<Menu.Item key="1" icon={<PieChartOutlined />}>
Option 1
@ -733,30 +759,34 @@ describe('Menu', () => {
</Menu>,
);
expect(wrapper.render()).toMatchSnapshot();
expect(asFragment()).toMatchSnapshot();
wrapper.setProps({ inlineCollapsed: true });
rerender(
<Menu mode="inline" inlineCollapsed>
<Menu.Item key="1" icon={<PieChartOutlined />}>
Option 1
</Menu.Item>
</Menu>,
);
expect(wrapper.render()).toMatchSnapshot();
expect(asFragment()).toMatchSnapshot();
});
it('not title if not collapsed', () => {
jest.useFakeTimers();
const wrapper = mount(
const { container } = render(
<Menu mode="inline" inlineCollapsed={false}>
<Menu.Item key="1" icon={<PieChartOutlined />}>
Option 1
</Menu.Item>
</Menu>,
);
wrapper.find('.ant-menu-item').hostNodes().simulate('mouseenter');
fireEvent.mouseEnter(container.querySelector('.ant-menu-item'));
act(() => {
jest.runAllTimers();
});
wrapper.update();
expect(wrapper.find('.ant-tooltip-inner').length).toBeFalsy();
expect(container.querySelectorAll('.ant-tooltip-inner').length).toBeFalsy();
jest.useRealTimers();
});
@ -799,45 +829,42 @@ describe('Menu', () => {
// https://github.com/ant-design/ant-design/issues/8587
it('should keep selectedKeys in state when collapsed to 0px', () => {
jest.useFakeTimers();
const wrapper = mount(
const Demo = props => (
<Menu
mode="inline"
inlineCollapsed={false}
defaultSelectedKeys={['1']}
collapsedWidth={0}
openKeys={['3']}
{...props}
>
<Menu.Item key="1">Option 1</Menu.Item>
<Menu.Item key="2">Option 2</Menu.Item>
<Menu.SubMenu key="3" title="Option 3">
<Menu.Item key="4">Option 4</Menu.Item>
</Menu.SubMenu>
</Menu>,
</Menu>
);
expect(wrapper.find('li.ant-menu-item-selected').getDOMNode().textContent).toBe('Option 1');
wrapper.find('li.ant-menu-item').at(1).simulate('click');
expect(wrapper.find('li.ant-menu-item-selected').getDOMNode().textContent).toBe('Option 2');
wrapper.setProps({ inlineCollapsed: true });
const { container, rerender } = render(<Demo />);
expect(container.querySelector('li.ant-menu-item-selected').textContent).toBe('Option 1');
fireEvent.click(container.querySelectorAll('li.ant-menu-item')[1]);
expect(container.querySelector('li.ant-menu-item-selected').textContent).toBe('Option 2');
rerender(<Demo inlineCollapsed />);
act(() => {
jest.runAllTimers();
wrapper.update();
});
expect(container.querySelector('li.ant-menu-item-selected').textContent).toBe('O');
expect(
wrapper
.find('PopupTrigger')
.map(node => node.prop('popupVisible'))
.findIndex(node => !!node),
).toBe(-1);
rerender(<Demo inlineCollapsed={false} />);
wrapper.setProps({ inlineCollapsed: false });
expect(wrapper.find('li.ant-menu-item-selected').getDOMNode().textContent).toBe('Option 2');
expect(container.querySelector('li.ant-menu-item-selected').textContent).toBe('Option 2');
jest.useRealTimers();
});
it('Menu.Item with icon children auto wrap span', () => {
const wrapper = mount(
const { asFragment } = render(
<Menu>
<Menu.Item key="1" icon={<MailOutlined />}>
Navigation One
@ -849,7 +876,7 @@ describe('Menu', () => {
<Menu.SubMenu key="4" icon={<MailOutlined />} title={<span>Navigation One</span>} />
</Menu>,
);
expect(wrapper.render()).toMatchSnapshot();
expect(asFragment()).toMatchSnapshot();
});
// https://github.com/ant-design/ant-design/issues/23755
@ -876,25 +903,29 @@ describe('Menu', () => {
</>
);
}
const wrapper = mount(<App />);
wrapper.find('button').simulate('click');
const { container } = render(<App />);
fireEvent.click(container.querySelector('button'));
expect(onOpenChange).toHaveBeenCalledWith([]);
});
it('Use first char as Icon when collapsed', () => {
const wrapper = mount(
const { container } = render(
<Menu mode="inline" inlineCollapsed>
<Menu.SubMenu title="Light" />
<Menu.Item>Bamboo</Menu.Item>
</Menu>,
);
expect(wrapper.find('.ant-menu-inline-collapsed-noicon').first().text()).toEqual('L');
expect(wrapper.find('.ant-menu-inline-collapsed-noicon').last().text()).toEqual('B');
expect(container.querySelectorAll('.ant-menu-inline-collapsed-noicon')[0].textContent).toEqual(
'L',
);
expect(container.querySelectorAll('.ant-menu-inline-collapsed-noicon')[1].textContent).toEqual(
'B',
);
});
it('divider should show', () => {
const wrapper = mount(
const { container } = render(
<Menu mode="vertical">
<SubMenu key="sub1" title="Navigation One">
<Menu.Item key="1">Option 1</Menu.Item>
@ -910,8 +941,8 @@ describe('Menu', () => {
</Menu>,
);
expect(wrapper.find('li.ant-menu-item-divider').length).toBe(2);
expect(wrapper.find('li.ant-menu-item-divider-dashed').length).toBe(1);
expect(container.querySelectorAll('li.ant-menu-item-divider').length).toBe(2);
expect(container.querySelectorAll('li.ant-menu-item-divider-dashed').length).toBe(1);
});
it('should support ref', async () => {
@ -927,7 +958,7 @@ describe('Menu', () => {
});
it('expandIcon', () => {
const wrapper = mount(
const { container } = render(
<Menu defaultOpenKeys={['1']} mode="inline" expandIcon={() => <span className="bamboo" />}>
<SubMenu key="1" title="submenu1">
<Menu.Item key="submenu1">Option 1</Menu.Item>
@ -935,11 +966,11 @@ describe('Menu', () => {
</Menu>,
);
expect(wrapper.exists('.bamboo')).toBeTruthy();
expect(container.querySelector('.bamboo')).toBeTruthy();
});
it('all types must be available in the "items" syntax', () => {
const wrapper = mount(
const { asFragment } = render(
<Menu
mode="inline"
defaultOpenKeys={['submenu', 'group-submenu']}
@ -977,12 +1008,12 @@ describe('Menu', () => {
/>,
);
expect(wrapper.render()).toMatchSnapshot();
expect(asFragment()).toMatchSnapshot();
});
it('should not warning deprecated message when items={undefined}', () => {
const errorSpy = jest.spyOn(console, 'error').mockImplementation(() => undefined);
mount(<Menu items={undefined} />);
render(<Menu items={undefined} />);
expect(errorSpy).not.toHaveBeenCalledWith(
expect.stringContaining('`children` will be removed in next major version'),
);

View File

@ -80,56 +80,6 @@ exports[`Slider should render in RTL direction 1`] = `
</div>
`;
exports[`Slider should show correct placement tooltip when set tooltipPlacement 1`] = `
<div
class="ant-tooltip ant-slider-tooltip ant-zoom-down-appear ant-zoom-down-appear-prepare ant-zoom-down"
style="opacity: 0;"
>
<div
class="ant-tooltip-content"
>
<div
class="ant-tooltip-arrow"
>
<span
class="ant-tooltip-arrow-content"
/>
</div>
<div
class="ant-tooltip-inner"
role="tooltip"
>
30
</div>
</div>
</div>
`;
exports[`Slider should show correct placement tooltip when set tooltipPlacement 2`] = `
<div
class="ant-tooltip ant-slider-tooltip ant-zoom-down-leave ant-zoom-down-leave-start ant-zoom-down"
style="pointer-events: none;"
>
<div
class="ant-tooltip-content"
>
<div
class="ant-tooltip-arrow"
>
<span
class="ant-tooltip-arrow-content"
/>
</div>
<div
class="ant-tooltip-inner"
role="tooltip"
>
30
</div>
</div>
</div>
`;
exports[`Slider should show tooltip when hovering slider handler 1`] = `
<div
class="ant-tooltip ant-slider-tooltip ant-zoom-down-appear ant-zoom-down-appear-prepare ant-zoom-down"

View File

@ -1,17 +1,42 @@
import React from 'react';
import Slider from '..';
import type { SliderSingleProps } from '..';
import focusTest from '../../../tests/shared/focusTest';
import mountTest from '../../../tests/shared/mountTest';
import rtlTest from '../../../tests/shared/rtlTest';
import { sleep, render, fireEvent } from '../../../tests/utils';
import { render, fireEvent, act } from '../../../tests/utils';
import ConfigProvider from '../../config-provider';
import SliderTooltip from '../SliderTooltip';
import type { TooltipProps } from '../../tooltip';
function tooltipProps(): TooltipProps {
return (global as any).tooltipProps;
}
jest.mock('../../tooltip', () => {
const ReactReal = jest.requireActual('react');
const Tooltip = jest.requireActual('../../tooltip');
const TooltipComponent = Tooltip.default;
return ReactReal.forwardRef((props: TooltipProps, ref: any) => {
(global as any).tooltipProps = props;
return <TooltipComponent {...props} ref={ref} />;
});
});
describe('Slider', () => {
mountTest(Slider);
rtlTest(Slider);
focusTest(Slider, { testLib: true });
beforeEach(() => {
jest.useFakeTimers();
});
afterEach(() => {
jest.clearAllTimers();
jest.useRealTimers();
});
it('should show tooltip when hovering slider handler', () => {
const { container } = render(<Slider defaultValue={30} />);
@ -23,34 +48,58 @@ describe('Slider', () => {
expect(document.querySelector('.ant-tooltip')).toMatchSnapshot();
});
it('should show correct placement tooltip when set tooltipPlacement', () => {
const { container } = render(<Slider vertical defaultValue={30} tooltipPlacement="left" />);
describe('should show correct placement tooltip when set tooltipPlacement', () => {
function test(name: string, props: Partial<SliderSingleProps>) {
it(name, () => {
const { container } = render(<Slider vertical defaultValue={30} {...props} />);
fireEvent.mouseEnter(container.querySelector('.ant-slider-handle')!);
expect(document.querySelector('.ant-tooltip')).toMatchSnapshot();
fireEvent.mouseEnter(container.querySelector('.ant-slider-handle')!);
expect(tooltipProps().placement).toEqual('left');
});
}
fireEvent.mouseLeave(container.querySelector('.ant-slider-handle')!);
expect(document.querySelector('.ant-tooltip')).toMatchSnapshot();
test('new', { tooltip: { placement: 'left' } });
test('legacy', { tooltipPlacement: 'left' });
});
it('when tooltipVisible is true, tooltip should show always, or should never show', () => {
const { container: container1 } = render(<Slider defaultValue={30} tooltipVisible />);
expect(
container1.querySelector('.ant-tooltip-content')!.className.includes('ant-tooltip-hidden'),
).toBeFalsy();
describe('when tooltip.open is true, tooltip should show always, or should never show', () => {
function test(
name: string,
showProps: Partial<SliderSingleProps>,
hideProps: Partial<SliderSingleProps>,
) {
it(name, () => {
const { container, rerender } = render(<Slider defaultValue={30} {...showProps} />);
expect(
container.querySelector('.ant-tooltip-content')!.className.includes('ant-tooltip-hidden'),
).toBeFalsy();
fireEvent.mouseEnter(container1.querySelector('.ant-slider-handle')!);
expect(
container1.querySelector('.ant-tooltip-content')!.className.includes('ant-tooltip-hidden'),
).toBeFalsy();
fireEvent.mouseEnter(container.querySelector('.ant-slider-handle')!);
expect(
container.querySelector('.ant-tooltip-content')!.className.includes('ant-tooltip-hidden'),
).toBeFalsy();
fireEvent.click(container1.querySelector('.ant-slider-handle')!);
expect(
container1.querySelector('.ant-tooltip-content')!.className.includes('ant-tooltip-hidden'),
).toBeFalsy();
fireEvent.click(container.querySelector('.ant-slider-handle')!);
expect(
container.querySelector('.ant-tooltip-content')!.className.includes('ant-tooltip-hidden'),
).toBeFalsy();
const { container: container2 } = render(<Slider defaultValue={30} tooltipVisible={false} />);
expect(container2.querySelector('.ant-tooltip-content')!).toBeNull();
// Force hide
rerender(<Slider defaultValue={30} {...hideProps} />);
act(() => {
jest.runAllTimers();
});
if (container.querySelector('.ant-zoom-down-leave-active')) {
fireEvent.animationEnd(container.querySelector('.ant-zoom-down-leave-active')!);
}
expect(container.querySelector('.ant-tooltip-hidden')!).toBeTruthy();
});
}
test('new', { tooltip: { open: true } }, { tooltip: { open: false } });
test('legacy', { tooltipVisible: true }, { tooltipVisible: false });
});
it('when step is null, thumb can only be slided to the specific mark', () => {
@ -62,7 +111,12 @@ describe('Slider', () => {
};
const { container } = render(
<Slider marks={marks} defaultValue={intentionallyWrongValue} step={null} tooltipVisible />,
<Slider
marks={marks}
defaultValue={intentionallyWrongValue}
step={null}
tooltip={{ open: true }}
/>,
);
expect(container.querySelector('.ant-slider-handle')!.getAttribute('aria-valuenow')).toBe('48');
});
@ -75,7 +129,7 @@ describe('Slider', () => {
};
const { container } = render(
<Slider marks={marks} defaultValue={49} step={1} tooltipVisible />,
<Slider marks={marks} defaultValue={49} step={1} tooltip={{ open: true }} />,
);
expect(container.querySelector('.ant-slider-handle')!.getAttribute('aria-valuenow')).toBe('49');
});
@ -88,7 +142,7 @@ describe('Slider', () => {
};
const { container } = render(
<Slider marks={marks} defaultValue={49} step={undefined} tooltipVisible />,
<Slider marks={marks} defaultValue={49} step={undefined} tooltip={{ open: true }} />,
);
expect(container.querySelector('.ant-slider-handle')!.getAttribute('aria-valuenow')).toBe('49');
});
@ -96,7 +150,7 @@ describe('Slider', () => {
it('should render in RTL direction', () => {
const { container } = render(
<ConfigProvider direction="rtl">
<Slider defaultValue={30} tooltipVisible />
<Slider defaultValue={30} tooltip={{ open: true }} />
</ConfigProvider>,
);
expect(container).toMatchSnapshot();
@ -114,18 +168,46 @@ describe('Slider', () => {
/>,
);
ref.forcePopupAlign = jest.fn();
await sleep(20);
act(() => {
jest.runAllTimers();
});
expect(ref.forcePopupAlign).toHaveBeenCalled();
});
it('tipFormatter should not crash with undefined value', () => {
[undefined, null].forEach(value => {
render(<Slider value={value as any} tooltipVisible />);
render(<Slider value={value as any} tooltip={{ open: true }} />);
});
});
it('step should not crash with undefined value', () => {
[undefined, null].forEach(value => {
render(<Slider step={value} tooltipVisible />);
render(<Slider step={value} tooltip={{ open: true }} />);
});
});
it('deprecated warning', () => {
const errSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
const { rerender } = render(<Slider tooltipPrefixCls="xxx" />);
expect(errSpy).toHaveBeenCalledWith(
'Warning: [antd: Slider] `tooltipPrefixCls` is deprecated which will be removed in next major version, please use `tooltip.prefixCls` instead.',
);
rerender(<Slider getTooltipPopupContainer={() => document.body} />);
expect(errSpy).toHaveBeenCalledWith(
'Warning: [antd: Slider] `getTooltipPopupContainer` is deprecated which will be removed in next major version, please use `tooltip.getPopupContainer` instead.',
);
rerender(<Slider tipFormatter={v => v} />);
expect(errSpy).toHaveBeenCalledWith(
'Warning: [antd: Slider] `tipFormatter` is deprecated which will be removed in next major version, please use `tooltip.formatter` instead.',
);
rerender(<Slider tooltipVisible />);
expect(errSpy).toHaveBeenCalledWith(
'Warning: [antd: Slider] `tooltipVisible` is deprecated which will be removed in next major version, please use `tooltip.open` instead.',
);
rerender(<Slider tooltipPlacement="left" />);
expect(errSpy).toHaveBeenCalledWith(
'Warning: [antd: Slider] `tooltipPlacement` is deprecated which will be removed in next major version, please use `tooltip.placement` instead.',
);
errSpy.mockRestore();
});
});

View File

@ -7,17 +7,17 @@ title:
## zh-CN
`tooltipVisible` 为 `true` 时,将始终显示 ToolTip反之则始终不显示即使在拖动、移入时也是如此。
`tooltip.open` 为 `true` 时,将始终显示 ToolTip反之则始终不显示即使在拖动、移入时也是如此。
## en-US
When `tooltipVisible` is `true`, ToolTip will show always, or ToolTip will not show anyway, even if dragging or hovering.
When `tooltip.open` is `true`, ToolTip will always show, or ToolTip will not show anyway, even if dragging or hovering.
```tsx
import { Slider } from 'antd';
import React from 'react';
const App: React.FC = () => <Slider defaultValue={30} tooltipVisible />;
const App: React.FC = () => <Slider defaultValue={30} tooltip={{ open: true }} />;
export default App;
```

View File

@ -7,11 +7,11 @@ title:
## zh-CN
使用 `tipFormatter` 可以格式化 `Tooltip` 的内容,设置 `tipFormatter={null}`,则隐藏 `Tooltip`
使用 `tooltip.formatter` 可以格式化 `Tooltip` 的内容,设置 `tooltip.formatter={null}`,则隐藏 `Tooltip`
## en-US
Use `tipFormatter` to format content of `Tooltip`. If `tipFormatter` is null, hide it.
Use `tooltip.formatter` to format content of `Tooltip`. If `tooltip.formatter` is null, hide it.
```tsx
import { Slider } from 'antd';
@ -21,8 +21,8 @@ const formatter = (value: number) => `${value}%`;
const App: React.FC = () => (
<>
<Slider tipFormatter={formatter} />
<Slider tipFormatter={null} />
<Slider tooltip={{ formatter }} />
<Slider tooltip={{ formatter: null }} />
</>
);

View File

@ -19,7 +19,6 @@ To input a value in a range.
| defaultValue | The default value of slider. When `range` is false, use number, otherwise, use \[number, number] | number \| \[number, number] | 0 \| \[0, 0] | |
| disabled | If true, the slider will not be interactable | boolean | false | |
| dots | Whether the thumb can drag over tick only | boolean | false | |
| getTooltipPopupContainer | The DOM container of the Tooltip, the default behavior is to create a div element in body | (triggerNode) => HTMLElement | () => document.body | |
| included | Make effect when `marks` not null, true means containment and false means coordinative | boolean | true | |
| marks | Tick mark of Slider, type of key must be `number`, and must in closed interval \[min, max], each mark can declare its own style | object | { number: ReactNode } \| { number: { style: CSSProperties, label: ReactNode } } | |
| max | The maximum value the slider can slide to | number | 100 | |
@ -27,9 +26,7 @@ To input a value in a range.
| range | Dual thumb mode | boolean | false | |
| reverse | Reverse the component | boolean | false | |
| step | The granularity the slider can step through values. Must greater than 0, and be divided by (max - min) . When `marks` no null, `step` can be null | number \| null | 1 | |
| tipFormatter | Slider will pass its value to `tipFormatter`, and display its value in Tooltip, and hide Tooltip when return value is null | value => ReactNode \| null | IDENTITY | |
| tooltipPlacement | Set Tooltip display position. Ref [Tooltip](/components/tooltip/) | string | - | |
| tooltipVisible | If true, Tooltip will show always, or it will not show anyway, even if dragging or hovering | boolean | - | |
| tooltip | The tooltip relate props | [tooltip](#tooltip) | - | 4.23.0 |
| value | The value of slider. When `range` is false, use number, otherwise, use \[number, number] | number \| \[number, number] | - | |
| vertical | If true, the slider will be vertical | boolean | false | |
| onAfterChange | Fire when onmouseup is fired | (value) => void | - | |
@ -39,13 +36,22 @@ To input a value in a range.
### range
| Property | Description | Type | Default | Version |
| Property | Description | Type | Default | Version |
| -------------- | ------------------------------- | ------- | ------- | ------- |
| draggableTrack | Whether range track can be drag | boolean | false | 4.10.0 |
### tooltip
| 参数 | 说明 | 类型 | 默认值 | 版本 |
| --- | --- | --- | --- | --- |
| draggableTrack | Whether range track can be drag | boolean | false | 4.10.0 |
| open | If true, Tooltip will show always, or it will not show anyway, even if dragging or hovering | boolean | - | 4.23.0 |
| placement | Set Tooltip display position. Ref [Tooltip](/components/tooltip/) | string | - | 4.23.0 |
| getPopupContainer | The DOM container of the Tooltip, the default behavior is to create a div element in body | (triggerNode) => HTMLElement | () => document.body | 4.23.0 |
| formatter | Slider will pass its value to `formatter`, and display its value in Tooltip, and hide Tooltip when return value is null | value => ReactNode \| null | IDENTITY | 4.23.0 |
## Methods
| Name | Description | Version |
| --- | --- | --- |
| blur() | Remove focus | |
| focus() | Get focus | |
| Name | Description | Version |
| ------- | ------------ | ------- |
| blur() | Remove focus | |
| focus() | Get focus | |

View File

@ -4,6 +4,7 @@ import RcSlider from 'rc-slider';
import * as React from 'react';
import { ConfigContext } from '../config-provider';
import type { TooltipPlacement } from '../tooltip';
import warning from '../_util/warning';
import SliderTooltip from './SliderTooltip';
import useStyle from './style';
@ -22,8 +23,20 @@ export type HandleGeneratorFn = (config: {
info: HandleGeneratorInfo;
}) => React.ReactElement;
export interface SliderTooltipProps {
prefixCls?: string;
open?: boolean;
placement?: TooltipPlacement;
getPopupContainer?: (triggerNode: HTMLElement) => HTMLElement;
formatter?: null | ((value?: number) => React.ReactNode);
}
export interface SliderBaseProps {
prefixCls?: string;
/**
* @deprecated `tooltipPrefixCls` is deprecated which will be removed in next major version.
* Please use `tooltip.prefixCls` instead.
*/
tooltipPrefixCls?: string;
reverse?: boolean;
min?: number;
@ -34,12 +47,29 @@ export interface SliderBaseProps {
included?: boolean;
disabled?: boolean;
vertical?: boolean;
/**
* @deprecated `tipFormatter` is deprecated which will be removed in next major version. Please
* use `tooltip.formatter` instead.
*/
tipFormatter?: null | ((value?: number) => React.ReactNode);
className?: string;
id?: string;
style?: React.CSSProperties;
/**
* @deprecated `tooltipVisible` is deprecated which will be removed in next major version. Please
* use `tooltip.open` instead.
*/
tooltipVisible?: boolean;
/**
* @deprecated `tooltipPlacement` is deprecated which will be removed in next major version.
* Please use `tooltip.placement` instead.
*/
tooltipPlacement?: TooltipPlacement;
tooltip?: SliderTooltipProps;
/**
* @deprecated `getTooltipPopupContainer` is deprecated which will be removed in next major
* version. Please use `tooltip.getPopupContainer` instead.
*/
getTooltipPopupContainer?: (triggerNode: HTMLElement) => HTMLElement;
autoFocus?: boolean;
}
@ -68,15 +98,15 @@ interface SliderRange {
draggableTrack?: boolean;
}
export type Visibles = { [index: number]: boolean };
export type Opens = { [index: number]: boolean };
const Slider = React.forwardRef<unknown, SliderSingleProps | SliderRangeProps>(
(props, ref: any) => {
const { getPrefixCls, direction, getPopupContainer } = React.useContext(ConfigContext);
const [visibles, setVisibles] = React.useState<Visibles>({});
const [opens, setOpens] = React.useState<Opens>({});
const toggleTooltipVisible = (index: number, visible: boolean) => {
setVisibles((prev: Visibles) => ({ ...prev, [index]: visible }));
const toggleTooltipOpen = (index: number, open: boolean) => {
setOpens((prev: Opens) => ({ ...prev, [index]: open }));
};
const getTooltipPlacement = (tooltipPlacement?: TooltipPlacement, vertical?: boolean) => {
@ -89,15 +119,8 @@ const Slider = React.forwardRef<unknown, SliderSingleProps | SliderRangeProps>(
return direction === 'rtl' ? 'left' : 'right';
};
const {
prefixCls: customizePrefixCls,
tooltipPrefixCls: customizeTooltipPrefixCls,
range,
className,
...restProps
} = props;
const { prefixCls: customizePrefixCls, range, className, ...restProps } = props;
const prefixCls = getPrefixCls('slider', customizePrefixCls);
const tooltipPrefixCls = getPrefixCls('tooltip', customizeTooltipPrefixCls);
const [wrapSSR, hashId] = useStyle(prefixCls);
@ -123,27 +146,66 @@ const Slider = React.forwardRef<unknown, SliderSingleProps | SliderRangeProps>(
return typeof range === 'object' ? [true, range.draggableTrack] : [true, false];
}, [range]);
// Warning for deprecated usage
if (process.env.NODE_ENV !== 'production') {
[
['tooltipPrefixCls', 'prefixCls'],
['getTooltipPopupContainer', 'getPopupContainer'],
['tipFormatter', 'formatter'],
['tooltipPlacement', 'placement'],
['tooltipVisible', 'open'],
].forEach(([deprecatedName, newName]) => {
warning(
!(deprecatedName in props),
'Slider',
`\`${deprecatedName}\` is deprecated which will be removed in next major version, please use \`tooltip.${newName}\` instead.`,
);
});
}
const handleRender: RcSliderProps['handleRender'] = (node, info) => {
const { index, dragging } = info;
const rootPrefixCls = getPrefixCls();
const { tipFormatter, tooltipVisible, tooltipPlacement, getTooltipPopupContainer, vertical } =
props;
const { tooltip = {}, vertical } = props;
const isTipFormatter = tipFormatter ? visibles[index] || dragging : false;
const visible = tooltipVisible || (tooltipVisible === undefined && isTipFormatter);
const tooltipProps: SliderTooltipProps = {
formatter:
props.tipFormatter ??
// eslint-disable-next-line func-names
function (value) {
return typeof value === 'number' ? value.toString() : '';
},
open: props.tooltipVisible,
placement: props.tooltipPlacement,
getPopupContainer: props.getTooltipPopupContainer,
...tooltip,
};
const {
open: tooltipOpen,
placement: tooltipPlacement,
getPopupContainer: getTooltipPopupContainer,
prefixCls: customizeTooltipPrefixCls,
formatter: tipFormatter,
} = tooltipProps;
const isTipFormatter = tipFormatter ? opens[index] || dragging : false;
const open = tooltipOpen || (tooltipOpen === undefined && isTipFormatter);
const passedProps = {
...node.props,
onMouseEnter: () => toggleTooltipVisible(index, true),
onMouseLeave: () => toggleTooltipVisible(index, false),
onMouseEnter: () => toggleTooltipOpen(index, true),
onMouseLeave: () => toggleTooltipOpen(index, false),
};
const tooltipPrefixCls = getPrefixCls('tooltip', customizeTooltipPrefixCls);
return (
<SliderTooltip
prefixCls={tooltipPrefixCls}
title={tipFormatter ? tipFormatter(info.value) : ''}
visible={visible}
visible={open}
placement={getTooltipPlacement(tooltipPlacement, vertical)}
transitionName={`${rootPrefixCls}-zoom-down`}
key={index}
@ -174,10 +236,4 @@ if (process.env.NODE_ENV !== 'production') {
Slider.displayName = 'Slider';
}
Slider.defaultProps = {
tipFormatter(value: number) {
return typeof value === 'number' ? value.toString() : '';
},
};
export default Slider;

View File

@ -28,9 +28,7 @@ cover: https://gw.alipayobjects.com/zos/alicdn/HZ3meFc6W/Silder.svg
| range | 双滑块模式 | boolean \| [range](#range) | false | |
| reverse | 反向坐标轴 | boolean | false | |
| step | 步长,取值必须大于 0并且可被 (max - min) 整除。当 `marks` 不为空对象时,可以设置 `step` 为 null此时 Slider 的可选值仅有 marks 标出来的部分 | number \| null | 1 | |
| tipFormatter | Slider 会把当前值传给 `tipFormatter`,并在 Tooltip 中显示 `tipFormatter` 的返回值,若为 null则隐藏 Tooltip | value => ReactNode \| null | IDENTITY | |
| tooltipPlacement | 设置 Tooltip 展示位置。参考 [Tooltip](/components/tooltip/) | string | - | |
| tooltipVisible | 值为 true 时Tooltip 将会始终显示;否则始终不显示,哪怕在拖拽及移入时 | boolean | - | |
| tooltip | 设置 Tooltip 相关属性 | [tooltip](#tooltip) | - | 4.23.0 |
| value | 设置当前取值。当 `range` 为 false 时,使用 number否则用 \[number, number] | number \| \[number, number] | - | |
| vertical | 值为 true 时Slider 为垂直方向 | boolean | false | |
| onAfterChange | 与 `onmouseup` 触发时机一致,把当前值作为参数传入 | (value) => void | - | |
@ -38,13 +36,22 @@ cover: https://gw.alipayobjects.com/zos/alicdn/HZ3meFc6W/Silder.svg
### range
| 参数 | 说明 | 类型 | 默认值 | 版本 |
| -------------- | -------------------- | ------- | ------ | ------ |
| draggableTrack | 范围刻度是否可被拖拽 | boolean | false | 4.10.0 |
### tooltip
| 参数 | 说明 | 类型 | 默认值 | 版本 |
| --- | --- | --- | --- | --- |
| draggableTrack | 范围刻度是否可被拖拽 | boolean | false | 4.10.0 |
| open | 值为 true 时Tooltip 将会始终显示;否则始终不显示,哪怕在拖拽及移入时 | boolean | - | 4.23.0 |
| placement | 设置 Tooltip 展示位置。参考 [Tooltip](/components/tooltip/) | string | - | 4.23.0 |
| getPopupContainer | Tooltip 渲染父节点,默认渲染到 body 上 | (triggerNode) => HTMLElement | () => document.body | 4.23.0 |
| formatter | Slider 会把当前值传给 `formatter`,并在 Tooltip 中显示 `formatter` 的返回值,若为 null则隐藏 Tooltip | value => ReactNode \| null | IDENTITY | 4.23.0 |
## 方法
| 名称 | 描述 | 版本 |
| --- | --- | --- |
| blur() | 移除焦点 | |
| focus() | 获取焦点 | |
| 名称 | 描述 | 版本 |
| ------- | -------- | ---- |
| blur() | 移除焦点 | |
| focus() | 获取焦点 | |

View File

@ -33,6 +33,7 @@ function renderExpandIcon(locale: TableLocale) {
[`${iconPrefix}-collapsed`]: expandable && !expanded,
})}
aria-label={expanded ? locale.collapse : locale.expand}
aria-expanded={expanded}
/>
);
};

View File

@ -63,7 +63,7 @@ interface ChangeEventInfo<RecordType> {
total?: number;
};
filters: Record<string, FilterValue | null>;
sorter: SorterResult<RecordType> | SorterResult<RecordType[]>;
sorter: SorterResult<RecordType> | SorterResult<RecordType>[];
filterStates: FilterState<RecordType>[];
sorterStates: SortState<RecordType>[];
@ -94,7 +94,7 @@ export interface TableProps<RecordType>
onChange?: (
pagination: TablePaginationConfig,
filters: Record<string, FilterValue | null>,
sorter: SorterResult<RecordType> | SorterResult<RecordType[]>,
sorter: SorterResult<RecordType> | SorterResult<RecordType>[],
extra: TableCurrentDataSource<RecordType>,
) => void;
rowSelection?: TableRowSelection<RecordType>;
@ -265,7 +265,7 @@ function InternalTable<RecordType extends object = any>(
// ============================ Sorter =============================
const onSorterChange = (
sorter: SorterResult<RecordType> | SorterResult<RecordType[]>,
sorter: SorterResult<RecordType> | SorterResult<RecordType>[],
sorterStates: SortState<RecordType>[],
) => {
triggerOnChange(

View File

@ -82,6 +82,13 @@ describe('Table.expand', () => {
expect(container.querySelector('.indent-level-1').style.paddingLeft).toEqual('0px');
});
it('has right aria-expanded state', () => {
const { container } = render(<Table columns={columns} dataSource={data} />);
expect(container.querySelector('[aria-expanded=false]')).toBeTruthy();
fireEvent.click(container.querySelector('.ant-table-row-expand-icon'));
expect(container.querySelector('[aria-expanded=true]')).toBeTruthy();
});
describe('expandIconColumnIndex', () => {
it('basic', () => {
const { container } = render(

View File

@ -992,4 +992,104 @@ describe('Table.sorter', () => {
clickToMatchExpect(1, { field: 'english', order: 'descend' });
clickToMatchExpect(1, { field: 'english', order: undefined });
});
// https://github.com/ant-design/ant-design/issues/37024
it('multiple sort should pass array sorter as onChange param', () => {
const columns = [
{
title: 'Name',
dataIndex: 'name',
},
{
title: 'Chinese Score',
dataIndex: 'chinese',
sorter: {
compare: (a, b) => a.chinese - b.chinese,
multiple: 3,
},
},
{
title: 'Math Score',
dataIndex: 'math',
sorter: {
compare: (a, b) => a.math - b.math,
multiple: 2,
},
},
{
title: 'English Score',
dataIndex: 'english',
sorter: {
compare: (a, b) => a.english - b.english,
multiple: 1,
},
},
];
const tableData = [
{
key: '1',
name: 'John Brown',
chinese: 98,
math: 60,
english: 70,
},
{
key: '2',
name: 'Jim Green',
chinese: 98,
math: 66,
english: 89,
},
{
key: '3',
name: 'Joe Black',
chinese: 98,
math: 90,
english: 70,
},
{
key: '4',
name: 'Jim Red',
chinese: 88,
math: 99,
english: 89,
},
];
const onChange = jest.fn();
const { container } = render(
<Table columns={columns} dataSource={tableData} onChange={onChange} />,
);
const sorterColumns = Array.from(container.querySelectorAll('.ant-table-column-has-sorters'));
expect(sorterColumns.length).toBe(3);
fireEvent.click(sorterColumns[0]);
expect(onChange).toHaveBeenLastCalledWith(
expect.anything(),
expect.anything(),
expect.objectContaining({ field: 'chinese' }),
expect.anything(),
);
fireEvent.click(sorterColumns[1]);
expect(onChange).toHaveBeenLastCalledWith(
expect.anything(),
expect.anything(),
expect.arrayContaining([
expect.objectContaining({ field: 'chinese' }),
expect.objectContaining({ field: 'math' }),
]),
expect.anything(),
);
fireEvent.click(sorterColumns[2]);
expect(onChange).toHaveBeenLastCalledWith(
expect.anything(),
expect.anything(),
expect.arrayContaining([
expect.objectContaining({ field: 'chinese' }),
expect.objectContaining({ field: 'math' }),
expect.objectContaining({ field: 'english' }),
]),
expect.anything(),
);
});
});

View File

@ -49,6 +49,7 @@ exports[`Table.expand click to expand 1`] = `
style="padding-left: 0px;"
/>
<button
aria-expanded="true"
aria-label="Collapse row"
class="ant-table-row-expand-icon ant-table-row-expand-icon-expanded"
type="button"
@ -67,6 +68,7 @@ exports[`Table.expand click to expand 1`] = `
style="padding-left: 15px;"
/>
<button
aria-expanded="false"
aria-label="Expand row"
class="ant-table-row-expand-icon ant-table-row-expand-icon-spaced"
type="button"

View File

@ -116,6 +116,7 @@ exports[`Table.rowSelection fix expand on th left when selection column fixed on
style="position: sticky; left: 0px;"
>
<button
aria-expanded="false"
aria-label="Expand row"
class="ant-table-row-expand-icon ant-table-row-expand-icon-collapsed"
type="button"
@ -157,6 +158,7 @@ exports[`Table.rowSelection fix expand on th left when selection column fixed on
style="position: sticky; left: 0px;"
>
<button
aria-expanded="false"
aria-label="Expand row"
class="ant-table-row-expand-icon ant-table-row-expand-icon-collapsed"
type="button"
@ -198,6 +200,7 @@ exports[`Table.rowSelection fix expand on th left when selection column fixed on
style="position: sticky; left: 0px;"
>
<button
aria-expanded="false"
aria-label="Expand row"
class="ant-table-row-expand-icon ant-table-row-expand-icon-collapsed"
type="button"
@ -239,6 +242,7 @@ exports[`Table.rowSelection fix expand on th left when selection column fixed on
style="position: sticky; left: 0px;"
>
<button
aria-expanded="false"
aria-label="Expand row"
class="ant-table-row-expand-icon ant-table-row-expand-icon-collapsed"
type="button"

View File

@ -3671,6 +3671,7 @@ Array [
class="ant-table-cell ant-table-row-expand-icon-cell"
>
<button
aria-expanded="false"
aria-label="Expand row"
class="ant-table-row-expand-icon ant-table-row-expand-icon-collapsed"
type="button"
@ -3774,6 +3775,7 @@ Array [
class="ant-table-cell ant-table-row-expand-icon-cell"
>
<button
aria-expanded="false"
aria-label="Expand row"
class="ant-table-row-expand-icon ant-table-row-expand-icon-collapsed"
type="button"
@ -3877,6 +3879,7 @@ Array [
class="ant-table-cell ant-table-row-expand-icon-cell"
>
<button
aria-expanded="false"
aria-label="Expand row"
class="ant-table-row-expand-icon ant-table-row-expand-icon-collapsed"
type="button"
@ -3980,6 +3983,7 @@ Array [
class="ant-table-cell ant-table-row-expand-icon-cell"
>
<button
aria-expanded="false"
aria-label="Expand row"
class="ant-table-row-expand-icon ant-table-row-expand-icon-collapsed"
type="button"
@ -4083,6 +4087,7 @@ Array [
class="ant-table-cell ant-table-row-expand-icon-cell"
>
<button
aria-expanded="false"
aria-label="Expand row"
class="ant-table-row-expand-icon ant-table-row-expand-icon-collapsed"
type="button"
@ -4186,6 +4191,7 @@ Array [
class="ant-table-cell ant-table-row-expand-icon-cell"
>
<button
aria-expanded="false"
aria-label="Expand row"
class="ant-table-row-expand-icon ant-table-row-expand-icon-collapsed"
type="button"
@ -4289,6 +4295,7 @@ Array [
class="ant-table-cell ant-table-row-expand-icon-cell"
>
<button
aria-expanded="false"
aria-label="Expand row"
class="ant-table-row-expand-icon ant-table-row-expand-icon-collapsed"
type="button"
@ -4392,6 +4399,7 @@ Array [
class="ant-table-cell ant-table-row-expand-icon-cell"
>
<button
aria-expanded="false"
aria-label="Expand row"
class="ant-table-row-expand-icon ant-table-row-expand-icon-collapsed"
type="button"
@ -4495,6 +4503,7 @@ Array [
class="ant-table-cell ant-table-row-expand-icon-cell"
>
<button
aria-expanded="false"
aria-label="Expand row"
class="ant-table-row-expand-icon ant-table-row-expand-icon-collapsed"
type="button"
@ -4598,6 +4607,7 @@ Array [
class="ant-table-cell ant-table-row-expand-icon-cell"
>
<button
aria-expanded="false"
aria-label="Expand row"
class="ant-table-row-expand-icon ant-table-row-expand-icon-collapsed"
type="button"
@ -6816,6 +6826,7 @@ exports[`renders ./components/table/demo/expand.md extend context correctly 1`]
class="ant-table-cell ant-table-row-expand-icon-cell"
>
<button
aria-expanded="false"
aria-label="Expand row"
class="ant-table-row-expand-icon ant-table-row-expand-icon-collapsed"
type="button"
@ -6852,6 +6863,7 @@ exports[`renders ./components/table/demo/expand.md extend context correctly 1`]
class="ant-table-cell ant-table-row-expand-icon-cell"
>
<button
aria-expanded="false"
aria-label="Expand row"
class="ant-table-row-expand-icon ant-table-row-expand-icon-collapsed"
type="button"
@ -6888,6 +6900,7 @@ exports[`renders ./components/table/demo/expand.md extend context correctly 1`]
class="ant-table-cell ant-table-row-expand-icon-cell"
>
<button
aria-expanded="false"
aria-label="Expand row"
class="ant-table-row-expand-icon ant-table-row-expand-icon-spaced"
type="button"
@ -6924,6 +6937,7 @@ exports[`renders ./components/table/demo/expand.md extend context correctly 1`]
class="ant-table-cell ant-table-row-expand-icon-cell"
>
<button
aria-expanded="false"
aria-label="Expand row"
class="ant-table-row-expand-icon ant-table-row-expand-icon-collapsed"
type="button"
@ -15951,6 +15965,7 @@ Array [
class="ant-table-cell ant-table-row-expand-icon-cell"
>
<button
aria-expanded="false"
aria-label="Expand row"
class="ant-table-row-expand-icon ant-table-row-expand-icon-collapsed"
type="button"
@ -16002,6 +16017,7 @@ Array [
class="ant-table-cell ant-table-row-expand-icon-cell"
>
<button
aria-expanded="false"
aria-label="Expand row"
class="ant-table-row-expand-icon ant-table-row-expand-icon-collapsed"
type="button"
@ -16053,6 +16069,7 @@ Array [
class="ant-table-cell ant-table-row-expand-icon-cell"
>
<button
aria-expanded="false"
aria-label="Expand row"
class="ant-table-row-expand-icon ant-table-row-expand-icon-collapsed"
type="button"
@ -16275,6 +16292,7 @@ Array [
class="ant-table-cell ant-table-row-expand-icon-cell"
>
<button
aria-expanded="true"
aria-label="Collapse row"
class="ant-table-row-expand-icon ant-table-row-expand-icon-expanded"
type="button"
@ -17053,6 +17071,7 @@ Array [
class="ant-table-cell ant-table-row-expand-icon-cell"
>
<button
aria-expanded="false"
aria-label="Expand row"
class="ant-table-row-expand-icon ant-table-row-expand-icon-collapsed"
type="button"
@ -17104,6 +17123,7 @@ Array [
class="ant-table-cell ant-table-row-expand-icon-cell"
>
<button
aria-expanded="false"
aria-label="Expand row"
class="ant-table-row-expand-icon ant-table-row-expand-icon-collapsed"
type="button"
@ -17316,6 +17336,7 @@ Array [
class="ant-table-cell ant-table-row-expand-icon-cell"
>
<button
aria-expanded="true"
aria-label="Collapse row"
class="ant-table-row-expand-icon ant-table-row-expand-icon-expanded"
type="button"
@ -18094,6 +18115,7 @@ Array [
class="ant-table-cell ant-table-row-expand-icon-cell"
>
<button
aria-expanded="false"
aria-label="Expand row"
class="ant-table-row-expand-icon ant-table-row-expand-icon-collapsed"
type="button"
@ -18145,6 +18167,7 @@ Array [
class="ant-table-cell ant-table-row-expand-icon-cell"
>
<button
aria-expanded="false"
aria-label="Expand row"
class="ant-table-row-expand-icon ant-table-row-expand-icon-collapsed"
type="button"
@ -18357,6 +18380,7 @@ Array [
class="ant-table-cell ant-table-row-expand-icon-cell"
>
<button
aria-expanded="true"
aria-label="Collapse row"
class="ant-table-row-expand-icon ant-table-row-expand-icon-expanded"
type="button"
@ -19135,6 +19159,7 @@ Array [
class="ant-table-cell ant-table-row-expand-icon-cell"
>
<button
aria-expanded="false"
aria-label="Expand row"
class="ant-table-row-expand-icon ant-table-row-expand-icon-collapsed"
type="button"
@ -19186,6 +19211,7 @@ Array [
class="ant-table-cell ant-table-row-expand-icon-cell"
>
<button
aria-expanded="false"
aria-label="Expand row"
class="ant-table-row-expand-icon ant-table-row-expand-icon-collapsed"
type="button"
@ -19415,6 +19441,7 @@ exports[`renders ./components/table/demo/order-column.md extend context correctl
class="ant-table-cell ant-table-row-expand-icon-cell"
>
<button
aria-expanded="false"
aria-label="Expand row"
class="ant-table-row-expand-icon ant-table-row-expand-icon-collapsed"
type="button"
@ -19463,6 +19490,7 @@ exports[`renders ./components/table/demo/order-column.md extend context correctl
class="ant-table-cell ant-table-row-expand-icon-cell"
>
<button
aria-expanded="false"
aria-label="Expand row"
class="ant-table-row-expand-icon ant-table-row-expand-icon-collapsed"
type="button"
@ -19511,6 +19539,7 @@ exports[`renders ./components/table/demo/order-column.md extend context correctl
class="ant-table-cell ant-table-row-expand-icon-cell"
>
<button
aria-expanded="false"
aria-label="Expand row"
class="ant-table-row-expand-icon ant-table-row-expand-icon-collapsed"
type="button"
@ -19559,6 +19588,7 @@ exports[`renders ./components/table/demo/order-column.md extend context correctl
class="ant-table-cell ant-table-row-expand-icon-cell"
>
<button
aria-expanded="false"
aria-label="Expand row"
class="ant-table-row-expand-icon ant-table-row-expand-icon-collapsed"
type="button"
@ -26480,6 +26510,7 @@ Array [
style="padding-left:0px"
/>
<button
aria-expanded="false"
aria-label="Expand row"
class="ant-table-row-expand-icon ant-table-row-expand-icon-collapsed"
type="button"
@ -26528,6 +26559,7 @@ Array [
style="padding-left:0px"
/>
<button
aria-expanded="false"
aria-label="Expand row"
class="ant-table-row-expand-icon ant-table-row-expand-icon-spaced"
type="button"
@ -26787,6 +26819,7 @@ Array [
style="padding-left:0px"
/>
<button
aria-expanded="true"
aria-label="Collapse row"
class="ant-table-row-expand-icon ant-table-row-expand-icon-expanded"
type="button"
@ -26842,6 +26875,7 @@ Array [
style="padding-left:15px"
/>
<button
aria-expanded="true"
aria-label="Collapse row"
class="ant-table-row-expand-icon ant-table-row-expand-icon-spaced"
type="button"
@ -26897,6 +26931,7 @@ Array [
style="padding-left:15px"
/>
<button
aria-expanded="true"
aria-label="Collapse row"
class="ant-table-row-expand-icon ant-table-row-expand-icon-expanded"
type="button"
@ -26952,6 +26987,7 @@ Array [
style="padding-left:30px"
/>
<button
aria-expanded="true"
aria-label="Collapse row"
class="ant-table-row-expand-icon ant-table-row-expand-icon-spaced"
type="button"
@ -27007,6 +27043,7 @@ Array [
style="padding-left:15px"
/>
<button
aria-expanded="true"
aria-label="Collapse row"
class="ant-table-row-expand-icon ant-table-row-expand-icon-expanded"
type="button"
@ -27062,6 +27099,7 @@ Array [
style="padding-left:30px"
/>
<button
aria-expanded="true"
aria-label="Collapse row"
class="ant-table-row-expand-icon ant-table-row-expand-icon-expanded"
type="button"
@ -27117,6 +27155,7 @@ Array [
style="padding-left:45px"
/>
<button
aria-expanded="true"
aria-label="Collapse row"
class="ant-table-row-expand-icon ant-table-row-expand-icon-spaced"
type="button"
@ -27172,6 +27211,7 @@ Array [
style="padding-left:45px"
/>
<button
aria-expanded="true"
aria-label="Collapse row"
class="ant-table-row-expand-icon ant-table-row-expand-icon-spaced"
type="button"
@ -27227,6 +27267,7 @@ Array [
style="padding-left:0px"
/>
<button
aria-expanded="true"
aria-label="Collapse row"
class="ant-table-row-expand-icon ant-table-row-expand-icon-spaced"
type="button"

View File

@ -2944,6 +2944,7 @@ Array [
class="ant-table-cell ant-table-row-expand-icon-cell"
>
<button
aria-expanded="false"
aria-label="Expand row"
class="ant-table-row-expand-icon ant-table-row-expand-icon-collapsed"
type="button"
@ -3047,6 +3048,7 @@ Array [
class="ant-table-cell ant-table-row-expand-icon-cell"
>
<button
aria-expanded="false"
aria-label="Expand row"
class="ant-table-row-expand-icon ant-table-row-expand-icon-collapsed"
type="button"
@ -3150,6 +3152,7 @@ Array [
class="ant-table-cell ant-table-row-expand-icon-cell"
>
<button
aria-expanded="false"
aria-label="Expand row"
class="ant-table-row-expand-icon ant-table-row-expand-icon-collapsed"
type="button"
@ -3253,6 +3256,7 @@ Array [
class="ant-table-cell ant-table-row-expand-icon-cell"
>
<button
aria-expanded="false"
aria-label="Expand row"
class="ant-table-row-expand-icon ant-table-row-expand-icon-collapsed"
type="button"
@ -3356,6 +3360,7 @@ Array [
class="ant-table-cell ant-table-row-expand-icon-cell"
>
<button
aria-expanded="false"
aria-label="Expand row"
class="ant-table-row-expand-icon ant-table-row-expand-icon-collapsed"
type="button"
@ -3459,6 +3464,7 @@ Array [
class="ant-table-cell ant-table-row-expand-icon-cell"
>
<button
aria-expanded="false"
aria-label="Expand row"
class="ant-table-row-expand-icon ant-table-row-expand-icon-collapsed"
type="button"
@ -3562,6 +3568,7 @@ Array [
class="ant-table-cell ant-table-row-expand-icon-cell"
>
<button
aria-expanded="false"
aria-label="Expand row"
class="ant-table-row-expand-icon ant-table-row-expand-icon-collapsed"
type="button"
@ -3665,6 +3672,7 @@ Array [
class="ant-table-cell ant-table-row-expand-icon-cell"
>
<button
aria-expanded="false"
aria-label="Expand row"
class="ant-table-row-expand-icon ant-table-row-expand-icon-collapsed"
type="button"
@ -3768,6 +3776,7 @@ Array [
class="ant-table-cell ant-table-row-expand-icon-cell"
>
<button
aria-expanded="false"
aria-label="Expand row"
class="ant-table-row-expand-icon ant-table-row-expand-icon-collapsed"
type="button"
@ -3871,6 +3880,7 @@ Array [
class="ant-table-cell ant-table-row-expand-icon-cell"
>
<button
aria-expanded="false"
aria-label="Expand row"
class="ant-table-row-expand-icon ant-table-row-expand-icon-collapsed"
type="button"
@ -5535,6 +5545,7 @@ exports[`renders ./components/table/demo/expand.md correctly 1`] = `
class="ant-table-cell ant-table-row-expand-icon-cell"
>
<button
aria-expanded="false"
aria-label="Expand row"
class="ant-table-row-expand-icon ant-table-row-expand-icon-collapsed"
type="button"
@ -5571,6 +5582,7 @@ exports[`renders ./components/table/demo/expand.md correctly 1`] = `
class="ant-table-cell ant-table-row-expand-icon-cell"
>
<button
aria-expanded="false"
aria-label="Expand row"
class="ant-table-row-expand-icon ant-table-row-expand-icon-collapsed"
type="button"
@ -5607,6 +5619,7 @@ exports[`renders ./components/table/demo/expand.md correctly 1`] = `
class="ant-table-cell ant-table-row-expand-icon-cell"
>
<button
aria-expanded="false"
aria-label="Expand row"
class="ant-table-row-expand-icon ant-table-row-expand-icon-spaced"
type="button"
@ -5643,6 +5656,7 @@ exports[`renders ./components/table/demo/expand.md correctly 1`] = `
class="ant-table-cell ant-table-row-expand-icon-cell"
>
<button
aria-expanded="false"
aria-label="Expand row"
class="ant-table-row-expand-icon ant-table-row-expand-icon-collapsed"
type="button"
@ -12173,6 +12187,7 @@ Array [
class="ant-table-cell ant-table-row-expand-icon-cell"
>
<button
aria-expanded="false"
aria-label="Expand row"
class="ant-table-row-expand-icon ant-table-row-expand-icon-collapsed"
type="button"
@ -12224,6 +12239,7 @@ Array [
class="ant-table-cell ant-table-row-expand-icon-cell"
>
<button
aria-expanded="false"
aria-label="Expand row"
class="ant-table-row-expand-icon ant-table-row-expand-icon-collapsed"
type="button"
@ -12275,6 +12291,7 @@ Array [
class="ant-table-cell ant-table-row-expand-icon-cell"
>
<button
aria-expanded="false"
aria-label="Expand row"
class="ant-table-row-expand-icon ant-table-row-expand-icon-collapsed"
type="button"
@ -12497,6 +12514,7 @@ Array [
class="ant-table-cell ant-table-row-expand-icon-cell"
>
<button
aria-expanded="true"
aria-label="Collapse row"
class="ant-table-row-expand-icon ant-table-row-expand-icon-expanded"
type="button"
@ -12888,6 +12906,7 @@ Array [
class="ant-table-cell ant-table-row-expand-icon-cell"
>
<button
aria-expanded="false"
aria-label="Expand row"
class="ant-table-row-expand-icon ant-table-row-expand-icon-collapsed"
type="button"
@ -12939,6 +12958,7 @@ Array [
class="ant-table-cell ant-table-row-expand-icon-cell"
>
<button
aria-expanded="false"
aria-label="Expand row"
class="ant-table-row-expand-icon ant-table-row-expand-icon-collapsed"
type="button"
@ -13151,6 +13171,7 @@ Array [
class="ant-table-cell ant-table-row-expand-icon-cell"
>
<button
aria-expanded="true"
aria-label="Collapse row"
class="ant-table-row-expand-icon ant-table-row-expand-icon-expanded"
type="button"
@ -13542,6 +13563,7 @@ Array [
class="ant-table-cell ant-table-row-expand-icon-cell"
>
<button
aria-expanded="false"
aria-label="Expand row"
class="ant-table-row-expand-icon ant-table-row-expand-icon-collapsed"
type="button"
@ -13593,6 +13615,7 @@ Array [
class="ant-table-cell ant-table-row-expand-icon-cell"
>
<button
aria-expanded="false"
aria-label="Expand row"
class="ant-table-row-expand-icon ant-table-row-expand-icon-collapsed"
type="button"
@ -13805,6 +13828,7 @@ Array [
class="ant-table-cell ant-table-row-expand-icon-cell"
>
<button
aria-expanded="true"
aria-label="Collapse row"
class="ant-table-row-expand-icon ant-table-row-expand-icon-expanded"
type="button"
@ -14196,6 +14220,7 @@ Array [
class="ant-table-cell ant-table-row-expand-icon-cell"
>
<button
aria-expanded="false"
aria-label="Expand row"
class="ant-table-row-expand-icon ant-table-row-expand-icon-collapsed"
type="button"
@ -14247,6 +14272,7 @@ Array [
class="ant-table-cell ant-table-row-expand-icon-cell"
>
<button
aria-expanded="false"
aria-label="Expand row"
class="ant-table-row-expand-icon ant-table-row-expand-icon-collapsed"
type="button"
@ -14476,6 +14502,7 @@ exports[`renders ./components/table/demo/order-column.md correctly 1`] = `
class="ant-table-cell ant-table-row-expand-icon-cell"
>
<button
aria-expanded="false"
aria-label="Expand row"
class="ant-table-row-expand-icon ant-table-row-expand-icon-collapsed"
type="button"
@ -14524,6 +14551,7 @@ exports[`renders ./components/table/demo/order-column.md correctly 1`] = `
class="ant-table-cell ant-table-row-expand-icon-cell"
>
<button
aria-expanded="false"
aria-label="Expand row"
class="ant-table-row-expand-icon ant-table-row-expand-icon-collapsed"
type="button"
@ -14572,6 +14600,7 @@ exports[`renders ./components/table/demo/order-column.md correctly 1`] = `
class="ant-table-cell ant-table-row-expand-icon-cell"
>
<button
aria-expanded="false"
aria-label="Expand row"
class="ant-table-row-expand-icon ant-table-row-expand-icon-collapsed"
type="button"
@ -14620,6 +14649,7 @@ exports[`renders ./components/table/demo/order-column.md correctly 1`] = `
class="ant-table-cell ant-table-row-expand-icon-cell"
>
<button
aria-expanded="false"
aria-label="Expand row"
class="ant-table-row-expand-icon ant-table-row-expand-icon-collapsed"
type="button"
@ -20659,6 +20689,7 @@ Array [
style="padding-left:0px"
/>
<button
aria-expanded="false"
aria-label="Expand row"
class="ant-table-row-expand-icon ant-table-row-expand-icon-collapsed"
type="button"
@ -20707,6 +20738,7 @@ Array [
style="padding-left:0px"
/>
<button
aria-expanded="false"
aria-label="Expand row"
class="ant-table-row-expand-icon ant-table-row-expand-icon-spaced"
type="button"
@ -20966,6 +20998,7 @@ Array [
style="padding-left:0px"
/>
<button
aria-expanded="true"
aria-label="Collapse row"
class="ant-table-row-expand-icon ant-table-row-expand-icon-expanded"
type="button"
@ -21021,6 +21054,7 @@ Array [
style="padding-left:15px"
/>
<button
aria-expanded="true"
aria-label="Collapse row"
class="ant-table-row-expand-icon ant-table-row-expand-icon-spaced"
type="button"
@ -21076,6 +21110,7 @@ Array [
style="padding-left:15px"
/>
<button
aria-expanded="true"
aria-label="Collapse row"
class="ant-table-row-expand-icon ant-table-row-expand-icon-expanded"
type="button"
@ -21131,6 +21166,7 @@ Array [
style="padding-left:30px"
/>
<button
aria-expanded="true"
aria-label="Collapse row"
class="ant-table-row-expand-icon ant-table-row-expand-icon-spaced"
type="button"
@ -21186,6 +21222,7 @@ Array [
style="padding-left:15px"
/>
<button
aria-expanded="true"
aria-label="Collapse row"
class="ant-table-row-expand-icon ant-table-row-expand-icon-expanded"
type="button"
@ -21241,6 +21278,7 @@ Array [
style="padding-left:30px"
/>
<button
aria-expanded="true"
aria-label="Collapse row"
class="ant-table-row-expand-icon ant-table-row-expand-icon-expanded"
type="button"
@ -21296,6 +21334,7 @@ Array [
style="padding-left:45px"
/>
<button
aria-expanded="true"
aria-label="Collapse row"
class="ant-table-row-expand-icon ant-table-row-expand-icon-spaced"
type="button"
@ -21351,6 +21390,7 @@ Array [
style="padding-left:45px"
/>
<button
aria-expanded="true"
aria-label="Collapse row"
class="ant-table-row-expand-icon ant-table-row-expand-icon-spaced"
type="button"
@ -21406,6 +21446,7 @@ Array [
style="padding-left:0px"
/>
<button
aria-expanded="true"
aria-label="Collapse row"
class="ant-table-row-expand-icon ant-table-row-expand-icon-spaced"
type="button"

View File

@ -36,12 +36,6 @@ describe('Table.typescript', () => {
const table = <Table<RecordType> dataSource={[{ key: 'Bamboo' }]} />;
expect(table).toBeTruthy();
});
it('Sorter types', () => {
const table = <Table onChange={(_pagination, _filters, sorter) => sorter.field} />;
expect(table).toBeTruthy();
});
});
describe('Table.typescript types', () => {

View File

@ -247,7 +247,7 @@ function stateToInfo<RecordType>(sorterStates: SortState<RecordType>) {
function generateSorterInfo<RecordType>(
sorterStates: SortState<RecordType>[],
): SorterResult<RecordType> | SorterResult<RecordType[]> {
): SorterResult<RecordType> | SorterResult<RecordType>[] {
const list = sorterStates.filter(({ sortOrder }) => sortOrder).map(stateToInfo);
// =========== Legacy compatible support ===========
@ -259,7 +259,11 @@ function generateSorterInfo<RecordType>(
};
}
return list[0] || {};
if (list.length <= 1) {
return list[0] || {};
}
return list;
}
export function getSortData<RecordType>(
@ -320,7 +324,7 @@ interface SorterConfig<RecordType> {
prefixCls: string;
mergedColumns: ColumnsType<RecordType>;
onSorterChange: (
sorterResult: SorterResult<RecordType> | SorterResult<RecordType[]>,
sorterResult: SorterResult<RecordType> | SorterResult<RecordType>[],
sortStates: SortState<RecordType>[],
) => void;
sortDirections: SortOrder[];
@ -339,7 +343,7 @@ export default function useFilterSorter<RecordType>({
TransformColumns<RecordType>,
SortState<RecordType>[],
ColumnTitleProps<RecordType>,
() => SorterResult<RecordType> | SorterResult<RecordType[]>,
() => SorterResult<RecordType> | SorterResult<RecordType>[],
] {
const [sortStates, setSortStates] = React.useState<SortState<RecordType>[]>(
collectSortStates(mergedColumns, true),

View File

@ -1,12 +1,12 @@
import dayjs from 'dayjs';
import customParseFormat from 'dayjs/plugin/customParseFormat';
import { mount } from 'enzyme';
import React from 'react';
import TimePicker from '..';
import focusTest from '../../../tests/shared/focusTest';
import mountTest from '../../../tests/shared/mountTest';
import rtlTest from '../../../tests/shared/rtlTest';
import { resetWarned } from '../../_util/warning';
import { render } from '../../../tests/utils';
dayjs.extend(customParseFormat);
@ -32,83 +32,84 @@ describe('TimePicker', () => {
OK
</button>
);
const wrapper = mount(<TimePicker addon={addon} open />);
expect(wrapper.find('.my-btn').length).toBeTruthy();
const { container } = render(<TimePicker addon={addon} open />);
expect(container.querySelectorAll('.my-btn').length).toBeTruthy();
expect(errorSpy).toHaveBeenCalledWith(
'Warning: [antd: TimePicker] `addon` is deprecated. Please use `renderExtraFooter` instead.',
);
});
it('not render clean icon when allowClear is false', () => {
const wrapper = mount(
const { container } = render(
<TimePicker defaultValue={dayjs('2000-01-01 00:00:00')} allowClear={false} />,
);
expect(wrapper.render()).toMatchSnapshot();
expect(container.firstChild).toMatchSnapshot();
});
it('clearIcon should render correctly', () => {
const clearIcon = <div className="test-clear-icon">test</div>;
const wrapper = mount(<TimePicker clearIcon={clearIcon} />);
expect(wrapper.find('Picker').last().prop('clearIcon')).toEqual(
<div className="test-clear-icon">test</div>,
const { container } = render(
<TimePicker clearIcon={clearIcon} value={dayjs('00:00:00', 'HH:mm:ss')} />,
);
expect(container.querySelector('.test-clear-icon')).toBeTruthy();
});
it('prop locale should works', () => {
const locale = {
placeholder: 'Избери дата',
};
const wrapper = mount(
<TimePicker defaultValue={dayjs('2000-01-01 00:00:00')} open locale={locale} />,
const { container } = render(
<TimePicker defaultValue={dayjs('2000-01-01 00:00:00')} open locale={locale as any} />,
);
expect(wrapper.render()).toMatchSnapshot();
expect(Array.from(container.children)).toMatchSnapshot();
});
it('should pass popupClassName prop to Picker as dropdownClassName prop', () => {
const popupClassName = 'myCustomClassName';
const wrapper = mount(
const { container } = render(
<TimePicker
open
defaultOpenValue={dayjs('00:00:00', 'HH:mm:ss')}
popupClassName={popupClassName}
/>,
);
expect(wrapper.find('Picker').last().prop('dropdownClassName')).toEqual(popupClassName);
expect(container.querySelector(`.${popupClassName}`)).toBeTruthy();
});
it('should pass popupClassName prop to RangePicker as dropdownClassName prop', () => {
const popupClassName = 'myCustomClassName';
const wrapper = mount(
const { container } = render(
<TimePicker.RangePicker
open
defaultOpenValue={dayjs('00:00:00', 'HH:mm:ss')}
popupClassName={popupClassName}
/>,
);
expect(wrapper.find('RangePicker').last().prop('dropdownClassName')).toEqual(popupClassName);
expect(container.querySelector(`.${popupClassName}`)).toBeTruthy();
});
it('RangePicker should show warning when use dropdownClassName', () => {
mount(<TimePicker.RangePicker dropdownClassName="myCustomClassName" />);
render(<TimePicker.RangePicker dropdownClassName="myCustomClassName" />);
expect(errorSpy).toHaveBeenCalledWith(
'Warning: [antd: RangePicker] `dropdownClassName` is deprecated which will be removed in next major version. Please use `popupClassName` instead.',
);
});
it('TimePicker should show warning when use dropdownClassName', () => {
mount(<TimePicker dropdownClassName="myCustomClassName" />);
render(<TimePicker dropdownClassName="myCustomClassName" />);
expect(errorSpy).toHaveBeenCalledWith(
'Warning: [antd: TimePicker] `dropdownClassName` is deprecated which will be removed in next major version. Please use `popupClassName` instead.',
);
});
it('should support bordered', () => {
const wrapper = mount(
const { container } = render(
<TimePicker
className="custom-class"
defaultValue={dayjs('2000-01-01 00:00:00')}
bordered={false}
/>,
);
expect(wrapper.render()).toMatchSnapshot();
expect(container.firstChild).toMatchSnapshot();
});
});

View File

@ -17,7 +17,11 @@ Please find below some of the design resources and tools about Ant Design that w
- Sketch Symbols
- https://gw.alipayobjects.com/zos/basement_prod/048ee28f-2c80-4d15-9aa3-4f5ddac50465.svg
- Sketch Symbols for Desktop
- https://github.com/ant-design/ant-design/files/2051729/Ant.Design.Template.sketch.zip
- https://gw.alipayobjects.com/os/bmw-prod/a5ff1d86-44cd-4b86-92f8-daab59cba5b7.sketch
- Sketch Symbols (Dark)
- https://gw.alipayobjects.com/zos/basement_prod/048ee28f-2c80-4d15-9aa3-4f5ddac50465.svg
- Sketch Symbols for Desktop with dark theme
- https://gw.alipayobjects.com/os/bmw-prod/6b670a1c-26e3-4379-9c86-7a2b95e170e5.sketch
- Mobile Components
- https://gw.alipayobjects.com/zos/basement_prod/c0c3852c-d245-4330-886b-cb02ef49eb6d.svg
- Sketch Symbols File for Mobile

View File

@ -17,7 +17,11 @@ toc: false
- Sketch 组件包
- https://gw.alipayobjects.com/zos/basement_prod/048ee28f-2c80-4d15-9aa3-4f5ddac50465.svg
- 桌面组件 Sketch 模板包
- https://gw.alipayobjects.com/os/antfincdn/EfSt1N5LCk/Ant.Design.Components.4.0.zip
- https://gw.alipayobjects.com/os/bmw-prod/82c08c51-9993-4568-90c1-249c8301c0af.sketch
- Sketch 组件包 (暗色)
- https://gw.alipayobjects.com/zos/basement_prod/048ee28f-2c80-4d15-9aa3-4f5ddac50465.svg
- 桌面组件 Sketch 模板包,内含暗色版本的 antd 组件
- https://gw.alipayobjects.com/os/bmw-prod/f002145c-33d9-408e-ba75-a1a68896dfa3.sketch
- Mobile Components
- https://gw.alipayobjects.com/zos/basement_prod/c0c3852c-d245-4330-886b-cb02ef49eb6d.svg
- 移动组件 Sketch 模板

View File

@ -131,7 +131,7 @@
"rc-input": "~0.1.2",
"rc-input-number": "~7.3.5",
"rc-mentions": "~1.9.1",
"rc-menu": "~9.6.0",
"rc-menu": "~9.6.3",
"rc-motion": "^2.6.1",
"rc-notification": "~5.0.0-alpha.9",
"rc-pagination": "~3.1.17",

View File

@ -9,6 +9,11 @@ const packageJson = require('../package.json');
const DEPRECIATED_VERSION = {
'>= 4.21.6 < 4.22.0': ['https://github.com/ant-design/ant-design/pull/36682'],
'>=4.22.2 <=4.22.5': [
'https://github.com/ant-design/ant-design/issues/36932',
'https://github.com/ant-design/ant-design/pull/36800',
'https://github.com/ant-design/ant-design/issues/37024',
],
};
function matchDeprecated(version) {
@ -89,7 +94,12 @@ const SAFE_DAYS_DIFF = 1000 * 60 * 60 * 24 * 3; // 3 days not update seems to be
// Not find to use the latest version instead
defaultVersionObj = defaultVersionObj || defaultVersionList[defaultVersionList.length - 1];
const defaultVersion = defaultVersionObj ? defaultVersionObj.value : null;
let defaultVersion = defaultVersionObj ? defaultVersionObj.value : null;
// If default version is less than current, use current
if (semver.compare(defaultVersion, distTags.conch) < 0) {
defaultVersion = distTags.conch;
}
// Selection
let { conchVersion } = await inquirer.prompt([
@ -102,11 +112,24 @@ const SAFE_DAYS_DIFF = 1000 * 60 * 60 * 24 * 3; // 3 days not update seems to be
const { value, publishTime, depreciated } = info;
const desc = dayjs(publishTime).fromNow();
//
return {
...info,
name: `${depreciated ? '🚨' : '✅'} ${value} (${desc}) ${
value === defaultVersion ? '(default)' : ''
}`,
name: [
// Warning
depreciated ? '🚨' : '✅',
// Version
value,
// Date Diff
`(${desc})`,
// Default Mark
value === defaultVersion ? '(default)' : '',
// Current Mark
value === distTags.conch ? chalk.gray('- current') : '',
]
.filter(str => String(str).trim())
.join(' '),
};
}),
},

View File

@ -17,6 +17,8 @@
}
html {
direction: initial;
&.rtl {
direction: rtl;
}

View File

@ -13,7 +13,6 @@ import './Navigation.less';
export interface NavigationProps extends SharedProps {
isMobile: boolean;
isRTL: boolean;
pathname: string;
responsive: null | 'narrow' | 'crowded';
location: { pathname: string; query: any };

View File

@ -186,7 +186,7 @@ const Header: React.FC<HeaderProps & WrappedComponentProps<'intl'>> = props => {
);
}, [location]);
const getNextDirectionText = useMemo<string>(
const nextDirectionText = useMemo<string>(
() => (direction !== 'rtl' ? 'RTL' : 'LTR'),
[direction],
);
@ -242,7 +242,7 @@ const Header: React.FC<HeaderProps & WrappedComponentProps<'intl'>> = props => {
isMobile={isMobile}
showTechUIButton={showTechUIButton}
pathname={pathname}
directionText={getNextDirectionText}
directionText={nextDirectionText}
onLangChange={onLangChange}
onDirectionChange={onDirectionChange}
/>
@ -275,7 +275,7 @@ const Header: React.FC<HeaderProps & WrappedComponentProps<'intl'>> = props => {
className="header-button header-direction-button"
key="direction-button"
>
{getNextDirectionText}
{nextDirectionText}
</Button>,
<More key="more" {...sharedProps} />,
<Github key="github" responsive={responsive} />,

View File

@ -270,6 +270,7 @@ export default class Layout extends React.Component<LayoutPropsType, LayoutState
appLocale.locale === 'zh-CN'
? '基于 Ant Design 设计体系的 React UI 组件库,用于研发企业级中后台产品。'
: 'An enterprise-class UI design language and React UI library with a set of high-quality React components, one of best React UI library for enterprises';
return (
<StyleProvider cache={styleCache}>
{/* eslint-disable-next-line react/jsx-no-constructed-context-values */}