diff --git a/components/_util/transKeys.ts b/components/_util/transKeys.ts new file mode 100644 index 000000000000..24e48be2c80c --- /dev/null +++ b/components/_util/transKeys.ts @@ -0,0 +1,16 @@ +export const groupKeysMap = (keys: string[]) => { + const map = new Map(); + keys.forEach((key, index) => { + map.set(key, index); + }); + return map; +}; +export const groupDisabledKeysMap = (dataSource: RecordType) => { + const map = new Map(); + dataSource.forEach(({ disabled, key }, index) => { + if (disabled) { + map.set(key, index); + } + }); + return map; +}; diff --git a/components/transfer/index.tsx b/components/transfer/index.tsx index 57ab58874745..83fcfb8b0ba1 100644 --- a/components/transfer/index.tsx +++ b/components/transfer/index.tsx @@ -8,6 +8,7 @@ import LocaleReceiver from '../locale/LocaleReceiver'; import defaultLocale from '../locale/en_US'; import type { InputStatus } from '../_util/statusUtils'; import { getMergedStatus, getStatusClassNames } from '../_util/statusUtils'; +import { groupKeysMap, groupDisabledKeysMap } from '../_util/transKeys'; import warning from '../_util/warning'; import type { PaginationType } from './interface'; import type { TransferListProps } from './list'; @@ -203,15 +204,16 @@ class Transfer extends React.Com const { targetKeys = [], dataSource = [], onChange } = this.props; const { sourceSelectedKeys, targetSelectedKeys } = this.state; const moveKeys = direction === 'right' ? sourceSelectedKeys : targetSelectedKeys; + const dataSourceDisabledKeysMap = groupDisabledKeysMap(dataSource); + // filter the disabled options - const newMoveKeys = moveKeys.filter( - (key) => !dataSource.some((data) => !!(key === data.key && data.disabled)), - ); + const newMoveKeys = moveKeys.filter((key) => !dataSourceDisabledKeysMap.has(key)); + const newMoveKeysMap = groupKeysMap(newMoveKeys); // move items to target box const newTargetKeys = direction === 'right' ? newMoveKeys.concat(targetKeys) - : targetKeys.filter((targetKey) => !newMoveKeys.includes(targetKey)); + : targetKeys.filter((targetKey) => !newMoveKeysMap.has(targetKey)); // empty checked keys const oppositeDirection = direction === 'right' ? 'left' : 'right'; @@ -232,8 +234,9 @@ class Transfer extends React.Com // Merge current keys with origin key mergedCheckedKeys = Array.from(new Set([...prevKeys, ...selectedKeys])); } else { + const selectedKeysMap = groupKeysMap(selectedKeys); // Remove current keys from origin keys - mergedCheckedKeys = prevKeys.filter((key) => !selectedKeys.includes(key)); + mergedCheckedKeys = prevKeys.filter((key) => !selectedKeysMap.has(key)); } this.handleSelectChange(direction, mergedCheckedKeys); @@ -341,6 +344,7 @@ class Transfer extends React.Com const leftDataSource: KeyWise[] = []; const rightDataSource: KeyWise[] = new Array(targetKeys.length); + const targetKeysMap = groupKeysMap(targetKeys); dataSource.forEach((record: KeyWise) => { if (rowKey) { record = { @@ -348,12 +352,10 @@ class Transfer extends React.Com key: rowKey(record), }; } - // rightDataSource should be ordered by targetKeys // leftDataSource should be ordered by dataSource - const indexOfKey = targetKeys.indexOf(record.key); - if (indexOfKey !== -1) { - rightDataSource[indexOfKey] = record; + if (targetKeysMap.has(record.key)) { + rightDataSource[targetKeysMap.get(record.key)!] = record; } else { leftDataSource.push(record); } diff --git a/components/transfer/list.tsx b/components/transfer/list.tsx index 769b5e3bd66f..6e62cae74b93 100644 --- a/components/transfer/list.tsx +++ b/components/transfer/list.tsx @@ -6,6 +6,7 @@ import Checkbox from '../checkbox'; import Dropdown from '../dropdown'; import type { MenuProps } from '../menu'; import { isValidElement } from '../_util/reactNode'; +import { groupKeysMap } from '../_util/transKeys'; import type { KeyWiseTransferItem, RenderResult, @@ -103,7 +104,8 @@ export default class TransferList< if (checkedKeys.length === 0) { return 'none'; } - if (filteredItems.every((item) => checkedKeys.includes(item.key) || !!item.disabled)) { + const checkedKeysMap = groupKeysMap(checkedKeys); + if (filteredItems.every((item) => checkedKeysMap.has(item.key) || !!item.disabled)) { return 'all'; } return 'part';