diff --git a/components/transfer/demo/basic.md b/components/transfer/demo/basic.md index 5e0eb30550..9b7a82f384 100644 --- a/components/transfer/demo/basic.md +++ b/components/transfer/demo/basic.md @@ -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); diff --git a/components/transfer/index.tsx b/components/transfer/index.tsx index 9da81af168..fed0f54641 100644 --- a/components/transfer/index.tsx +++ b/components/transfer/index.tsx @@ -12,24 +12,24 @@ export interface TransferItem { key: number | string; title: string; description?: string; - chosen: boolean; + disabled?: boolean; } // Transfer export interface TransferProps { - dataSource: Array; - render?: (record: TransferItem) => any; + dataSource: TransferItem[]; targetKeys: string[]; - onChange?: (targetKeys: Array, 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; - operations?: Array; + 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 { 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 { // 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'; diff --git a/components/transfer/list.tsx b/components/transfer/list.tsx index e25519f9fe..bf64a8bbd1 100644 --- a/components/transfer/list.tsx +++ b/components/transfer/list.tsx @@ -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; + dataSource: TransferItem[]; filter?: string; showSearch?: boolean; searchPlaceholder?: string; @@ -176,43 +176,52 @@ export default class TransferList extends React.Component { + 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 ( -
  • this.handleSelect(item)} key={item.key} title={renderedText}> - key === item.key)} /> +
  • this.handleSelect(item)} + > + key === item.key)} disabled={item.disabled} /> {renderedEl}
  • ); - }).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 : null} - {showItems.length > 0 diff --git a/components/transfer/operation.tsx b/components/transfer/operation.tsx index b516f97293..277d16e86f 100644 --- a/components/transfer/operation.tsx +++ b/components/transfer/operation.tsx @@ -1,4 +1,4 @@ -import * as React from 'react'; +import React from 'react'; import Button from '../button'; import Icon from '../icon'; diff --git a/components/transfer/style/index.less b/components/transfer/style/index.less index ca2153e93d..3cc5e26127 100644 --- a/components/transfer/style/index.less +++ b/components/transfer/style/index.less @@ -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;