mirror of
https://github.com/ant-design/ant-design.git
synced 2024-11-27 20:49:53 +08:00
commit
6386431c49
2
.github/workflows/release-helper.yml
vendored
2
.github/workflows/release-helper.yml
vendored
@ -28,7 +28,6 @@ jobs:
|
||||
branch: 'master'
|
||||
dingding-token: ${{ secrets.DINGDING_BOT_TOKEN }}
|
||||
dingding-msg: 'CHANGELOG.zh-CN.md'
|
||||
dingding-delay-minute: 10
|
||||
msg-title: '# Ant Design {{v}} 发布日志'
|
||||
msg-poster: 'https://gw.alipayobjects.com/mdn/rms_08e378/afts/img/A*zx7LTI_ECSAAAAAAAAAAAABkARQnAQ'
|
||||
msg-footer: '💬 前往 [**Ant Design Releases**]({{url}}) 查看更新日志'
|
||||
@ -44,6 +43,7 @@ jobs:
|
||||
dingding-token: ${{ secrets.DINGDING_BOT_BIGFISH_TOKEN }}
|
||||
dingding-msg: 'CHANGELOG.zh-CN.md'
|
||||
dingding-delay-minute: 10
|
||||
release: false
|
||||
antd-conch-msg: '🐟 当前 Bigfish 内嵌 antd 版本:'
|
||||
msg-title: '# Ant Design {{v}} 发布日志'
|
||||
msg-poster: 'https://gw.alipayobjects.com/mdn/rms_08e378/afts/img/A*zx7LTI_ECSAAAAAAAAAAAABkARQnAQ'
|
||||
|
@ -1,7 +1,6 @@
|
||||
import { mount } from 'enzyme';
|
||||
import React from 'react';
|
||||
import { act } from 'react-dom/test-utils';
|
||||
import { render, sleep } from '../../../tests/utils';
|
||||
import { sleep, render, fireEvent } from '../../../tests/utils';
|
||||
import { resetWarned } from '../../_util/warning';
|
||||
|
||||
describe('Collapse', () => {
|
||||
@ -10,6 +9,15 @@ describe('Collapse', () => {
|
||||
|
||||
const errorSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
|
||||
|
||||
// fix React concurrent
|
||||
function triggerAllTimer() {
|
||||
for (let i = 0; i < 10; i += 1) {
|
||||
act(() => {
|
||||
jest.runAllTimers();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
resetWarned();
|
||||
});
|
||||
@ -23,16 +31,16 @@ describe('Collapse', () => {
|
||||
});
|
||||
|
||||
it('should support remove expandIcon', () => {
|
||||
const wrapper = mount(
|
||||
const { asFragment } = render(
|
||||
<Collapse expandIcon={() => null}>
|
||||
<Collapse.Panel header="header" />
|
||||
</Collapse>,
|
||||
);
|
||||
expect(wrapper.render()).toMatchSnapshot();
|
||||
expect(asFragment().firstChild).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should keep the className of the expandIcon', () => {
|
||||
const wrapper = mount(
|
||||
const { container } = render(
|
||||
<Collapse
|
||||
expandIcon={() => (
|
||||
<button type="button" className="custom-expandicon-classname">
|
||||
@ -44,49 +52,51 @@ describe('Collapse', () => {
|
||||
</Collapse>,
|
||||
);
|
||||
|
||||
expect(wrapper.find('.custom-expandicon-classname').exists()).toBe(true);
|
||||
expect(container.querySelectorAll('.custom-expandicon-classname').length).toBe(1);
|
||||
});
|
||||
|
||||
it('should render extra node of panel', () => {
|
||||
const wrapper = mount(
|
||||
const { asFragment } = render(
|
||||
<Collapse>
|
||||
<Collapse.Panel header="header" extra={<button type="button">action</button>} />
|
||||
<Collapse.Panel header="header" extra={<button type="button">action</button>} />
|
||||
</Collapse>,
|
||||
);
|
||||
expect(wrapper.render()).toMatchSnapshot();
|
||||
expect(asFragment().firstChild).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('could be expand and collapse', async () => {
|
||||
const wrapper = mount(
|
||||
const { container } = render(
|
||||
<Collapse>
|
||||
<Collapse.Panel header="This is panel header 1" key="1">
|
||||
content
|
||||
</Collapse.Panel>
|
||||
</Collapse>,
|
||||
);
|
||||
expect(wrapper.find('.ant-collapse-item').hasClass('ant-collapse-item-active')).toBe(false);
|
||||
wrapper.find('.ant-collapse-header').at(0).simulate('click');
|
||||
wrapper.update();
|
||||
expect(
|
||||
container.querySelector('.ant-collapse-item')?.classList.contains('ant-collapse-item-active'),
|
||||
).toBe(false);
|
||||
fireEvent.click(container.querySelector('.ant-collapse-header')!);
|
||||
await sleep(400);
|
||||
wrapper.update();
|
||||
expect(wrapper.find('.ant-collapse-item').hasClass('ant-collapse-item-active')).toBe(true);
|
||||
expect(
|
||||
container.querySelector('.ant-collapse-item')?.classList.contains('ant-collapse-item-active'),
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
it('could override default openMotion', () => {
|
||||
const wrapper = mount(
|
||||
const { container, asFragment } = render(
|
||||
<Collapse openMotion={{}}>
|
||||
<Collapse.Panel header="This is panel header 1" key="1">
|
||||
content
|
||||
</Collapse.Panel>
|
||||
</Collapse>,
|
||||
);
|
||||
wrapper.find('.ant-collapse-header').at(0).simulate('click');
|
||||
expect(wrapper.render()).toMatchSnapshot();
|
||||
fireEvent.click(container.querySelector('.ant-collapse-header')!);
|
||||
expect(asFragment().firstChild).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should trigger warning and keep compatibility when using disabled in Panel', () => {
|
||||
const wrapper = mount(
|
||||
const { container } = render(
|
||||
<Collapse>
|
||||
<Collapse.Panel disabled header="This is panel header 1" key="1">
|
||||
content
|
||||
@ -98,19 +108,19 @@ describe('Collapse', () => {
|
||||
'Warning: [antd: Collapse.Panel] `disabled` is deprecated. Please use `collapsible="disabled"` instead.',
|
||||
);
|
||||
|
||||
expect(wrapper.find('.ant-collapse-item-disabled').length).toBe(1);
|
||||
expect(container.querySelectorAll('.ant-collapse-item-disabled').length).toBe(1);
|
||||
|
||||
wrapper.find('.ant-collapse-header').simulate('click');
|
||||
expect(wrapper.find('.ant-collapse-item-active').length).toBe(0);
|
||||
fireEvent.click(container.querySelector('.ant-collapse-header')!);
|
||||
expect(container.querySelectorAll('.ant-collapse-item-active').length).toBe(0);
|
||||
});
|
||||
|
||||
it('should end motion when set activeKey while hiding', async () => {
|
||||
jest.useFakeTimers();
|
||||
jest.spyOn(window, 'requestAnimationFrame').mockImplementation(cb => {
|
||||
setTimeout(cb, 16.66);
|
||||
});
|
||||
const spiedRAF = jest
|
||||
.spyOn(window, 'requestAnimationFrame')
|
||||
.mockImplementation(cb => setTimeout(cb, 16.66));
|
||||
|
||||
let setActiveKeyOuter;
|
||||
let setActiveKeyOuter: React.Dispatch<React.SetStateAction<React.Key | undefined>>;
|
||||
const Test = () => {
|
||||
const [activeKey, setActiveKey] = React.useState();
|
||||
setActiveKeyOuter = setActiveKey;
|
||||
@ -125,17 +135,18 @@ describe('Collapse', () => {
|
||||
);
|
||||
};
|
||||
|
||||
const wrapper = mount(<Test />);
|
||||
const { container } = render(<Test />);
|
||||
|
||||
await act(async () => {
|
||||
setActiveKeyOuter('1');
|
||||
await Promise.resolve();
|
||||
jest.runAllTimers();
|
||||
});
|
||||
|
||||
expect(wrapper.render().find('.ant-motion-collapse').length).toBe(0);
|
||||
triggerAllTimer();
|
||||
|
||||
window.requestAnimationFrame.mockRestore();
|
||||
expect(container.querySelectorAll('.ant-motion-collapse').length).toBe(0);
|
||||
|
||||
spiedRAF.mockRestore();
|
||||
jest.useRealTimers();
|
||||
});
|
||||
|
@ -1,10 +1,10 @@
|
||||
import { ArrowDownOutlined, ArrowUpOutlined } from '@ant-design/icons';
|
||||
import { mount } from 'enzyme';
|
||||
import React from 'react';
|
||||
import { ArrowDownOutlined, ArrowUpOutlined } from '@ant-design/icons';
|
||||
import InputNumber from '..';
|
||||
import focusTest from '../../../tests/shared/focusTest';
|
||||
import mountTest from '../../../tests/shared/mountTest';
|
||||
import rtlTest from '../../../tests/shared/rtlTest';
|
||||
import { fireEvent, render } from '../../../tests/utils';
|
||||
|
||||
describe('InputNumber', () => {
|
||||
focusTest(InputNumber, { refFocus: true });
|
||||
@ -14,32 +14,35 @@ describe('InputNumber', () => {
|
||||
// https://github.com/ant-design/ant-design/issues/13896
|
||||
it('should return null when blur a empty input number', () => {
|
||||
const onChange = jest.fn();
|
||||
const wrapper = mount(<InputNumber defaultValue="1" onChange={onChange} />);
|
||||
wrapper.find('input').simulate('change', { target: { value: '' } });
|
||||
const { container } = render(<InputNumber defaultValue="1" onChange={onChange} />);
|
||||
fireEvent.change(container.querySelector('input'), { target: { value: '' } });
|
||||
expect(onChange).toHaveBeenLastCalledWith(null);
|
||||
});
|
||||
|
||||
it('should call onStep when press up or down button', () => {
|
||||
const onStep = jest.fn();
|
||||
const wrapper = mount(<InputNumber defaultValue={1} onStep={onStep} />);
|
||||
wrapper.find('.ant-input-number-handler-up').simulate('mousedown');
|
||||
const { container } = render(<InputNumber defaultValue={1} onStep={onStep} />);
|
||||
fireEvent.mouseDown(container.querySelector('.ant-input-number-handler-up'));
|
||||
expect(onStep).toBeCalledTimes(1);
|
||||
expect(onStep).toHaveBeenLastCalledWith(2, { offset: 1, type: 'up' });
|
||||
wrapper.find('.ant-input-number-handler-down').simulate('mousedown');
|
||||
|
||||
fireEvent.mouseDown(container.querySelector('.ant-input-number-handler-down'));
|
||||
expect(onStep).toBeCalledTimes(2);
|
||||
expect(onStep).toHaveBeenLastCalledWith(1, { offset: 1, type: 'down' });
|
||||
});
|
||||
|
||||
it('renders correctly when controls is boolean', () => {
|
||||
expect(mount(<InputNumber controls={false} />).render()).toMatchSnapshot();
|
||||
const { asFragment } = render(<InputNumber controls={false} />);
|
||||
expect(asFragment().firstChild).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('renders correctly when controls is {}', () => {
|
||||
expect(mount(<InputNumber controls={{}} />).render()).toMatchSnapshot();
|
||||
const { asFragment } = render(<InputNumber controls={{}} />);
|
||||
expect(asFragment().firstChild).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('renders correctly when controls has custom upIcon and downIcon', () => {
|
||||
const wrapper = mount(
|
||||
const { asFragment } = render(
|
||||
<InputNumber
|
||||
controls={{
|
||||
upIcon: <ArrowUpOutlined />,
|
||||
@ -47,11 +50,11 @@ describe('InputNumber', () => {
|
||||
}}
|
||||
/>,
|
||||
);
|
||||
expect(wrapper.render()).toMatchSnapshot();
|
||||
expect(asFragment().firstChild).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should support className', () => {
|
||||
const wrapper = mount(
|
||||
const { container } = render(
|
||||
<InputNumber
|
||||
controls={{
|
||||
upIcon: <ArrowUpOutlined className="my-class-name" />,
|
||||
@ -59,11 +62,11 @@ describe('InputNumber', () => {
|
||||
}}
|
||||
/>,
|
||||
);
|
||||
expect(wrapper.find('.anticon-arrow-up').getDOMNode().className.includes('my-class-name')).toBe(
|
||||
expect(container.querySelector('.anticon-arrow-up')?.className.includes('my-class-name')).toBe(
|
||||
true,
|
||||
);
|
||||
expect(
|
||||
wrapper.find('.anticon-arrow-down').getDOMNode().className.includes('my-class-name'),
|
||||
container.querySelector('.anticon-arrow-down')?.className.includes('my-class-name'),
|
||||
).toBe(true);
|
||||
});
|
||||
});
|
||||
|
@ -1,25 +1,24 @@
|
||||
import { render } from '@testing-library/react';
|
||||
import { mount } from 'enzyme';
|
||||
import React from 'react';
|
||||
import React, { forwardRef } from 'react';
|
||||
import InputNumber from '..';
|
||||
import focusTest from '../../../tests/shared/focusTest';
|
||||
import { fireEvent, render } from '../../../tests/utils';
|
||||
|
||||
describe('prefix', () => {
|
||||
focusTest(
|
||||
React.forwardRef((props, ref) => <InputNumber {...props} prefix="A" ref={ref} />),
|
||||
forwardRef((props, ref) => <InputNumber {...props} prefix="A" ref={ref} />),
|
||||
{ refFocus: true },
|
||||
);
|
||||
it('should support className when has prefix', () => {
|
||||
const { container } = render(<InputNumber prefix="suffix" className="my-class-name" />);
|
||||
expect(container.firstChild.className.includes('my-class-name')).toBe(true);
|
||||
expect(container.firstChild?.className.includes('my-class-name')).toBe(true);
|
||||
expect(container.querySelector('input')?.className.includes('my-class-name')).toBe(false);
|
||||
});
|
||||
|
||||
it('should trigger focus when prefix is clicked', () => {
|
||||
const wrapper = mount(<InputNumber prefix={<i>123</i>} />);
|
||||
const { container } = render(<InputNumber prefix={<i>123</i>} />);
|
||||
|
||||
const mockFocus = jest.spyOn(wrapper.find('input').getDOMNode(), 'focus');
|
||||
wrapper.find('i').simulate('mouseUp');
|
||||
const mockFocus = jest.spyOn(container.querySelector('input'), 'focus');
|
||||
fireEvent.mouseUp(container.querySelector('i'));
|
||||
expect(mockFocus).toBeCalled();
|
||||
});
|
||||
});
|
||||
|
@ -39,7 +39,7 @@ export function resolveOnChange<E extends HTMLInputElement | HTMLTextAreaElement
|
||||
if (!onChange) {
|
||||
return;
|
||||
}
|
||||
let event = e;
|
||||
let event = e as React.ChangeEvent<E>;
|
||||
|
||||
if (e.type === 'click') {
|
||||
// Clone a new target for event.
|
||||
@ -63,7 +63,7 @@ export function resolveOnChange<E extends HTMLInputElement | HTMLTextAreaElement
|
||||
});
|
||||
|
||||
currentTarget.value = '';
|
||||
onChange(event as React.ChangeEvent<E>);
|
||||
onChange(event);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -75,10 +75,10 @@ export function resolveOnChange<E extends HTMLInputElement | HTMLTextAreaElement
|
||||
});
|
||||
|
||||
target.value = targetValue;
|
||||
onChange(event as React.ChangeEvent<E>);
|
||||
onChange(event);
|
||||
return;
|
||||
}
|
||||
onChange(event as React.ChangeEvent<E>);
|
||||
onChange(event);
|
||||
}
|
||||
|
||||
export function triggerFocus(
|
||||
|
@ -119,7 +119,7 @@ The legacy demo code for version `<4.20.0` could be found at [https://github.com
|
||||
#### SubMenuType
|
||||
|
||||
| Param | Description | Type | Default value | Version |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| children | Sub-menus or sub-menu items | [ItemType\[\]](#ItemType) | - | |
|
||||
| disabled | Whether sub-menu is disabled | boolean | false | |
|
||||
| icon | Icon of sub menu | ReactNode | - | |
|
||||
@ -166,3 +166,14 @@ const dividerItem = {
|
||||
### Why will Menu's children be rendered twice?
|
||||
|
||||
Menu collects structure info with [twice-render](https://github.com/react-component/menu/blob/f4684514096d6b7123339cbe72e7b0f68db0bce2/src/Menu.tsx#L543) to support HOC usage. Merging into one render may cause the logic to become much more complex. Contributions to help improve the collection logic are welcomed.
|
||||
|
||||
### Why Menu do not responsive collapse in Flex layout?
|
||||
|
||||
Menu will render fully item in flex layout and then collapse it. You need tell flex not consider Menu width to enable responsive ([online demo](https://codesandbox.io/s/ding-bu-dao-hang-antd-4-21-7-forked-5e3imy?file=/demo.js)):
|
||||
|
||||
```jsx
|
||||
<div style={{ flex }}>
|
||||
<div style={{ ... }}>Some Content</div>
|
||||
<Menu style={{ minWidth: 0, flex: "auto" }} />
|
||||
</div>
|
||||
```
|
||||
|
@ -120,7 +120,7 @@ return <Menu items={items} />;
|
||||
#### SubMenuType
|
||||
|
||||
| 参数 | 说明 | 类型 | 默认值 | 版本 |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| children | 子菜单的菜单项 | [ItemType\[\]](#ItemType) | - | |
|
||||
| disabled | 是否禁用 | boolean | false | |
|
||||
| icon | 菜单图标 | ReactNode | - | |
|
||||
@ -167,3 +167,14 @@ const dividerItem = {
|
||||
### 为何 Menu 的子元素会渲染两次?
|
||||
|
||||
Menu 通过[二次渲染](https://github.com/react-component/menu/blob/f4684514096d6b7123339cbe72e7b0f68db0bce2/src/Menu.tsx#L543)收集嵌套结构信息以支持 HOC 的结构。合并成一个推导结构会使得逻辑变得十分复杂,欢迎 PR 以协助改进该设计。
|
||||
|
||||
### 在 Flex 布局中,Menu 没有按照预期响应式省略菜单?
|
||||
|
||||
Menu 初始化时会先全部渲染,然后根据宽度裁剪内容。当处于 Flex 布局中,你需要告知其预期宽度为响应式宽度([在线 Demo](https://codesandbox.io/s/ding-bu-dao-hang-antd-4-21-7-forked-5e3imy?file=/demo.js)):
|
||||
|
||||
```jsx
|
||||
<div style={{ flex }}>
|
||||
<div style={{ ... }}>Some Content</div>
|
||||
<Menu style={{ minWidth: 0, flex: "auto" }} />
|
||||
</div>
|
||||
```
|
||||
|
@ -305,7 +305,7 @@ describe('Modal.confirm triggers callbacks correctly', () => {
|
||||
});
|
||||
|
||||
describe('should not close modals when click confirm button when onOk has argument', () => {
|
||||
['info', 'success', 'warning', 'error'].forEach(type => {
|
||||
['confirm', 'info', 'success', 'warning', 'error'].forEach(type => {
|
||||
it(type, async () => {
|
||||
jest.useFakeTimers();
|
||||
Modal[type]({
|
||||
@ -318,7 +318,7 @@ describe('Modal.confirm triggers callbacks correctly', () => {
|
||||
await sleep();
|
||||
});
|
||||
expect($$(`.ant-modal-confirm-${type}`)).toHaveLength(1);
|
||||
$$('.ant-btn')[0].click();
|
||||
$$('.ant-btn-primary')[0].click();
|
||||
|
||||
await act(async () => {
|
||||
jest.runAllTimers();
|
||||
@ -674,4 +674,149 @@ describe('Modal.confirm triggers callbacks correctly', () => {
|
||||
const { width } = $$('.ant-modal-body')[0].style;
|
||||
expect(width).toBe('500px');
|
||||
});
|
||||
|
||||
describe('the callback close should be a method when onCancel has a close parameter', () => {
|
||||
['confirm', 'info', 'success', 'warning', 'error'].forEach(type => {
|
||||
it(`click the close icon to trigger ${type} onCancel`, async () => {
|
||||
jest.useFakeTimers();
|
||||
const mock = jest.fn();
|
||||
|
||||
Modal[type]({
|
||||
closable: true,
|
||||
onCancel: close => mock(close),
|
||||
});
|
||||
|
||||
await act(async () => {
|
||||
jest.runAllTimers();
|
||||
await sleep();
|
||||
});
|
||||
|
||||
expect($$(`.ant-modal-confirm-${type}`)).toHaveLength(1);
|
||||
$$('.ant-modal-close')[0].click();
|
||||
|
||||
await act(async () => {
|
||||
jest.runAllTimers();
|
||||
await sleep();
|
||||
});
|
||||
|
||||
expect($$(`.ant-modal-confirm-${type}`)).toHaveLength(0);
|
||||
expect(mock).toBeCalledWith(expect.any(Function));
|
||||
|
||||
jest.useRealTimers();
|
||||
});
|
||||
});
|
||||
|
||||
['confirm', 'info', 'success', 'warning', 'error'].forEach(type => {
|
||||
it(`press ESC to trigger ${type} onCancel`, async () => {
|
||||
jest.useFakeTimers();
|
||||
const mock = jest.fn();
|
||||
|
||||
Modal[type]({
|
||||
keyboard: true,
|
||||
onCancel: close => mock(close),
|
||||
});
|
||||
|
||||
jest.runAllTimers();
|
||||
await sleep();
|
||||
jest.runAllTimers();
|
||||
|
||||
expect($$(`.ant-modal-confirm-${type}`)).toHaveLength(1);
|
||||
TestUtils.Simulate.keyDown($$('.ant-modal')[0], {
|
||||
keyCode: KeyCode.ESC,
|
||||
});
|
||||
|
||||
jest.runAllTimers();
|
||||
await sleep(0);
|
||||
jest.runAllTimers();
|
||||
|
||||
expect($$(`.ant-modal-confirm-${type}`)).toHaveLength(0);
|
||||
expect(mock).toBeCalledWith(expect.any(Function));
|
||||
|
||||
jest.useRealTimers();
|
||||
});
|
||||
});
|
||||
|
||||
['confirm', 'info', 'success', 'warning', 'error'].forEach(type => {
|
||||
it(`click the mask to trigger ${type} onCancel`, async () => {
|
||||
jest.useFakeTimers();
|
||||
const mock = jest.fn();
|
||||
|
||||
Modal[type]({
|
||||
maskClosable: true,
|
||||
onCancel: close => mock(close),
|
||||
});
|
||||
|
||||
await act(async () => {
|
||||
jest.runAllTimers();
|
||||
await sleep();
|
||||
});
|
||||
|
||||
expect($$('.ant-modal-mask')).toHaveLength(1);
|
||||
expect($$(`.ant-modal-confirm-${type}`)).toHaveLength(1);
|
||||
|
||||
$$('.ant-modal-wrap')[0].click();
|
||||
|
||||
await act(async () => {
|
||||
jest.runAllTimers();
|
||||
await sleep();
|
||||
});
|
||||
|
||||
expect($$(`.ant-modal-confirm-${type}`)).toHaveLength(0);
|
||||
expect(mock).toBeCalledWith(expect.any(Function));
|
||||
|
||||
jest.useRealTimers();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('confirm modal click Cancel button close callback is a function', async () => {
|
||||
jest.useFakeTimers();
|
||||
const mock = jest.fn();
|
||||
|
||||
Modal.confirm({
|
||||
onCancel: close => mock(close),
|
||||
});
|
||||
|
||||
await act(async () => {
|
||||
jest.runAllTimers();
|
||||
await sleep();
|
||||
});
|
||||
|
||||
$$('.ant-modal-confirm-btns > .ant-btn')[0].click();
|
||||
|
||||
await act(async () => {
|
||||
jest.runAllTimers();
|
||||
await sleep();
|
||||
});
|
||||
|
||||
expect(mock).toBeCalledWith(expect.any(Function));
|
||||
|
||||
jest.useRealTimers();
|
||||
});
|
||||
|
||||
it('close can close modal when onCancel has a close parameter', async () => {
|
||||
jest.useFakeTimers();
|
||||
|
||||
Modal.confirm({
|
||||
onCancel: close => close(),
|
||||
});
|
||||
|
||||
await act(async () => {
|
||||
jest.runAllTimers();
|
||||
await sleep();
|
||||
});
|
||||
|
||||
expect($$('.ant-modal-confirm-confirm')).toHaveLength(1);
|
||||
|
||||
$$('.ant-modal-confirm-btns > .ant-btn')[0].click();
|
||||
|
||||
await act(async () => {
|
||||
jest.runAllTimers();
|
||||
await sleep();
|
||||
});
|
||||
|
||||
expect($$('.ant-modal-confirm-confirm')).toHaveLength(0);
|
||||
|
||||
jest.useRealTimers();
|
||||
});
|
||||
});
|
||||
|
@ -1,9 +1,11 @@
|
||||
import CSSMotion from 'rc-motion';
|
||||
import { genCSSMotion } from 'rc-motion/lib/CSSMotion';
|
||||
import KeyCode from 'rc-util/lib/KeyCode';
|
||||
import React from 'react';
|
||||
import { act } from 'react-dom/test-utils';
|
||||
import TestUtils, { act } from 'react-dom/test-utils';
|
||||
|
||||
import Modal from '..';
|
||||
import { fireEvent, render } from '../../../tests/utils';
|
||||
import { fireEvent, render, sleep } from '../../../tests/utils';
|
||||
import Button from '../../button';
|
||||
import ConfigProvider from '../../config-provider';
|
||||
import Input from '../../input';
|
||||
@ -193,4 +195,110 @@ describe('Modal.hook', () => {
|
||||
fireEvent.click(container.querySelectorAll('.open-hook-modal-btn')[0]);
|
||||
expect(document.body.classList.contains('ant-modal-confirm-title')).toBeFalsy();
|
||||
});
|
||||
|
||||
it('the callback close should be a method when onCancel has a close parameter', async () => {
|
||||
jest.useFakeTimers();
|
||||
|
||||
const clear = async function clear() {
|
||||
await act(async () => {
|
||||
jest.runAllTimers();
|
||||
await sleep();
|
||||
});
|
||||
};
|
||||
|
||||
const mockFn = jest.fn();
|
||||
const Demo = () => {
|
||||
const [modal, contextHolder] = Modal.useModal();
|
||||
|
||||
const openBrokenModal = React.useCallback(() => {
|
||||
modal.confirm({
|
||||
closable: true,
|
||||
keyboard: true,
|
||||
maskClosable: true,
|
||||
onCancel: close => mockFn(close),
|
||||
});
|
||||
}, [modal]);
|
||||
|
||||
return (
|
||||
<div className="App">
|
||||
{contextHolder}
|
||||
<div className="open-hook-modal-btn" onClick={openBrokenModal}>
|
||||
Test hook modal
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const { container } = render(<Demo />);
|
||||
|
||||
await clear();
|
||||
|
||||
expect(document.body.querySelectorAll('.ant-modal-confirm-confirm')).toHaveLength(0);
|
||||
// First open
|
||||
fireEvent.click(container.querySelectorAll('.open-hook-modal-btn')[0]);
|
||||
await clear();
|
||||
|
||||
expect(document.body.querySelectorAll('.ant-modal-confirm-confirm')).toHaveLength(1);
|
||||
// Click mask to close
|
||||
fireEvent.click(document.body.querySelectorAll('.ant-modal-wrap')[0]);
|
||||
|
||||
await clear();
|
||||
|
||||
expect(document.body.querySelectorAll('.ant-modal-confirm-confirm')).toHaveLength(0);
|
||||
// Second open
|
||||
fireEvent.click(container.querySelectorAll('.open-hook-modal-btn')[0]);
|
||||
|
||||
await clear();
|
||||
|
||||
expect(document.body.querySelectorAll('.ant-modal-confirm-confirm')).toHaveLength(1);
|
||||
// Press ESC to turn off
|
||||
TestUtils.Simulate.keyDown(document.body.querySelectorAll('.ant-modal')[0], {
|
||||
keyCode: KeyCode.ESC,
|
||||
});
|
||||
|
||||
await clear();
|
||||
|
||||
expect(document.body.querySelectorAll('.ant-modal-confirm-confirm')).toHaveLength(0);
|
||||
// Third open
|
||||
fireEvent.click(container.querySelectorAll('.open-hook-modal-btn')[0]);
|
||||
|
||||
await clear();
|
||||
|
||||
expect(document.body.querySelectorAll('.ant-modal-confirm-confirm')).toHaveLength(1);
|
||||
// Click the close icon to close
|
||||
fireEvent.click(document.body.querySelectorAll('.ant-modal-close')[0]);
|
||||
|
||||
await clear();
|
||||
|
||||
expect(document.body.querySelectorAll('.ant-modal-confirm-confirm')).toHaveLength(0);
|
||||
// Last open
|
||||
fireEvent.click(container.querySelectorAll('.open-hook-modal-btn')[0]);
|
||||
|
||||
await clear();
|
||||
|
||||
expect(document.body.querySelectorAll('.ant-modal-confirm-confirm')).toHaveLength(1);
|
||||
|
||||
// Click the Cancel button to close (invalid)
|
||||
fireEvent.click(document.body.querySelectorAll('.ant-modal-confirm-btns > .ant-btn')[0]);
|
||||
|
||||
await clear();
|
||||
|
||||
expect(document.body.querySelectorAll('.ant-modal-confirm-confirm')).toHaveLength(1);
|
||||
|
||||
mockFn.mockImplementation(close => close());
|
||||
|
||||
// Click the Cancel button to close (valid)
|
||||
fireEvent.click(document.body.querySelectorAll('.ant-modal-confirm-btns > .ant-btn')[0]);
|
||||
|
||||
await clear();
|
||||
|
||||
expect(document.body.querySelectorAll('.ant-modal-confirm-confirm')).toHaveLength(0);
|
||||
|
||||
// Close called 5 times
|
||||
expect(mockFn).toHaveBeenCalledTimes(5);
|
||||
|
||||
expect(mockFn.mock.calls).toEqual(Array.from({ length: 5 }, () => [expect.any(Function)]));
|
||||
|
||||
jest.useRealTimers();
|
||||
});
|
||||
});
|
||||
|
@ -34,7 +34,7 @@ export default function confirm(config: ModalFuncProps) {
|
||||
function destroy(...args: any[]) {
|
||||
const triggerCancel = args.some(param => param && param.triggerCancel);
|
||||
if (config.onCancel && triggerCancel) {
|
||||
config.onCancel(...args);
|
||||
config.onCancel(() => {}, ...args.slice(1));
|
||||
}
|
||||
for (let i = 0; i < destroyFns.length; i++) {
|
||||
const fn = destroyFns[i];
|
||||
|
@ -36,7 +36,7 @@ const HookModal: React.ForwardRefRenderFunction<HookModalRef, HookModalProps> =
|
||||
setVisible(false);
|
||||
const triggerCancel = args.some(param => param && param.triggerCancel);
|
||||
if (innerConfig.onCancel && triggerCancel) {
|
||||
innerConfig.onCancel();
|
||||
innerConfig.onCancel(() => {}, ...args.slice(1));
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -25,7 +25,7 @@ exports[`Radio Group passes prefixCls down to radio 1`] = `
|
||||
</label>
|
||||
<label
|
||||
class="my-radio-wrapper"
|
||||
style="font-size:12px"
|
||||
style="font-size: 12px;"
|
||||
>
|
||||
<span
|
||||
class="my-radio"
|
||||
|
@ -29,6 +29,7 @@ exports[`Radio Button should render correctly 1`] = `
|
||||
<input
|
||||
class="ant-radio-button-input"
|
||||
type="radio"
|
||||
value=""
|
||||
/>
|
||||
<span
|
||||
class="ant-radio-button-inner"
|
||||
@ -65,7 +66,7 @@ exports[`Radio Group passes prefixCls down to radio 1`] = `
|
||||
</label>
|
||||
<label
|
||||
class="my-radio-wrapper"
|
||||
style="font-size:12px"
|
||||
style="font-size: 12px;"
|
||||
>
|
||||
<span
|
||||
class="my-radio"
|
||||
|
@ -54,6 +54,7 @@ exports[`Radio should render correctly 1`] = `
|
||||
<input
|
||||
class="ant-radio-input"
|
||||
type="radio"
|
||||
value=""
|
||||
/>
|
||||
<span
|
||||
class="ant-radio-inner"
|
||||
|
@ -1,8 +1,8 @@
|
||||
import React from 'react';
|
||||
import { mount, render } from 'enzyme';
|
||||
import { fireEvent, render as testLibRender } from '@testing-library/react';
|
||||
import Radio from '..';
|
||||
|
||||
import { render, fireEvent } from '../../../tests/utils';
|
||||
|
||||
describe('Radio Group', () => {
|
||||
function createRadioGroup(props) {
|
||||
return (
|
||||
@ -28,32 +28,37 @@ describe('Radio Group', () => {
|
||||
const onMouseEnter = jest.fn();
|
||||
const onMouseLeave = jest.fn();
|
||||
|
||||
const wrapper = mount(
|
||||
const { container } = render(
|
||||
<Radio.Group onMouseEnter={onMouseEnter} onMouseLeave={onMouseLeave}>
|
||||
<Radio />
|
||||
</Radio.Group>,
|
||||
);
|
||||
|
||||
wrapper.find('div').at(0).simulate('mouseenter');
|
||||
fireEvent.mouseEnter(container.querySelector('div'));
|
||||
expect(onMouseEnter).toHaveBeenCalled();
|
||||
|
||||
wrapper.find('div').at(0).simulate('mouseleave');
|
||||
fireEvent.mouseLeave(container.querySelector('div'));
|
||||
expect(onMouseLeave).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('fire change events when value changes', () => {
|
||||
const onChange = jest.fn();
|
||||
|
||||
const wrapper = mount(
|
||||
const { container, rerender } = render(
|
||||
createRadioGroup({
|
||||
onChange,
|
||||
}),
|
||||
);
|
||||
const radios = wrapper.find('input');
|
||||
const radios = container.querySelectorAll('input');
|
||||
|
||||
// controlled component
|
||||
wrapper.setProps({ value: 'A' });
|
||||
radios.at(1).simulate('change');
|
||||
rerender(
|
||||
createRadioGroup({
|
||||
onChange,
|
||||
value: 'A',
|
||||
}),
|
||||
);
|
||||
fireEvent.click(radios[1]);
|
||||
expect(onChange.mock.calls.length).toBe(1);
|
||||
});
|
||||
|
||||
@ -61,83 +66,95 @@ describe('Radio Group', () => {
|
||||
const onChange = jest.fn();
|
||||
const onChangeRadioGroup = jest.fn();
|
||||
|
||||
const wrapper = mount(
|
||||
<Radio.Group onChange={onChangeRadioGroup}>
|
||||
<Radio value="A" onChange={onChange}>
|
||||
const RadioGroup = props => (
|
||||
<Radio.Group onChange={props.onChangeRadioGroup}>
|
||||
<Radio value="A" onChange={props.onChange}>
|
||||
A
|
||||
</Radio>
|
||||
<Radio value="B" onChange={onChange}>
|
||||
<Radio value="B" onChange={props.onChange}>
|
||||
B
|
||||
</Radio>
|
||||
<Radio value="C" onChange={onChange}>
|
||||
<Radio value="C" onChange={props.onChange}>
|
||||
C
|
||||
</Radio>
|
||||
</Radio.Group>,
|
||||
</Radio.Group>
|
||||
);
|
||||
const radios = wrapper.find('input');
|
||||
|
||||
const { container, rerender } = render(
|
||||
<RadioGroup onChangeRadioGroup={onChangeRadioGroup} onChange={onChange} />,
|
||||
);
|
||||
const radios = container.querySelectorAll('input');
|
||||
|
||||
// controlled component
|
||||
wrapper.setProps({ value: 'A' });
|
||||
radios.at(1).simulate('change');
|
||||
rerender(<RadioGroup value="A" onChangeRadioGroup={onChangeRadioGroup} onChange={onChange} />);
|
||||
fireEvent.click(radios[1]);
|
||||
expect(onChange.mock.calls.length).toBe(1);
|
||||
expect(onChangeRadioGroup.mock.calls.length).toBe(1);
|
||||
});
|
||||
|
||||
it('Trigger onChange when both of radioButton and radioGroup exists', () => {
|
||||
const onChange = jest.fn();
|
||||
|
||||
const wrapper = mount(
|
||||
<Radio.Group onChange={onChange}>
|
||||
const RadioGroup = props => (
|
||||
<Radio.Group {...props}>
|
||||
<Radio.Button value="A">A</Radio.Button>
|
||||
<Radio.Button value="B">B</Radio.Button>
|
||||
<Radio.Button value="C">C</Radio.Button>
|
||||
</Radio.Group>,
|
||||
</Radio.Group>
|
||||
);
|
||||
const radios = wrapper.find('input');
|
||||
|
||||
const { container, rerender } = render(<RadioGroup onChange={onChange} />);
|
||||
const radios = container.querySelectorAll('input');
|
||||
|
||||
// controlled component
|
||||
wrapper.setProps({ value: 'A' });
|
||||
radios.at(1).simulate('change');
|
||||
rerender(<RadioGroup value="A" onChange={onChange} />);
|
||||
fireEvent.click(radios[1]);
|
||||
expect(onChange.mock.calls.length).toBe(1);
|
||||
});
|
||||
|
||||
it('should only trigger once when in group with options', () => {
|
||||
const onChange = jest.fn();
|
||||
const options = [{ label: 'Bamboo', value: 'Bamboo' }];
|
||||
const wrapper = mount(<Radio.Group options={options} onChange={onChange} />);
|
||||
const { container } = render(<Radio.Group options={options} onChange={onChange} />);
|
||||
|
||||
wrapper.find('input').simulate('change');
|
||||
fireEvent.click(container.querySelector('input'));
|
||||
expect(onChange).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it("won't fire change events when value not changes", () => {
|
||||
const onChange = jest.fn();
|
||||
|
||||
const wrapper = mount(
|
||||
const { container, rerender } = render(
|
||||
createRadioGroup({
|
||||
onChange,
|
||||
}),
|
||||
);
|
||||
const radios = wrapper.find('input');
|
||||
const radios = container.querySelectorAll('input');
|
||||
|
||||
// controlled component
|
||||
wrapper.setProps({ value: 'A' });
|
||||
radios.at(0).simulate('change');
|
||||
rerender(
|
||||
createRadioGroup({
|
||||
onChange,
|
||||
value: 'A',
|
||||
}),
|
||||
);
|
||||
fireEvent.click(radios[0]);
|
||||
expect(onChange.mock.calls.length).toBe(0);
|
||||
});
|
||||
|
||||
it('optional should correct render', () => {
|
||||
const wrapper = mount(createRadioGroupByOption());
|
||||
const radios = wrapper.find('input');
|
||||
const { container } = render(createRadioGroupByOption());
|
||||
const radios = container.querySelectorAll('input');
|
||||
|
||||
expect(radios.length).toBe(3);
|
||||
});
|
||||
|
||||
it('all children should have a name property', () => {
|
||||
const GROUP_NAME = 'radiogroup';
|
||||
const wrapper = mount(createRadioGroup({ name: GROUP_NAME }));
|
||||
const GROUP_NAME = 'GROUP_NAME';
|
||||
const { container } = render(createRadioGroup({ name: GROUP_NAME }));
|
||||
|
||||
wrapper.find('input[type="radio"]').forEach(el => {
|
||||
expect(el.props().name).toEqual(GROUP_NAME);
|
||||
container.querySelectorAll('input[type="radio"]').forEach(el => {
|
||||
expect(el.name).toEqual(GROUP_NAME);
|
||||
});
|
||||
});
|
||||
|
||||
@ -146,13 +163,13 @@ describe('Radio Group', () => {
|
||||
{ label: 'Apple', value: 'Apple' },
|
||||
{ label: 'Orange', value: 'Orange', style: { fontSize: 12 } },
|
||||
];
|
||||
const wrapper = render(<Radio.Group prefixCls="my-radio" options={options} />);
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
const { container } = render(<Radio.Group prefixCls="my-radio" options={options} />);
|
||||
expect(container.firstChild).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should forward ref', () => {
|
||||
let radioGroupRef;
|
||||
const { container } = testLibRender(
|
||||
const { container } = render(
|
||||
createRadioGroupByOption({
|
||||
ref: ref => {
|
||||
radioGroupRef = ref;
|
||||
@ -164,7 +181,7 @@ describe('Radio Group', () => {
|
||||
});
|
||||
|
||||
it('should support data-* or aria-* props', () => {
|
||||
const { container } = testLibRender(
|
||||
const { container } = render(
|
||||
createRadioGroup({
|
||||
'data-radio-group-id': 'radio-group-id',
|
||||
'aria-label': 'radio-group',
|
||||
@ -176,7 +193,7 @@ describe('Radio Group', () => {
|
||||
|
||||
it('Radio type should not be override', () => {
|
||||
const onChange = jest.fn();
|
||||
const wrapper = mount(
|
||||
const { container } = render(
|
||||
<Radio.Group onChange={onChange}>
|
||||
<Radio value={1} type="1">
|
||||
A
|
||||
@ -192,35 +209,28 @@ describe('Radio Group', () => {
|
||||
</Radio>
|
||||
</Radio.Group>,
|
||||
);
|
||||
const radios = wrapper.find('input');
|
||||
radios.at(1).simulate('change');
|
||||
const radios = container.querySelectorAll('input');
|
||||
fireEvent.click(radios[0]);
|
||||
expect(onChange).toHaveBeenCalled();
|
||||
expect(radios.at(1).getDOMNode().type).toBe('radio');
|
||||
expect(radios[1].type).toBe('radio');
|
||||
});
|
||||
|
||||
describe('value is null or undefined', () => {
|
||||
it('use `defaultValue` when `value` is undefined', () => {
|
||||
const options = [{ label: 'Bamboo', value: 'bamboo' }];
|
||||
const wrapper = mount(
|
||||
const { container } = render(
|
||||
<Radio.Group defaultValue="bamboo" value={undefined} options={options} />,
|
||||
);
|
||||
expect(wrapper.find('.ant-radio-wrapper').at(0).hasClass('ant-radio-wrapper-checked')).toBe(
|
||||
true,
|
||||
);
|
||||
expect(container.querySelectorAll('.ant-radio-wrapper-checked').length).toBe(1);
|
||||
});
|
||||
|
||||
[undefined, null].forEach(newValue => {
|
||||
it(`should set value back when value change back to ${newValue}`, () => {
|
||||
const options = [{ label: 'Bamboo', value: 'bamboo' }];
|
||||
const wrapper = mount(<Radio.Group value="bamboo" options={options} />);
|
||||
expect(wrapper.find('.ant-radio-wrapper').at(0).hasClass('ant-radio-wrapper-checked')).toBe(
|
||||
true,
|
||||
);
|
||||
wrapper.setProps({ value: newValue });
|
||||
wrapper.update();
|
||||
expect(wrapper.find('.ant-radio-wrapper').at(0).hasClass('ant-radio-wrapper-checked')).toBe(
|
||||
false,
|
||||
);
|
||||
const { container, rerender } = render(<Radio.Group value="bamboo" options={options} />);
|
||||
expect(container.querySelectorAll('.ant-radio-wrapper-checked').length).toBe(1);
|
||||
rerender(<Radio.Group value={newValue} options={options} />);
|
||||
expect(container.querySelectorAll('.ant-radio-wrapper-checked').length).toBe(0);
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -228,7 +238,7 @@ describe('Radio Group', () => {
|
||||
it('onBlur & onFocus should work', () => {
|
||||
const handleBlur = jest.fn();
|
||||
const handleFocus = jest.fn();
|
||||
const { container } = testLibRender(
|
||||
const { container } = render(
|
||||
<Radio.Group options={['1', '2', '3']} onBlur={handleBlur} onFocus={handleFocus} />,
|
||||
);
|
||||
fireEvent.focus(container.firstChild);
|
||||
|
@ -1,11 +1,11 @@
|
||||
import { render as testLibRender } from '@testing-library/react';
|
||||
import { mount, render } from 'enzyme';
|
||||
import React from 'react';
|
||||
import Radio, { Button } from '..';
|
||||
import focusTest from '../../../tests/shared/focusTest';
|
||||
import mountTest from '../../../tests/shared/mountTest';
|
||||
import rtlTest from '../../../tests/shared/rtlTest';
|
||||
|
||||
import { render, fireEvent } from '../../../tests/utils';
|
||||
|
||||
describe('Radio Button', () => {
|
||||
focusTest(Button, { refFocus: true });
|
||||
mountTest(Button);
|
||||
@ -13,20 +13,22 @@ describe('Radio Button', () => {
|
||||
rtlTest(Button);
|
||||
|
||||
it('should render correctly', () => {
|
||||
const wrapper = render(<Button className="customized">Test</Button>);
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
const { container } = render(<Button className="customized">Test</Button>);
|
||||
expect(container.firstChild).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('responses hover events', () => {
|
||||
const onMouseEnter = jest.fn();
|
||||
const onMouseLeave = jest.fn();
|
||||
|
||||
const wrapper = mount(<Button onMouseEnter={onMouseEnter} onMouseLeave={onMouseLeave} />);
|
||||
const { container } = render(
|
||||
<Button onMouseEnter={onMouseEnter} onMouseLeave={onMouseLeave} />,
|
||||
);
|
||||
|
||||
wrapper.find('label').simulate('mouseenter');
|
||||
fireEvent.mouseEnter(container.querySelector('label'));
|
||||
expect(onMouseEnter).toHaveBeenCalled();
|
||||
|
||||
wrapper.find('label').simulate('mouseleave');
|
||||
fireEvent.mouseLeave(container.querySelector('label'));
|
||||
expect(onMouseLeave).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
@ -46,32 +48,29 @@ describe('Radio Group', () => {
|
||||
const onMouseEnter = jest.fn();
|
||||
const onMouseLeave = jest.fn();
|
||||
|
||||
const wrapper = mount(
|
||||
const { container } = render(
|
||||
<Radio.Group onMouseEnter={onMouseEnter} onMouseLeave={onMouseLeave}>
|
||||
<Radio />
|
||||
</Radio.Group>,
|
||||
);
|
||||
|
||||
wrapper.find('div').at(0).simulate('mouseenter');
|
||||
fireEvent.mouseEnter(container.querySelectorAll('div')[0]);
|
||||
expect(onMouseEnter).toHaveBeenCalled();
|
||||
|
||||
wrapper.find('div').at(0).simulate('mouseleave');
|
||||
fireEvent.mouseLeave(container.querySelectorAll('div')[0]);
|
||||
expect(onMouseLeave).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('fire change events when value changes', () => {
|
||||
const onChange = jest.fn();
|
||||
|
||||
const wrapper = mount(
|
||||
createRadioGroup({
|
||||
onChange,
|
||||
}),
|
||||
);
|
||||
const radios = wrapper.find('input');
|
||||
const { container, rerender } = render(createRadioGroup({ onChange }));
|
||||
|
||||
const radios = container.querySelectorAll('input');
|
||||
|
||||
// controlled component
|
||||
wrapper.setProps({ value: 'A' });
|
||||
radios.at(1).simulate('change');
|
||||
rerender(createRadioGroup({ onChange, value: 'A' }));
|
||||
fireEvent.click(radios[1]);
|
||||
expect(onChange.mock.calls.length).toBe(1);
|
||||
});
|
||||
|
||||
@ -79,7 +78,7 @@ describe('Radio Group', () => {
|
||||
const onChange = jest.fn();
|
||||
const onChangeRadioGroup = jest.fn();
|
||||
|
||||
const wrapper = mount(
|
||||
const { container } = render(
|
||||
<Radio.Group onChange={onChangeRadioGroup}>
|
||||
<Radio value="A" onChange={onChange}>
|
||||
A
|
||||
@ -92,63 +91,69 @@ describe('Radio Group', () => {
|
||||
</Radio>
|
||||
</Radio.Group>,
|
||||
);
|
||||
const radios = wrapper.find('input');
|
||||
const radios = container.querySelectorAll('input');
|
||||
|
||||
// controlled component
|
||||
wrapper.setProps({ value: 'A' });
|
||||
radios.at(1).simulate('change');
|
||||
fireEvent.click(radios[1]);
|
||||
expect(onChange.mock.calls.length).toBe(1);
|
||||
expect(onChangeRadioGroup.mock.calls.length).toBe(1);
|
||||
});
|
||||
|
||||
it('Trigger onChange when both of Button and radioGroup exists', () => {
|
||||
const onChange = jest.fn();
|
||||
|
||||
const wrapper = mount(
|
||||
const { container, rerender } = render(
|
||||
<Radio.Group onChange={onChange}>
|
||||
<Button value="A">A</Button>
|
||||
<Button value="B">B</Button>
|
||||
<Button value="C">C</Button>
|
||||
</Radio.Group>,
|
||||
);
|
||||
const radios = wrapper.find('input');
|
||||
const radios = container.querySelectorAll('input');
|
||||
|
||||
// controlled component
|
||||
wrapper.setProps({ value: 'A' });
|
||||
radios.at(1).simulate('change');
|
||||
rerender(
|
||||
<Radio.Group value="A" onChange={onChange}>
|
||||
<Button value="A">A</Button>
|
||||
<Button value="B">B</Button>
|
||||
<Button value="C">C</Button>
|
||||
</Radio.Group>,
|
||||
);
|
||||
fireEvent.click(radios[1]);
|
||||
expect(onChange.mock.calls.length).toBe(1);
|
||||
});
|
||||
|
||||
it('should only trigger once when in group with options', () => {
|
||||
const onChange = jest.fn();
|
||||
const options = [{ label: 'Bamboo', value: 'Bamboo' }];
|
||||
const wrapper = mount(<Radio.Group options={options} onChange={onChange} />);
|
||||
const { container } = render(<Radio.Group options={options} onChange={onChange} />);
|
||||
|
||||
wrapper.find('input').simulate('change');
|
||||
fireEvent.click(container.querySelector('input'));
|
||||
expect(onChange).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it("won't fire change events when value not changes", () => {
|
||||
const onChange = jest.fn();
|
||||
|
||||
const wrapper = mount(
|
||||
const { container, rerender } = render(
|
||||
createRadioGroup({
|
||||
onChange,
|
||||
}),
|
||||
);
|
||||
const radios = wrapper.find('input');
|
||||
const radios = container.querySelectorAll('input');
|
||||
|
||||
// controlled component
|
||||
wrapper.setProps({ value: 'A' });
|
||||
radios.at(0).simulate('change');
|
||||
rerender(createRadioGroup({ onChange, value: 'A' }));
|
||||
fireEvent.click(radios[0]);
|
||||
expect(onChange.mock.calls.length).toBe(0);
|
||||
});
|
||||
|
||||
it('all children should have a name property', () => {
|
||||
const GROUP_NAME = 'radiogroup';
|
||||
const wrapper = mount(createRadioGroup({ name: GROUP_NAME }));
|
||||
const GROUP_NAME = 'GROUP_NAME';
|
||||
const { container } = render(createRadioGroup({ name: GROUP_NAME }));
|
||||
|
||||
wrapper.find('input[type="radio"]').forEach(el => {
|
||||
expect(el.props().name).toEqual(GROUP_NAME);
|
||||
container.querySelectorAll('input[type="radio"]').forEach(el => {
|
||||
expect(el.name).toEqual(GROUP_NAME);
|
||||
});
|
||||
});
|
||||
|
||||
@ -157,13 +162,13 @@ describe('Radio Group', () => {
|
||||
{ label: 'Apple', value: 'Apple' },
|
||||
{ label: 'Orange', value: 'Orange', style: { fontSize: 12 } },
|
||||
];
|
||||
const wrapper = render(<Radio.Group prefixCls="my-radio" options={options} />);
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
const { container } = render(<Radio.Group prefixCls="my-radio" options={options} />);
|
||||
expect(container.firstChild).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should forward ref', () => {
|
||||
let radioGroupRef;
|
||||
const { container } = testLibRender(
|
||||
const { container } = render(
|
||||
createRadioGroup({
|
||||
ref: ref => {
|
||||
radioGroupRef = ref;
|
||||
@ -175,7 +180,7 @@ describe('Radio Group', () => {
|
||||
});
|
||||
|
||||
it('should support data-* or aria-* props', () => {
|
||||
const { container } = testLibRender(
|
||||
const { container } = render(
|
||||
createRadioGroup({
|
||||
'data-radio-group-id': 'radio-group-id',
|
||||
'aria-label': 'radio-group',
|
||||
@ -187,7 +192,7 @@ describe('Radio Group', () => {
|
||||
|
||||
it('Radio type should not be override', () => {
|
||||
const onChange = jest.fn();
|
||||
const wrapper = mount(
|
||||
const { container } = render(
|
||||
<Radio.Group onChange={onChange}>
|
||||
<Radio value={1} type="1">
|
||||
A
|
||||
@ -203,48 +208,36 @@ describe('Radio Group', () => {
|
||||
</Radio>
|
||||
</Radio.Group>,
|
||||
);
|
||||
const radios = wrapper.find('input');
|
||||
radios.at(1).simulate('change');
|
||||
const radios = container.querySelectorAll('input');
|
||||
fireEvent.click(radios[0]);
|
||||
expect(onChange).toHaveBeenCalled();
|
||||
expect(radios.at(1).getDOMNode().type).toBe('radio');
|
||||
expect(radios[1].type).toBe('radio');
|
||||
});
|
||||
|
||||
describe('value is null or undefined', () => {
|
||||
it('use `defaultValue` when `value` is undefined', () => {
|
||||
const wrapper = mount(
|
||||
const { container } = render(
|
||||
<Radio.Group defaultValue="bamboo" value={undefined}>
|
||||
<Button value="bamboo">Bamboo</Button>
|
||||
</Radio.Group>,
|
||||
);
|
||||
expect(
|
||||
wrapper
|
||||
.find('.ant-radio-button-wrapper')
|
||||
.at(0)
|
||||
.hasClass('ant-radio-button-wrapper-checked'),
|
||||
).toBe(true);
|
||||
expect(container.querySelectorAll('.ant-radio-button-wrapper-checked').length).toBe(1);
|
||||
});
|
||||
|
||||
[undefined, null].forEach(newValue => {
|
||||
it(`should set value back when value change back to ${newValue}`, () => {
|
||||
const wrapper = mount(
|
||||
const { container, rerender } = render(
|
||||
<Radio.Group value="bamboo">
|
||||
<Button value="bamboo">Bamboo</Button>
|
||||
</Radio.Group>,
|
||||
);
|
||||
expect(
|
||||
wrapper
|
||||
.find('.ant-radio-button-wrapper')
|
||||
.at(0)
|
||||
.hasClass('ant-radio-button-wrapper-checked'),
|
||||
).toBe(true);
|
||||
wrapper.setProps({ value: newValue });
|
||||
wrapper.update();
|
||||
expect(
|
||||
wrapper
|
||||
.find('.ant-radio-button-wrapper')
|
||||
.at(0)
|
||||
.hasClass('ant-radio-button-wrapper-checked'),
|
||||
).toBe(false);
|
||||
expect(container.querySelectorAll('.ant-radio-button-wrapper-checked').length).toBe(1);
|
||||
rerender(
|
||||
<Radio.Group value={newValue}>
|
||||
<Button value="bamboo">Bamboo</Button>
|
||||
</Radio.Group>,
|
||||
);
|
||||
expect(container.querySelectorAll('.ant-radio-button-wrapper-checked').length).toBe(0);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -1,10 +1,11 @@
|
||||
import { mount, render } from 'enzyme';
|
||||
import React from 'react';
|
||||
import Radio, { Button, Group } from '..';
|
||||
import focusTest from '../../../tests/shared/focusTest';
|
||||
import mountTest from '../../../tests/shared/mountTest';
|
||||
import rtlTest from '../../../tests/shared/rtlTest';
|
||||
|
||||
import { render, fireEvent } from '../../../tests/utils';
|
||||
|
||||
describe('Radio', () => {
|
||||
focusTest(Radio, { refFocus: true });
|
||||
mountTest(Radio);
|
||||
@ -16,20 +17,20 @@ describe('Radio', () => {
|
||||
rtlTest(Button);
|
||||
|
||||
it('should render correctly', () => {
|
||||
const wrapper = render(<Radio className="customized">Test</Radio>);
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
const { container } = render(<Radio className="customized">Test</Radio>);
|
||||
expect(container.firstChild).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('responses hover events', () => {
|
||||
const onMouseEnter = jest.fn();
|
||||
const onMouseLeave = jest.fn();
|
||||
|
||||
const wrapper = mount(<Radio onMouseEnter={onMouseEnter} onMouseLeave={onMouseLeave} />);
|
||||
const { container } = render(<Radio onMouseEnter={onMouseEnter} onMouseLeave={onMouseLeave} />);
|
||||
|
||||
wrapper.find('label').simulate('mouseenter');
|
||||
fireEvent.mouseEnter(container.querySelector('label'));
|
||||
expect(onMouseEnter).toHaveBeenCalled();
|
||||
|
||||
wrapper.find('label').simulate('mouseleave');
|
||||
fireEvent.mouseLeave(container.querySelector('label'));
|
||||
expect(onMouseLeave).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
@ -1665,9 +1665,9 @@ exports[`renders ./components/select/demo/custom-dropdown-menu.md extend context
|
||||
<div
|
||||
class="ant-space-item"
|
||||
>
|
||||
<a
|
||||
class="ant-typography"
|
||||
style="white-space:nowrap"
|
||||
<button
|
||||
class="ant-btn ant-btn-text"
|
||||
type="button"
|
||||
>
|
||||
<span
|
||||
aria-label="plus"
|
||||
@ -1692,8 +1692,10 @@ exports[`renders ./components/select/demo/custom-dropdown-menu.md extend context
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
Add item
|
||||
</a>
|
||||
<span>
|
||||
Add item
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -7,16 +7,17 @@ title:
|
||||
|
||||
## zh-CN
|
||||
|
||||
使用 `dropdownRender` 对下拉菜单进行自由扩展。自定义内容点击时会关闭浮层,如果不喜欢关闭,可以添加 `onMouseDown={e => e.preventDefault()}` 进行阻止(更多详情见 [#13448](https://github.com/ant-design/ant-design/issues/13448))。
|
||||
使用 `open` 对下拉菜单进行自由扩展。如果希望点击自定义内容后关闭浮层,你需要使用受控模式自行控制([codesandbox](https://codesandbox.io/s/ji-ben-shi-yong-antd-4-21-7-forked-gnp4cy?file=/demo.js))。
|
||||
|
||||
## en-US
|
||||
|
||||
Customize the dropdown menu via `dropdownRender`. Dropdown menu will be closed if click `dropdownRender` area, you can prevent it by wrapping `onMouseDown={e => e.preventDefault()}` (see more at [#13448](https://github.com/ant-design/ant-design/issues/13448)).
|
||||
Customize the dropdown menu via `dropdownRender`. If you want to close the dropdown after clicking the custom content, you need to control `open` prop, here is an [codesandbox](https://codesandbox.io/s/ji-ben-shi-yong-antd-4-21-7-forked-gnp4cy?file=/demo.js).
|
||||
|
||||
```tsx
|
||||
import { PlusOutlined } from '@ant-design/icons';
|
||||
import { Divider, Input, Select, Space, Typography } from 'antd';
|
||||
import React, { useState } from 'react';
|
||||
import { Divider, Input, Select, Space, Button } from 'antd';
|
||||
import type { InputRef } from 'antd';
|
||||
import React, { useState, useRef } from 'react';
|
||||
|
||||
const { Option } = Select;
|
||||
|
||||
@ -25,6 +26,7 @@ let index = 0;
|
||||
const App: React.FC = () => {
|
||||
const [items, setItems] = useState(['jack', 'lucy']);
|
||||
const [name, setName] = useState('');
|
||||
const inputRef = useRef<InputRef>(null);
|
||||
|
||||
const onNameChange = (event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
setName(event.target.value);
|
||||
@ -34,6 +36,9 @@ const App: React.FC = () => {
|
||||
e.preventDefault();
|
||||
setItems([...items, name || `New item ${index++}`]);
|
||||
setName('');
|
||||
setTimeout(() => {
|
||||
inputRef.current?.focus();
|
||||
}, 0);
|
||||
};
|
||||
|
||||
return (
|
||||
@ -44,11 +49,16 @@ const App: React.FC = () => {
|
||||
<>
|
||||
{menu}
|
||||
<Divider style={{ margin: '8px 0' }} />
|
||||
<Space align="center" style={{ padding: '0 8px 4px' }}>
|
||||
<Input placeholder="Please enter item" value={name} onChange={onNameChange} />
|
||||
<Typography.Link onClick={addItem} style={{ whiteSpace: 'nowrap' }}>
|
||||
<PlusOutlined /> Add item
|
||||
</Typography.Link>
|
||||
<Space style={{ padding: '0 8px 4px' }}>
|
||||
<Input
|
||||
placeholder="Please enter item"
|
||||
ref={inputRef}
|
||||
value={name}
|
||||
onChange={onNameChange}
|
||||
/>
|
||||
<Button type="text" icon={<PlusOutlined />} onClick={addItem}>
|
||||
Add item
|
||||
</Button>
|
||||
</Space>
|
||||
</>
|
||||
)}
|
||||
|
@ -111,15 +111,15 @@ Select component to select value from options.
|
||||
|
||||
It's caused by option with different `label` and `value`. You can use `optionFilterProp="label"` to change filter logic instead.
|
||||
|
||||
### The dropdown is closed when click `dropdownRender` area?
|
||||
### When I click elements in dropdownRender, the select dropdown will not be closed?
|
||||
|
||||
Dropdown menu will be closed if click `dropdownRender` area, you can prevent it by wrapping `onMouseDown={e => e.preventDefault()}` (see more at [#13448](https://github.com/ant-design/ant-design/issues/13448)).
|
||||
You can control it by `open` prop: [codesandbox](https://codesandbox.io/s/ji-ben-shi-yong-antd-4-21-7-forked-gnp4cy?file=/demo.js).
|
||||
|
||||
### Why sometime customize Option cause scroll break?
|
||||
|
||||
Virtual scroll internal set item height as `32px`. You need to adjust `listItemHeight` when your option height is less and `listHeight` config list container height:
|
||||
|
||||
```tsx
|
||||
```jsx
|
||||
<Select listItemHeight={10} listHeight={250} />
|
||||
```
|
||||
|
||||
|
@ -112,9 +112,9 @@ cover: https://gw.alipayobjects.com/zos/alicdn/_0XzgOis7/Select.svg
|
||||
|
||||
这一般是 `options` 中的 `label` 和 `value` 不同导致的,你可以通过 `optionFilterProp="label"` 将过滤设置为展示值以避免这种情况。
|
||||
|
||||
### 点击 `dropdownRender` 里的内容浮层关闭怎么办?
|
||||
### 点击 `dropdownRender` 里的元素,下拉菜单不会自动消失?
|
||||
|
||||
自定义内容点击时会关闭浮层,如果不喜欢关闭,可以添加 `onMouseDown={e => e.preventDefault()}` 进行阻止(更多详情见 [#13448](https://github.com/ant-design/ant-design/issues/13448))。
|
||||
你可以使用受控模式,手动设置 `open` 属性:[codesandbox](https://codesandbox.io/s/ji-ben-shi-yong-antd-4-21-7-forked-gnp4cy?file=/demo.js)。
|
||||
|
||||
### 自定义 Option 样式导致滚动异常怎么办?
|
||||
|
||||
|
@ -26637,6 +26637,709 @@ Array [
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`renders ./components/table/demo/tree-table-ellipsis.md extend context correctly 1`] = `
|
||||
Array [
|
||||
<div
|
||||
class="ant-space ant-space-horizontal ant-space-align-center"
|
||||
style="margin-bottom:16px"
|
||||
>
|
||||
<div
|
||||
class="ant-space-item"
|
||||
style="margin-right:8px"
|
||||
>
|
||||
Fixed first column:
|
||||
</div>
|
||||
<div
|
||||
class="ant-space-item"
|
||||
>
|
||||
<button
|
||||
aria-checked="true"
|
||||
class="ant-switch ant-switch-checked"
|
||||
role="switch"
|
||||
type="button"
|
||||
>
|
||||
<div
|
||||
class="ant-switch-handle"
|
||||
/>
|
||||
<span
|
||||
class="ant-switch-inner"
|
||||
/>
|
||||
</button>
|
||||
</div>
|
||||
</div>,
|
||||
<div
|
||||
class="ant-table-wrapper"
|
||||
>
|
||||
<div
|
||||
class="ant-spin-nested-loading"
|
||||
>
|
||||
<div
|
||||
class="ant-spin-container"
|
||||
>
|
||||
<div
|
||||
class="ant-table ant-table-has-fix-left"
|
||||
>
|
||||
<div
|
||||
class="ant-table-container"
|
||||
>
|
||||
<div
|
||||
class="ant-table-content"
|
||||
>
|
||||
<table
|
||||
style="table-layout:fixed"
|
||||
>
|
||||
<colgroup>
|
||||
<col
|
||||
class="ant-table-selection-col"
|
||||
style="width:100px"
|
||||
/>
|
||||
<col
|
||||
style="width:30%"
|
||||
/>
|
||||
<col
|
||||
style="width:12%"
|
||||
/>
|
||||
</colgroup>
|
||||
<thead
|
||||
class="ant-table-thead"
|
||||
>
|
||||
<tr>
|
||||
<th
|
||||
class="ant-table-cell ant-table-selection-column ant-table-cell-fix-left"
|
||||
style="position:sticky;left:0"
|
||||
>
|
||||
<div
|
||||
class="ant-table-selection"
|
||||
>
|
||||
<label
|
||||
class="ant-checkbox-wrapper"
|
||||
>
|
||||
<span
|
||||
class="ant-checkbox"
|
||||
>
|
||||
<input
|
||||
class="ant-checkbox-input"
|
||||
type="checkbox"
|
||||
/>
|
||||
<span
|
||||
class="ant-checkbox-inner"
|
||||
/>
|
||||
</span>
|
||||
</label>
|
||||
</div>
|
||||
</th>
|
||||
<th
|
||||
class="ant-table-cell ant-table-cell-fix-left ant-table-cell-fix-left-last ant-table-cell-ellipsis"
|
||||
style="position:sticky;left:0"
|
||||
title="Name"
|
||||
>
|
||||
<span
|
||||
class="ant-table-cell-content"
|
||||
>
|
||||
Name
|
||||
</span>
|
||||
</th>
|
||||
<th
|
||||
class="ant-table-cell"
|
||||
>
|
||||
Age
|
||||
</th>
|
||||
<th
|
||||
class="ant-table-cell"
|
||||
>
|
||||
Address
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody
|
||||
class="ant-table-tbody"
|
||||
>
|
||||
<tr
|
||||
class="ant-table-row ant-table-row-level-0"
|
||||
data-row-key="1"
|
||||
>
|
||||
<td
|
||||
class="ant-table-cell ant-table-selection-column ant-table-cell-fix-left"
|
||||
style="position:sticky;left:0"
|
||||
>
|
||||
<label
|
||||
class="ant-checkbox-wrapper"
|
||||
>
|
||||
<span
|
||||
class="ant-checkbox"
|
||||
>
|
||||
<input
|
||||
class="ant-checkbox-input"
|
||||
type="checkbox"
|
||||
/>
|
||||
<span
|
||||
class="ant-checkbox-inner"
|
||||
/>
|
||||
</span>
|
||||
</label>
|
||||
</td>
|
||||
<td
|
||||
class="ant-table-cell ant-table-cell-fix-left ant-table-cell-fix-left-last ant-table-cell-ellipsis ant-table-cell-with-append"
|
||||
style="position:sticky;left:0"
|
||||
title="John Brown sr. John Brown sr. John Brown sr. John Brown sr. John Brown sr. John Brown sr."
|
||||
>
|
||||
<span
|
||||
class="ant-table-row-indent indent-level-0"
|
||||
style="padding-left:0px"
|
||||
/>
|
||||
<button
|
||||
aria-label="Collapse row"
|
||||
class="ant-table-row-expand-icon ant-table-row-expand-icon-expanded"
|
||||
type="button"
|
||||
/>
|
||||
<span
|
||||
class="ant-table-cell-content"
|
||||
>
|
||||
John Brown sr. John Brown sr. John Brown sr. John Brown sr. John Brown sr. John Brown sr.
|
||||
</span>
|
||||
</td>
|
||||
<td
|
||||
class="ant-table-cell"
|
||||
>
|
||||
60
|
||||
</td>
|
||||
<td
|
||||
class="ant-table-cell"
|
||||
>
|
||||
New York No. 1 Lake Park
|
||||
</td>
|
||||
</tr>
|
||||
<tr
|
||||
class="ant-table-row ant-table-row-level-1"
|
||||
data-row-key="11"
|
||||
>
|
||||
<td
|
||||
class="ant-table-cell ant-table-selection-column ant-table-cell-fix-left"
|
||||
style="position:sticky;left:0"
|
||||
>
|
||||
<label
|
||||
class="ant-checkbox-wrapper"
|
||||
>
|
||||
<span
|
||||
class="ant-checkbox"
|
||||
>
|
||||
<input
|
||||
class="ant-checkbox-input"
|
||||
type="checkbox"
|
||||
/>
|
||||
<span
|
||||
class="ant-checkbox-inner"
|
||||
/>
|
||||
</span>
|
||||
</label>
|
||||
</td>
|
||||
<td
|
||||
class="ant-table-cell ant-table-cell-fix-left ant-table-cell-fix-left-last ant-table-cell-ellipsis ant-table-cell-with-append"
|
||||
style="position:sticky;left:0"
|
||||
title="John Brown sr. John Brown sr. John Brown sr. John Brown sr. John Brown sr. John Brown sr."
|
||||
>
|
||||
<span
|
||||
class="ant-table-row-indent indent-level-1"
|
||||
style="padding-left:15px"
|
||||
/>
|
||||
<button
|
||||
aria-label="Collapse row"
|
||||
class="ant-table-row-expand-icon ant-table-row-expand-icon-spaced"
|
||||
type="button"
|
||||
/>
|
||||
<span
|
||||
class="ant-table-cell-content"
|
||||
>
|
||||
John Brown sr. John Brown sr. John Brown sr. John Brown sr. John Brown sr. John Brown sr.
|
||||
</span>
|
||||
</td>
|
||||
<td
|
||||
class="ant-table-cell"
|
||||
>
|
||||
42
|
||||
</td>
|
||||
<td
|
||||
class="ant-table-cell"
|
||||
>
|
||||
New York No. 2 Lake Park
|
||||
</td>
|
||||
</tr>
|
||||
<tr
|
||||
class="ant-table-row ant-table-row-level-1"
|
||||
data-row-key="12"
|
||||
>
|
||||
<td
|
||||
class="ant-table-cell ant-table-selection-column ant-table-cell-fix-left"
|
||||
style="position:sticky;left:0"
|
||||
>
|
||||
<label
|
||||
class="ant-checkbox-wrapper"
|
||||
>
|
||||
<span
|
||||
class="ant-checkbox"
|
||||
>
|
||||
<input
|
||||
class="ant-checkbox-input"
|
||||
type="checkbox"
|
||||
/>
|
||||
<span
|
||||
class="ant-checkbox-inner"
|
||||
/>
|
||||
</span>
|
||||
</label>
|
||||
</td>
|
||||
<td
|
||||
class="ant-table-cell ant-table-cell-fix-left ant-table-cell-fix-left-last ant-table-cell-ellipsis ant-table-cell-with-append"
|
||||
style="position:sticky;left:0"
|
||||
title="John Brown sr. John Brown sr. John Brown sr. John Brown sr. John Brown sr. John Brown sr."
|
||||
>
|
||||
<span
|
||||
class="ant-table-row-indent indent-level-1"
|
||||
style="padding-left:15px"
|
||||
/>
|
||||
<button
|
||||
aria-label="Collapse row"
|
||||
class="ant-table-row-expand-icon ant-table-row-expand-icon-expanded"
|
||||
type="button"
|
||||
/>
|
||||
<span
|
||||
class="ant-table-cell-content"
|
||||
>
|
||||
John Brown sr. John Brown sr. John Brown sr. John Brown sr. John Brown sr. John Brown sr.
|
||||
</span>
|
||||
</td>
|
||||
<td
|
||||
class="ant-table-cell"
|
||||
>
|
||||
30
|
||||
</td>
|
||||
<td
|
||||
class="ant-table-cell"
|
||||
>
|
||||
New York No. 3 Lake Park
|
||||
</td>
|
||||
</tr>
|
||||
<tr
|
||||
class="ant-table-row ant-table-row-level-2"
|
||||
data-row-key="121"
|
||||
>
|
||||
<td
|
||||
class="ant-table-cell ant-table-selection-column ant-table-cell-fix-left"
|
||||
style="position:sticky;left:0"
|
||||
>
|
||||
<label
|
||||
class="ant-checkbox-wrapper"
|
||||
>
|
||||
<span
|
||||
class="ant-checkbox"
|
||||
>
|
||||
<input
|
||||
class="ant-checkbox-input"
|
||||
type="checkbox"
|
||||
/>
|
||||
<span
|
||||
class="ant-checkbox-inner"
|
||||
/>
|
||||
</span>
|
||||
</label>
|
||||
</td>
|
||||
<td
|
||||
class="ant-table-cell ant-table-cell-fix-left ant-table-cell-fix-left-last ant-table-cell-ellipsis ant-table-cell-with-append"
|
||||
style="position:sticky;left:0"
|
||||
title="John Brown sr. John Brown sr. John Brown sr. John Brown sr. John Brown sr. John Brown sr."
|
||||
>
|
||||
<span
|
||||
class="ant-table-row-indent indent-level-2"
|
||||
style="padding-left:30px"
|
||||
/>
|
||||
<button
|
||||
aria-label="Collapse row"
|
||||
class="ant-table-row-expand-icon ant-table-row-expand-icon-spaced"
|
||||
type="button"
|
||||
/>
|
||||
<span
|
||||
class="ant-table-cell-content"
|
||||
>
|
||||
John Brown sr. John Brown sr. John Brown sr. John Brown sr. John Brown sr. John Brown sr.
|
||||
</span>
|
||||
</td>
|
||||
<td
|
||||
class="ant-table-cell"
|
||||
>
|
||||
16
|
||||
</td>
|
||||
<td
|
||||
class="ant-table-cell"
|
||||
>
|
||||
New York No. 3 Lake Park
|
||||
</td>
|
||||
</tr>
|
||||
<tr
|
||||
class="ant-table-row ant-table-row-level-1"
|
||||
data-row-key="13"
|
||||
>
|
||||
<td
|
||||
class="ant-table-cell ant-table-selection-column ant-table-cell-fix-left"
|
||||
style="position:sticky;left:0"
|
||||
>
|
||||
<label
|
||||
class="ant-checkbox-wrapper"
|
||||
>
|
||||
<span
|
||||
class="ant-checkbox"
|
||||
>
|
||||
<input
|
||||
class="ant-checkbox-input"
|
||||
type="checkbox"
|
||||
/>
|
||||
<span
|
||||
class="ant-checkbox-inner"
|
||||
/>
|
||||
</span>
|
||||
</label>
|
||||
</td>
|
||||
<td
|
||||
class="ant-table-cell ant-table-cell-fix-left ant-table-cell-fix-left-last ant-table-cell-ellipsis ant-table-cell-with-append"
|
||||
style="position:sticky;left:0"
|
||||
title="Jim Green sr. Jim Green sr. Jim Green sr. Jim Green sr."
|
||||
>
|
||||
<span
|
||||
class="ant-table-row-indent indent-level-1"
|
||||
style="padding-left:15px"
|
||||
/>
|
||||
<button
|
||||
aria-label="Collapse row"
|
||||
class="ant-table-row-expand-icon ant-table-row-expand-icon-expanded"
|
||||
type="button"
|
||||
/>
|
||||
<span
|
||||
class="ant-table-cell-content"
|
||||
>
|
||||
Jim Green sr. Jim Green sr. Jim Green sr. Jim Green sr.
|
||||
</span>
|
||||
</td>
|
||||
<td
|
||||
class="ant-table-cell"
|
||||
>
|
||||
72
|
||||
</td>
|
||||
<td
|
||||
class="ant-table-cell"
|
||||
>
|
||||
London No. 1 Lake Park
|
||||
</td>
|
||||
</tr>
|
||||
<tr
|
||||
class="ant-table-row ant-table-row-level-2"
|
||||
data-row-key="131"
|
||||
>
|
||||
<td
|
||||
class="ant-table-cell ant-table-selection-column ant-table-cell-fix-left"
|
||||
style="position:sticky;left:0"
|
||||
>
|
||||
<label
|
||||
class="ant-checkbox-wrapper"
|
||||
>
|
||||
<span
|
||||
class="ant-checkbox"
|
||||
>
|
||||
<input
|
||||
class="ant-checkbox-input"
|
||||
type="checkbox"
|
||||
/>
|
||||
<span
|
||||
class="ant-checkbox-inner"
|
||||
/>
|
||||
</span>
|
||||
</label>
|
||||
</td>
|
||||
<td
|
||||
class="ant-table-cell ant-table-cell-fix-left ant-table-cell-fix-left-last ant-table-cell-ellipsis ant-table-cell-with-append"
|
||||
style="position:sticky;left:0"
|
||||
title="Jim Green. Jim Green. Jim Green. Jim Green. Jim Green. Jim Green."
|
||||
>
|
||||
<span
|
||||
class="ant-table-row-indent indent-level-2"
|
||||
style="padding-left:30px"
|
||||
/>
|
||||
<button
|
||||
aria-label="Collapse row"
|
||||
class="ant-table-row-expand-icon ant-table-row-expand-icon-expanded"
|
||||
type="button"
|
||||
/>
|
||||
<span
|
||||
class="ant-table-cell-content"
|
||||
>
|
||||
Jim Green. Jim Green. Jim Green. Jim Green. Jim Green. Jim Green.
|
||||
</span>
|
||||
</td>
|
||||
<td
|
||||
class="ant-table-cell"
|
||||
>
|
||||
42
|
||||
</td>
|
||||
<td
|
||||
class="ant-table-cell"
|
||||
>
|
||||
London No. 2 Lake Park
|
||||
</td>
|
||||
</tr>
|
||||
<tr
|
||||
class="ant-table-row ant-table-row-level-3"
|
||||
data-row-key="1311"
|
||||
>
|
||||
<td
|
||||
class="ant-table-cell ant-table-selection-column ant-table-cell-fix-left"
|
||||
style="position:sticky;left:0"
|
||||
>
|
||||
<label
|
||||
class="ant-checkbox-wrapper"
|
||||
>
|
||||
<span
|
||||
class="ant-checkbox"
|
||||
>
|
||||
<input
|
||||
class="ant-checkbox-input"
|
||||
type="checkbox"
|
||||
/>
|
||||
<span
|
||||
class="ant-checkbox-inner"
|
||||
/>
|
||||
</span>
|
||||
</label>
|
||||
</td>
|
||||
<td
|
||||
class="ant-table-cell ant-table-cell-fix-left ant-table-cell-fix-left-last ant-table-cell-ellipsis ant-table-cell-with-append"
|
||||
style="position:sticky;left:0"
|
||||
title="Jim Green jr. Jim Green jr. Jim Green jr. Jim Green jr."
|
||||
>
|
||||
<span
|
||||
class="ant-table-row-indent indent-level-3"
|
||||
style="padding-left:45px"
|
||||
/>
|
||||
<button
|
||||
aria-label="Collapse row"
|
||||
class="ant-table-row-expand-icon ant-table-row-expand-icon-spaced"
|
||||
type="button"
|
||||
/>
|
||||
<span
|
||||
class="ant-table-cell-content"
|
||||
>
|
||||
Jim Green jr. Jim Green jr. Jim Green jr. Jim Green jr.
|
||||
</span>
|
||||
</td>
|
||||
<td
|
||||
class="ant-table-cell"
|
||||
>
|
||||
25
|
||||
</td>
|
||||
<td
|
||||
class="ant-table-cell"
|
||||
>
|
||||
London No. 3 Lake Park
|
||||
</td>
|
||||
</tr>
|
||||
<tr
|
||||
class="ant-table-row ant-table-row-level-3"
|
||||
data-row-key="1312"
|
||||
>
|
||||
<td
|
||||
class="ant-table-cell ant-table-selection-column ant-table-cell-fix-left"
|
||||
style="position:sticky;left:0"
|
||||
>
|
||||
<label
|
||||
class="ant-checkbox-wrapper"
|
||||
>
|
||||
<span
|
||||
class="ant-checkbox"
|
||||
>
|
||||
<input
|
||||
class="ant-checkbox-input"
|
||||
type="checkbox"
|
||||
/>
|
||||
<span
|
||||
class="ant-checkbox-inner"
|
||||
/>
|
||||
</span>
|
||||
</label>
|
||||
</td>
|
||||
<td
|
||||
class="ant-table-cell ant-table-cell-fix-left ant-table-cell-fix-left-last ant-table-cell-ellipsis ant-table-cell-with-append"
|
||||
style="position:sticky;left:0"
|
||||
title="Jimmy Green sr. Jimmy Green sr. Jimmy Green sr."
|
||||
>
|
||||
<span
|
||||
class="ant-table-row-indent indent-level-3"
|
||||
style="padding-left:45px"
|
||||
/>
|
||||
<button
|
||||
aria-label="Collapse row"
|
||||
class="ant-table-row-expand-icon ant-table-row-expand-icon-spaced"
|
||||
type="button"
|
||||
/>
|
||||
<span
|
||||
class="ant-table-cell-content"
|
||||
>
|
||||
Jimmy Green sr. Jimmy Green sr. Jimmy Green sr.
|
||||
</span>
|
||||
</td>
|
||||
<td
|
||||
class="ant-table-cell"
|
||||
>
|
||||
18
|
||||
</td>
|
||||
<td
|
||||
class="ant-table-cell"
|
||||
>
|
||||
London No. 4 Lake Park
|
||||
</td>
|
||||
</tr>
|
||||
<tr
|
||||
class="ant-table-row ant-table-row-level-0"
|
||||
data-row-key="2"
|
||||
>
|
||||
<td
|
||||
class="ant-table-cell ant-table-selection-column ant-table-cell-fix-left"
|
||||
style="position:sticky;left:0"
|
||||
>
|
||||
<label
|
||||
class="ant-checkbox-wrapper"
|
||||
>
|
||||
<span
|
||||
class="ant-checkbox"
|
||||
>
|
||||
<input
|
||||
class="ant-checkbox-input"
|
||||
type="checkbox"
|
||||
/>
|
||||
<span
|
||||
class="ant-checkbox-inner"
|
||||
/>
|
||||
</span>
|
||||
</label>
|
||||
</td>
|
||||
<td
|
||||
class="ant-table-cell ant-table-cell-fix-left ant-table-cell-fix-left-last ant-table-cell-ellipsis ant-table-cell-with-append"
|
||||
style="position:sticky;left:0"
|
||||
title="Joe Black"
|
||||
>
|
||||
<span
|
||||
class="ant-table-row-indent indent-level-0"
|
||||
style="padding-left:0px"
|
||||
/>
|
||||
<button
|
||||
aria-label="Collapse row"
|
||||
class="ant-table-row-expand-icon ant-table-row-expand-icon-spaced"
|
||||
type="button"
|
||||
/>
|
||||
<span
|
||||
class="ant-table-cell-content"
|
||||
>
|
||||
Joe Black
|
||||
</span>
|
||||
</td>
|
||||
<td
|
||||
class="ant-table-cell"
|
||||
>
|
||||
32
|
||||
</td>
|
||||
<td
|
||||
class="ant-table-cell"
|
||||
>
|
||||
Sidney No. 1 Lake Park
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<ul
|
||||
class="ant-pagination ant-table-pagination ant-table-pagination-right"
|
||||
unselectable="unselectable"
|
||||
>
|
||||
<li
|
||||
aria-disabled="true"
|
||||
class="ant-pagination-prev ant-pagination-disabled"
|
||||
title="Previous Page"
|
||||
>
|
||||
<button
|
||||
class="ant-pagination-item-link"
|
||||
disabled=""
|
||||
tabindex="-1"
|
||||
type="button"
|
||||
>
|
||||
<span
|
||||
aria-label="left"
|
||||
class="anticon anticon-left"
|
||||
role="img"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
data-icon="left"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M724 218.3V141c0-6.7-7.7-10.4-12.9-6.3L260.3 486.8a31.86 31.86 0 000 50.3l450.8 352.1c5.3 4.1 12.9.4 12.9-6.3v-77.3c0-4.9-2.3-9.6-6.1-12.6l-360-281 360-281.1c3.8-3 6.1-7.7 6.1-12.6z"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</button>
|
||||
</li>
|
||||
<li
|
||||
class="ant-pagination-item ant-pagination-item-1 ant-pagination-item-active"
|
||||
tabindex="0"
|
||||
title="1"
|
||||
>
|
||||
<a
|
||||
rel="nofollow"
|
||||
>
|
||||
1
|
||||
</a>
|
||||
</li>
|
||||
<li
|
||||
aria-disabled="true"
|
||||
class="ant-pagination-next ant-pagination-disabled"
|
||||
title="Next Page"
|
||||
>
|
||||
<button
|
||||
class="ant-pagination-item-link"
|
||||
disabled=""
|
||||
tabindex="-1"
|
||||
type="button"
|
||||
>
|
||||
<span
|
||||
aria-label="right"
|
||||
class="anticon anticon-right"
|
||||
role="img"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
data-icon="right"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M765.7 486.8L314.9 134.7A7.97 7.97 0 00302 141v77.3c0 4.9 2.3 9.6 6.1 12.6l360 281.1-360 281.1c-3.9 3-6.1 7.7-6.1 12.6V883c0 6.7 7.7 10.4 12.9 6.3l450.8-352.1a31.96 31.96 0 000-50.4z"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</button>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>,
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`renders ./components/table/demo/virtual-list.md extend context correctly 1`] = `
|
||||
<div
|
||||
class="ant-table-wrapper virtual-table"
|
||||
|
@ -20816,6 +20816,709 @@ Array [
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`renders ./components/table/demo/tree-table-ellipsis.md correctly 1`] = `
|
||||
Array [
|
||||
<div
|
||||
class="ant-space ant-space-horizontal ant-space-align-center"
|
||||
style="margin-bottom:16px"
|
||||
>
|
||||
<div
|
||||
class="ant-space-item"
|
||||
style="margin-right:8px"
|
||||
>
|
||||
Fixed first column:
|
||||
</div>
|
||||
<div
|
||||
class="ant-space-item"
|
||||
>
|
||||
<button
|
||||
aria-checked="true"
|
||||
class="ant-switch ant-switch-checked"
|
||||
role="switch"
|
||||
type="button"
|
||||
>
|
||||
<div
|
||||
class="ant-switch-handle"
|
||||
/>
|
||||
<span
|
||||
class="ant-switch-inner"
|
||||
/>
|
||||
</button>
|
||||
</div>
|
||||
</div>,
|
||||
<div
|
||||
class="ant-table-wrapper"
|
||||
>
|
||||
<div
|
||||
class="ant-spin-nested-loading"
|
||||
>
|
||||
<div
|
||||
class="ant-spin-container"
|
||||
>
|
||||
<div
|
||||
class="ant-table ant-table-has-fix-left"
|
||||
>
|
||||
<div
|
||||
class="ant-table-container"
|
||||
>
|
||||
<div
|
||||
class="ant-table-content"
|
||||
>
|
||||
<table
|
||||
style="table-layout:fixed"
|
||||
>
|
||||
<colgroup>
|
||||
<col
|
||||
class="ant-table-selection-col"
|
||||
style="width:100px"
|
||||
/>
|
||||
<col
|
||||
style="width:30%"
|
||||
/>
|
||||
<col
|
||||
style="width:12%"
|
||||
/>
|
||||
</colgroup>
|
||||
<thead
|
||||
class="ant-table-thead"
|
||||
>
|
||||
<tr>
|
||||
<th
|
||||
class="ant-table-cell ant-table-selection-column ant-table-cell-fix-left"
|
||||
style="position:sticky;left:0"
|
||||
>
|
||||
<div
|
||||
class="ant-table-selection"
|
||||
>
|
||||
<label
|
||||
class="ant-checkbox-wrapper"
|
||||
>
|
||||
<span
|
||||
class="ant-checkbox"
|
||||
>
|
||||
<input
|
||||
class="ant-checkbox-input"
|
||||
type="checkbox"
|
||||
/>
|
||||
<span
|
||||
class="ant-checkbox-inner"
|
||||
/>
|
||||
</span>
|
||||
</label>
|
||||
</div>
|
||||
</th>
|
||||
<th
|
||||
class="ant-table-cell ant-table-cell-fix-left ant-table-cell-fix-left-last ant-table-cell-ellipsis"
|
||||
style="position:sticky;left:0"
|
||||
title="Name"
|
||||
>
|
||||
<span
|
||||
class="ant-table-cell-content"
|
||||
>
|
||||
Name
|
||||
</span>
|
||||
</th>
|
||||
<th
|
||||
class="ant-table-cell"
|
||||
>
|
||||
Age
|
||||
</th>
|
||||
<th
|
||||
class="ant-table-cell"
|
||||
>
|
||||
Address
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody
|
||||
class="ant-table-tbody"
|
||||
>
|
||||
<tr
|
||||
class="ant-table-row ant-table-row-level-0"
|
||||
data-row-key="1"
|
||||
>
|
||||
<td
|
||||
class="ant-table-cell ant-table-selection-column ant-table-cell-fix-left"
|
||||
style="position:sticky;left:0"
|
||||
>
|
||||
<label
|
||||
class="ant-checkbox-wrapper"
|
||||
>
|
||||
<span
|
||||
class="ant-checkbox"
|
||||
>
|
||||
<input
|
||||
class="ant-checkbox-input"
|
||||
type="checkbox"
|
||||
/>
|
||||
<span
|
||||
class="ant-checkbox-inner"
|
||||
/>
|
||||
</span>
|
||||
</label>
|
||||
</td>
|
||||
<td
|
||||
class="ant-table-cell ant-table-cell-fix-left ant-table-cell-fix-left-last ant-table-cell-ellipsis ant-table-cell-with-append"
|
||||
style="position:sticky;left:0"
|
||||
title="John Brown sr. John Brown sr. John Brown sr. John Brown sr. John Brown sr. John Brown sr."
|
||||
>
|
||||
<span
|
||||
class="ant-table-row-indent indent-level-0"
|
||||
style="padding-left:0px"
|
||||
/>
|
||||
<button
|
||||
aria-label="Collapse row"
|
||||
class="ant-table-row-expand-icon ant-table-row-expand-icon-expanded"
|
||||
type="button"
|
||||
/>
|
||||
<span
|
||||
class="ant-table-cell-content"
|
||||
>
|
||||
John Brown sr. John Brown sr. John Brown sr. John Brown sr. John Brown sr. John Brown sr.
|
||||
</span>
|
||||
</td>
|
||||
<td
|
||||
class="ant-table-cell"
|
||||
>
|
||||
60
|
||||
</td>
|
||||
<td
|
||||
class="ant-table-cell"
|
||||
>
|
||||
New York No. 1 Lake Park
|
||||
</td>
|
||||
</tr>
|
||||
<tr
|
||||
class="ant-table-row ant-table-row-level-1"
|
||||
data-row-key="11"
|
||||
>
|
||||
<td
|
||||
class="ant-table-cell ant-table-selection-column ant-table-cell-fix-left"
|
||||
style="position:sticky;left:0"
|
||||
>
|
||||
<label
|
||||
class="ant-checkbox-wrapper"
|
||||
>
|
||||
<span
|
||||
class="ant-checkbox"
|
||||
>
|
||||
<input
|
||||
class="ant-checkbox-input"
|
||||
type="checkbox"
|
||||
/>
|
||||
<span
|
||||
class="ant-checkbox-inner"
|
||||
/>
|
||||
</span>
|
||||
</label>
|
||||
</td>
|
||||
<td
|
||||
class="ant-table-cell ant-table-cell-fix-left ant-table-cell-fix-left-last ant-table-cell-ellipsis ant-table-cell-with-append"
|
||||
style="position:sticky;left:0"
|
||||
title="John Brown sr. John Brown sr. John Brown sr. John Brown sr. John Brown sr. John Brown sr."
|
||||
>
|
||||
<span
|
||||
class="ant-table-row-indent indent-level-1"
|
||||
style="padding-left:15px"
|
||||
/>
|
||||
<button
|
||||
aria-label="Collapse row"
|
||||
class="ant-table-row-expand-icon ant-table-row-expand-icon-spaced"
|
||||
type="button"
|
||||
/>
|
||||
<span
|
||||
class="ant-table-cell-content"
|
||||
>
|
||||
John Brown sr. John Brown sr. John Brown sr. John Brown sr. John Brown sr. John Brown sr.
|
||||
</span>
|
||||
</td>
|
||||
<td
|
||||
class="ant-table-cell"
|
||||
>
|
||||
42
|
||||
</td>
|
||||
<td
|
||||
class="ant-table-cell"
|
||||
>
|
||||
New York No. 2 Lake Park
|
||||
</td>
|
||||
</tr>
|
||||
<tr
|
||||
class="ant-table-row ant-table-row-level-1"
|
||||
data-row-key="12"
|
||||
>
|
||||
<td
|
||||
class="ant-table-cell ant-table-selection-column ant-table-cell-fix-left"
|
||||
style="position:sticky;left:0"
|
||||
>
|
||||
<label
|
||||
class="ant-checkbox-wrapper"
|
||||
>
|
||||
<span
|
||||
class="ant-checkbox"
|
||||
>
|
||||
<input
|
||||
class="ant-checkbox-input"
|
||||
type="checkbox"
|
||||
/>
|
||||
<span
|
||||
class="ant-checkbox-inner"
|
||||
/>
|
||||
</span>
|
||||
</label>
|
||||
</td>
|
||||
<td
|
||||
class="ant-table-cell ant-table-cell-fix-left ant-table-cell-fix-left-last ant-table-cell-ellipsis ant-table-cell-with-append"
|
||||
style="position:sticky;left:0"
|
||||
title="John Brown sr. John Brown sr. John Brown sr. John Brown sr. John Brown sr. John Brown sr."
|
||||
>
|
||||
<span
|
||||
class="ant-table-row-indent indent-level-1"
|
||||
style="padding-left:15px"
|
||||
/>
|
||||
<button
|
||||
aria-label="Collapse row"
|
||||
class="ant-table-row-expand-icon ant-table-row-expand-icon-expanded"
|
||||
type="button"
|
||||
/>
|
||||
<span
|
||||
class="ant-table-cell-content"
|
||||
>
|
||||
John Brown sr. John Brown sr. John Brown sr. John Brown sr. John Brown sr. John Brown sr.
|
||||
</span>
|
||||
</td>
|
||||
<td
|
||||
class="ant-table-cell"
|
||||
>
|
||||
30
|
||||
</td>
|
||||
<td
|
||||
class="ant-table-cell"
|
||||
>
|
||||
New York No. 3 Lake Park
|
||||
</td>
|
||||
</tr>
|
||||
<tr
|
||||
class="ant-table-row ant-table-row-level-2"
|
||||
data-row-key="121"
|
||||
>
|
||||
<td
|
||||
class="ant-table-cell ant-table-selection-column ant-table-cell-fix-left"
|
||||
style="position:sticky;left:0"
|
||||
>
|
||||
<label
|
||||
class="ant-checkbox-wrapper"
|
||||
>
|
||||
<span
|
||||
class="ant-checkbox"
|
||||
>
|
||||
<input
|
||||
class="ant-checkbox-input"
|
||||
type="checkbox"
|
||||
/>
|
||||
<span
|
||||
class="ant-checkbox-inner"
|
||||
/>
|
||||
</span>
|
||||
</label>
|
||||
</td>
|
||||
<td
|
||||
class="ant-table-cell ant-table-cell-fix-left ant-table-cell-fix-left-last ant-table-cell-ellipsis ant-table-cell-with-append"
|
||||
style="position:sticky;left:0"
|
||||
title="John Brown sr. John Brown sr. John Brown sr. John Brown sr. John Brown sr. John Brown sr."
|
||||
>
|
||||
<span
|
||||
class="ant-table-row-indent indent-level-2"
|
||||
style="padding-left:30px"
|
||||
/>
|
||||
<button
|
||||
aria-label="Collapse row"
|
||||
class="ant-table-row-expand-icon ant-table-row-expand-icon-spaced"
|
||||
type="button"
|
||||
/>
|
||||
<span
|
||||
class="ant-table-cell-content"
|
||||
>
|
||||
John Brown sr. John Brown sr. John Brown sr. John Brown sr. John Brown sr. John Brown sr.
|
||||
</span>
|
||||
</td>
|
||||
<td
|
||||
class="ant-table-cell"
|
||||
>
|
||||
16
|
||||
</td>
|
||||
<td
|
||||
class="ant-table-cell"
|
||||
>
|
||||
New York No. 3 Lake Park
|
||||
</td>
|
||||
</tr>
|
||||
<tr
|
||||
class="ant-table-row ant-table-row-level-1"
|
||||
data-row-key="13"
|
||||
>
|
||||
<td
|
||||
class="ant-table-cell ant-table-selection-column ant-table-cell-fix-left"
|
||||
style="position:sticky;left:0"
|
||||
>
|
||||
<label
|
||||
class="ant-checkbox-wrapper"
|
||||
>
|
||||
<span
|
||||
class="ant-checkbox"
|
||||
>
|
||||
<input
|
||||
class="ant-checkbox-input"
|
||||
type="checkbox"
|
||||
/>
|
||||
<span
|
||||
class="ant-checkbox-inner"
|
||||
/>
|
||||
</span>
|
||||
</label>
|
||||
</td>
|
||||
<td
|
||||
class="ant-table-cell ant-table-cell-fix-left ant-table-cell-fix-left-last ant-table-cell-ellipsis ant-table-cell-with-append"
|
||||
style="position:sticky;left:0"
|
||||
title="Jim Green sr. Jim Green sr. Jim Green sr. Jim Green sr."
|
||||
>
|
||||
<span
|
||||
class="ant-table-row-indent indent-level-1"
|
||||
style="padding-left:15px"
|
||||
/>
|
||||
<button
|
||||
aria-label="Collapse row"
|
||||
class="ant-table-row-expand-icon ant-table-row-expand-icon-expanded"
|
||||
type="button"
|
||||
/>
|
||||
<span
|
||||
class="ant-table-cell-content"
|
||||
>
|
||||
Jim Green sr. Jim Green sr. Jim Green sr. Jim Green sr.
|
||||
</span>
|
||||
</td>
|
||||
<td
|
||||
class="ant-table-cell"
|
||||
>
|
||||
72
|
||||
</td>
|
||||
<td
|
||||
class="ant-table-cell"
|
||||
>
|
||||
London No. 1 Lake Park
|
||||
</td>
|
||||
</tr>
|
||||
<tr
|
||||
class="ant-table-row ant-table-row-level-2"
|
||||
data-row-key="131"
|
||||
>
|
||||
<td
|
||||
class="ant-table-cell ant-table-selection-column ant-table-cell-fix-left"
|
||||
style="position:sticky;left:0"
|
||||
>
|
||||
<label
|
||||
class="ant-checkbox-wrapper"
|
||||
>
|
||||
<span
|
||||
class="ant-checkbox"
|
||||
>
|
||||
<input
|
||||
class="ant-checkbox-input"
|
||||
type="checkbox"
|
||||
/>
|
||||
<span
|
||||
class="ant-checkbox-inner"
|
||||
/>
|
||||
</span>
|
||||
</label>
|
||||
</td>
|
||||
<td
|
||||
class="ant-table-cell ant-table-cell-fix-left ant-table-cell-fix-left-last ant-table-cell-ellipsis ant-table-cell-with-append"
|
||||
style="position:sticky;left:0"
|
||||
title="Jim Green. Jim Green. Jim Green. Jim Green. Jim Green. Jim Green."
|
||||
>
|
||||
<span
|
||||
class="ant-table-row-indent indent-level-2"
|
||||
style="padding-left:30px"
|
||||
/>
|
||||
<button
|
||||
aria-label="Collapse row"
|
||||
class="ant-table-row-expand-icon ant-table-row-expand-icon-expanded"
|
||||
type="button"
|
||||
/>
|
||||
<span
|
||||
class="ant-table-cell-content"
|
||||
>
|
||||
Jim Green. Jim Green. Jim Green. Jim Green. Jim Green. Jim Green.
|
||||
</span>
|
||||
</td>
|
||||
<td
|
||||
class="ant-table-cell"
|
||||
>
|
||||
42
|
||||
</td>
|
||||
<td
|
||||
class="ant-table-cell"
|
||||
>
|
||||
London No. 2 Lake Park
|
||||
</td>
|
||||
</tr>
|
||||
<tr
|
||||
class="ant-table-row ant-table-row-level-3"
|
||||
data-row-key="1311"
|
||||
>
|
||||
<td
|
||||
class="ant-table-cell ant-table-selection-column ant-table-cell-fix-left"
|
||||
style="position:sticky;left:0"
|
||||
>
|
||||
<label
|
||||
class="ant-checkbox-wrapper"
|
||||
>
|
||||
<span
|
||||
class="ant-checkbox"
|
||||
>
|
||||
<input
|
||||
class="ant-checkbox-input"
|
||||
type="checkbox"
|
||||
/>
|
||||
<span
|
||||
class="ant-checkbox-inner"
|
||||
/>
|
||||
</span>
|
||||
</label>
|
||||
</td>
|
||||
<td
|
||||
class="ant-table-cell ant-table-cell-fix-left ant-table-cell-fix-left-last ant-table-cell-ellipsis ant-table-cell-with-append"
|
||||
style="position:sticky;left:0"
|
||||
title="Jim Green jr. Jim Green jr. Jim Green jr. Jim Green jr."
|
||||
>
|
||||
<span
|
||||
class="ant-table-row-indent indent-level-3"
|
||||
style="padding-left:45px"
|
||||
/>
|
||||
<button
|
||||
aria-label="Collapse row"
|
||||
class="ant-table-row-expand-icon ant-table-row-expand-icon-spaced"
|
||||
type="button"
|
||||
/>
|
||||
<span
|
||||
class="ant-table-cell-content"
|
||||
>
|
||||
Jim Green jr. Jim Green jr. Jim Green jr. Jim Green jr.
|
||||
</span>
|
||||
</td>
|
||||
<td
|
||||
class="ant-table-cell"
|
||||
>
|
||||
25
|
||||
</td>
|
||||
<td
|
||||
class="ant-table-cell"
|
||||
>
|
||||
London No. 3 Lake Park
|
||||
</td>
|
||||
</tr>
|
||||
<tr
|
||||
class="ant-table-row ant-table-row-level-3"
|
||||
data-row-key="1312"
|
||||
>
|
||||
<td
|
||||
class="ant-table-cell ant-table-selection-column ant-table-cell-fix-left"
|
||||
style="position:sticky;left:0"
|
||||
>
|
||||
<label
|
||||
class="ant-checkbox-wrapper"
|
||||
>
|
||||
<span
|
||||
class="ant-checkbox"
|
||||
>
|
||||
<input
|
||||
class="ant-checkbox-input"
|
||||
type="checkbox"
|
||||
/>
|
||||
<span
|
||||
class="ant-checkbox-inner"
|
||||
/>
|
||||
</span>
|
||||
</label>
|
||||
</td>
|
||||
<td
|
||||
class="ant-table-cell ant-table-cell-fix-left ant-table-cell-fix-left-last ant-table-cell-ellipsis ant-table-cell-with-append"
|
||||
style="position:sticky;left:0"
|
||||
title="Jimmy Green sr. Jimmy Green sr. Jimmy Green sr."
|
||||
>
|
||||
<span
|
||||
class="ant-table-row-indent indent-level-3"
|
||||
style="padding-left:45px"
|
||||
/>
|
||||
<button
|
||||
aria-label="Collapse row"
|
||||
class="ant-table-row-expand-icon ant-table-row-expand-icon-spaced"
|
||||
type="button"
|
||||
/>
|
||||
<span
|
||||
class="ant-table-cell-content"
|
||||
>
|
||||
Jimmy Green sr. Jimmy Green sr. Jimmy Green sr.
|
||||
</span>
|
||||
</td>
|
||||
<td
|
||||
class="ant-table-cell"
|
||||
>
|
||||
18
|
||||
</td>
|
||||
<td
|
||||
class="ant-table-cell"
|
||||
>
|
||||
London No. 4 Lake Park
|
||||
</td>
|
||||
</tr>
|
||||
<tr
|
||||
class="ant-table-row ant-table-row-level-0"
|
||||
data-row-key="2"
|
||||
>
|
||||
<td
|
||||
class="ant-table-cell ant-table-selection-column ant-table-cell-fix-left"
|
||||
style="position:sticky;left:0"
|
||||
>
|
||||
<label
|
||||
class="ant-checkbox-wrapper"
|
||||
>
|
||||
<span
|
||||
class="ant-checkbox"
|
||||
>
|
||||
<input
|
||||
class="ant-checkbox-input"
|
||||
type="checkbox"
|
||||
/>
|
||||
<span
|
||||
class="ant-checkbox-inner"
|
||||
/>
|
||||
</span>
|
||||
</label>
|
||||
</td>
|
||||
<td
|
||||
class="ant-table-cell ant-table-cell-fix-left ant-table-cell-fix-left-last ant-table-cell-ellipsis ant-table-cell-with-append"
|
||||
style="position:sticky;left:0"
|
||||
title="Joe Black"
|
||||
>
|
||||
<span
|
||||
class="ant-table-row-indent indent-level-0"
|
||||
style="padding-left:0px"
|
||||
/>
|
||||
<button
|
||||
aria-label="Collapse row"
|
||||
class="ant-table-row-expand-icon ant-table-row-expand-icon-spaced"
|
||||
type="button"
|
||||
/>
|
||||
<span
|
||||
class="ant-table-cell-content"
|
||||
>
|
||||
Joe Black
|
||||
</span>
|
||||
</td>
|
||||
<td
|
||||
class="ant-table-cell"
|
||||
>
|
||||
32
|
||||
</td>
|
||||
<td
|
||||
class="ant-table-cell"
|
||||
>
|
||||
Sidney No. 1 Lake Park
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<ul
|
||||
class="ant-pagination ant-table-pagination ant-table-pagination-right"
|
||||
unselectable="unselectable"
|
||||
>
|
||||
<li
|
||||
aria-disabled="true"
|
||||
class="ant-pagination-prev ant-pagination-disabled"
|
||||
title="Previous Page"
|
||||
>
|
||||
<button
|
||||
class="ant-pagination-item-link"
|
||||
disabled=""
|
||||
tabindex="-1"
|
||||
type="button"
|
||||
>
|
||||
<span
|
||||
aria-label="left"
|
||||
class="anticon anticon-left"
|
||||
role="img"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
data-icon="left"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M724 218.3V141c0-6.7-7.7-10.4-12.9-6.3L260.3 486.8a31.86 31.86 0 000 50.3l450.8 352.1c5.3 4.1 12.9.4 12.9-6.3v-77.3c0-4.9-2.3-9.6-6.1-12.6l-360-281 360-281.1c3.8-3 6.1-7.7 6.1-12.6z"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</button>
|
||||
</li>
|
||||
<li
|
||||
class="ant-pagination-item ant-pagination-item-1 ant-pagination-item-active"
|
||||
tabindex="0"
|
||||
title="1"
|
||||
>
|
||||
<a
|
||||
rel="nofollow"
|
||||
>
|
||||
1
|
||||
</a>
|
||||
</li>
|
||||
<li
|
||||
aria-disabled="true"
|
||||
class="ant-pagination-next ant-pagination-disabled"
|
||||
title="Next Page"
|
||||
>
|
||||
<button
|
||||
class="ant-pagination-item-link"
|
||||
disabled=""
|
||||
tabindex="-1"
|
||||
type="button"
|
||||
>
|
||||
<span
|
||||
aria-label="right"
|
||||
class="anticon anticon-right"
|
||||
role="img"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
data-icon="right"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M765.7 486.8L314.9 134.7A7.97 7.97 0 00302 141v77.3c0 4.9 2.3 9.6 6.1 12.6l360 281.1-360 281.1c-3.9 3-6.1 7.7-6.1 12.6V883c0 6.7 7.7 10.4 12.9 6.3l450.8-352.1a31.96 31.96 0 000-50.4z"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</button>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>,
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`renders ./components/table/demo/virtual-list.md correctly 1`] = `
|
||||
<div
|
||||
class="ant-table-wrapper virtual-table"
|
||||
|
136
components/table/demo/tree-table-ellipsis.md
Normal file
136
components/table/demo/tree-table-ellipsis.md
Normal file
@ -0,0 +1,136 @@
|
||||
---
|
||||
order: 17.1
|
||||
title:
|
||||
en-US: Tree data ellipsis debug demo
|
||||
zh-CN: 树形数据省略情况测试
|
||||
debug: true
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
https://github.com/ant-design/ant-design/issues/36583
|
||||
|
||||
## en-US
|
||||
|
||||
https://github.com/ant-design/ant-design/issues/36583
|
||||
|
||||
```tsx
|
||||
import { Space, Switch, Table } from 'antd';
|
||||
import type { ColumnsType } from 'antd/es/table';
|
||||
import React, { useState } from 'react';
|
||||
|
||||
interface DataType {
|
||||
key: React.ReactNode;
|
||||
name: string;
|
||||
age: number;
|
||||
address: string;
|
||||
children?: DataType[];
|
||||
}
|
||||
|
||||
const data: DataType[] = [
|
||||
{
|
||||
key: 1,
|
||||
name: 'John Brown sr. John Brown sr. John Brown sr. John Brown sr. John Brown sr. John Brown sr.',
|
||||
age: 60,
|
||||
address: 'New York No. 1 Lake Park',
|
||||
children: [
|
||||
{
|
||||
key: 11,
|
||||
name: 'John Brown sr. John Brown sr. John Brown sr. John Brown sr. John Brown sr. John Brown sr.',
|
||||
age: 42,
|
||||
address: 'New York No. 2 Lake Park',
|
||||
},
|
||||
{
|
||||
key: 12,
|
||||
name: 'John Brown sr. John Brown sr. John Brown sr. John Brown sr. John Brown sr. John Brown sr.',
|
||||
age: 30,
|
||||
address: 'New York No. 3 Lake Park',
|
||||
children: [
|
||||
{
|
||||
key: 121,
|
||||
name: 'John Brown sr. John Brown sr. John Brown sr. John Brown sr. John Brown sr. John Brown sr.',
|
||||
age: 16,
|
||||
address: 'New York No. 3 Lake Park',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
key: 13,
|
||||
name: 'Jim Green sr. Jim Green sr. Jim Green sr. Jim Green sr.',
|
||||
age: 72,
|
||||
address: 'London No. 1 Lake Park',
|
||||
children: [
|
||||
{
|
||||
key: 131,
|
||||
name: 'Jim Green. Jim Green. Jim Green. Jim Green. Jim Green. Jim Green.',
|
||||
age: 42,
|
||||
address: 'London No. 2 Lake Park',
|
||||
children: [
|
||||
{
|
||||
key: 1311,
|
||||
name: 'Jim Green jr. Jim Green jr. Jim Green jr. Jim Green jr.',
|
||||
age: 25,
|
||||
address: 'London No. 3 Lake Park',
|
||||
},
|
||||
{
|
||||
key: 1312,
|
||||
name: 'Jimmy Green sr. Jimmy Green sr. Jimmy Green sr.',
|
||||
age: 18,
|
||||
address: 'London No. 4 Lake Park',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
key: 2,
|
||||
name: 'Joe Black',
|
||||
age: 32,
|
||||
address: 'Sidney No. 1 Lake Park',
|
||||
},
|
||||
];
|
||||
|
||||
const App: React.FC = () => {
|
||||
const [fixed, setFixed] = useState(true);
|
||||
|
||||
const columns: ColumnsType<DataType> = [
|
||||
{
|
||||
title: 'Name',
|
||||
dataIndex: 'name',
|
||||
key: 'name',
|
||||
width: '30%',
|
||||
ellipsis: true,
|
||||
fixed,
|
||||
},
|
||||
{
|
||||
title: 'Age',
|
||||
dataIndex: 'age',
|
||||
key: 'age',
|
||||
width: '12%',
|
||||
},
|
||||
{
|
||||
title: 'Address',
|
||||
dataIndex: 'address',
|
||||
key: 'address',
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<>
|
||||
<Space align="center" style={{ marginBottom: 16 }}>
|
||||
Fixed first column: <Switch checked={fixed} onChange={setFixed} />
|
||||
</Space>
|
||||
<Table
|
||||
columns={columns}
|
||||
rowSelection={{ columnWidth: 100 }}
|
||||
expandable={{ defaultExpandAllRows: true }}
|
||||
dataSource={data}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default App;
|
||||
```
|
@ -482,6 +482,12 @@
|
||||
|
||||
&-row-expand-icon-cell {
|
||||
text-align: center;
|
||||
|
||||
.@{table-prefix-cls}-row-expand-icon {
|
||||
display: inline-flex;
|
||||
float: none;
|
||||
vertical-align: sub;
|
||||
}
|
||||
}
|
||||
|
||||
&-row-indent {
|
||||
@ -492,7 +498,7 @@
|
||||
&-row-expand-icon {
|
||||
.operation-unit();
|
||||
position: relative;
|
||||
display: inline-flex;
|
||||
float: left;
|
||||
box-sizing: border-box;
|
||||
width: @expand-icon-size;
|
||||
height: @expand-icon-size;
|
||||
@ -500,7 +506,6 @@
|
||||
color: inherit;
|
||||
line-height: ceil(((@font-size-sm * 1.4 - @border-width-base * 3) / 2)) * 2 + @border-width-base *
|
||||
3;
|
||||
vertical-align: -2.5px;
|
||||
background: @table-expand-icon-bg;
|
||||
border: @border-width-base @border-style-base @table-border-color;
|
||||
border-radius: @border-radius-base;
|
||||
@ -561,14 +566,10 @@
|
||||
}
|
||||
|
||||
.@{table-prefix-cls}-row-indent + & {
|
||||
margin-top: ((@font-size-base * @line-height-base - @border-width-base * 3) / 2) -
|
||||
ceil(((@font-size-sm * 1.4 - @border-width-base * 3) / 2));
|
||||
margin-right: @padding-xs;
|
||||
}
|
||||
|
||||
+ .@{table-prefix-cls}-cell-content {
|
||||
display: inline-block !important;
|
||||
width: calc(100% - (@expand-icon-size + @padding-xs));
|
||||
vertical-align: top;
|
||||
}
|
||||
}
|
||||
|
||||
tr&-expanded-row {
|
||||
@ -632,6 +633,10 @@
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
&-cell-fix-left-all::after {
|
||||
display: none;
|
||||
}
|
||||
|
||||
&-cell-fix-right-first::after,
|
||||
&-cell-fix-right-last::after {
|
||||
position: absolute;
|
||||
|
@ -21,7 +21,7 @@ Ant Design has 3 types of Tabs for different situations.
|
||||
### Tabs
|
||||
|
||||
| Property | Description | Type | Default | Version |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| activeKey | Current TabPane's key | string | - | |
|
||||
| addIcon | Customize add icon | ReactNode | - | 4.4.0 |
|
||||
| animated | Whether to change tabs with animation. Only works while `tabPosition="top"` | boolean \| { inkBar: boolean, tabPane: boolean } | { inkBar: true, tabPane: false } | |
|
||||
@ -35,7 +35,7 @@ Ant Design has 3 types of Tabs for different situations.
|
||||
| tabBarExtraContent | Extra content in tab bar | ReactNode \| {left?: ReactNode, right?: ReactNode} | - | object: 4.6.0 |
|
||||
| tabBarGutter | The gap between tabs | number | - | |
|
||||
| tabBarStyle | Tab bar style object | CSSProperties | - | |
|
||||
| tabPosition | Position of tabs | `top` \| `right` \| `bottom` \| `left` | `top` | |
|
||||
| tabPosition | Position of tabs | `top` \| `right` \| `bottom` \ | `left` | `top` | |
|
||||
| destroyInactiveTabPane | Whether destroy inactive TabPane when change tab | boolean | false | |
|
||||
| type | Basic style of tabs | `line` \| `card` \| `editable-card` | `line` | |
|
||||
| onChange | Callback executed when active tab is changed | function(activeKey) {} | - | |
|
||||
@ -50,6 +50,7 @@ More option at [rc-tabs option](https://github.com/react-component/tabs#tabs)
|
||||
| Property | Description | Type | Default |
|
||||
| --- | --- | --- | --- |
|
||||
| closeIcon | Customize close icon in TabPane's head. Only works while `type="editable-card"` | ReactNode | - |
|
||||
| disabled | Set TabPane disabled | boolean | false |
|
||||
| forceRender | Forced render of content in tabs, not lazy render after clicking on tabs | boolean | false |
|
||||
| key | TabPane's key | string | - |
|
||||
| tab | Show text in TabPane's head | ReactNode | - |
|
||||
|
@ -27,7 +27,7 @@ Ant Design 依次提供了三级选项卡,分别用于不同的场景。
|
||||
| --- | --- | --- | --- | --- |
|
||||
| activeKey | 当前激活 tab 面板的 key | string | - | |
|
||||
| addIcon | 自定义添加按钮 | ReactNode | - | 4.4.0 |
|
||||
| animated | 是否使用动画切换 Tabs, 仅生效于 `tabPosition="top"` | boolean \| { inkBar: boolean, tabPane: boolean } | { inkBar: true, tabPane: false } | |
|
||||
| animated | 是否使用动画切换 Tabs, 仅生效于 `tabPosition="top"` | boolean\| { inkBar: boolean, tabPane: boolean } | { inkBar: true, tabPane: false } | |
|
||||
| centered | 标签居中展示 | boolean | false | 4.4.0 |
|
||||
| defaultActiveKey | 初始化选中面板的 key,如果没有设置 activeKey | string | `第一个面板` | |
|
||||
| hideAdd | 是否隐藏加号图标,在 `type="editable-card"` 时有效 | boolean | false | |
|
||||
@ -46,11 +46,16 @@ Ant Design 依次提供了三级选项卡,分别用于不同的场景。
|
||||
| onTabClick | tab 被点击的回调 | function(key: string, event: MouseEvent) | - | |
|
||||
| onTabScroll | tab 滚动时触发 | function({ direction: `left` \| `right` \| `top` \| `bottom` }) | - | 4.3.0 |
|
||||
|
||||
> 更多属性查看 [rc-tabs tabs](https://github.com/react-component/tabs#tabs)
|
||||
|
||||
### Tabs.TabPane
|
||||
|
||||
| 参数 | 说明 | 类型 | 默认值 |
|
||||
| ----------- | ----------------------------------------------- | --------- | ------ |
|
||||
| closeIcon | 自定义关闭图标,`在 type="editable-card"`时有效 | ReactNode | - |
|
||||
| disabled | 禁用某一项 | boolean | false |
|
||||
| forceRender | 被隐藏时是否渲染 DOM 结构 | boolean | false |
|
||||
| key | 对应 activeKey | string | - |
|
||||
| tab | 选项卡头显示文字 | ReactNode | - |
|
||||
|
||||
> 更多属性查看 [rc-tabs tabpane](https://github.com/react-component/tabs#tabpane)
|
||||
|
@ -95,7 +95,8 @@ export interface AntTreeNodeDropEvent {
|
||||
// [Legacy] Compatible for v3
|
||||
export type TreeNodeNormal = DataNode;
|
||||
|
||||
type DraggableFn = (node: AntTreeNode) => boolean;
|
||||
type DraggableFn = (node: DataNode) => boolean;
|
||||
|
||||
interface DraggableConfig {
|
||||
icon?: React.ReactNode | false;
|
||||
nodeDraggable?: DraggableFn;
|
||||
|
@ -1,6 +1,7 @@
|
||||
import type { BasicDataNode } from 'rc-tree';
|
||||
import * as React from 'react';
|
||||
import { render } from '../../../tests/utils';
|
||||
import type { DataNode } from '../index';
|
||||
import Tree from '../index';
|
||||
|
||||
const { DirectoryTree } = Tree;
|
||||
@ -74,4 +75,25 @@ describe('Tree.TypeScript', () => {
|
||||
|
||||
expect(container).toBeTruthy();
|
||||
});
|
||||
|
||||
it('draggable params type', () => {
|
||||
const { container } = render(
|
||||
<Tree
|
||||
treeData={[
|
||||
{
|
||||
title: 'Bamboo',
|
||||
key: 'bamboo',
|
||||
children: [
|
||||
{
|
||||
title: 'Little',
|
||||
key: 'little',
|
||||
},
|
||||
],
|
||||
},
|
||||
]}
|
||||
draggable={(node: DataNode) => node.title === 'Little'}
|
||||
/>,
|
||||
);
|
||||
expect(container).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
@ -21,6 +21,10 @@ But in antd, `undefined` is treated as uncontrolled, and `null` is used as an ex
|
||||
|
||||
Note: For `options` in `Select-like` components, it is **strongly recommended not** to use `undefined` and `null` as `value` in `option`. Please use `string | number` as a valid `value` in `option`.
|
||||
|
||||
## Can I use internal API which is not documented on the site?
|
||||
|
||||
NOT RECOMMEND. Internal API is not guaranteed to be compatible with future versions. It may be removed or changed in some versions. If you really need to use it, you should to make sure these API is still valid when upgrading to a new version or just lock version for usage.
|
||||
|
||||
## `Select Dropdown DatePicker TimePicker Popover Popconfirm` disappears when I click another popup component inside it. How do I resolve this?
|
||||
|
||||
This is an old bug that has been fixed since `v3.11.x`. If you're using an older version, you can use `<Select getPopupContainer={trigger => trigger.parentElement}>` to render a component inside Popover. (Or other `getXxxxContainer` props)
|
||||
|
@ -21,6 +21,10 @@ title: FAQ
|
||||
|
||||
注意:对于类 `Select` 组件的 `options`,我们**强烈不建议**使用 `undefined` 和 `null` 作为 `option` 中的 `value`,请使用 `string | number` 作为 `option` 的 `value`。
|
||||
|
||||
## 官方文档中没有提供的隐藏 API 我可以使用吗?
|
||||
|
||||
不推荐。对内接口不保证兼容性,它很可能在某个版本中因重构而移除。如果你确实需要使用,需自行确保版本升级时隐藏接口仍旧可用,或者锁定版本。
|
||||
|
||||
## 当我点击 `Select Dropdown DatePicker TimePicker Popover Popconfirm` 内的另一个 popup 组件时它会消失,如何解决?
|
||||
|
||||
该问题在 `3.11.0` 后已经解决。如果你仍在使用旧版本,你可以通过 `<Select getPopupContainer={trigger => trigger.parentElement}>` 来在 Popover 中渲染组件,或者使用其他的 `getXxxxContainer` 参数。
|
||||
|
@ -132,7 +132,7 @@
|
||||
"rc-field-form": "~1.27.0",
|
||||
"rc-image": "~5.7.0",
|
||||
"rc-input": "~0.0.1-alpha.5",
|
||||
"rc-input-number": "~7.3.0",
|
||||
"rc-input-number": "~7.3.5",
|
||||
"rc-mentions": "~1.9.0",
|
||||
"rc-menu": "~9.6.0",
|
||||
"rc-motion": "^2.6.1",
|
||||
|
Loading…
Reference in New Issue
Block a user