Merge pull request #28894 from ant-design/master

chore: merge master into feature
This commit is contained in:
偏右 2021-01-18 09:55:46 +08:00 committed by GitHub
commit 16ecb15be1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
35 changed files with 651 additions and 577 deletions

10
.github/config.yml vendored
View File

@ -1,10 +0,0 @@
# Configuration for request-info - https://github.com/behaviorbot/request-info
# *Required* Comment to reply with
requestInfoReplyComment: >
We would appreciate it if you could provide us with more info about this issue/pr!
Please provide a online reproduction by forking this link https://u.ant.design/codesandbox-repro or a minimal GitHub repository.
Issues labeled by Need Reproduce will be closed if no activities in 7 days.
# *OPTIONAL* Label to be added to Issues and Pull Requests with insufficient information given
requestInfoLabelToAdd: needs-more-info

View File

@ -12,9 +12,9 @@ Uma solução empresarial de design e biblioteca UI para React.
[![CI status][github-action-image]][github-action-url] [![codecov][codecov-image]][codecov-url] [![NPM version][npm-image]][npm-url] [![NPM downloads][download-image]][download-url]
[![david deps][david-image]][david-url] [![david devDeps][david-dev-image]][david-dev-url] [![Total alerts][lgtm-image]][lgtm-url] [![FOSSA Status][fossa-image]][fossa-url]
[![david deps][david-image]][david-url] [![david devDeps][david-dev-image]][david-dev-url] [![Total alerts][lgtm-image]][lgtm-url] [![][bundlesize-js-image]][unpkg-js-url] [![][bundlesize-css-image]][unpkg-css-url]
[![Follow Twitter][twitter-image]][twitter-url] [![Discussions][discussions-image]][discussions-url] [![Issues need help][help-wanted-image]][help-wanted-url]
[![Follow Twitter][twitter-image]][twitter-url] [![FOSSA Status][fossa-image]][fossa-url] [![Discussions][discussions-image]][discussions-url] [![Issues need help][help-wanted-image]][help-wanted-url]
[npm-image]: http://img.shields.io/npm/v/antd.svg?style=flat-square
[npm-url]: http://npmjs.org/package/antd
@ -38,6 +38,10 @@ Uma solução empresarial de design e biblioteca UI para React.
[twitter-url]: https://twitter.com/AntDesignUI
[discussions-image]: https://img.shields.io/badge/discussions-on%20github-blue?style=flat-square
[discussions-url]: https://github.com/ant-design/ant-design/discussions
[bundlesize-js-image]: https://img.badgesize.io/https:/unpkg.com/antd/dist/antd.min.js?label=antd.min.js&compression=gzip&style=flat-square
[bundlesize-css-image]: https://img.badgesize.io/https:/unpkg.com/antd/dist/antd.min.css?label=antd.min.css&compression=gzip&style=flat-square
[unpkg-js-url]: https://unpkg.com/browse/antd/dist/antd.min.js
[unpkg-css-url]: https://unpkg.com/browse/antd/dist/antd.min.css
</div>

View File

@ -12,9 +12,9 @@
[![CI status][github-action-image]][github-action-url] [![codecov][codecov-image]][codecov-url] [![NPM version][npm-image]][npm-url] [![NPM downloads][download-image]][download-url]
[![david deps][david-image]][david-url] [![david devDeps][david-dev-image]][david-dev-url] [![Total alerts][lgtm-image]][lgtm-url] [![FOSSA Status][fossa-image]][fossa-url]
[![david deps][david-image]][david-url] [![david devDeps][david-dev-image]][david-dev-url] [![Total alerts][lgtm-image]][lgtm-url] [![][bundlesize-js-image]][unpkg-js-url] [![][bundlesize-css-image]][unpkg-css-url]
[![Follow Twitter][twitter-image]][twitter-url] [![Discussions][discussions-image]][discussions-url] [![Issues need help][help-wanted-image]][help-wanted-url]
[![Follow Twitter][twitter-image]][twitter-url] [![FOSSA Status][fossa-image]][fossa-url] [![Discussions][discussions-image]][discussions-url] [![Issues need help][help-wanted-image]][help-wanted-url]
[npm-image]: http://img.shields.io/npm/v/antd.svg?style=flat-square
[npm-url]: http://npmjs.org/package/antd
@ -38,6 +38,10 @@
[twitter-url]: https://twitter.com/AntDesignUI
[discussions-image]: https://img.shields.io/badge/discussions-on%20github-blue?style=flat-square
[discussions-url]: https://github.com/ant-design/ant-design/discussions
[bundlesize-js-image]: https://img.badgesize.io/https:/unpkg.com/antd/dist/antd.min.js?label=antd.min.js&compression=gzip&style=flat-square
[bundlesize-css-image]: https://img.badgesize.io/https:/unpkg.com/antd/dist/antd.min.css?label=antd.min.css&compression=gzip&style=flat-square
[unpkg-js-url]: https://unpkg.com/browse/antd/dist/antd.min.js
[unpkg-css-url]: https://unpkg.com/browse/antd/dist/antd.min.css
</div>

