mirror of
https://gitee.com/ant-design/ant-design.git
synced 2024-11-30 19:19:26 +08:00
commit
85707ff36f
4
.github/CODEOWNERS
vendored
Normal file
4
.github/CODEOWNERS
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
package.json @ant-design/ant-design-core
|
||||
.github/workflows/ @ant-design/ant-design-core
|
||||
scripts/ @ant-design/ant-design-core
|
||||
LICENSE @ant-design/ant-design-core
|
2
.github/workflows/verify-files-modify.yml
vendored
2
.github/workflows/verify-files-modify.yml
vendored
@ -22,7 +22,7 @@ jobs:
|
||||
assignees: 'afc163, zombieJ, xrkffgg, MadCcc'
|
||||
comment-mark: 'version'
|
||||
comment: |
|
||||
Hi @${{ github.event.pull_request.user.login }}. Thanks for your contribution. The path `.github/` or `scripts/` and `CHANGELOG` `package.json` is only maintained by team members. This current PR will be closed and team members will help on this.
|
||||
Hi @${{ github.event.pull_request.user.login }}. Thanks for your contribution. The path `.github/` or `scripts/` and `CHANGELOG` is only maintained by team members. This current PR will be closed and team members will help on this.
|
||||
close: true
|
||||
set-failed: false
|
||||
|
||||
|
@ -15,6 +15,22 @@ timeline: true
|
||||
|
||||
---
|
||||
|
||||
## 4.20.2
|
||||
|
||||
`2022-04-30`
|
||||
|
||||
- Segmented
|
||||
- 🐞 Fix Segmented inconsisit height with other controls. [#35281](https://github.com/ant-design/ant-design/pull/35281)
|
||||
- 🐞 Fix Segmented animation not working correct in StrictMode mode. [#35281](https://github.com/ant-design/ant-design/pull/35281)
|
||||
- 🆕 Segmented `options` now supports `icon` property. [#35256](https://github.com/ant-design/ant-design/pull/35256)
|
||||
- Table
|
||||
- ⌨️ Improve Table columns sorter a11y experience. [#35269](https://github.com/ant-design/ant-design/pull/35269)
|
||||
- 🇪🇸 Added Table filter localization for es_ES. [#35309](https://github.com/ant-design/ant-design/pull/35309) [@agarciaguillo](https://github.com/agarciaguillo)
|
||||
- 💄 Fix Switch color in dark theme. [#35332](https://github.com/ant-design/ant-design/pull/35332)
|
||||
- 💄 Tweak Breadcrumb link hover color. [#35324](https://github.com/ant-design/ant-design/pull/35324)
|
||||
- 🐞 Fix Space throws `Encountered two children with the same key` warning in some cases. [#35311](https://github.com/ant-design/ant-design/pull/35311)
|
||||
- 🐞 Fix Select tag remove icon position issue. [#35336](https://github.com/ant-design/ant-design/pull/35336) [@walidcherhane](https://github.com/walidcherhane)
|
||||
|
||||
## 4.20.1
|
||||
|
||||
`2022-04-26`
|
||||
|
@ -15,6 +15,22 @@ timeline: true
|
||||
|
||||
---
|
||||
|
||||
## 4.20.2
|
||||
|
||||
`2022-04-30`
|
||||
|
||||
- Segmented
|
||||
- 🐞 修复 Segmented 组件高度和其他控件不一致的问题。[#35281](https://github.com/ant-design/ant-design/pull/35281)
|
||||
- 🐞 修复 React StrictMode 下 Segmented 动画丢失的问题。[#35281](https://github.com/ant-design/ant-design/pull/35281)
|
||||
- 🆕 Segmented `options` 支持设置 `icon` 属性。[#35256](https://github.com/ant-design/ant-design/pull/35256)
|
||||
- Table
|
||||
- ⌨️ 优化 Table 排序按钮的键盘可访问性。[#35269](https://github.com/ant-design/ant-design/pull/35269)
|
||||
- 🇪🇸 补充 Table 西班牙语筛选文案。[#35309](https://github.com/ant-design/ant-design/pull/35309) [@agarciaguillo](https://github.com/agarciaguillo)
|
||||
- 🐞 修复 Switch 在暗黑主题下关闭时的颜色问题。[#35332](https://github.com/ant-design/ant-design/pull/35332)
|
||||
- 💄 微调 Breadcrumb 链接 hover 色为中性色。[#35324](https://github.com/ant-design/ant-design/pull/35324)
|
||||
- 🐞 修复 Space 在某些情况下抛出 `Encountered two children with the same key` 警告的问题。[#35311](https://github.com/ant-design/ant-design/pull/35311)
|
||||
- 🐞 修复 Select 多选标签移除图标位置偏下的问题。[#35336](https://github.com/ant-design/ant-design/pull/35336) [@walidcherhane](https://github.com/walidcherhane)
|
||||
|
||||
## 4.20.1
|
||||
|
||||
`2022-04-26`
|
||||
|
@ -10,6 +10,7 @@ import Group from '../../radio/group';
|
||||
import Button from '../../radio/radioButton';
|
||||
import mountTest from '../../../tests/shared/mountTest';
|
||||
import rtlTest from '../../../tests/shared/rtlTest';
|
||||
import { render, fireEvent } from '../../../tests/utils';
|
||||
|
||||
describe('Calendar', () => {
|
||||
mountTest(Calendar);
|
||||
@ -40,14 +41,21 @@ describe('Calendar', () => {
|
||||
});
|
||||
|
||||
it('Calendar should be selectable', () => {
|
||||
MockDate.set(Moment('2000-01-01').valueOf());
|
||||
|
||||
const onSelect = jest.fn();
|
||||
const onChange = jest.fn();
|
||||
const wrapper = mount(<Calendar onSelect={onSelect} onChange={onChange} />);
|
||||
wrapper.find('.ant-picker-cell').at(0).simulate('click');
|
||||
const { container } = render(<Calendar onSelect={onSelect} onChange={onChange} />);
|
||||
|
||||
fireEvent.click(container.querySelector('.ant-picker-cell'));
|
||||
expect(onSelect).toHaveBeenCalledWith(expect.anything());
|
||||
|
||||
const value = onSelect.mock.calls[0][0];
|
||||
expect(Moment.isMoment(value)).toBe(true);
|
||||
|
||||
expect(onChange).toHaveBeenCalled();
|
||||
|
||||
MockDate.reset();
|
||||
});
|
||||
|
||||
it('only Valid range should be selectable', () => {
|
||||
|
@ -139,6 +139,8 @@ function generateCalendar<DateType>(generateConfig: GenerateConfig<DateType>) {
|
||||
};
|
||||
|
||||
const triggerChange = (date: DateType) => {
|
||||
console.log('trigger change!!!', isSameDate(date, mergedValue));
|
||||
console.log('trigger change!!!', String(date), String(mergedValue));
|
||||
setMergedValue(date);
|
||||
|
||||
if (!isSameDate(date, mergedValue)) {
|
||||
|
@ -22867,6 +22867,7 @@ exports[`ConfigProvider components Table configProvider 1`] = `
|
||||
<tr>
|
||||
<th
|
||||
class="config-table-cell config-table-column-has-sorters"
|
||||
tabindex="0"
|
||||
>
|
||||
<div
|
||||
class="config-table-filter-column"
|
||||
@ -23147,6 +23148,7 @@ exports[`ConfigProvider components Table configProvider componentSize large 1`]
|
||||
<tr>
|
||||
<th
|
||||
class="config-table-cell config-table-column-has-sorters"
|
||||
tabindex="0"
|
||||
>
|
||||
<div
|
||||
class="config-table-filter-column"
|
||||
@ -23427,6 +23429,7 @@ exports[`ConfigProvider components Table configProvider componentSize middle 1`]
|
||||
<tr>
|
||||
<th
|
||||
class="config-table-cell config-table-column-has-sorters"
|
||||
tabindex="0"
|
||||
>
|
||||
<div
|
||||
class="config-table-filter-column"
|
||||
@ -23707,6 +23710,7 @@ exports[`ConfigProvider components Table configProvider virtual and dropdownMatc
|
||||
<tr>
|
||||
<th
|
||||
class="ant-table-cell ant-table-column-has-sorters"
|
||||
tabindex="0"
|
||||
>
|
||||
<div
|
||||
class="ant-table-filter-column"
|
||||
@ -23987,6 +23991,7 @@ exports[`ConfigProvider components Table normal 1`] = `
|
||||
<tr>
|
||||
<th
|
||||
class="ant-table-cell ant-table-column-has-sorters"
|
||||
tabindex="0"
|
||||
>
|
||||
<div
|
||||
class="ant-table-filter-column"
|
||||
@ -24267,6 +24272,7 @@ exports[`ConfigProvider components Table prefixCls 1`] = `
|
||||
<tr>
|
||||
<th
|
||||
class="prefix-Table-cell prefix-Table-column-has-sorters"
|
||||
tabindex="0"
|
||||
>
|
||||
<div
|
||||
class="prefix-Table-filter-column"
|
||||
|
@ -1,7 +1,7 @@
|
||||
import React from 'react';
|
||||
import { mount } from 'enzyme';
|
||||
import Empty from '..';
|
||||
import ConfigProvider from '../../config-provider';
|
||||
import { render } from '../../../tests/utils';
|
||||
import mountTest from '../../../tests/shared/mountTest';
|
||||
import rtlTest from '../../../tests/shared/rtlTest';
|
||||
|
||||
@ -10,21 +10,21 @@ describe('Empty', () => {
|
||||
rtlTest(Empty);
|
||||
|
||||
it('image size should change', () => {
|
||||
const wrapper = mount(<Empty imageStyle={{ height: 20 }} />);
|
||||
expect(wrapper.find('.ant-empty-image').props().style.height).toBe(20);
|
||||
const { container } = render(<Empty imageStyle={{ height: 20 }} />);
|
||||
expect(container.querySelector('.ant-empty-image').style.height).toBe('20px');
|
||||
});
|
||||
|
||||
it('description can be false', () => {
|
||||
const wrapper = mount(<Empty description={false} />);
|
||||
expect(wrapper.find('.ant-empty-description').length).toBe(0);
|
||||
const { container } = render(<Empty description={false} />);
|
||||
expect(container.querySelector('.ant-empty-description')).toBeFalsy();
|
||||
});
|
||||
|
||||
it('should render in RTL direction', () => {
|
||||
const wrapper = mount(
|
||||
const { asFragment } = render(
|
||||
<ConfigProvider direction="rtl">
|
||||
<Empty />
|
||||
</ConfigProvider>,
|
||||
);
|
||||
expect(wrapper.render()).toMatchSnapshot();
|
||||
expect(asFragment().firstChild).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
|
@ -283,7 +283,7 @@ validateFields()
|
||||
|
||||
### Form.useForm
|
||||
|
||||
`type Form.useForm = (): FormInstance`
|
||||
`type Form.useForm = (): [FormInstance]`
|
||||
|
||||
Create Form instance to maintain data store.
|
||||
|
||||
|
@ -282,7 +282,7 @@ validateFields()
|
||||
|
||||
### Form.useForm
|
||||
|
||||
`type Form.useForm = (): FormInstance`
|
||||
`type Form.useForm = (): [FormInstance]`
|
||||
|
||||
创建 Form 实例,用于管理所有数据状态。
|
||||
|
||||
|
@ -21,6 +21,8 @@ const localeValues: Locale = {
|
||||
filterConfirm: 'Aceptar',
|
||||
filterReset: 'Reiniciar',
|
||||
filterEmptyText: 'Sin filtros',
|
||||
filterCheckall: 'Seleccionar todo',
|
||||
filterSearchPlaceholder: 'Buscar en filtros',
|
||||
emptyText: 'Sin datos',
|
||||
selectAll: 'Seleccionar todo',
|
||||
selectInvert: 'Invertir selección',
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,5 +1,7 @@
|
||||
import React from 'react';
|
||||
import { mount } from 'enzyme';
|
||||
import { AppstoreOutlined, BarsOutlined } from '@ant-design/icons';
|
||||
|
||||
import mountTest from '../../../tests/shared/mountTest';
|
||||
import rtlTest from '../../../tests/shared/rtlTest';
|
||||
import Segmented from '../index';
|
||||
@ -86,10 +88,7 @@ describe('Segmented', () => {
|
||||
it('render segmented with string options', () => {
|
||||
const handleValueChange = jest.fn();
|
||||
const wrapper = mount(
|
||||
<Segmented
|
||||
options={['Daily', 'Weekly', 'Monthly']}
|
||||
onChange={handleValueChange}
|
||||
/>,
|
||||
<Segmented options={['Daily', 'Weekly', 'Monthly']} onChange={handleValueChange} />,
|
||||
);
|
||||
expect(wrapper.render()).toMatchSnapshot();
|
||||
|
||||
@ -356,4 +355,25 @@ describe('Segmented', () => {
|
||||
|
||||
expect(wrapper.find(`.${prefixCls}`).at(0).hasClass(`${prefixCls}-lg`)).toBeTruthy();
|
||||
});
|
||||
|
||||
it('render with icons', () => {
|
||||
const wrapper = mount(
|
||||
<Segmented
|
||||
options={[
|
||||
{
|
||||
value: 'List',
|
||||
icon: <BarsOutlined />,
|
||||
},
|
||||
{
|
||||
value: 'Kanban',
|
||||
label: 'KanbanYes',
|
||||
icon: <AppstoreOutlined />,
|
||||
},
|
||||
]}
|
||||
/>,
|
||||
);
|
||||
expect(wrapper.render()).toMatchSnapshot();
|
||||
expect(wrapper.find(`span.${prefixCls}-item-icon`).length).toBe(2);
|
||||
expect(wrapper.find(`div.${prefixCls}-item-label`).at(1).contains('KanbanYes')).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
@ -1,5 +1,5 @@
|
||||
---
|
||||
order: 10
|
||||
order: 1
|
||||
title:
|
||||
zh-CN: Block 分段选择器
|
||||
en-US: Block Segmented
|
||||
|
@ -1,5 +1,5 @@
|
||||
---
|
||||
order: 0
|
||||
order: 3
|
||||
title:
|
||||
zh-CN: 受控模式
|
||||
en-US: Controlled mode
|
||||
|
@ -1,5 +1,5 @@
|
||||
---
|
||||
order: 1
|
||||
order: 4
|
||||
title:
|
||||
zh-CN: 自定义渲染
|
||||
en-US: Custom Render
|
||||
@ -23,28 +23,28 @@ export default () => (
|
||||
options={[
|
||||
{
|
||||
label: (
|
||||
<>
|
||||
<div style={{ padding: 4 }}>
|
||||
<Avatar src="https://joeschmoe.io/api/v1/random" />
|
||||
<div>User 1</div>
|
||||
</>
|
||||
</div>
|
||||
),
|
||||
value: 'user1',
|
||||
},
|
||||
{
|
||||
label: (
|
||||
<>
|
||||
<div style={{ padding: 4 }}>
|
||||
<Avatar style={{ backgroundColor: '#f56a00' }}>K</Avatar>
|
||||
<div>User 2</div>
|
||||
</>
|
||||
</div>
|
||||
),
|
||||
value: 'user2',
|
||||
},
|
||||
{
|
||||
label: (
|
||||
<>
|
||||
<div style={{ padding: 4 }}>
|
||||
<Avatar style={{ backgroundColor: '#87d068' }} icon={<UserOutlined />} />
|
||||
<div>User 3</div>
|
||||
</>
|
||||
</div>
|
||||
),
|
||||
value: 'user3',
|
||||
},
|
||||
@ -55,37 +55,37 @@ export default () => (
|
||||
options={[
|
||||
{
|
||||
label: (
|
||||
<>
|
||||
<div style={{ padding: 4 }}>
|
||||
<div>Spring</div>
|
||||
<div>Jan-Mar</div>
|
||||
</>
|
||||
</div>
|
||||
),
|
||||
value: 'spring',
|
||||
},
|
||||
{
|
||||
label: (
|
||||
<>
|
||||
<div style={{ padding: 4 }}>
|
||||
<div>Summer</div>
|
||||
<div>Apr-Jun</div>
|
||||
</>
|
||||
</div>
|
||||
),
|
||||
value: 'summer',
|
||||
},
|
||||
{
|
||||
label: (
|
||||
<>
|
||||
<div style={{ padding: 4 }}>
|
||||
<div>Autumn</div>
|
||||
<div>Jul-Sept</div>
|
||||
</>
|
||||
</div>
|
||||
),
|
||||
value: 'autumn',
|
||||
},
|
||||
{
|
||||
label: (
|
||||
<>
|
||||
<div style={{ padding: 4 }}>
|
||||
<div>Winter</div>
|
||||
<div>Oct-Dec</div>
|
||||
</>
|
||||
</div>
|
||||
),
|
||||
value: 'winter',
|
||||
},
|
||||
|
@ -1,5 +1,5 @@
|
||||
---
|
||||
order: 0
|
||||
order: 2
|
||||
title:
|
||||
zh-CN: 不可用
|
||||
en-US: Basic
|
||||
|
@ -1,5 +1,5 @@
|
||||
---
|
||||
order: 0
|
||||
order: 5
|
||||
title:
|
||||
zh-CN: 动态数据
|
||||
en-US: Dynamic
|
||||
|
34
components/segmented/demo/icon-only.md
Normal file
34
components/segmented/demo/icon-only.md
Normal file
@ -0,0 +1,34 @@
|
||||
---
|
||||
order: 8
|
||||
title:
|
||||
zh-CN: 只设置图标
|
||||
en-US: With Icon only
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
在 Segmented Item 选项中只设置 Icon。
|
||||
|
||||
## en-US
|
||||
|
||||
Set `icon` without `label` for Segmented Item.
|
||||
|
||||
```jsx
|
||||
import { Segmented } from 'antd';
|
||||
import { AppstoreOutlined, BarsOutlined } from '@ant-design/icons';
|
||||
|
||||
export default () => (
|
||||
<Segmented
|
||||
options={[
|
||||
{
|
||||
value: 'List',
|
||||
icon: <BarsOutlined />,
|
||||
},
|
||||
{
|
||||
value: 'Kanban',
|
||||
icon: <AppstoreOutlined />,
|
||||
},
|
||||
]}
|
||||
/>
|
||||
);
|
||||
```
|
40
components/segmented/demo/size-consistent.md
Normal file
40
components/segmented/demo/size-consistent.md
Normal file
@ -0,0 +1,40 @@
|
||||
---
|
||||
order: 99
|
||||
title:
|
||||
zh-CN: 统一高度
|
||||
en-US: Consistent height
|
||||
debug: true
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
与其他组件保持统一高度。
|
||||
|
||||
## en-US
|
||||
|
||||
Keep consistent height with other components.
|
||||
|
||||
```jsx
|
||||
import { Button, Input, Select, Segmented } from 'antd';
|
||||
|
||||
export default () => (
|
||||
<>
|
||||
<div>
|
||||
<Segmented style={{ marginRight: 6 }} size="large" options={['Daily', 'Weekly', 'Monthly']} />
|
||||
<Button type="primary" size="large">
|
||||
Button
|
||||
</Button>
|
||||
</div>
|
||||
<div>
|
||||
<Segmented style={{ marginRight: 6 }} options={['Daily', 'Weekly', 'Monthly']} />
|
||||
<Input placeholder="default size" style={{ width: 150 }} />
|
||||
</div>
|
||||
<div>
|
||||
<Segmented style={{ marginRight: 6 }} size="small" options={['Daily', 'Weekly', 'Monthly']} />
|
||||
<Select size="small" defaultValue="lucy" style={{ width: 150 }}>
|
||||
<Select.Option value="lucy">Lucy</Select.Option>
|
||||
</Select>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
```
|
@ -1,5 +1,5 @@
|
||||
---
|
||||
order: 1
|
||||
order: 6
|
||||
title:
|
||||
zh-CN: 三种大小
|
||||
en-US: Three sizes of Segmented
|
||||
|
@ -1,5 +1,5 @@
|
||||
---
|
||||
order: 0
|
||||
order: 7
|
||||
title:
|
||||
zh-CN: 设置图标
|
||||
en-US: With Icon
|
||||
|
@ -12,12 +12,27 @@ import SizeContext, { SizeType } from '../config-provider/SizeContext';
|
||||
|
||||
export type { SegmentedValue } from 'rc-segmented';
|
||||
|
||||
export interface SegmentedLabeledOption extends RcSegmentedLabeledOption {
|
||||
/** Set icon for Segmented item */
|
||||
icon?: React.ReactNode;
|
||||
interface SegmentedLabeledOptionWithoutIcon extends RcSegmentedLabeledOption {
|
||||
label: RcSegmentedLabeledOption['label'];
|
||||
}
|
||||
|
||||
export interface SegmentedProps extends Omit<RCSegmentedProps, 'size'> {
|
||||
interface SegmentedLabeledOptionWithIcon extends Omit<RcSegmentedLabeledOption, 'label'> {
|
||||
label?: RcSegmentedLabeledOption['label'];
|
||||
/** Set icon for Segmented item */
|
||||
icon: React.ReactNode;
|
||||
}
|
||||
|
||||
function isSegmentedLabeledOptionWithIcon(
|
||||
option: SegmentedRawOption | SegmentedLabeledOptionWithIcon | SegmentedLabeledOptionWithoutIcon,
|
||||
): option is SegmentedLabeledOptionWithIcon {
|
||||
return typeof option === 'object' && !!(option as SegmentedLabeledOptionWithIcon)?.icon;
|
||||
}
|
||||
|
||||
export type SegmentedLabeledOption =
|
||||
| SegmentedLabeledOptionWithIcon
|
||||
| SegmentedLabeledOptionWithoutIcon;
|
||||
|
||||
export interface SegmentedProps extends Omit<RCSegmentedProps, 'size' | 'options'> {
|
||||
options: (SegmentedRawOption | SegmentedLabeledOption)[];
|
||||
/** Option to fit width to its parent's width */
|
||||
block?: boolean;
|
||||
@ -46,14 +61,14 @@ const Segmented = React.forwardRef<HTMLDivElement, SegmentedProps>((props, ref)
|
||||
const extendedOptions = React.useMemo(
|
||||
() =>
|
||||
options.map(option => {
|
||||
if (typeof option === 'object' && option?.icon) {
|
||||
if (isSegmentedLabeledOptionWithIcon(option)) {
|
||||
const { icon, label, ...restOption } = option;
|
||||
return {
|
||||
...restOption,
|
||||
label: (
|
||||
<>
|
||||
<span className={`${prefixCls}-item-icon`}>{icon}</span>
|
||||
<span>{label}</span>
|
||||
{label && <span>{label}</span>}
|
||||
</>
|
||||
),
|
||||
};
|
||||
|
@ -4,26 +4,23 @@
|
||||
|
||||
@segmented-prefix-cls: ~'@{ant-prefix}-segmented';
|
||||
|
||||
@segmented-container-padding: 2px;
|
||||
|
||||
.@{segmented-prefix-cls} {
|
||||
.reset-component();
|
||||
|
||||
position: relative;
|
||||
display: inline-flex;
|
||||
align-items: stretch;
|
||||
justify-items: flex-start;
|
||||
display: inline-block;
|
||||
padding: @segmented-container-padding;
|
||||
color: @segmented-label-color;
|
||||
background-color: @segmented-bg;
|
||||
border-radius: 2px;
|
||||
box-shadow: 0 0 0 2px @segmented-bg;
|
||||
transition: all 0.3s @ease-in-out;
|
||||
|
||||
// hover/focus styles
|
||||
&:not(&-disabled) {
|
||||
&:hover,
|
||||
&:focus {
|
||||
background-color: @segmented-hover-bg;
|
||||
box-shadow: 0 0 0 2px @segmented-hover-bg;
|
||||
}
|
||||
&-group {
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: stretch;
|
||||
justify-items: flex-start;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
// block styles
|
||||
@ -36,6 +33,14 @@
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
// hover/focus styles
|
||||
&:not(&-disabled) {
|
||||
&:hover,
|
||||
&:focus {
|
||||
background-color: @segmented-hover-bg;
|
||||
}
|
||||
}
|
||||
|
||||
// item styles
|
||||
&-item {
|
||||
position: relative;
|
||||
@ -54,15 +59,15 @@
|
||||
}
|
||||
|
||||
&-label {
|
||||
min-height: @input-height-base;
|
||||
padding: @input-padding-vertical-base @input-padding-horizontal-base;
|
||||
line-height: @input-height-base - @input-padding-vertical-base * 2;
|
||||
min-height: @input-height-base - @segmented-container-padding * 2;
|
||||
padding: 0 @input-padding-horizontal-base;
|
||||
line-height: @input-height-base - @segmented-container-padding * 2;
|
||||
.segmented-text-ellipsis();
|
||||
}
|
||||
|
||||
// syntactic sugar to add `icon` for Segmented Item
|
||||
&-icon {
|
||||
margin-right: 6px;
|
||||
&-icon + * {
|
||||
margin-left: 6px;
|
||||
}
|
||||
|
||||
&-input {
|
||||
@ -78,20 +83,19 @@
|
||||
|
||||
// size styles
|
||||
&&-lg &-item-label {
|
||||
min-height: @input-height-lg;
|
||||
padding: @input-padding-vertical-lg @input-padding-horizontal-lg;
|
||||
min-height: @input-height-lg - @segmented-container-padding * 2;
|
||||
padding: 0 @input-padding-horizontal-lg;
|
||||
font-size: @font-size-lg;
|
||||
line-height: @input-height-lg - @input-padding-vertical-lg * 2;
|
||||
line-height: @input-height-lg - @segmented-container-padding * 2;
|
||||
}
|
||||
|
||||
&&-sm &-item-label {
|
||||
min-height: @input-height-sm;
|
||||
padding: @input-padding-vertical-sm @input-padding-horizontal-sm;
|
||||
line-height: @input-height-sm - @input-padding-vertical-sm * 2;
|
||||
min-height: @input-height-sm - @segmented-container-padding * 2;
|
||||
padding: 0 @input-padding-horizontal-sm;
|
||||
line-height: @input-height-sm - @segmented-container-padding * 2;
|
||||
}
|
||||
|
||||
// disabled styles
|
||||
&-disabled &-item,
|
||||
&-item-disabled {
|
||||
.segmented-disabled-item();
|
||||
}
|
||||
@ -108,8 +112,8 @@
|
||||
padding: 4px 0;
|
||||
}
|
||||
|
||||
// transition effect when `enter-active`
|
||||
&-thumb-motion-enter-active {
|
||||
// transition effect when `appear-active`
|
||||
&-thumb-motion-appear-active {
|
||||
transition: transform 0.3s @ease-in-out, width 0.3s @ease-in-out;
|
||||
will-change: transform, width;
|
||||
}
|
||||
|
@ -64,7 +64,7 @@ Select component to select value from options.
|
||||
| status | Set validation status | 'error' \| 'warning' | - | 4.19.0 |
|
||||
| suffixIcon | The custom suffix icon | ReactNode | - | |
|
||||
| tagRender | Customize tag render, only applies when `mode` is set to `multiple` or `tags` | (props) => ReactNode | - | |
|
||||
| tokenSeparators | Separator used to tokenize on `tag` and `multiple` mode | string\[] | - | |
|
||||
| tokenSeparators | Separator used to tokenize, only applies when `mode="tags"` | string\[] | - | |
|
||||
| value | Current selected option (considered as a immutable array) | string \| string\[]<br />number \| number\[]<br />LabeledValue \| LabeledValue\[] | - | |
|
||||
| virtual | Disable virtual scroll when set to false | boolean | true | 4.1.0 |
|
||||
| onBlur | Called when blur | function | - | |
|
||||
|
@ -65,7 +65,7 @@ cover: https://gw.alipayobjects.com/zos/alicdn/_0XzgOis7/Select.svg
|
||||
| status | 设置校验状态 | 'error' \| 'warning' | - | 4.19.0 |
|
||||
| suffixIcon | 自定义的选择框后缀图标 | ReactNode | - | |
|
||||
| tagRender | 自定义 tag 内容 render,仅在 `mode` 为 `multiple` 或 `tags` 时生效 | (props) => ReactNode | - | |
|
||||
| tokenSeparators | 在 `tags` 和 `multiple` 模式下自动分词的分隔符 | string\[] | - | |
|
||||
| tokenSeparators | 自动分词的分隔符,仅在 `mode="tags"` 时生效 | string\[] | - | |
|
||||
| value | 指定当前选中的条目,多选时为一个数组。(value 数组引用未变化时,Select 不会更新) | string \| string\[]<br />number \| number\[]<br />LabeledValue \| LabeledValue\[] | - | |
|
||||
| virtual | 设置 false 时关闭虚拟滚动 | boolean | true | 4.1.0 |
|
||||
| onBlur | 失去焦点时回调 | function | - | |
|
||||
|
@ -110,7 +110,7 @@
|
||||
cursor: pointer;
|
||||
|
||||
> .@{iconfont-css-prefix} {
|
||||
vertical-align: -0.2em;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
|
@ -172,4 +172,25 @@ describe('Space', () => {
|
||||
|
||||
expect(wrapper.render()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
// https://github.com/ant-design/ant-design/issues/35305
|
||||
it('should not throw duplicated key warning', () => {
|
||||
jest.spyOn(console, 'error').mockImplementation(() => undefined);
|
||||
mount(
|
||||
<Space>
|
||||
<div key="1" />
|
||||
<div />
|
||||
<div key="3" />
|
||||
<div />
|
||||
</Space>,
|
||||
);
|
||||
// eslint-disable-next-line no-console
|
||||
expect(console.error).not.toHaveBeenCalledWith(
|
||||
expect.stringContaining('Encountered two children with the same key'),
|
||||
expect.anything(),
|
||||
expect.anything(),
|
||||
);
|
||||
// eslint-disable-next-line no-console
|
||||
console.error.mockRestore();
|
||||
});
|
||||
});
|
||||
|
@ -17,22 +17,20 @@ Crowded components horizontal spacing.
|
||||
import { Button, Space, Upload, Popconfirm } from 'antd';
|
||||
import { UploadOutlined } from '@ant-design/icons';
|
||||
|
||||
function SpaceDemo() {
|
||||
return (
|
||||
<Space>
|
||||
Space
|
||||
<Button type="primary">Button</Button>
|
||||
<Upload>
|
||||
<Button>
|
||||
<UploadOutlined /> Click to Upload
|
||||
</Button>
|
||||
</Upload>
|
||||
<Popconfirm title="Are you sure delete this task?" okText="Yes" cancelText="No">
|
||||
<Button>Confirm</Button>
|
||||
</Popconfirm>
|
||||
</Space>
|
||||
);
|
||||
}
|
||||
const App = () => (
|
||||
<Space>
|
||||
Space
|
||||
<Button type="primary">Button</Button>
|
||||
<Upload>
|
||||
<Button>
|
||||
<UploadOutlined /> Click to Upload
|
||||
</Button>
|
||||
</Upload>
|
||||
<Popconfirm title="Are you sure delete this task?" okText="Yes" cancelText="No">
|
||||
<Button>Confirm</Button>
|
||||
</Popconfirm>
|
||||
</Space>
|
||||
);
|
||||
|
||||
export default () => <SpaceDemo />;
|
||||
export default App;
|
||||
```
|
||||
|
@ -17,7 +17,7 @@ Custom spacing size.
|
||||
import React, { useState } from 'react';
|
||||
import { Space, Slider, Button } from 'antd';
|
||||
|
||||
function SpaceCustomizeSize() {
|
||||
function App() {
|
||||
const [size, setSize] = useState(8);
|
||||
|
||||
return (
|
||||
@ -35,5 +35,5 @@ function SpaceCustomizeSize() {
|
||||
);
|
||||
}
|
||||
|
||||
export default () => <SpaceCustomizeSize />;
|
||||
export default App;
|
||||
```
|
||||
|
@ -21,7 +21,7 @@ Set the size to `large` and `middle` by setting size to large and middle respect
|
||||
import React, { useState } from 'react';
|
||||
import { Space, Radio, Button } from 'antd';
|
||||
|
||||
function SpaceSize() {
|
||||
function App() {
|
||||
const [size, setSize] = useState('small');
|
||||
|
||||
return (
|
||||
@ -43,5 +43,5 @@ function SpaceSize() {
|
||||
);
|
||||
}
|
||||
|
||||
export default () => <SpaceSize />;
|
||||
export default App;
|
||||
```
|
||||
|
@ -16,15 +16,13 @@ Crowded components split.
|
||||
```jsx
|
||||
import { Space, Typography, Divider } from 'antd';
|
||||
|
||||
function SpaceSplit() {
|
||||
return (
|
||||
<Space split={<Divider type="vertical" />}>
|
||||
<Typography.Link>Link</Typography.Link>
|
||||
<Typography.Link>Link</Typography.Link>
|
||||
<Typography.Link>Link</Typography.Link>
|
||||
</Space>
|
||||
);
|
||||
}
|
||||
const App = () => (
|
||||
<Space split={<Divider type="vertical" />}>
|
||||
<Typography.Link>Link</Typography.Link>
|
||||
<Typography.Link>Link</Typography.Link>
|
||||
<Typography.Link>Link</Typography.Link>
|
||||
</Space>
|
||||
);
|
||||
|
||||
export default () => <SpaceSplit />;
|
||||
export default App;
|
||||
```
|
||||
|
@ -16,24 +16,22 @@ Crowded components vertical spacing.
|
||||
```jsx
|
||||
import { Space, Card } from 'antd';
|
||||
|
||||
function SpaceVertical() {
|
||||
return (
|
||||
<Space direction="vertical" size="middle" style={{ display: 'flex' }}>
|
||||
<Card title="Card" size="small">
|
||||
<p>Card content</p>
|
||||
<p>Card content</p>
|
||||
</Card>
|
||||
<Card title="Card" size="small">
|
||||
<p>Card content</p>
|
||||
<p>Card content</p>
|
||||
</Card>
|
||||
<Card title="Card" size="small">
|
||||
<p>Card content</p>
|
||||
<p>Card content</p>
|
||||
</Card>
|
||||
</Space>
|
||||
);
|
||||
}
|
||||
const App = () => (
|
||||
<Space direction="vertical" size="middle" style={{ display: 'flex' }}>
|
||||
<Card title="Card" size="small">
|
||||
<p>Card content</p>
|
||||
<p>Card content</p>
|
||||
</Card>
|
||||
<Card title="Card" size="small">
|
||||
<p>Card content</p>
|
||||
<p>Card content</p>
|
||||
</Card>
|
||||
<Card title="Card" size="small">
|
||||
<p>Card content</p>
|
||||
<p>Card content</p>
|
||||
</Card>
|
||||
</Space>
|
||||
);
|
||||
|
||||
export default () => <SpaceVertical />;
|
||||
export default App;
|
||||
```
|
||||
|
@ -16,7 +16,7 @@ Auto wrap line.
|
||||
```jsx
|
||||
import { Space, Button } from 'antd';
|
||||
|
||||
const Demo = () => (
|
||||
const App = () => (
|
||||
<Space size={[8, 16]} wrap>
|
||||
{new Array(20).fill(null).map((_, index) => (
|
||||
// eslint-disable-next-line react/no-array-index-key
|
||||
@ -25,5 +25,5 @@ const Demo = () => (
|
||||
</Space>
|
||||
);
|
||||
|
||||
export default Demo;
|
||||
export default App;
|
||||
```
|
||||
|
@ -89,11 +89,14 @@ const Space: React.FC<SpaceProps> = props => {
|
||||
}
|
||||
|
||||
const keyOfChild = child && child.key;
|
||||
// Add `-space-item` as suffix in case simple key string trigger duplicated key warning
|
||||
// https://github.com/ant-design/ant-design/issues/35305
|
||||
const defaultKey = `${i}-space-item`;
|
||||
|
||||
return (
|
||||
<Item
|
||||
className={itemClassName}
|
||||
key={`${itemClassName}-${keyOfChild || i}`}
|
||||
key={`${itemClassName}-${keyOfChild || defaultKey}`}
|
||||
direction={direction}
|
||||
index={i}
|
||||
marginDirection={marginDirection}
|
||||
|
@ -872,7 +872,7 @@
|
||||
@breadcrumb-font-size: @font-size-base;
|
||||
@breadcrumb-icon-font-size: @font-size-base;
|
||||
@breadcrumb-link-color: @text-color-secondary;
|
||||
@breadcrumb-link-color-hover: @primary-5;
|
||||
@breadcrumb-link-color-hover: @text-color;
|
||||
@breadcrumb-separator-color: @text-color-secondary;
|
||||
@breadcrumb-separator-margin: 0 @padding-xs;
|
||||
|
||||
|
@ -927,7 +927,7 @@
|
||||
@breadcrumb-font-size: @font-size-base;
|
||||
@breadcrumb-icon-font-size: @font-size-base;
|
||||
@breadcrumb-link-color: @text-color-secondary;
|
||||
@breadcrumb-link-color-hover: @primary-5;
|
||||
@breadcrumb-link-color-hover: @text-color;
|
||||
@breadcrumb-separator-color: @text-color-secondary;
|
||||
@breadcrumb-separator-margin: 0 @padding-xs;
|
||||
|
||||
|
@ -18,7 +18,7 @@
|
||||
line-height: @switch-height;
|
||||
vertical-align: middle;
|
||||
background-image: linear-gradient(to right, @disabled-color, @disabled-color),
|
||||
linear-gradient(to right, @white, @white);
|
||||
linear-gradient(to right, @component-background, @component-background);
|
||||
border: 0;
|
||||
border-radius: 100px;
|
||||
cursor: pointer;
|
||||
|
@ -119,6 +119,18 @@ describe('Table.sorter', () => {
|
||||
expect(getNameColumn().prop('aria-sort')).toEqual('descending');
|
||||
});
|
||||
|
||||
it('sort records with keydown', () => {
|
||||
const wrapper = mount(createTable());
|
||||
|
||||
// ascend
|
||||
wrapper.find('.ant-table-column-sorters').simulate('keydown', { keyCode: 13 });
|
||||
expect(renderedNames(wrapper)).toEqual(['Jack', 'Jerry', 'Lucy', 'Tom']);
|
||||
|
||||
// descend
|
||||
wrapper.find('.ant-table-column-sorters').simulate('keydown', { keyCode: 13 });
|
||||
expect(renderedNames(wrapper)).toEqual(['Tom', 'Lucy', 'Jack', 'Jerry']);
|
||||
});
|
||||
|
||||
describe('can be controlled by sortOrder', () => {
|
||||
it('single', () => {
|
||||
const wrapper = mount(
|
||||
|
@ -7,6 +7,7 @@ exports[`Table.sorter renders sorter icon correctly 1`] = `
|
||||
<tr>
|
||||
<th
|
||||
class="ant-table-cell ant-table-column-has-sorters"
|
||||
tabindex="0"
|
||||
>
|
||||
<div
|
||||
class="ant-table-column-sorters"
|
||||
@ -98,6 +99,7 @@ exports[`Table.sorter should support defaultOrder in Column 1`] = `
|
||||
<th
|
||||
aria-sort="ascending"
|
||||
class="ant-table-cell ant-table-column-sort ant-table-column-has-sorters"
|
||||
tabindex="0"
|
||||
>
|
||||
<div
|
||||
class="ant-table-column-sorters"
|
||||
|
@ -36,6 +36,7 @@ exports[`renders ./components/table/demo/ajax.md extend context correctly 1`] =
|
||||
<tr>
|
||||
<th
|
||||
class="ant-table-cell ant-table-column-has-sorters"
|
||||
tabindex="0"
|
||||
>
|
||||
<div
|
||||
class="ant-table-column-sorters"
|
||||
@ -1516,6 +1517,7 @@ exports[`renders ./components/table/demo/custom-filter-panel.md extend context c
|
||||
</th>
|
||||
<th
|
||||
class="ant-table-cell ant-table-column-has-sorters"
|
||||
tabindex="0"
|
||||
>
|
||||
<div
|
||||
class="ant-table-filter-column"
|
||||
@ -3205,6 +3207,7 @@ Array [
|
||||
</th>
|
||||
<th
|
||||
class="ant-table-cell ant-table-column-has-sorters"
|
||||
tabindex="0"
|
||||
>
|
||||
<div
|
||||
class="ant-table-column-sorters"
|
||||
@ -3514,6 +3517,7 @@ Array [
|
||||
</th>
|
||||
<th
|
||||
class="ant-table-cell ant-table-column-has-sorters"
|
||||
tabindex="0"
|
||||
>
|
||||
<div
|
||||
class="ant-table-column-sorters"
|
||||
@ -7454,6 +7458,7 @@ exports[`renders ./components/table/demo/filter-in-tree.md extend context correc
|
||||
</th>
|
||||
<th
|
||||
class="ant-table-cell ant-table-column-has-sorters"
|
||||
tabindex="0"
|
||||
>
|
||||
<div
|
||||
class="ant-table-column-sorters"
|
||||
@ -8273,6 +8278,7 @@ exports[`renders ./components/table/demo/filter-search.md extend context correct
|
||||
</th>
|
||||
<th
|
||||
class="ant-table-cell ant-table-column-has-sorters"
|
||||
tabindex="0"
|
||||
>
|
||||
<div
|
||||
class="ant-table-column-sorters"
|
||||
@ -12145,6 +12151,7 @@ exports[`renders ./components/table/demo/grouping-columns.md extend context corr
|
||||
<th
|
||||
class="ant-table-cell ant-table-column-has-sorters"
|
||||
rowspan="3"
|
||||
tabindex="0"
|
||||
>
|
||||
<div
|
||||
class="ant-table-column-sorters"
|
||||
@ -13250,6 +13257,7 @@ exports[`renders ./components/table/demo/head.md extend context correctly 1`] =
|
||||
<tr>
|
||||
<th
|
||||
class="ant-table-cell ant-table-column-has-sorters"
|
||||
tabindex="0"
|
||||
>
|
||||
<div
|
||||
class="ant-table-filter-column"
|
||||
@ -13713,6 +13721,7 @@ exports[`renders ./components/table/demo/head.md extend context correctly 1`] =
|
||||
<th
|
||||
aria-sort="descending"
|
||||
class="ant-table-cell ant-table-column-sort ant-table-column-has-sorters"
|
||||
tabindex="0"
|
||||
>
|
||||
<div
|
||||
class="ant-table-column-sorters"
|
||||
@ -14574,6 +14583,7 @@ exports[`renders ./components/table/demo/multiple-sorter.md extend context corre
|
||||
</th>
|
||||
<th
|
||||
class="ant-table-cell ant-table-column-has-sorters"
|
||||
tabindex="0"
|
||||
>
|
||||
<div
|
||||
class="ant-table-column-sorters"
|
||||
@ -14657,6 +14667,7 @@ exports[`renders ./components/table/demo/multiple-sorter.md extend context corre
|
||||
</th>
|
||||
<th
|
||||
class="ant-table-cell ant-table-column-has-sorters"
|
||||
tabindex="0"
|
||||
>
|
||||
<div
|
||||
class="ant-table-column-sorters"
|
||||
@ -14740,6 +14751,7 @@ exports[`renders ./components/table/demo/multiple-sorter.md extend context corre
|
||||
</th>
|
||||
<th
|
||||
class="ant-table-cell ant-table-column-has-sorters"
|
||||
tabindex="0"
|
||||
>
|
||||
<div
|
||||
class="ant-table-column-sorters"
|
||||
@ -17420,6 +17432,7 @@ Array [
|
||||
<tr>
|
||||
<th
|
||||
class="ant-table-cell ant-table-cell-ellipsis ant-table-column-has-sorters"
|
||||
tabindex="0"
|
||||
>
|
||||
<div
|
||||
class="ant-table-filter-column"
|
||||
@ -17724,6 +17737,7 @@ Array [
|
||||
</th>
|
||||
<th
|
||||
class="ant-table-cell ant-table-cell-ellipsis ant-table-column-has-sorters"
|
||||
tabindex="0"
|
||||
>
|
||||
<div
|
||||
class="ant-table-column-sorters"
|
||||
@ -17807,6 +17821,7 @@ Array [
|
||||
</th>
|
||||
<th
|
||||
class="ant-table-cell ant-table-cell-ellipsis ant-table-column-has-sorters"
|
||||
tabindex="0"
|
||||
>
|
||||
<div
|
||||
class="ant-table-filter-column"
|
||||
@ -18347,6 +18362,7 @@ exports[`renders ./components/table/demo/resizable-column.md extend context corr
|
||||
</th>
|
||||
<th
|
||||
class="ant-table-cell ant-table-column-has-sorters react-resizable"
|
||||
tabindex="0"
|
||||
>
|
||||
<div
|
||||
class="ant-table-column-sorters"
|
||||
|
@ -36,6 +36,7 @@ exports[`renders ./components/table/demo/ajax.md correctly 1`] = `
|
||||
<tr>
|
||||
<th
|
||||
class="ant-table-cell ant-table-column-has-sorters"
|
||||
tabindex="0"
|
||||
>
|
||||
<div
|
||||
class="ant-table-column-sorters"
|
||||
@ -1134,6 +1135,7 @@ exports[`renders ./components/table/demo/custom-filter-panel.md correctly 1`] =
|
||||
</th>
|
||||
<th
|
||||
class="ant-table-cell ant-table-column-has-sorters"
|
||||
tabindex="0"
|
||||
>
|
||||
<div
|
||||
class="ant-table-filter-column"
|
||||
@ -2714,6 +2716,7 @@ Array [
|
||||
</th>
|
||||
<th
|
||||
class="ant-table-cell ant-table-column-has-sorters"
|
||||
tabindex="0"
|
||||
>
|
||||
<div
|
||||
class="ant-table-column-sorters"
|
||||
@ -2811,6 +2814,7 @@ Array [
|
||||
</th>
|
||||
<th
|
||||
class="ant-table-cell ant-table-column-has-sorters"
|
||||
tabindex="0"
|
||||
>
|
||||
<div
|
||||
class="ant-table-column-sorters"
|
||||
@ -5773,6 +5777,7 @@ exports[`renders ./components/table/demo/filter-in-tree.md correctly 1`] = `
|
||||
</th>
|
||||
<th
|
||||
class="ant-table-cell ant-table-column-has-sorters"
|
||||
tabindex="0"
|
||||
>
|
||||
<div
|
||||
class="ant-table-column-sorters"
|
||||
@ -6118,6 +6123,7 @@ exports[`renders ./components/table/demo/filter-search.md correctly 1`] = `
|
||||
</th>
|
||||
<th
|
||||
class="ant-table-cell ant-table-column-has-sorters"
|
||||
tabindex="0"
|
||||
>
|
||||
<div
|
||||
class="ant-table-column-sorters"
|
||||
@ -9316,6 +9322,7 @@ exports[`renders ./components/table/demo/grouping-columns.md correctly 1`] = `
|
||||
<th
|
||||
class="ant-table-cell ant-table-column-has-sorters"
|
||||
rowspan="3"
|
||||
tabindex="0"
|
||||
>
|
||||
<div
|
||||
class="ant-table-column-sorters"
|
||||
@ -10281,6 +10288,7 @@ exports[`renders ./components/table/demo/head.md correctly 1`] = `
|
||||
<tr>
|
||||
<th
|
||||
class="ant-table-cell ant-table-column-has-sorters"
|
||||
tabindex="0"
|
||||
>
|
||||
<div
|
||||
class="ant-table-filter-column"
|
||||
@ -10355,6 +10363,7 @@ exports[`renders ./components/table/demo/head.md correctly 1`] = `
|
||||
<th
|
||||
aria-sort="descending"
|
||||
class="ant-table-cell ant-table-column-sort ant-table-column-has-sorters"
|
||||
tabindex="0"
|
||||
>
|
||||
<div
|
||||
class="ant-table-column-sorters"
|
||||
@ -11004,6 +11013,7 @@ exports[`renders ./components/table/demo/multiple-sorter.md correctly 1`] = `
|
||||
</th>
|
||||
<th
|
||||
class="ant-table-cell ant-table-column-has-sorters"
|
||||
tabindex="0"
|
||||
>
|
||||
<div
|
||||
class="ant-table-column-sorters"
|
||||
@ -11063,6 +11073,7 @@ exports[`renders ./components/table/demo/multiple-sorter.md correctly 1`] = `
|
||||
</th>
|
||||
<th
|
||||
class="ant-table-cell ant-table-column-has-sorters"
|
||||
tabindex="0"
|
||||
>
|
||||
<div
|
||||
class="ant-table-column-sorters"
|
||||
@ -11122,6 +11133,7 @@ exports[`renders ./components/table/demo/multiple-sorter.md correctly 1`] = `
|
||||
</th>
|
||||
<th
|
||||
class="ant-table-cell ant-table-column-has-sorters"
|
||||
tabindex="0"
|
||||
>
|
||||
<div
|
||||
class="ant-table-column-sorters"
|
||||
@ -13662,6 +13674,7 @@ Array [
|
||||
<tr>
|
||||
<th
|
||||
class="ant-table-cell ant-table-cell-ellipsis ant-table-column-has-sorters"
|
||||
tabindex="0"
|
||||
>
|
||||
<div
|
||||
class="ant-table-filter-column"
|
||||
@ -13754,6 +13767,7 @@ Array [
|
||||
</th>
|
||||
<th
|
||||
class="ant-table-cell ant-table-cell-ellipsis ant-table-column-has-sorters"
|
||||
tabindex="0"
|
||||
>
|
||||
<div
|
||||
class="ant-table-column-sorters"
|
||||
@ -13813,6 +13827,7 @@ Array [
|
||||
</th>
|
||||
<th
|
||||
class="ant-table-cell ant-table-cell-ellipsis ant-table-column-has-sorters"
|
||||
tabindex="0"
|
||||
>
|
||||
<div
|
||||
class="ant-table-filter-column"
|
||||
@ -14141,6 +14156,7 @@ exports[`renders ./components/table/demo/resizable-column.md correctly 1`] = `
|
||||
</th>
|
||||
<th
|
||||
class="ant-table-cell ant-table-column-has-sorters react-resizable"
|
||||
tabindex="0"
|
||||
>
|
||||
<div
|
||||
class="ant-table-column-sorters"
|
||||
|
@ -2,6 +2,7 @@ import * as React from 'react';
|
||||
import classNames from 'classnames';
|
||||
import CaretDownOutlined from '@ant-design/icons/CaretDownOutlined';
|
||||
import CaretUpOutlined from '@ant-design/icons/CaretUpOutlined';
|
||||
import KeyCode from 'rc-util/lib/KeyCode';
|
||||
import {
|
||||
TransformColumns,
|
||||
ColumnsType,
|
||||
@ -104,7 +105,7 @@ function collectSortStates<RecordType>(
|
||||
function injectSorter<RecordType>(
|
||||
prefixCls: string,
|
||||
columns: ColumnsType<RecordType>,
|
||||
sorterSates: SortState<RecordType>[],
|
||||
sorterStates: SortState<RecordType>[],
|
||||
triggerSorter: (sorterSates: SortState<RecordType>) => void,
|
||||
defaultSortDirections: SortOrder[],
|
||||
tableLocale?: TableLocale,
|
||||
@ -122,7 +123,7 @@ function injectSorter<RecordType>(
|
||||
? tableShowSorterTooltip
|
||||
: newColumn.showSorterTooltip;
|
||||
const columnKey = getColumnKey(newColumn, columnPos);
|
||||
const sorterState = sorterSates.find(({ key }) => key === columnKey);
|
||||
const sorterState = sorterStates.find(({ key }) => key === columnKey);
|
||||
const sorterOrder = sorterState ? sorterState.sortOrder : null;
|
||||
const nextSortOrder = nextSortDirection(sortDirections, sorterOrder);
|
||||
const upNode: React.ReactNode = sortDirections.includes(ASCEND) && (
|
||||
@ -179,6 +180,7 @@ function injectSorter<RecordType>(
|
||||
const cell: React.HTMLAttributes<HTMLElement> =
|
||||
(column.onHeaderCell && column.onHeaderCell(col)) || {};
|
||||
const originOnClick = cell.onClick;
|
||||
const originOKeyDown = cell.onKeyDown;
|
||||
cell.onClick = (event: React.MouseEvent<HTMLElement>) => {
|
||||
triggerSorter({
|
||||
column,
|
||||
@ -186,9 +188,17 @@ function injectSorter<RecordType>(
|
||||
sortOrder: nextSortOrder,
|
||||
multiplePriority: getMultiplePriority(column),
|
||||
});
|
||||
|
||||
if (originOnClick) {
|
||||
originOnClick(event);
|
||||
originOnClick?.(event);
|
||||
};
|
||||
cell.onKeyDown = (event: React.KeyboardEvent<HTMLElement>) => {
|
||||
if (event.keyCode === KeyCode.ENTER) {
|
||||
triggerSorter({
|
||||
column,
|
||||
key: columnKey,
|
||||
sortOrder: nextSortOrder,
|
||||
multiplePriority: getMultiplePriority(column),
|
||||
});
|
||||
originOKeyDown?.(event);
|
||||
}
|
||||
};
|
||||
|
||||
@ -202,6 +212,7 @@ function injectSorter<RecordType>(
|
||||
}
|
||||
|
||||
cell.className = classNames(cell.className, `${prefixCls}-column-has-sorters`);
|
||||
cell.tabIndex = 0;
|
||||
|
||||
return cell;
|
||||
},
|
||||
@ -214,7 +225,7 @@ function injectSorter<RecordType>(
|
||||
children: injectSorter(
|
||||
prefixCls,
|
||||
newColumn.children,
|
||||
sorterSates,
|
||||
sorterStates,
|
||||
triggerSorter,
|
||||
defaultSortDirections,
|
||||
tableLocale,
|
||||
|
@ -216,6 +216,7 @@
|
||||
|
||||
// ============================ Sorter ============================
|
||||
&-thead th.@{table-prefix-cls}-column-has-sorters {
|
||||
outline: none;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s;
|
||||
|
||||
@ -227,6 +228,10 @@
|
||||
}
|
||||
}
|
||||
|
||||
&:focus-visible {
|
||||
color: @primary-color;
|
||||
}
|
||||
|
||||
// https://github.com/ant-design/ant-design/issues/30969
|
||||
&.@{table-prefix-cls}-cell-fix-left:hover,
|
||||
&.@{table-prefix-cls}-cell-fix-right:hover {
|
||||
|
@ -28,7 +28,7 @@ Ant Design has 3 types of Tabs for different situations.
|
||||
| centered | Centers tabs | boolean | false | 4.4.0 |
|
||||
| defaultActiveKey | Initial active TabPane's key, if `activeKey` is not set | string | - | |
|
||||
| hideAdd | Hide plus icon or not. Only works while `type="editable-card"` | boolean | false | |
|
||||
| moreIcon | The custom icon of ellipsis | ReactNode | <EllipsisOutlined /> | 4.14.0 |
|
||||
| moreIcon | The custom icon of ellipsis | ReactNode | <EllipsisOutlined /> | 4.14.0 |
|
||||
| renderTabBar | Replace the TabBar | (props: DefaultTabBarProps, DefaultTabBar: React.ComponentClass) => React.ReactElement | - | |
|
||||
| size | Preset tab bar size | `large` \| `default` \| `small` | `default` | |
|
||||
| tabBarExtraContent | Extra content in tab bar | ReactNode \| {left?: ReactNode, right?: ReactNode} | - | object: 4.6.0 |
|
||||
@ -38,7 +38,7 @@ Ant Design has 3 types of Tabs for different situations.
|
||||
| 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) {} | - | |
|
||||
| onEdit | Callback executed when tab is added or removed. Only works while `type="editable-card"` | (targetKey, action) => void | - | |
|
||||
| onEdit | Callback executed when tab is added or removed. Only works while `type="editable-card"` | (action === 'add' ? event : targetKey, action): void | - | |
|
||||
| onTabClick | Callback executed when tab is clicked | function(key: string, event: MouseEvent) | - | |
|
||||
| onTabScroll | Trigger when tab scroll | function({ direction: `left` \| `right` \| `top` \| `bottom` }) | - | 4.3.0 |
|
||||
|
||||
|
@ -41,15 +41,15 @@ Ant Design 依次提供了三级选项卡,分别用于不同的场景。
|
||||
| destroyInactiveTabPane | 被隐藏时是否销毁 DOM 结构 | boolean | false | |
|
||||
| type | 页签的基本样式,可选 `line`、`card` `editable-card` 类型 | string | `line` | |
|
||||
| onChange | 切换面板的回调 | function(activeKey) {} | - | |
|
||||
| onEdit | 新增和删除页签的回调,在 `type="editable-card"` 时有效 | (targetKey, action): void | - | |
|
||||
| onEdit | 新增和删除页签的回调,在 `type="editable-card"` 时有效 | (action === 'add' ? event : targetKey, action): void | - | |
|
||||
| onTabClick | tab 被点击的回调 | function(key: string, event: MouseEvent) | - | |
|
||||
| onTabScroll | tab 滚动时触发 | function({ direction: `left` \| `right` \| `top` \| `bottom` }) | - | 4.3.0 |
|
||||
|
||||
### Tabs.TabPane
|
||||
|
||||
| 参数 | 说明 | 类型 | 默认值 |
|
||||
| --- | --- | --- | --- |
|
||||
| closeIcon | 自定义关闭图标,`在 type="editable-card"`时有效 | ReactNode | - |
|
||||
| forceRender | 被隐藏时是否渲染 DOM 结构 | boolean | false |
|
||||
| key | 对应 activeKey | string | - |
|
||||
| tab | 选项卡头显示文字 | ReactNode | - |
|
||||
| 参数 | 说明 | 类型 | 默认值 |
|
||||
| ----------- | ----------------------------------------------- | --------- | ------ |
|
||||
| closeIcon | 自定义关闭图标,`在 type="editable-card"`时有效 | ReactNode | - |
|
||||
| forceRender | 被隐藏时是否渲染 DOM 结构 | boolean | false |
|
||||
| key | 对应 activeKey | string | - |
|
||||
| tab | 选项卡头显示文字 | ReactNode | - |
|
||||
|
@ -21,7 +21,7 @@ One or more elements can be selected from either column, one click on the proper
|
||||
|
||||
| Property | Description | Type | Default | Version |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| dataSource | Used for setting the source data. The elements that are part of this array will be present the left column. Except the elements whose keys are included in `targetKeys` prop | [RecordType extends TransferItem = TransferItem](https://git.io/vMM64)\[] | \[] | |
|
||||
| dataSource | Used for setting the source data. The elements that are part of this array will be present the left column. Except the elements whose keys are included in `targetKeys` prop | [RecordType extends TransferItem = TransferItem](https://github.com/ant-design/ant-design/blob/1bf0bab2a7bc0a774119f501806e3e0e3a6ba283/components/transfer/index.tsx#L12)\[] | \[] | |
|
||||
| disabled | Whether disabled transfer | boolean | false | |
|
||||
| filterOption | A function to determine whether an item should show in search result list | (inputValue, option): boolean | - | |
|
||||
| footer | A function used for rendering the footer | (props, { direction }) => ReactNode | - | direction: 4.17.0 |
|
||||
|
@ -24,7 +24,7 @@ cover: https://gw.alipayobjects.com/zos/alicdn/QAXskNI4G/Transfer.svg
|
||||
|
||||
| 参数 | 说明 | 类型 | 默认值 | 版本 |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| dataSource | 数据源,其中的数据将会被渲染到左边一栏中,`targetKeys` 中指定的除外 | [RecordType extends TransferItem = TransferItem](https://git.io/vMM64)\[] | \[] | |
|
||||
| dataSource | 数据源,其中的数据将会被渲染到左边一栏中,`targetKeys` 中指定的除外 | [RecordType extends TransferItem = TransferItem](https://github.com/ant-design/ant-design/blob/1bf0bab2a7bc0a774119f501806e3e0e3a6ba283/components/transfer/index.tsx#L12)\[] | \[] | |
|
||||
| disabled | 是否禁用 | boolean | false | |
|
||||
| filterOption | 接收 `inputValue` `option` 两个参数,当 `option` 符合筛选条件时,应返回 true,反之则返回 false | (inputValue, option): boolean | - | |
|
||||
| footer | 底部渲染函数 | (props, { direction }) => ReactNode | - | direction: 4.17.0 |
|
||||
|
@ -273,113 +273,6 @@ exports[`Upload List should be uploading when upload a file 1`] = `
|
||||
</span>
|
||||
`;
|
||||
|
||||
exports[`Upload List should be uploading when upload a file 2`] = `
|
||||
<span
|
||||
class=""
|
||||
>
|
||||
<div
|
||||
class="ant-upload ant-upload-select ant-upload-select-text"
|
||||
>
|
||||
<span
|
||||
class="ant-upload"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
>
|
||||
<input
|
||||
accept=""
|
||||
style="display: none;"
|
||||
type="file"
|
||||
/>
|
||||
<button
|
||||
type="button"
|
||||
>
|
||||
upload
|
||||
</button>
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="ant-upload-list ant-upload-list-text"
|
||||
>
|
||||
<div
|
||||
class="ant-upload-list-text-container ant-upload-animate-appear ant-upload-animate-appear-start ant-upload-animate"
|
||||
style="height: 0px; opacity: 0;"
|
||||
>
|
||||
<div
|
||||
class="ant-upload-list-item ant-upload-list-item-done ant-upload-list-item-list-type-text"
|
||||
>
|
||||
<div
|
||||
class="ant-upload-list-item-info"
|
||||
>
|
||||
<span
|
||||
class="ant-upload-span"
|
||||
>
|
||||
<div
|
||||
class="ant-upload-text-icon"
|
||||
>
|
||||
<span
|
||||
aria-label="paper-clip"
|
||||
class="anticon anticon-paper-clip"
|
||||
role="img"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
data-icon="paper-clip"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M779.3 196.6c-94.2-94.2-247.6-94.2-341.7 0l-261 260.8c-1.7 1.7-2.6 4-2.6 6.4s.9 4.7 2.6 6.4l36.9 36.9a9 9 0 0012.7 0l261-260.8c32.4-32.4 75.5-50.2 121.3-50.2s88.9 17.8 121.2 50.2c32.4 32.4 50.2 75.5 50.2 121.2 0 45.8-17.8 88.8-50.2 121.2l-266 265.9-43.1 43.1c-40.3 40.3-105.8 40.3-146.1 0-19.5-19.5-30.2-45.4-30.2-73s10.7-53.5 30.2-73l263.9-263.8c6.7-6.6 15.5-10.3 24.9-10.3h.1c9.4 0 18.1 3.7 24.7 10.3 6.7 6.7 10.3 15.5 10.3 24.9 0 9.3-3.7 18.1-10.3 24.7L372.4 653c-1.7 1.7-2.6 4-2.6 6.4s.9 4.7 2.6 6.4l36.9 36.9a9 9 0 0012.7 0l215.6-215.6c19.9-19.9 30.8-46.3 30.8-74.4s-11-54.6-30.8-74.4c-41.1-41.1-107.9-41-149 0L463 364 224.8 602.1A172.22 172.22 0 00174 724.8c0 46.3 18.1 89.8 50.8 122.5 33.9 33.8 78.3 50.7 122.7 50.7 44.4 0 88.8-16.9 122.6-50.7l309.2-309C824.8 492.7 850 432 850 367.5c.1-64.6-25.1-125.3-70.7-170.9z"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</div>
|
||||
<span
|
||||
class="ant-upload-list-item-name"
|
||||
title="foo.png"
|
||||
>
|
||||
foo.png
|
||||
</span>
|
||||
<span
|
||||
class="ant-upload-list-item-card-actions"
|
||||
>
|
||||
<button
|
||||
class="ant-btn ant-btn-text ant-btn-sm ant-btn-icon-only ant-upload-list-item-card-actions-btn"
|
||||
title="Remove file"
|
||||
type="button"
|
||||
>
|
||||
<span
|
||||
aria-label="delete"
|
||||
class="anticon anticon-delete"
|
||||
role="img"
|
||||
tabindex="-1"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
data-icon="delete"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M360 184h-8c4.4 0 8-3.6 8-8v8h304v-8c0 4.4 3.6 8 8 8h-8v72h72v-80c0-35.3-28.7-64-64-64H352c-35.3 0-64 28.7-64 64v80h72v-72zm504 72H160c-17.7 0-32 14.3-32 32v32c0 4.4 3.6 8 8 8h60.4l24.7 523c1.6 34.1 29.8 61 63.9 61h454c34.2 0 62.3-26.8 63.9-61l24.7-523H888c4.4 0 8-3.6 8-8v-32c0-17.7-14.3-32-32-32zM731.3 840H292.7l-24.2-512h487l-24.2 512z"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</button>
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</span>
|
||||
`;
|
||||
|
||||
exports[`Upload List should non-image format file preview 1`] = `
|
||||
<span
|
||||
class=""
|
||||
|
@ -160,9 +160,13 @@ describe('Upload List', () => {
|
||||
expect(wrapper.render()).toMatchSnapshot();
|
||||
}
|
||||
if (file.status === 'done') {
|
||||
expect(wrapper.render()).toMatchSnapshot();
|
||||
wrapper.unmount();
|
||||
done();
|
||||
(async function run() {
|
||||
await sleep(200);
|
||||
wrapper.update();
|
||||
// expect(wrapper.render()).toMatchSnapshot();
|
||||
wrapper.unmount();
|
||||
done();
|
||||
})();
|
||||
}
|
||||
|
||||
latestFileList = eventFileList;
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "antd",
|
||||
"version": "4.20.1",
|
||||
"version": "4.20.2",
|
||||
"description": "An enterprise-class UI design language and React components implementation",
|
||||
"title": "Ant Design",
|
||||
"keywords": [
|
||||
@ -142,7 +142,7 @@
|
||||
"rc-progress": "~3.2.1",
|
||||
"rc-rate": "~2.9.0",
|
||||
"rc-resize-observer": "^1.2.0",
|
||||
"rc-segmented": "~2.0.0",
|
||||
"rc-segmented": "~2.1.0 ",
|
||||
"rc-select": "~14.1.1",
|
||||
"rc-slider": "~10.0.0",
|
||||
"rc-steps": "~4.1.0",
|
||||
|
@ -1,15 +1,15 @@
|
||||
import React from 'react';
|
||||
import { mount } from 'enzyme';
|
||||
import { render } from '../utils';
|
||||
|
||||
// eslint-disable-next-line jest/no-export
|
||||
export default function mountTest(Component: React.ComponentType) {
|
||||
describe(`mount and unmount`, () => {
|
||||
// https://github.com/ant-design/ant-design/pull/18441
|
||||
it(`component could be updated and unmounted without errors`, () => {
|
||||
const wrapper = mount(<Component />);
|
||||
const { unmount, rerender } = render(<Component />);
|
||||
expect(() => {
|
||||
wrapper.setProps({});
|
||||
wrapper.unmount();
|
||||
rerender(<Component />);
|
||||
unmount();
|
||||
}).not.toThrow();
|
||||
});
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user