Feat(Transfer): Allow to specify item-unit (#11348)

* Add itemUnit, itemsUnit props

* Add document

* Integrate locales

* Keep old locale props still working.
This commit is contained in:
y-take 2018-08-28 17:26:32 +09:00 committed by 偏右
parent badfac83b0
commit 6f443be4d5
4 changed files with 85 additions and 19 deletions

View File

@ -148,6 +148,13 @@ describe('Transfer', () => {
expect(wrapper.find(TransferList).at(0).find(TransferItem).find(Checkbox)).toHaveLength(1);
});
const headerText = wrapper => wrapper
.find(TransferList).at(0)
.find('.ant-transfer-list-header-selected > span').at(0)
.first()
.text()
.trim();
it('should display the correct count of items when filter by input', () => {
const filterOption = (inputValue, option) => option.description.indexOf(inputValue) > -1;
const renderFunc = item => item.title;
@ -160,10 +167,55 @@ describe('Transfer', () => {
/>
);
wrapper.find(TransferSearch).at(0).find('input').simulate('change', { target: { value: 'content2' } });
expect(wrapper.find(TransferList).at(0).find('.ant-transfer-list-header-selected > span').at(0)
.first()
.text()
.trim()).toEqual('1 items');
expect(headerText(wrapper)).toEqual('1 items');
});
it('should display the correct locale', () => {
const emptyProps = { dataSource: [], selectedKeys: [], targetKeys: [] };
const locale = { itemUnit: 'Person', notFoundContent: 'Nothing', searchPlaceholder: 'Search' };
const wrapper = mount(<Transfer {...listCommonProps} {...emptyProps} showSearch locale={locale} />);
expect(headerText(wrapper)).toEqual('0 Person');
expect(
wrapper
.find(TransferList).at(0)
.find('.ant-transfer-list-search').at(0)
.prop('placeholder')
).toEqual('Search');
expect(
wrapper
.find(TransferList).at(0)
.find('.ant-transfer-list-body-not-found').at(0)
.text()
).toEqual('Nothing');
});
it('should display the correct locale using old API', () => {
const emptyProps = { dataSource: [], selectedKeys: [], targetKeys: [] };
const locale = { notFoundContent: 'old1', searchPlaceholder: 'old2' };
const wrapper = mount(<Transfer {...listCommonProps} {...emptyProps} {...locale} showSearch />);
expect(
wrapper
.find(TransferList).at(0)
.find('.ant-transfer-list-search').at(0)
.prop('placeholder')
).toEqual('old2');
expect(
wrapper
.find(TransferList).at(0)
.find('.ant-transfer-list-body-not-found').at(0)
.text()
).toEqual('old1');
});
it('should display the correct items unit', () => {
const wrapper = mount(<Transfer {...listCommonProps} locale={{ itemsUnit: 'People' }} />);
expect(headerText(wrapper)).toEqual('1/2 People');
});
it('should just check the filtered item when click on check all after search by input', () => {

View File

@ -23,11 +23,10 @@ One or more elements can be selected from either column, one click on the proper
| footer | A function used for rendering the footer. | (props): ReactNode | |
| lazy | property of [react-lazy-load](https://github.com/loktar00/react-lazy-load) for lazy rendering items. Turn off it by set to `false`. | object\|boolean | `{ height: 32, offset: 32 }` |
| listStyle | A custom CSS style used for rendering the transfer columns. | object | |
| notFoundContent | Text to display when a column is empty. | string\|ReactNode | 'The list is empty' |
| locale | i18n text including filter, empty text, item unit, etc | object | `{ itemUnit: 'item', itemsUnit: 'items', notFoundContent: 'The list is empty', searchPlaceholder: 'Search here' }` |
| operations | A set of operations that are sorted from bottom to top. | string\[] | ['>', '<'] |
| operationStyle | A custom CSS style used for rendering the operations column. | object | |
| render | The function to generate the item shown on a column. Based on an record (element of the dataSource array), this function should return a React element which is generated from that record. Also, it can return a plain object with `value` and `label`, `label` is a React element and `value` is for title | Function(record) | |
| searchPlaceholder | The hint text of the search box. | string | 'Search here' |
| selectedKeys | A set of keys of selected items. | string\[] | \[] |
| showSearch | If included, a search box is shown on each column. | boolean | false |
| style | A custom CSS style used for rendering wrapper element. | object | |

View File

@ -4,6 +4,7 @@ import classNames from 'classnames';
import List, { TransferListProps } from './list';
import Operation from './operation';
import Search from './search';
import warning from '../_util/warning';
import LocaleReceiver from '../locale-provider/LocaleReceiver';
import defaultLocale from '../locale-provider/default';
@ -41,6 +42,7 @@ export interface TransferProps {
filterOption?: (inputValue: any, item: any) => boolean;
searchPlaceholder?: string;
notFoundContent?: React.ReactNode;
locale?: {};
footer?: (props: TransferListProps) => React.ReactNode;
body?: (props: TransferListProps) => React.ReactNode;
rowKey?: (record: TransferItem) => string;
@ -66,6 +68,7 @@ export default class Transfer extends React.Component<TransferProps, any> {
static defaultProps = {
dataSource: [],
render: noop,
locale: {},
showSearch: false,
};
@ -86,6 +89,7 @@ export default class Transfer extends React.Component<TransferProps, any> {
filterOption: PropTypes.func,
searchPlaceholder: PropTypes.string,
notFoundContent: PropTypes.node,
locale: PropTypes.object,
body: PropTypes.func,
footer: PropTypes.func,
rowKey: PropTypes.func,
@ -100,6 +104,12 @@ export default class Transfer extends React.Component<TransferProps, any> {
constructor(props: TransferProps) {
super(props);
warning(
!('notFoundContent' in props || 'searchPlaceholder' in props),
'Transfer[notFoundContent] and Transfer[searchPlaceholder] will be removed, ' +
'please use Transfer[locale] instead.',
);
const { selectedKeys = [], targetKeys = [] } = props;
this.state = {
leftFilter: '',
@ -321,14 +331,25 @@ export default class Transfer extends React.Component<TransferProps, any> {
return direction === 'left' ? 'sourceSelectedKeys' : 'targetSelectedKeys';
}
renderTransfer = (locale: TransferLocale) => {
getLocale = (transferLocale: TransferLocale) => {
// Keep old locale props still working.
const oldLocale: { notFoundContent?: any, searchPlaceholder?: string } = {};
if ('notFoundContent' in this.props) {
oldLocale.notFoundContent = this.props.notFoundContent;
}
if ('searchPlaceholder' in this.props) {
oldLocale.searchPlaceholder = this.props.searchPlaceholder;
}
return ({ ...transferLocale, ...oldLocale, ...this.props.locale });
}
renderTransfer = (transferLocale: TransferLocale) => {
const {
prefixCls = 'ant-transfer',
className,
operations = [],
showSearch,
notFoundContent,
searchPlaceholder,
body,
footer,
style,
@ -338,6 +359,7 @@ export default class Transfer extends React.Component<TransferProps, any> {
render,
lazy,
} = this.props;
const locale = this.getLocale(transferLocale);
const { leftFilter, rightFilter, sourceSelectedKeys, targetSelectedKeys } = this.state;
const { leftDataSource, rightDataSource } = this.separateDataSource(this.props);
@ -363,14 +385,11 @@ export default class Transfer extends React.Component<TransferProps, any> {
handleSelectAll={this.handleLeftSelectAll}
render={render}
showSearch={showSearch}
searchPlaceholder={searchPlaceholder || locale.searchPlaceholder}
notFoundContent={notFoundContent || locale.notFoundContent}
itemUnit={locale.itemUnit}
itemsUnit={locale.itemsUnit}
body={body}
footer={footer}
lazy={lazy}
onScroll={this.handleLeftScroll}
{...locale}
/>
<Operation
className={`${prefixCls}-operation`}
@ -396,14 +415,11 @@ export default class Transfer extends React.Component<TransferProps, any> {
handleSelectAll={this.handleRightSelectAll}
render={render}
showSearch={showSearch}
searchPlaceholder={searchPlaceholder || locale.searchPlaceholder}
notFoundContent={notFoundContent || locale.notFoundContent}
itemUnit={locale.itemUnit}
itemsUnit={locale.itemsUnit}
body={body}
footer={footer}
lazy={lazy}
onScroll={this.handleRightScroll}
{...locale}
/>
</div>
);

View File

@ -25,10 +25,9 @@ title: Transfer
| footer | 底部渲染函数 | (props): ReactNode | |
| lazy | Transfer 使用了 [react-lazy-load](https://github.com/loktar00/react-lazy-load) 优化性能,这里可以设置相关参数。设为 `false` 可以关闭懒加载。 | object\|boolean | `{ height: 32, offset: 32 }` |
| listStyle | 两个穿梭框的自定义样式 | object | |
| notFoundContent | 当列表为空时显示的内容 | string\|ReactNode | '列表为空' |
| locale | 各种语言 | object | `{ itemUnit: '项', itemsUnit: '项', notFoundContent: '列表为空', searchPlaceholder: '请输入搜索内容' }` |
| operations | 操作文案集合,顺序从下至上 | string\[] | ['>', '<'] |
| render | 每行数据渲染函数,该函数的入参为 `dataSource` 中的项,返回值为 ReactElement。或者返回一个普通对象其中 `label` 字段为 ReactElement`value` 字段为 title | Function(record) | |
| searchPlaceholder | 搜索框的默认值 | string | '请输入搜索内容' |
| selectedKeys | 设置哪些项应该被选中 | string\[] | \[] |
| showSearch | 是否显示搜索框 | boolean | false |
| targetKeys | 显示在右侧框数据的key集合 | string\[] | \[] |