feat: support disabled item for Transfer, close: #3038 (#3044)

* feat: support disabled item for Transfer, close: #3038

* refactor: Transfer
This commit is contained in:
Benjy Cui 2016-09-19 17:52:20 +08:00 committed by GitHub
parent 41266f6374
commit 31615c9793
5 changed files with 82 additions and 77 deletions

View File

@ -35,6 +35,7 @@ const App = React.createClass({
title: `content${i + 1}`,
description: `description of content${i + 1}`,
chosen: Math.random() * 2 > 1,
disabled: Math.random() * 3 < 1,
};
if (data.chosen) {
targetKeys.push(data.key);

View File

@ -12,24 +12,24 @@ export interface TransferItem {
key: number | string;
title: string;
description?: string;
chosen: boolean;
disabled?: boolean;
}
// Transfer
export interface TransferProps {
dataSource: Array<TransferItem>;
render?: (record: TransferItem) => any;
dataSource: TransferItem[];
targetKeys: string[];
onChange?: (targetKeys: Array<TransferItem>, direction: string, moveKeys: any) => void;
render?: (record: TransferItem) => any;
onChange?: (targetKeys: TransferItem[], direction: string, moveKeys: any) => void;
onSelectChange?: (sourceSelectedKeys: string[], targetSelectedKeys: string[]) => void;
listStyle?: React.CSSProperties;
className?: string;
prefixCls?: string;
titles?: Array<string>;
operations?: Array<string>;
titles?: string[];
operations?: string[];
showSearch?: boolean;
searchPlaceholder?: string;
notFoundContent?: React.ReactNode | string;
notFoundContent?: React.ReactNode;
footer?: (props: any) => any;
style?: React.CSSProperties;
filterOption: (inputValue: any, item: any) => boolean;
@ -112,29 +112,16 @@ export default class Transfer extends React.Component<TransferProps, any> {
if (this.splitedDataSource) {
return this.splitedDataSource;
}
const { targetKeys } = props;
let { dataSource } = props;
const { dataSource, targetKeys } = props;
if (props.rowKey) {
dataSource = dataSource.map(record => {
dataSource.forEach(record => {
record.key = props.rowKey(record);
return record;
});
}
let leftDataSource = [...dataSource];
let rightDataSource = [];
if (targetKeys.length > 0) {
targetKeys.forEach((targetKey) => {
rightDataSource.push(leftDataSource.filter((data, index) => {
if (data.key === targetKey) {
leftDataSource.splice(index, 1);
return true;
}
return false;
})[0]);
});
}
const leftDataSource = dataSource.filter(({ key }) => targetKeys.indexOf(key) === -1);
const rightDataSource = dataSource.filter(({ key }) => targetKeys.indexOf(key) >= 0);
this.splitedDataSource = {
leftDataSource,
@ -151,7 +138,7 @@ export default class Transfer extends React.Component<TransferProps, any> {
// move items to target box
const newTargetKeys = direction === 'right'
? moveKeys.concat(targetKeys)
: targetKeys.filter(targetKey => !moveKeys.some(checkedKey => targetKey === checkedKey));
: targetKeys.filter(targetKey => moveKeys.indexOf(targetKey) === -1);
// empty checked keys
const oppositeDirection = direction === 'right' ? 'left' : 'right';

View File

@ -1,4 +1,4 @@
import * as React from 'react';
import React from 'react';
import { PropTypes } from 'react';
import Checkbox from '../checkbox';
import Search from './search';
@ -18,7 +18,7 @@ export function isRenderResultPlainObject(result) {
export interface TransferListProps {
prefixCls?: string;
dataSource: Array<TransferItem>;
dataSource: TransferItem[];
filter?: string;
showSearch?: boolean;
searchPlaceholder?: string;
@ -176,43 +176,52 @@ export default class TransferList extends React.Component<TransferListProps, any
const filteredDataSource = [];
const showItems = dataSource.map(item => {
const showItems = dataSource.map((item) => {
const renderResult = render(item);
let renderedText;
let renderedEl;
if (isRenderResultPlainObject(renderResult)) {
renderedText = renderResult.value;
renderedEl = renderResult.label;
} else {
renderedText = renderResult;
renderedEl = renderResult;
return {
item: item,
renderedText: renderResult.value,
renderedEl: renderResult.label,
};
}
return {
item: item,
renderedText: renderResult,
renderedEl: renderResult,
};
}).filter(({ item, renderedText }) => {
return !(filter && filter.trim() && !this.matchFilter(filter, item, renderedText));
}).map(({ item, renderedText, renderedEl }) => {
if (!item.disabled) {
filteredDataSource.push(item);
}
if (filter && filter.trim() && !this.matchFilter(filter, item, renderedText)) {
return null;
}
filteredDataSource.push(item);
const className = classNames({
[`${prefixCls}-content-item`]: true,
[`${prefixCls}-content-item-disabled`]: item.disabled,
});
return (
<li onClick={() => this.handleSelect(item)} key={item.key} title={renderedText}>
<Checkbox checked={checkedKeys.some(key => key === item.key)} />
<li
key={item.key}
className={className}
title={renderedText}
onClick={item.disabled ? null : () => this.handleSelect(item)}
>
<Checkbox checked={checkedKeys.some(key => key === item.key)} disabled={item.disabled} />
<span>{renderedEl}</span>
</li>
);
}).filter(item => !!item);
});
let unit = '条';
if (this.context.antLocale &&
this.context.antLocale.Transfer) {
unit = dataSource.length > 1
? this.context.antLocale.Transfer.itemsUnit
: this.context.antLocale.Transfer.itemUnit;
searchPlaceholder = searchPlaceholder
|| this.context.antLocale.Transfer.searchPlaceholder;
notFoundContent = notFoundContent
|| this.context.antLocale.Transfer.notFoundContent;
const antLocale = this.context.antLocale;
if (antLocale && antLocale.Transfer) {
const transferLocale = antLocale.Transfer;
unit = dataSource.length > 1 ? transferLocale.itemsUnit : transferLocale.itemUnit;
searchPlaceholder = searchPlaceholder || transferLocale.searchPlaceholder;
notFoundContent = notFoundContent || transferLocale.notFoundContent;
}
const checkStatus = this.getCheckStatus(filteredDataSource);
@ -248,8 +257,10 @@ export default class TransferList extends React.Component<TransferListProps, any
value={filter}
/>
</div> : null}
<Animate component="ul"
transitionName={this.state.mounted ? `${prefixCls}-highlight` : ''}
<Animate
component="ul"
className={`${prefixCls}-content`}
transitionName={this.state.mounted ? `${prefixCls}-content-item-highlight` : ''}
transitionLeave={false}
>
{showItems.length > 0

View File

@ -1,4 +1,4 @@
import * as React from 'react';
import React from 'react';
import Button from '../button';
import Icon from '../icon';

View File

@ -83,33 +83,39 @@
text-align: center;
height: 100%;
}
ul {
height: 100%;
overflow: auto;
li {
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
padding: 7px 16px;
transition: all 0.3s ease;
&:hover {
cursor: pointer;
background-color: tint(@primary-color, 90%);
}
}
}
}
ul li&-highlight-enter {
animation: transferHighlightIn 1s ease;
transition: none;
}
&-body-with-search {
padding-top: 34px;
}
&-content {
height: 100%;
overflow: auto;
&-item {
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
padding: 7px 16px;
transition: all 0.3s ease;
}
&-item:not(&-item-disabled):hover {
cursor: pointer;
background-color: tint(@primary-color, 90%);
}
&-item-disabled {
cursor: not-allowed;
color: @btn-disable-color;
}
&-item-highlight-enter {
animation: transferHighlightIn 1s ease;
transition: none;
}
}
&-footer {
border-top: 1px solid @border-color-split;
border-radius: 0 0 @border-radius-base @border-radius-base;