View File

@ -117,10 +117,10 @@
&::before {
position: absolute;
top: -1px;
right: -1px;
bottom: -1px;
left: -1px;
top: -@btn-border-width;
right: -@btn-border-width;
bottom: -@btn-border-width;
left: -@btn-border-width;
z-index: 1;
display: none;
background: @component-background;

View File

@ -639,11 +639,11 @@ exports[`Cascader have a notFoundContent that fit trigger input width 1`] = `
</g>
</svg>
</div>
<p
<div
class="ant-empty-description"
>
No Data
</p>
</div>
</div>
</li>
</ul>
@ -1156,11 +1156,11 @@ exports[`Cascader should render not found content 1`] = `
</g>
</svg>
</div>
<p
<div
class="ant-empty-description"
>
No Data
</p>
</div>
</div>
</li>
</ul>
@ -1225,11 +1225,11 @@ exports[`Cascader should show not found content when options.length is 0 1`] = `
</g>
</svg>
</div>
<p
<div
class="ant-empty-description"
>
No Data
</p>
</div>
</div>
</li>
</ul>

View File

@ -13735,11 +13735,11 @@ exports[`ConfigProvider components Empty configProvider 1`] = `
</g>
</svg>
</div>
<p
<div
class="config-empty-description"
>
No Data
</p>
</div>
</div>
`;
@ -13810,11 +13810,11 @@ exports[`ConfigProvider components Empty configProvider componentSize large 1`]
</g>
</svg>
</div>
<p
<div
class="config-empty-description"
>
No Data
</p>
</div>
</div>
`;
@ -13885,11 +13885,11 @@ exports[`ConfigProvider components Empty configProvider componentSize middle 1`]
</g>
</svg>
</div>
<p
<div
class="config-empty-description"
>
No Data
</p>
</div>
</div>
`;
@ -13960,11 +13960,11 @@ exports[`ConfigProvider components Empty configProvider virtual and dropdownMatc
</g>
</svg>
</div>
<p
<div
class="ant-empty-description"
>
No Data
</p>
</div>
</div>
`;
@ -14035,11 +14035,11 @@ exports[`ConfigProvider components Empty normal 1`] = `
</g>
</svg>
</div>
<p
<div
class="ant-empty-description"
>
No Data
</p>
</div>
</div>
`;
@ -14110,11 +14110,11 @@ exports[`ConfigProvider components Empty prefixCls 1`] = `
</g>
</svg>
</div>
<p
<div
class="prefix-Empty-description"
>
No Data
</p>
</div>
</div>
`;
@ -23857,11 +23857,11 @@ exports[`ConfigProvider components Table configProvider 1`] = `
</g>
</svg>
</div>
<p
<div
class="config-empty-description"
>
No Data
</p>
</div>
</div>
</td>
</tr>
@ -24128,11 +24128,11 @@ exports[`ConfigProvider components Table configProvider componentSize large 1`]
</g>
</svg>
</div>
<p
<div
class="config-empty-description"
>
No Data
</p>
</div>
</div>
</td>
</tr>
@ -24399,11 +24399,11 @@ exports[`ConfigProvider components Table configProvider componentSize middle 1`]
</g>
</svg>
</div>
<p
<div
class="config-empty-description"
>
No Data
</p>
</div>
</div>
</td>
</tr>
@ -24670,11 +24670,11 @@ exports[`ConfigProvider components Table configProvider virtual and dropdownMatc
</g>
</svg>
</div>
<p
<div
class="ant-empty-description"
>
No Data
</p>
</div>
</div>
</td>
</tr>
@ -24941,11 +24941,11 @@ exports[`ConfigProvider components Table normal 1`] = `
</g>
</svg>
</div>
<p
<div
class="ant-empty-description"
>
No Data
</p>
</div>
</div>
</td>
</tr>
@ -25212,11 +25212,11 @@ exports[`ConfigProvider components Table prefixCls 1`] = `
</g>
</svg>
</div>
<p
<div
class="ant-empty-description"
>
No Data
</p>
</div>
</div>
</td>
</tr>
@ -34731,11 +34731,11 @@ exports[`ConfigProvider components Transfer configProvider 1`] = `
</g>
</svg>
</div>
<p
<div
class="config-empty-description"
>
No Data
</p>
</div>
</div>
</div>
</div>
@ -34889,11 +34889,11 @@ exports[`ConfigProvider components Transfer configProvider 1`] = `
</g>
</svg>
</div>
<p
<div
class="config-empty-description"
>
No Data
</p>
</div>
</div>
</div>
</div>
@ -35000,11 +35000,11 @@ exports[`ConfigProvider components Transfer configProvider componentSize large 1
</g>
</svg>
</div>
<p
<div
class="config-empty-description"
>
No Data
</p>
</div>
</div>
</div>
</div>
@ -35158,11 +35158,11 @@ exports[`ConfigProvider components Transfer configProvider componentSize large 1
</g>
</svg>
</div>
<p
<div
class="config-empty-description"
>
No Data
</p>
</div>
</div>
</div>
</div>
@ -35269,11 +35269,11 @@ exports[`ConfigProvider components Transfer configProvider componentSize middle
</g>
</svg>
</div>
<p
<div
class="config-empty-description"
>
No Data
</p>
</div>
</div>
</div>
</div>
@ -35427,11 +35427,11 @@ exports[`ConfigProvider components Transfer configProvider componentSize middle
</g>
</svg>
</div>
<p
<div
class="config-empty-description"
>
No Data
</p>
</div>
</div>
</div>
</div>
@ -35538,11 +35538,11 @@ exports[`ConfigProvider components Transfer configProvider virtual and dropdownM
</g>
</svg>
</div>
<p
<div
class="ant-empty-description"
>
No Data
</p>
</div>
</div>
</div>
</div>
@ -35696,11 +35696,11 @@ exports[`ConfigProvider components Transfer configProvider virtual and dropdownM
</g>
</svg>
</div>
<p
<div
class="ant-empty-description"
>
No Data
</p>
</div>
</div>
</div>
</div>
@ -35807,11 +35807,11 @@ exports[`ConfigProvider components Transfer normal 1`] = `
</g>
</svg>
</div>
<p
<div
class="ant-empty-description"
>
No Data
</p>
</div>
</div>
</div>
</div>
@ -35965,11 +35965,11 @@ exports[`ConfigProvider components Transfer normal 1`] = `
</g>
</svg>
</div>
<p
<div
class="ant-empty-description"
>
No Data
</p>
</div>
</div>
</div>
</div>
@ -36076,11 +36076,11 @@ exports[`ConfigProvider components Transfer prefixCls 1`] = `
</g>
</svg>
</div>
<p
<div
class="ant-empty-description"
>
No Data
</p>
</div>
</div>
</div>
</div>
@ -36234,11 +36234,11 @@ exports[`ConfigProvider components Transfer prefixCls 1`] = `
</g>
</svg>
</div>
<p
<div
class="ant-empty-description"
>
No Data
</p>
</div>
</div>
</div>
</div>

View File

@ -67,10 +67,10 @@ exports[`ConfigProvider render empty 1`] = `
</g>
</svg>
</div>
<p
<div
class="ant-empty-description"
>
No Data
</p>
</div>
</div>
`;

View File

@ -67,11 +67,11 @@ exports[`renders ./components/empty/demo/basic.md correctly 1`] = `
</g>
</svg>
</div>
<p
<div
class="ant-empty-description"
>
No Data
</p>
</div>
</div>
`;
@ -359,11 +359,11 @@ exports[`renders ./components/empty/demo/config-provider.md correctly 1`] = `
</g>
</svg>
</div>
<p
<div
class="ant-empty-description"
>
No Data
</p>
</div>
</div>
</div>
</div>
@ -517,11 +517,11 @@ exports[`renders ./components/empty/demo/config-provider.md correctly 1`] = `
</g>
</svg>
</div>
<p
<div
class="ant-empty-description"
>
No Data
</p>
</div>
</div>
</div>
</div>
@ -619,11 +619,11 @@ exports[`renders ./components/empty/demo/config-provider.md correctly 1`] = `
</g>
</svg>
</div>
<p
<div
class="ant-empty-description"
>
No Data
</p>
</div>
</div>
</td>
</tr>
@ -690,11 +690,11 @@ exports[`renders ./components/empty/demo/config-provider.md correctly 1`] = `
</g>
</svg>
</div>
<p
<div
class="ant-empty-description"
>
No Data
</p>
</div>
</div>
</div>
</div>
@ -717,7 +717,7 @@ exports[`renders ./components/empty/demo/customize.md correctly 1`] = `
src="https://gw.alipayobjects.com/zos/antfincdn/ZHrcdLPrvN/empty.svg"
/>
</div>
<p
<div
class="ant-empty-description"
>
<span>
@ -728,7 +728,7 @@ exports[`renders ./components/empty/demo/customize.md correctly 1`] = `
Description
</a>
</span>
</p>
</div>
<div
class="ant-empty-footer"
>
@ -855,10 +855,10 @@ exports[`renders ./components/empty/demo/simple.md correctly 1`] = `
</g>
</svg>
</div>
<p
<div
class="ant-empty-description"
>
No Data
</p>
</div>
</div>
`;

View File

@ -67,11 +67,11 @@ exports[`Empty rtl render component should be rendered correctly in RTL directio
</g>
</svg>
</div>
<p
<div
class="ant-empty-description"
>
No Data
</p>
</div>
</div>
`;
@ -142,10 +142,10 @@ exports[`Empty should render in RTL direction 1`] = `
</g>
</svg>
</div>
<p
<div
class="ant-empty-description"
>
No Data
</p>
</div>
</div>
`;

View File

@ -69,7 +69,7 @@ const Empty: EmptyType = ({
<div className={`${prefixCls}-image`} style={imageStyle}>
{imageNode}
</div>
{des && <p className={`${prefixCls}-description`}>{des}</p>}
{des && <div className={`${prefixCls}-description`}>{des}</div>}
{children && <div className={`${prefixCls}-footer`}>{children}</div>}
</div>
);

View File

@ -24,10 +24,6 @@
}
}
&-description {
margin: 0;
}
&-footer {
margin-top: 16px;
}

View File

@ -1076,11 +1076,11 @@ exports[`renders ./components/list/demo/infinite-load.md correctly 1`] = `
</g>
</svg>
</div>
<p
<div
class="ant-empty-description"
>
No Data
</p>
</div>
</div>
</div>
</div>

View File

@ -53,11 +53,11 @@ exports[`List renders empty list 1`] = `
</g>
</svg>
</div>
<p
<div
class="ant-empty-description"
>
No Data
</p>
</div>
</div>
</div>
</div>

View File

@ -53,11 +53,11 @@ exports[`List rtl render component should be rendered correctly in RTL direction
</g>
</svg>
</div>
<p
<div
class="ant-empty-description"
>
No Data
</p>
</div>
</div>
</div>
</div>

View File

@ -116,7 +116,7 @@ const Slider = React.forwardRef<unknown, SliderSingleProps | SliderRangeProps>(
transitionName="zoom-down"
key={index}
overlayClassName={`${prefixCls}-tooltip`}
getPopupContainer={getTooltipPopupContainer || getPopupContainer || (() => document.body)}
getPopupContainer={getTooltipPopupContainer || getPopupContainer}
>
<RcHandle
{...restProps}

View File

@ -600,6 +600,7 @@
@table-padding-horizontal-md: (@table-padding-horizontal / 2);
@table-padding-vertical-sm: (@table-padding-vertical / 2);
@table-padding-horizontal-sm: (@table-padding-horizontal / 2);
@table-border-color: @border-color-split;
@table-border-radius-base: @border-radius-base;
@table-footer-bg: @background-color-light;
@table-footer-color: @heading-color;

View File

@ -5,6 +5,7 @@ import Table from '..';
import Input from '../../input';
import Tooltip from '../../tooltip';
import Button from '../../button';
import Select from '../../select';
import ConfigProvider from '../../config-provider';
// https://github.com/Semantic-Org/Semantic-UI-React/blob/72c45080e4f20b531fda2e3e430e384083d6766b/test/specs/modules/Dropdown/Dropdown-test.js#L73
@ -507,6 +508,7 @@ describe('Table.filter', () => {
});
it('three levels menu', () => {
const onChange = jest.fn();
const filters = [
{ text: 'Upper', value: 'Upper' },
{ text: 'Lower', value: 'Lower' },
@ -536,6 +538,7 @@ describe('Table.filter', () => {
filters,
},
],
onChange,
}),
);
jest.useFakeTimers();
@ -551,6 +554,10 @@ describe('Table.filter', () => {
dropdownWrapper = getDropdownWrapper(wrapper);
dropdownWrapper.find('MenuItem').last().simulate('click');
dropdownWrapper.find('.ant-table-filter-dropdown-btns .ant-btn-primary').simulate('click');
onChange.mock.calls.forEach(([, currentFilters]) => {
const [, val] = Object.entries(currentFilters)[0];
expect(val).toEqual(['Jack']);
});
wrapper.update();
expect(renderedNames(wrapper)).toEqual(['Jack']);
dropdownWrapper.find('MenuItem').last().simulate('click');
@ -906,6 +913,87 @@ describe('Table.filter', () => {
});
});
it('should work as expected with complex custom filterDropdown', () => {
const onChange = jest.fn();
const filterDropdown = ({ setSelectedKeys, selectedKeys, confirm }) => {
const handleChange = selectedValues => {
setSelectedKeys(selectedValues);
};
return (
<div>
<Select
mode="multiple"
allowClear
labelInValue
style={{ width: 200 }}
value={selectedKeys}
onChange={handleChange}
options={[
{
value: 1,
label: 'Not Identified',
},
{
value: 2,
label: 'Closed',
},
{
value: 3,
label: 'Communicated',
},
]}
/>
<button className="confirm-btn" type="submit" onClick={confirm}>
Confirm
</button>
</div>
);
};
const filteredValue = [
{
value: 2,
label: 'Closed',
},
];
const selectedValue = [
{
key: 2,
value: 2,
label: 'Closed',
},
{
key: 1,
value: 1,
label: 'Not Identified',
},
];
const wrapper = mount(
createTable({
onChange,
columns: [
{
title: 'Name',
dataIndex: 'name',
key: 'name',
filterDropdown,
filteredValue,
},
],
}),
);
expect(wrapper.find('FilterDropdown').props().filterState.filteredKeys).toEqual(filteredValue);
wrapper.find('.ant-dropdown-trigger').first().simulate('click');
wrapper.find('.ant-select-selector').simulate('mousedown');
wrapper.find('.ant-select-item-option').first().simulate('click');
wrapper.find('.confirm-btn').first().simulate('click');
expect(onChange).toHaveBeenCalled();
onChange.mock.calls.forEach(([, currentFilters]) => {
const [, val] = Object.entries(currentFilters)[0];
expect(val).toEqual(selectedValue);
});
});
// https://github.com/ant-design/ant-design/issues/17089
it('not crash when dynamic change filter', () => {
const onChange = jest.fn();

View File

@ -187,11 +187,11 @@ exports[`Table rtl render component should be rendered correctly in RTL directio
</g>
</svg>
</div>
<p
<div
class="ant-empty-description"
>
No Data
</p>
</div>
</div>
</td>
</tr>

View File

@ -194,11 +194,11 @@ exports[`renders ./components/table/demo/ajax.md correctly 1`] = `
</g>
</svg>
</div>
<p
<div
class="ant-empty-description"
>
No Data
</p>
</div>
</div>
</td>
</tr>

View File

@ -119,11 +119,11 @@ exports[`Table renders empty table 1`] = `
</g>
</svg>
</div>
<p
<div
class="ant-empty-description"
>
No Data
</p>
</div>
</div>
</td>
</tr>
@ -494,11 +494,11 @@ exports[`Table renders empty table with fixed columns 1`] = `
</g>
</svg>
</div>
<p
<div
class="ant-empty-description"
>
No Data
</p>
</div>
</div>
</div>
</td>
@ -654,11 +654,11 @@ exports[`Table renders empty table without emptyText when loading 1`] = `
</g>
</svg>
</div>
<p
<div
class="ant-empty-description"
>
No Data
</p>
</div>
</div>
</td>
</tr>

View File

@ -34,9 +34,10 @@ function collectFilterStates<RecordType>(
} else if (column.filters || 'filterDropdown' in column || 'onFilter' in column) {
if ('filteredValue' in column) {
// Controlled
const filteredValues = Array.isArray(column.filteredValue)
? column.filteredValue.map(String)
: column.filteredValue;
let filteredValues = column.filteredValue;
if (!('filterDropdown' in column)) {
filteredValues = filteredValues?.map(String) ?? filteredValues;
}
filterStates.push({
column,
key: getColumnKey(column, columnPos),
@ -119,31 +120,6 @@ function injectFilter<RecordType>(
});
}
function generateFilterInfo<RecordType>(filterStates: FilterState<RecordType>[]) {
const currentFilters: Record<string, (Key | boolean)[] | null> = {};
filterStates.forEach(({ key, filteredKeys, column }) => {
const { filters, filterDropdown } = column;
if (filterDropdown) {
currentFilters[key] = filteredKeys || null;
} else {
const originKeys: ColumnFilterItem['value'][] = [];
if (Array.isArray(filteredKeys)) {
filters?.forEach((filter: ColumnFilterItem) => {
if (filteredKeys.includes(String(filter.value))) {
originKeys.push(filter.value);
}
});
currentFilters[key] = originKeys;
} else {
currentFilters[key] = null;
}
}
});
return currentFilters;
}
function flattenKeys(filters?: ColumnFilterItem[]) {
let keys: (string | number | boolean)[] = [];
(filters || []).forEach(({ value, children }) => {
@ -155,6 +131,24 @@ function flattenKeys(filters?: ColumnFilterItem[]) {
return keys;
}
function generateFilterInfo<RecordType>(filterStates: FilterState<RecordType>[]) {
const currentFilters: Record<string, (Key | boolean)[] | null> = {};
filterStates.forEach(({ key, filteredKeys, column }) => {
const { filters, filterDropdown } = column;
if (filterDropdown) {
currentFilters[key] = filteredKeys || null;
} else if (Array.isArray(filteredKeys)) {
const keys = flattenKeys(filters);
currentFilters[key] = keys.filter(originKey => filteredKeys.includes(String(originKey)));
} else {
currentFilters[key] = null;
}
});
return currentFilters;
}
export function getFilterData<RecordType>(
data: RecordType[],
filterStates: FilterState<RecordType>[],

View File

@ -1,7 +1,7 @@
@import './index';
@import './size';
@table-border: @border-width-base @border-style-base @border-color-split;
@table-border: @border-width-base @border-style-base @table-border-color;
.@{table-prefix-cls}.@{table-prefix-cls}-bordered {
// ============================ Title =============================
@ -30,7 +30,7 @@
// ============================ Header ============================
> thead {
> tr:not(:last-child) > th {
border-bottom: @border-width-base @border-style-base @border-color-split;
border-bottom: @border-width-base @border-style-base @table-border-color;
}
}

View File

@ -83,7 +83,7 @@
font-weight: 500;
text-align: left;
background: @table-header-bg;
border-bottom: @border-width-base @border-style-base @border-color-split;
border-bottom: @border-width-base @border-style-base @table-border-color;
transition: background 0.3s ease;
&[colspan]:not([colspan='1']) {
@ -103,7 +103,7 @@
&-tbody {
> tr {
> td {
border-bottom: @border-width-base @border-style-base @border-color-split;
border-bottom: @border-width-base @border-style-base @table-border-color;
transition: background 0.3s;
// ========================= Nest Table ===========================
@ -150,7 +150,7 @@
> tr {
> th,
> td {
border-bottom: @border-width-base @border-style-base @border-color-split;
border-bottom: @border-width-base @border-style-base @table-border-color;
}
}
}
@ -351,7 +351,7 @@
padding: 7px 8px 7px 3px;
overflow: hidden;
background-color: @table-filter-btns-bg;
border-top: @border-width-base @border-style-base @border-color-split;
border-top: @border-width-base @border-style-base @table-border-color;
}
}
@ -424,7 +424,7 @@
line-height: ceil(((@font-size-sm * 1.4 - @border-width-base * 3) / 2)) * 2 + @border-width-base *
3;
background: @table-expand-icon-bg;
border: @border-width-base @border-style-base @border-color-split;
border: @border-width-base @border-style-base @table-border-color;
border-radius: @border-radius-base;
outline: none;
transition: all 0.3s;
@ -614,8 +614,8 @@
z-index: @table-sticky-zindex;
display: flex;
align-items: center;
background: lighten(@border-color-split, 80%);
border-top: 1px solid @border-color-split;
background: lighten(@table-border-color, 80%);
border-top: 1px solid @table-border-color;
opacity: 0.6;
&:hover {
transform-origin: center bottom;

View File

@ -133,11 +133,11 @@ exports[`renders ./components/transfer/demo/advanced.md correctly 1`] = `
</g>
</svg>
</div>
<p
<div
class="ant-empty-description"
>
No Data
</p>
</div>
</div>
</div>
</div>
@ -344,11 +344,11 @@ exports[`renders ./components/transfer/demo/advanced.md correctly 1`] = `
</g>
</svg>
</div>
<p
<div
class="ant-empty-description"
>
No Data
</p>
</div>
</div>
</div>
</div>
@ -1150,11 +1150,11 @@ exports[`renders ./components/transfer/demo/custom-item.md correctly 1`] = `
</g>
</svg>
</div>
<p
<div
class="ant-empty-description"
>
No Data
</p>
</div>
</div>
</div>
</div>
@ -1309,11 +1309,11 @@ exports[`renders ./components/transfer/demo/custom-item.md correctly 1`] = `
</g>
</svg>
</div>
<p
<div
class="ant-empty-description"
>
No Data
</p>
</div>
</div>
</div>
</div>
@ -1833,11 +1833,11 @@ Array [
</g>
</svg>
</div>
<p
<div
class="ant-empty-description"
>
No Data
</p>
</div>
</div>
</div>
</div>
@ -1976,11 +1976,11 @@ Array [
</g>
</svg>
</div>
<p
<div
class="ant-empty-description"
>
No Data
</p>
</div>
</div>
</div>
</div>
@ -2875,11 +2875,11 @@ exports[`renders ./components/transfer/demo/search.md correctly 1`] = `
</g>
</svg>
</div>
<p
<div
class="ant-empty-description"
>
No Data
</p>
</div>
</div>
</div>
</div>
@ -3066,11 +3066,11 @@ exports[`renders ./components/transfer/demo/search.md correctly 1`] = `
</g>
</svg>
</div>
<p
<div
class="ant-empty-description"
>
No Data
</p>
</div>
</div>
</div>
</div>
@ -4581,11 +4581,11 @@ exports[`renders ./components/transfer/demo/tree-transfer.md correctly 1`] = `
</g>
</svg>
</div>
<p
<div
class="ant-empty-description"
>
No Data
</p>
</div>
</div>
</div>
</div>

View File

@ -99,11 +99,11 @@ exports[`Transfer rtl render component should be rendered correctly in RTL direc
</g>
</svg>
</div>
<p
<div
class="ant-empty-description"
>
No Data
</p>
</div>
</div>
</div>
</div>
@ -257,11 +257,11 @@ exports[`Transfer rtl render component should be rendered correctly in RTL direc
</g>
</svg>
</div>
<p
<div
class="ant-empty-description"
>
No Data
</p>
</div>
</div>
</div>
</div>
@ -1002,11 +1002,11 @@ exports[`Transfer should support render value and label in item 1`] = `
</g>
</svg>
</div>
<p
<div
class="ant-empty-description"
>
No Data
</p>
</div>
</div>
</div>
</div>
@ -1247,11 +1247,11 @@ exports[`immutable data dataSource is frozen 1`] = `
</g>
</svg>
</div>
<p
<div
class="ant-empty-description"
>
No Data
</p>
</div>
</div>
</div>
</div>

View File

@ -13,50 +13,41 @@ export interface TransferSearchProps {
disabled?: boolean;
}
export default class Search extends React.Component<TransferSearchProps, any> {
static defaultProps = {
placeholder: '',
};
export default function Search(props: TransferSearchProps) {
const { placeholder = '', value, prefixCls, disabled, onChange, handleClear } = props;
handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const { onChange } = this.props;
if (onChange) {
onChange(e);
}
};
const handleChange = React.useCallback(
(e: React.ChangeEvent<HTMLInputElement>) => {
onChange?.(e);
},
[onChange],
);
handleClear = (e: React.MouseEvent<HTMLAnchorElement>) => {
const handleClearFn = (e: React.MouseEvent<HTMLAnchorElement>) => {
e.preventDefault();
const { handleClear, disabled } = this.props;
if (!disabled && handleClear) {
handleClear(e);
}
};
render() {
const { placeholder, value, prefixCls, disabled } = this.props;
const icon =
value && value.length > 0 ? (
<a className={`${prefixCls}-action`} onClick={this.handleClear}>
return (
<>
<Input
placeholder={placeholder}
className={prefixCls}
value={value}
onChange={handleChange}
disabled={disabled}
/>
{value && value.length > 0 ? (
<a className={`${prefixCls}-action`} onClick={handleClearFn}>
<CloseCircleFilled />
</a>
) : (
<span className={`${prefixCls}-action`}>
<SearchOutlined />
</span>
);
return (
<>
<Input
placeholder={placeholder}
className={prefixCls}
value={value}
onChange={this.handleChange}
disabled={disabled}
/>
{icon}
</>
);
}
)}
</>
);
}

View File

@ -5,6 +5,7 @@
@select-tree-prefix-cls: ~'@{ant-prefix}-select-tree';
@tree-motion: ~'@{ant-prefix}-motion-collapse';
@tree-node-padding: (@padding-xs / 2);
@tree-node-hightlight-color: @volcano-7;
.antTreeSwitcherIcon(@type: 'tree-default-open-icon') {
.@{tree-prefix-cls}-switcher-icon,
@ -90,6 +91,11 @@
&-active .@{custom-tree-prefix-cls}-node-content-wrapper {
background: @tree-node-hover-bg;
}
&.filter-node .@{custom-tree-prefix-cls}-title {
color: @tree-node-hightlight-color;
font-weight: 500;
}
}
// >>> Indent

View File

@ -183,17 +183,13 @@ const InternalUpload: React.ForwardRefRenderFunction<unknown, UploadProps> = (pr
if (removedFileList) {
currentFile = { ...file, status: 'removed' };
fileList?.some(item => {
fileList?.forEach(item => {
const matchKey = currentFile.uid !== undefined ? 'uid' : 'name';
if (item[matchKey] === currentFile[matchKey]) {
item.status = 'removed';
return true;
}
return false;
});
if (upload.current) {
upload.current.abort(currentFile);
}
upload.current?.abort(currentFile);
onInternalChange({
file: currentFile,

View File

@ -220,7 +220,7 @@ const ListItem = React.forwardRef(
if (file.response && typeof file.response === 'string') {
message = file.response;
} else {
message = (file.error && file.error.statusText) || locale.uploadError;
message = file.error?.statusText || file.error?.message || locale.uploadError;
}
const iconAndPreview = (
<span className={spanClassName}>

View File

@ -350,6 +350,7 @@ describe('Upload', () => {
const targetItem = removeFileItem(file, fileList);
expect(targetItem).toEqual(fileList.slice(0, 2));
});
it('should not be able to remove fileItem', () => {
const file = { uid: '-3', name: 'item.jpg' };
const fileList = [

View File

@ -494,6 +494,7 @@ describe('Upload List', () => {
);
expect(wrapper.render()).toMatchSnapshot();
});
it('should support custom onClick in custom icon', async () => {
const handleRemove = jest.fn();
const handleChange = jest.fn();

View File

@ -195,7 +195,7 @@
"enquire-js": "^0.2.1",
"enzyme": "^3.10.0",
"enzyme-to-json": "^3.6.0",
"esbuild-webpack-plugin": "^1.0.0",
"esbuild-loader": "^2.7.0",
"eslint": "^7.9.0",
"eslint-config-airbnb": "^18.0.0",
"eslint-config-prettier": "^7.0.0",

View File

@ -2,7 +2,7 @@ const path = require('path');
const replaceLib = require('@ant-design/tools/lib/replaceLib');
const getWebpackConfig = require('@ant-design/tools/lib/getWebpackConfig');
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');
const EsbuildPlugin = require('esbuild-webpack-plugin').default;
const { ESBuildPlugin, ESBuildMinifyPlugin } = require('esbuild-loader');
const { version } = require('../package.json');
const themeConfig = require('./themeConfig');
@ -79,9 +79,10 @@ module.exports = {
config.resolve.alias = { ...config.resolve.alias, react: require.resolve('react') };
} else if (process.env.ESBUILD) {
// use esbuild
config.plugins.push(new ESBuildPlugin());
config.optimization.minimizer = [
new EsbuildPlugin({
target: 'chrome49',
new ESBuildMinifyPlugin({
target: 'es2015',
}),
new CssMinimizerPlugin(),
];

View File

@ -3,7 +3,7 @@
const getWebpackConfig = require('@ant-design/tools/lib/getWebpackConfig');
const IgnoreEmitPlugin = require('ignore-emit-webpack-plugin');
const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer');
const EsbuildPlugin = require('esbuild-webpack-plugin').default;
const { ESBuildPlugin, ESBuildMinifyPlugin } = require('esbuild-loader');
const darkVars = require('./scripts/dark-vars');
const compactVars = require('./scripts/compact-vars');
@ -99,8 +99,9 @@ if (process.env.RUN_ENV === 'PRODUCTION') {
config.optimization.usedExports = true;
// use esbuild
if (process.env.ESBUILD || process.env.CSB_REPO) {
config.optimization.minimizer[0] = new EsbuildPlugin({
target: 'chrome49',
config.plugins.push(new ESBuildPlugin());
config.optimization.minimizer[0] = new ESBuildMinifyPlugin({
target: 'es2015',
});
}