mirror of
https://github.com/ant-design/ant-design.git
synced 2024-11-28 05:05:48 +08:00
refactor: (TransferBody) CC => FC (#39988)
* fix * fix * fix type * rerun ci * fix * fix * fix * fix * rename * add useMemo * fix * Code style optimization * Code style optimization * fix * fix * remove useMemo
This commit is contained in:
parent
81a1ffd53c
commit
c5ab5971fd
@ -1,9 +1,9 @@
|
|||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import type { KeyWiseTransferItem } from '.';
|
import type { KeyWiseTransferItem } from '.';
|
||||||
import Pagination from '../pagination';
|
|
||||||
import type { PaginationType } from './interface';
|
import type { PaginationType } from './interface';
|
||||||
import type { RenderedItem, TransferListProps } from './list';
|
import type { RenderedItem, TransferListProps } from './list';
|
||||||
|
import Pagination from '../pagination';
|
||||||
import ListItem from './ListItem';
|
import ListItem from './ListItem';
|
||||||
|
|
||||||
export const OmitProps = ['handleFilter', 'handleClear', 'checkedKeys'] as const;
|
export const OmitProps = ['handleFilter', 'handleClear', 'checkedKeys'] as const;
|
||||||
@ -16,12 +16,12 @@ export interface TransferListBodyProps<RecordType> extends PartialTransferListPr
|
|||||||
selectedKeys: string[];
|
selectedKeys: string[];
|
||||||
}
|
}
|
||||||
|
|
||||||
function parsePagination(pagination?: PaginationType) {
|
const parsePagination = (pagination?: PaginationType) => {
|
||||||
if (!pagination) {
|
if (!pagination) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const defaultPagination = {
|
const defaultPagination: PaginationType = {
|
||||||
pageSize: 10,
|
pageSize: 10,
|
||||||
simple: true,
|
simple: true,
|
||||||
showSizeChanger: false,
|
showSizeChanger: false,
|
||||||
@ -29,139 +29,119 @@ function parsePagination(pagination?: PaginationType) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
if (typeof pagination === 'object') {
|
if (typeof pagination === 'object') {
|
||||||
return {
|
return { ...defaultPagination, ...pagination };
|
||||||
...defaultPagination,
|
|
||||||
...pagination,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return defaultPagination;
|
return defaultPagination;
|
||||||
|
};
|
||||||
|
|
||||||
|
export interface ListBodyRef<RecordType extends KeyWiseTransferItem> {
|
||||||
|
items?: RenderedItem<RecordType>[];
|
||||||
}
|
}
|
||||||
|
|
||||||
interface TransferListBodyState {
|
const TransferListBody: React.ForwardRefRenderFunction<
|
||||||
current: number;
|
ListBodyRef<KeyWiseTransferItem>,
|
||||||
}
|
TransferListBodyProps<KeyWiseTransferItem>
|
||||||
|
> = <RecordType extends KeyWiseTransferItem>(
|
||||||
|
props: TransferListBodyProps<RecordType>,
|
||||||
|
ref: React.ForwardedRef<ListBodyRef<RecordType>>,
|
||||||
|
) => {
|
||||||
|
const {
|
||||||
|
prefixCls,
|
||||||
|
filteredRenderItems,
|
||||||
|
selectedKeys,
|
||||||
|
disabled: globalDisabled,
|
||||||
|
showRemove,
|
||||||
|
pagination,
|
||||||
|
onScroll,
|
||||||
|
onItemSelect,
|
||||||
|
onItemRemove,
|
||||||
|
} = props;
|
||||||
|
|
||||||
class ListBody<RecordType extends KeyWiseTransferItem> extends React.Component<
|
const [current, setCurrent] = React.useState<number>(1);
|
||||||
TransferListBodyProps<RecordType>,
|
|
||||||
TransferListBodyState
|
|
||||||
> {
|
|
||||||
state = {
|
|
||||||
current: 1,
|
|
||||||
};
|
|
||||||
|
|
||||||
static getDerivedStateFromProps<T>(
|
React.useEffect(() => {
|
||||||
{ filteredRenderItems, pagination }: TransferListBodyProps<T>,
|
|
||||||
{ current }: TransferListBodyState,
|
|
||||||
) {
|
|
||||||
const mergedPagination = parsePagination(pagination);
|
const mergedPagination = parsePagination(pagination);
|
||||||
if (mergedPagination) {
|
if (mergedPagination) {
|
||||||
// Calculate the page number
|
const maxPageCount = Math.ceil(filteredRenderItems.length / mergedPagination.pageSize!);
|
||||||
const maxPageCount = Math.ceil(filteredRenderItems.length / mergedPagination.pageSize);
|
setCurrent(Math.min(current, maxPageCount));
|
||||||
if (current > maxPageCount) {
|
|
||||||
return { current: maxPageCount };
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}, [filteredRenderItems, pagination]);
|
||||||
|
|
||||||
return null;
|
const onClick = (item: RecordType) => {
|
||||||
}
|
onItemSelect?.(item.key, !selectedKeys.includes(item.key));
|
||||||
|
|
||||||
onItemSelect = (item: RecordType) => {
|
|
||||||
const { onItemSelect, selectedKeys } = this.props;
|
|
||||||
const checked = selectedKeys.includes(item.key);
|
|
||||||
onItemSelect(item.key, !checked);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
onItemRemove = (item: RecordType) => {
|
const onRemove = (item: RecordType) => {
|
||||||
const { onItemRemove } = this.props;
|
|
||||||
onItemRemove?.([item.key]);
|
onItemRemove?.([item.key]);
|
||||||
};
|
};
|
||||||
|
|
||||||
onPageChange = (current: number) => {
|
const onPageChange = (cur: number) => {
|
||||||
this.setState({ current });
|
setCurrent(cur);
|
||||||
};
|
};
|
||||||
|
|
||||||
getItems = () => {
|
const memoizedItems = React.useMemo<RenderedItem<RecordType>[]>(() => {
|
||||||
const { current } = this.state;
|
|
||||||
const { pagination, filteredRenderItems } = this.props;
|
|
||||||
|
|
||||||
const mergedPagination = parsePagination(pagination);
|
const mergedPagination = parsePagination(pagination);
|
||||||
|
const displayItems = mergedPagination
|
||||||
let displayItems = filteredRenderItems;
|
? filteredRenderItems.slice(
|
||||||
|
(current - 1) * mergedPagination.pageSize!,
|
||||||
if (mergedPagination) {
|
current * mergedPagination.pageSize!,
|
||||||
displayItems = filteredRenderItems.slice(
|
)
|
||||||
(current - 1) * mergedPagination.pageSize,
|
: filteredRenderItems;
|
||||||
current * mergedPagination.pageSize,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return displayItems;
|
return displayItems;
|
||||||
};
|
}, [current, filteredRenderItems, pagination]);
|
||||||
|
|
||||||
render() {
|
React.useImperativeHandle(ref, () => ({ items: memoizedItems }));
|
||||||
const { current } = this.state;
|
|
||||||
const {
|
|
||||||
prefixCls,
|
|
||||||
onScroll,
|
|
||||||
filteredRenderItems,
|
|
||||||
selectedKeys,
|
|
||||||
disabled: globalDisabled,
|
|
||||||
showRemove,
|
|
||||||
pagination,
|
|
||||||
} = this.props;
|
|
||||||
|
|
||||||
const mergedPagination = parsePagination(pagination);
|
const mergedPagination = parsePagination(pagination);
|
||||||
let paginationNode: React.ReactNode = null;
|
|
||||||
|
|
||||||
if (mergedPagination) {
|
const paginationNode: React.ReactNode = mergedPagination ? (
|
||||||
paginationNode = (
|
<Pagination
|
||||||
<Pagination
|
size="small"
|
||||||
simple={mergedPagination.simple}
|
disabled={globalDisabled}
|
||||||
showSizeChanger={mergedPagination.showSizeChanger}
|
simple={mergedPagination.simple}
|
||||||
showLessItems={mergedPagination.showLessItems}
|
pageSize={mergedPagination.pageSize}
|
||||||
size="small"
|
showLessItems={mergedPagination.showLessItems}
|
||||||
disabled={globalDisabled}
|
showSizeChanger={mergedPagination.showSizeChanger}
|
||||||
className={`${prefixCls}-pagination`}
|
className={`${prefixCls}-pagination`}
|
||||||
total={filteredRenderItems.length}
|
total={filteredRenderItems.length}
|
||||||
pageSize={mergedPagination.pageSize}
|
current={current}
|
||||||
current={current}
|
onChange={onPageChange}
|
||||||
onChange={this.onPageChange}
|
/>
|
||||||
/>
|
) : null;
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
const cls = classNames(`${prefixCls}-content`, {
|
||||||
<>
|
[`${prefixCls}-content-show-remove`]: showRemove,
|
||||||
<ul
|
});
|
||||||
className={classNames(`${prefixCls}-content`, {
|
|
||||||
[`${prefixCls}-content-show-remove`]: showRemove,
|
return (
|
||||||
})}
|
<>
|
||||||
onScroll={onScroll}
|
<ul className={cls} onScroll={onScroll}>
|
||||||
>
|
{(memoizedItems || []).map(({ renderedEl, renderedText, item }) => (
|
||||||
{this.getItems().map(({ renderedEl, renderedText, item }: RenderedItem<RecordType>) => {
|
<ListItem
|
||||||
const { disabled } = item;
|
key={item.key}
|
||||||
const checked = selectedKeys.includes(item.key);
|
item={item}
|
||||||
return (
|
renderedText={renderedText}
|
||||||
<ListItem
|
renderedEl={renderedEl}
|
||||||
disabled={globalDisabled || disabled}
|
prefixCls={prefixCls}
|
||||||
key={item.key}
|
showRemove={showRemove}
|
||||||
item={item}
|
onClick={onClick}
|
||||||
renderedText={renderedText}
|
onRemove={onRemove}
|
||||||
renderedEl={renderedEl}
|
checked={selectedKeys.includes(item.key)}
|
||||||
checked={checked}
|
disabled={globalDisabled || item.disabled}
|
||||||
prefixCls={prefixCls}
|
/>
|
||||||
onClick={this.onItemSelect}
|
))}
|
||||||
onRemove={this.onItemRemove}
|
</ul>
|
||||||
showRemove={showRemove}
|
{paginationNode}
|
||||||
/>
|
</>
|
||||||
);
|
);
|
||||||
})}
|
};
|
||||||
</ul>
|
|
||||||
{paginationNode}
|
if (process.env.NODE_ENV !== 'production') {
|
||||||
</>
|
TransferListBody.displayName = 'TransferListBody';
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default ListBody;
|
export default React.forwardRef<
|
||||||
|
ListBodyRef<KeyWiseTransferItem>,
|
||||||
|
TransferListBodyProps<KeyWiseTransferItem>
|
||||||
|
>(TransferListBody);
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { render } from '../../../tests/utils';
|
import type { KeyWiseTransferItem } from '..';
|
||||||
import type { TransferListProps } from '../list';
|
import type { TransferListProps } from '../list';
|
||||||
|
import { render } from '../../../tests/utils';
|
||||||
import List from '../list';
|
import List from '../list';
|
||||||
|
|
||||||
const listCommonProps: TransferListProps<any> = {
|
const listCommonProps: TransferListProps<KeyWiseTransferItem> = {
|
||||||
prefixCls: 'ant-transfer-list',
|
prefixCls: 'ant-transfer-list',
|
||||||
dataSource: [
|
dataSource: [
|
||||||
{ key: 'a', title: 'a' },
|
{ key: 'a', title: 'a' },
|
||||||
@ -12,11 +13,11 @@ const listCommonProps: TransferListProps<any> = {
|
|||||||
],
|
],
|
||||||
checkedKeys: ['a'],
|
checkedKeys: ['a'],
|
||||||
notFoundContent: 'Not Found',
|
notFoundContent: 'Not Found',
|
||||||
} as TransferListProps<any>;
|
} as TransferListProps<KeyWiseTransferItem>;
|
||||||
|
|
||||||
const listProps: TransferListProps<any> = {
|
const listProps: TransferListProps<KeyWiseTransferItem> = {
|
||||||
...listCommonProps,
|
...listCommonProps,
|
||||||
dataSource: undefined as unknown as any[],
|
dataSource: undefined as unknown as KeyWiseTransferItem[],
|
||||||
};
|
};
|
||||||
|
|
||||||
describe('Transfer.List', () => {
|
describe('Transfer.List', () => {
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-shadow */
|
|
||||||
import DownOutlined from '@ant-design/icons/DownOutlined';
|
import DownOutlined from '@ant-design/icons/DownOutlined';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import omit from 'rc-util/lib/omit';
|
import omit from 'rc-util/lib/omit';
|
||||||
import * as React from 'react';
|
import React, { useMemo, useRef, useState } from 'react';
|
||||||
import Checkbox from '../checkbox';
|
import Checkbox from '../checkbox';
|
||||||
import Dropdown from '../dropdown';
|
import Dropdown from '../dropdown';
|
||||||
import type { MenuProps } from '../menu';
|
import type { MenuProps } from '../menu';
|
||||||
@ -17,7 +16,7 @@ import type {
|
|||||||
TransferLocale,
|
TransferLocale,
|
||||||
} from './index';
|
} from './index';
|
||||||
import type { PaginationType } from './interface';
|
import type { PaginationType } from './interface';
|
||||||
import type { TransferListBodyProps } from './ListBody';
|
import type { ListBodyRef, TransferListBodyProps } from './ListBody';
|
||||||
import DefaultListBody, { OmitProps } from './ListBody';
|
import DefaultListBody, { OmitProps } from './ListBody';
|
||||||
import Search from './search';
|
import Search from './search';
|
||||||
|
|
||||||
@ -66,7 +65,7 @@ export interface TransferListProps<RecordType> extends TransferLocale {
|
|||||||
props: TransferListProps<RecordType>,
|
props: TransferListProps<RecordType>,
|
||||||
info?: { direction: TransferDirection },
|
info?: { direction: TransferDirection },
|
||||||
) => React.ReactNode;
|
) => React.ReactNode;
|
||||||
onScroll: (e: React.UIEvent<HTMLUListElement>) => void;
|
onScroll: (e: React.UIEvent<HTMLUListElement, UIEvent>) => void;
|
||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
direction: TransferDirection;
|
direction: TransferDirection;
|
||||||
showSelectAll?: boolean;
|
showSelectAll?: boolean;
|
||||||
@ -110,20 +109,9 @@ const TransferList = <RecordType extends KeyWiseTransferItem>(
|
|||||||
render = defaultRender,
|
render = defaultRender,
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
const [filterValue, setFilterValue] = React.useState<string>('');
|
const [filterValue, setFilterValue] = useState<string>('');
|
||||||
|
|
||||||
const defaultListBodyRef = React.useRef<DefaultListBody<RecordType>>(null);
|
const listBodyRef = useRef<ListBodyRef<RecordType>>({});
|
||||||
|
|
||||||
const getCheckStatus = (filteredItems: RecordType[]) => {
|
|
||||||
if (checkedKeys.length === 0) {
|
|
||||||
return 'none';
|
|
||||||
}
|
|
||||||
const checkedKeysMap = groupKeysMap(checkedKeys);
|
|
||||||
if (filteredItems.every((item) => checkedKeysMap.has(item.key) || !!item.disabled)) {
|
|
||||||
return 'all';
|
|
||||||
}
|
|
||||||
return 'part';
|
|
||||||
};
|
|
||||||
|
|
||||||
const internalHandleFilter = (e: React.ChangeEvent<HTMLInputElement>) => {
|
const internalHandleFilter = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
setFilterValue(e.target.value);
|
setFilterValue(e.target.value);
|
||||||
@ -142,14 +130,11 @@ const TransferList = <RecordType extends KeyWiseTransferItem>(
|
|||||||
return text.includes(filterValue);
|
return text.includes(filterValue);
|
||||||
};
|
};
|
||||||
|
|
||||||
const renderListBody = (
|
const renderListBody = (listProps: TransferListBodyProps<RecordType>) => {
|
||||||
renderList: RenderListFunction<RecordType> | undefined,
|
let bodyContent: React.ReactNode = renderList ? renderList(listProps) : null;
|
||||||
props: TransferListBodyProps<RecordType>,
|
|
||||||
) => {
|
|
||||||
let bodyContent: React.ReactNode = renderList ? renderList(props) : null;
|
|
||||||
const customize: boolean = !!bodyContent;
|
const customize: boolean = !!bodyContent;
|
||||||
if (!customize) {
|
if (!customize) {
|
||||||
bodyContent = <DefaultListBody ref={defaultListBodyRef} {...props} />;
|
bodyContent = <DefaultListBody ref={listBodyRef} {...listProps} />;
|
||||||
}
|
}
|
||||||
return { customize, bodyContent };
|
return { customize, bodyContent };
|
||||||
};
|
};
|
||||||
@ -158,51 +143,46 @@ const TransferList = <RecordType extends KeyWiseTransferItem>(
|
|||||||
const renderResult = render(item);
|
const renderResult = render(item);
|
||||||
const isRenderResultPlain = isRenderResultPlainObject(renderResult);
|
const isRenderResultPlain = isRenderResultPlainObject(renderResult);
|
||||||
return {
|
return {
|
||||||
renderedText: isRenderResultPlain
|
|
||||||
? (renderResult as RenderResultObject).value
|
|
||||||
: (renderResult as string),
|
|
||||||
renderedEl: isRenderResultPlain ? (renderResult as RenderResultObject).label : renderResult,
|
|
||||||
item,
|
item,
|
||||||
|
renderedEl: isRenderResultPlain ? renderResult.label : renderResult,
|
||||||
|
renderedText: isRenderResultPlain ? renderResult.value : (renderResult as string),
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
const getFilteredItems = (
|
const notFoundContentEle = useMemo<React.ReactNode>(
|
||||||
dataSource: RecordType[],
|
() =>
|
||||||
filterValue: string,
|
Array.isArray(notFoundContent)
|
||||||
): {
|
? notFoundContent[direction === 'left' ? 0 : 1]
|
||||||
filteredItems: RecordType[];
|
: notFoundContent,
|
||||||
filteredRenderItems: RenderedItem<RecordType>[];
|
[notFoundContent, direction],
|
||||||
} => {
|
);
|
||||||
const filteredItems: RecordType[] = [];
|
|
||||||
const filteredRenderItems: RenderedItem<RecordType>[] = [];
|
|
||||||
|
|
||||||
|
const [filteredItems, filteredRenderItems] = useMemo(() => {
|
||||||
|
const filterItems: RecordType[] = [];
|
||||||
|
const filterRenderItems: RenderedItem<RecordType>[] = [];
|
||||||
dataSource.forEach((item) => {
|
dataSource.forEach((item) => {
|
||||||
const renderedItem = renderItem(item);
|
const renderedItem = renderItem(item);
|
||||||
const { renderedText } = renderedItem;
|
if (filterValue && !matchFilter(renderedItem.renderedText, item)) {
|
||||||
|
return;
|
||||||
// Filter skip
|
|
||||||
if (filterValue && !matchFilter(renderedText, item)) {
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
filterItems.push(item);
|
||||||
filteredItems.push(item);
|
filterRenderItems.push(renderedItem);
|
||||||
filteredRenderItems.push(renderedItem);
|
|
||||||
});
|
});
|
||||||
return { filteredItems, filteredRenderItems };
|
return [filterItems, filterRenderItems] as const;
|
||||||
};
|
}, [dataSource, filterValue]);
|
||||||
|
|
||||||
const getListBody = (
|
const checkStatus = useMemo<string>(() => {
|
||||||
prefixCls: string,
|
if (checkedKeys.length === 0) {
|
||||||
searchPlaceholder: string,
|
return 'none';
|
||||||
filterValue: string,
|
}
|
||||||
filteredItems: RecordType[],
|
const checkedKeysMap = groupKeysMap(checkedKeys);
|
||||||
notFoundContent: React.ReactNode | React.ReactNode[],
|
if (filteredItems.every((item) => checkedKeysMap.has(item.key) || !!item.disabled)) {
|
||||||
filteredRenderItems: RenderedItem<RecordType>[],
|
return 'all';
|
||||||
checkedKeys: string[],
|
}
|
||||||
renderList?: RenderListFunction<RecordType>,
|
return 'part';
|
||||||
showSearch?: boolean,
|
}, [checkedKeys, filteredItems]);
|
||||||
disabled?: boolean,
|
|
||||||
): React.ReactNode => {
|
const listBody = useMemo<React.ReactNode>(() => {
|
||||||
const search = showSearch ? (
|
const search = showSearch ? (
|
||||||
<div className={`${prefixCls}-body-search-wrapper`}>
|
<div className={`${prefixCls}-body-search-wrapper`}>
|
||||||
<Search
|
<Search
|
||||||
@ -216,18 +196,13 @@ const TransferList = <RecordType extends KeyWiseTransferItem>(
|
|||||||
</div>
|
</div>
|
||||||
) : null;
|
) : null;
|
||||||
|
|
||||||
const { bodyContent, customize } = renderListBody(renderList, {
|
const { customize, bodyContent } = renderListBody({
|
||||||
...omit(props, OmitProps),
|
...omit(props, OmitProps),
|
||||||
filteredItems,
|
filteredItems,
|
||||||
filteredRenderItems,
|
filteredRenderItems,
|
||||||
selectedKeys: checkedKeys,
|
selectedKeys: checkedKeys,
|
||||||
});
|
});
|
||||||
|
|
||||||
const getNotFoundContent = () =>
|
|
||||||
Array.isArray(notFoundContent)
|
|
||||||
? notFoundContent[direction === 'left' ? 0 : 1]
|
|
||||||
: notFoundContent;
|
|
||||||
|
|
||||||
let bodyNode: React.ReactNode;
|
let bodyNode: React.ReactNode;
|
||||||
// We should wrap customize list body in a classNamed div to use flex layout.
|
// We should wrap customize list body in a classNamed div to use flex layout.
|
||||||
if (customize) {
|
if (customize) {
|
||||||
@ -236,10 +211,9 @@ const TransferList = <RecordType extends KeyWiseTransferItem>(
|
|||||||
bodyNode = filteredItems.length ? (
|
bodyNode = filteredItems.length ? (
|
||||||
bodyContent
|
bodyContent
|
||||||
) : (
|
) : (
|
||||||
<div className={`${prefixCls}-body-not-found`}>{getNotFoundContent()}</div>
|
<div className={`${prefixCls}-body-not-found`}>{notFoundContentEle}</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={classNames(
|
className={classNames(
|
||||||
@ -250,38 +224,33 @@ const TransferList = <RecordType extends KeyWiseTransferItem>(
|
|||||||
{bodyNode}
|
{bodyNode}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
}, [
|
||||||
|
showSearch,
|
||||||
const getCheckBox = ({
|
|
||||||
filteredItems,
|
|
||||||
onItemSelectAll,
|
|
||||||
disabled,
|
|
||||||
prefixCls,
|
prefixCls,
|
||||||
}: {
|
searchPlaceholder,
|
||||||
filteredItems: RecordType[];
|
filterValue,
|
||||||
onItemSelectAll: (dataSource: string[], checkAll: boolean) => void;
|
disabled,
|
||||||
disabled?: boolean;
|
checkedKeys,
|
||||||
prefixCls?: string;
|
filteredItems,
|
||||||
}): false | React.ReactNode => {
|
filteredRenderItems,
|
||||||
const checkStatus = getCheckStatus(filteredItems);
|
notFoundContentEle,
|
||||||
const checkedAll = checkStatus === 'all';
|
]);
|
||||||
const checkAllCheckbox: React.ReactNode = (
|
|
||||||
<Checkbox
|
const checkBox = (
|
||||||
disabled={disabled}
|
<Checkbox
|
||||||
checked={checkedAll}
|
disabled={disabled}
|
||||||
indeterminate={checkStatus === 'part'}
|
checked={checkStatus === 'all'}
|
||||||
className={`${prefixCls}-checkbox`}
|
indeterminate={checkStatus === 'part'}
|
||||||
onChange={() => {
|
className={`${prefixCls}-checkbox`}
|
||||||
// Only select enabled items
|
onChange={() => {
|
||||||
onItemSelectAll(
|
// Only select enabled items
|
||||||
filteredItems.filter((item) => !item.disabled).map(({ key }) => key),
|
onItemSelectAll?.(
|
||||||
!checkedAll,
|
filteredItems.filter((item) => !item.disabled).map(({ key }) => key),
|
||||||
);
|
checkStatus !== 'all',
|
||||||
}}
|
);
|
||||||
/>
|
}}
|
||||||
);
|
/>
|
||||||
return checkAllCheckbox;
|
);
|
||||||
};
|
|
||||||
|
|
||||||
const getSelectAllLabel = (selectedCount: number, totalCount: number): React.ReactNode => {
|
const getSelectAllLabel = (selectedCount: number, totalCount: number): React.ReactNode => {
|
||||||
if (selectAllLabel) {
|
if (selectAllLabel) {
|
||||||
@ -307,27 +276,9 @@ const TransferList = <RecordType extends KeyWiseTransferItem>(
|
|||||||
|
|
||||||
// ====================== Get filtered, checked item list ======================
|
// ====================== Get filtered, checked item list ======================
|
||||||
|
|
||||||
const { filteredItems, filteredRenderItems } = getFilteredItems(dataSource, filterValue);
|
|
||||||
|
|
||||||
const listBody = getListBody(
|
|
||||||
prefixCls,
|
|
||||||
searchPlaceholder,
|
|
||||||
filterValue,
|
|
||||||
filteredItems,
|
|
||||||
notFoundContent,
|
|
||||||
filteredRenderItems,
|
|
||||||
checkedKeys,
|
|
||||||
renderList,
|
|
||||||
showSearch,
|
|
||||||
disabled,
|
|
||||||
);
|
|
||||||
|
|
||||||
const listFooter = footerDom ? <div className={`${prefixCls}-footer`}>{footerDom}</div> : null;
|
const listFooter = footerDom ? <div className={`${prefixCls}-footer`}>{footerDom}</div> : null;
|
||||||
|
|
||||||
const checkAllCheckbox =
|
const checkAllCheckbox = !showRemove && !pagination && checkBox;
|
||||||
!showRemove &&
|
|
||||||
!pagination &&
|
|
||||||
getCheckBox({ filteredItems, onItemSelectAll, disabled, prefixCls });
|
|
||||||
|
|
||||||
let items: MenuProps['items'];
|
let items: MenuProps['items'];
|
||||||
|
|
||||||
@ -340,7 +291,7 @@ const TransferList = <RecordType extends KeyWiseTransferItem>(
|
|||||||
label: removeCurrent,
|
label: removeCurrent,
|
||||||
onClick() {
|
onClick() {
|
||||||
const pageKeys = getEnabledItemKeys(
|
const pageKeys = getEnabledItemKeys(
|
||||||
(defaultListBodyRef.current?.getItems() || []).map((entity) => entity.item),
|
(listBodyRef.current?.items || []).map((entity) => entity.item),
|
||||||
);
|
);
|
||||||
onItemRemove?.(pageKeys);
|
onItemRemove?.(pageKeys);
|
||||||
},
|
},
|
||||||
@ -362,7 +313,7 @@ const TransferList = <RecordType extends KeyWiseTransferItem>(
|
|||||||
label: selectAll,
|
label: selectAll,
|
||||||
onClick() {
|
onClick() {
|
||||||
const keys = getEnabledItemKeys(filteredItems);
|
const keys = getEnabledItemKeys(filteredItems);
|
||||||
onItemSelectAll(keys, keys.length !== checkedKeys.length);
|
onItemSelectAll?.(keys, keys.length !== checkedKeys.length);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
pagination
|
pagination
|
||||||
@ -370,8 +321,8 @@ const TransferList = <RecordType extends KeyWiseTransferItem>(
|
|||||||
key: 'selectCurrent',
|
key: 'selectCurrent',
|
||||||
label: selectCurrent,
|
label: selectCurrent,
|
||||||
onClick() {
|
onClick() {
|
||||||
const pageItems = defaultListBodyRef.current?.getItems() || [];
|
const pageItems = listBodyRef.current?.items || [];
|
||||||
onItemSelectAll(getEnabledItemKeys(pageItems.map((entity) => entity.item)), true);
|
onItemSelectAll?.(getEnabledItemKeys(pageItems.map((entity) => entity.item)), true);
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
: null,
|
: null,
|
||||||
@ -381,7 +332,7 @@ const TransferList = <RecordType extends KeyWiseTransferItem>(
|
|||||||
onClick() {
|
onClick() {
|
||||||
const availableKeys = getEnabledItemKeys(
|
const availableKeys = getEnabledItemKeys(
|
||||||
pagination
|
pagination
|
||||||
? (defaultListBodyRef.current?.getItems() || []).map((entity) => entity.item)
|
? (listBodyRef.current?.items || []).map((entity) => entity.item)
|
||||||
: filteredItems,
|
: filteredItems,
|
||||||
);
|
);
|
||||||
const checkedKeySet = new Set<string>(checkedKeys);
|
const checkedKeySet = new Set<string>(checkedKeys);
|
||||||
@ -394,14 +345,14 @@ const TransferList = <RecordType extends KeyWiseTransferItem>(
|
|||||||
newCheckedKeys.push(key);
|
newCheckedKeys.push(key);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
onItemSelectAll(newCheckedKeys, true);
|
onItemSelectAll?.(newCheckedKeys, true);
|
||||||
onItemSelectAll(newUnCheckedKeys, false);
|
onItemSelectAll?.(newUnCheckedKeys, false);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
const dropdown = (
|
const dropdown: React.ReactNode = (
|
||||||
<Dropdown className={`${prefixCls}-header-dropdown`} menu={{ items }} disabled={disabled}>
|
<Dropdown className={`${prefixCls}-header-dropdown`} menu={{ items }} disabled={disabled}>
|
||||||
<DownOutlined />
|
<DownOutlined />
|
||||||
</Dropdown>
|
</Dropdown>
|
||||||
|
Loading…
Reference in New Issue
Block a user