mirror of
https://github.com/ant-design/ant-design.git
synced 2024-11-24 19:19:57 +08:00
fix(Transfer): Dropdown is hidden & showSizeChanger
not work (#41906)
* fix: Page size dropdown is hidden * fix: SizeChange not work * chore: add test case --------- Co-authored-by: MadCcc <1075746765@qq.com>
This commit is contained in:
parent
6cbf3e102b
commit
91be823272
@ -1,14 +1,17 @@
|
|||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
|
|
||||||
|
import useMergedState from 'rc-util/lib/hooks/useMergedState';
|
||||||
import type { KeyWiseTransferItem } from '.';
|
import type { KeyWiseTransferItem } from '.';
|
||||||
import type { PaginationType } from './interface';
|
|
||||||
import type { RenderedItem, TransferListProps } from './list';
|
|
||||||
import Pagination from '../pagination';
|
import Pagination from '../pagination';
|
||||||
import ListItem from './ListItem';
|
import ListItem from './ListItem';
|
||||||
|
import type { PaginationType } from './interface';
|
||||||
|
import type { RenderedItem, TransferListProps } from './list';
|
||||||
|
|
||||||
export const OmitProps = ['handleFilter', 'handleClear', 'checkedKeys'] as const;
|
export const OmitProps = ['handleFilter', 'handleClear', 'checkedKeys'] as const;
|
||||||
export type OmitProp = typeof OmitProps[number];
|
export type OmitProp = (typeof OmitProps)[number];
|
||||||
type PartialTransferListProps<RecordType> = Omit<TransferListProps<RecordType>, OmitProp>;
|
type PartialTransferListProps<RecordType> = Omit<TransferListProps<RecordType>, OmitProp>;
|
||||||
|
type ExistPagination = Exclude<PaginationType, boolean>;
|
||||||
|
|
||||||
export interface TransferListBodyProps<RecordType> extends PartialTransferListProps<RecordType> {
|
export interface TransferListBodyProps<RecordType> extends PartialTransferListProps<RecordType> {
|
||||||
filteredItems: RecordType[];
|
filteredItems: RecordType[];
|
||||||
@ -16,25 +19,15 @@ export interface TransferListBodyProps<RecordType> extends PartialTransferListPr
|
|||||||
selectedKeys: string[];
|
selectedKeys: string[];
|
||||||
}
|
}
|
||||||
|
|
||||||
const parsePagination = (pagination?: PaginationType) => {
|
const parsePagination = (pagination?: ExistPagination) => {
|
||||||
if (!pagination) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
const defaultPagination: PaginationType = {
|
const defaultPagination: PaginationType = {
|
||||||
pageSize: 10,
|
|
||||||
simple: true,
|
simple: true,
|
||||||
showSizeChanger: false,
|
showSizeChanger: false,
|
||||||
showLessItems: false,
|
showLessItems: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (typeof pagination === 'object') {
|
return { ...defaultPagination, ...pagination };
|
||||||
return { ...defaultPagination, ...pagination };
|
|
||||||
}
|
|
||||||
|
|
||||||
return defaultPagination;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export interface ListBodyRef<RecordType extends KeyWiseTransferItem> {
|
export interface ListBodyRef<RecordType extends KeyWiseTransferItem> {
|
||||||
items?: RenderedItem<RecordType>[];
|
items?: RenderedItem<RecordType>[];
|
||||||
}
|
}
|
||||||
@ -57,16 +50,28 @@ const TransferListBody: React.ForwardRefRenderFunction<
|
|||||||
onItemSelect,
|
onItemSelect,
|
||||||
onItemRemove,
|
onItemRemove,
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
const [current, setCurrent] = React.useState<number>(1);
|
const [current, setCurrent] = React.useState<number>(1);
|
||||||
|
|
||||||
|
const mergedPagination = React.useMemo(() => {
|
||||||
|
if (!pagination) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const convertPagination = typeof pagination === 'object' ? pagination : {};
|
||||||
|
|
||||||
|
return parsePagination(convertPagination);
|
||||||
|
}, [pagination]);
|
||||||
|
|
||||||
|
const [pageSize, setPageSize] = useMergedState<number>(10, {
|
||||||
|
value: mergedPagination?.pageSize,
|
||||||
|
});
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
const mergedPagination = parsePagination(pagination);
|
|
||||||
if (mergedPagination) {
|
if (mergedPagination) {
|
||||||
const maxPageCount = Math.ceil(filteredRenderItems.length / mergedPagination.pageSize!);
|
const maxPageCount = Math.ceil(filteredRenderItems.length / pageSize!);
|
||||||
setCurrent(Math.min(current, maxPageCount));
|
setCurrent(Math.min(current, maxPageCount));
|
||||||
}
|
}
|
||||||
}, [filteredRenderItems, pagination]);
|
}, [filteredRenderItems, mergedPagination, pageSize]);
|
||||||
|
|
||||||
const onClick = (item: RecordType) => {
|
const onClick = (item: RecordType) => {
|
||||||
onItemSelect?.(item.key, !selectedKeys.includes(item.key));
|
onItemSelect?.(item.key, !selectedKeys.includes(item.key));
|
||||||
@ -80,33 +85,33 @@ const TransferListBody: React.ForwardRefRenderFunction<
|
|||||||
setCurrent(cur);
|
setCurrent(cur);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const onSizeChange = (cur: number, size: number) => {
|
||||||
|
setCurrent(cur);
|
||||||
|
setPageSize(size);
|
||||||
|
};
|
||||||
|
|
||||||
const memoizedItems = React.useMemo<RenderedItem<RecordType>[]>(() => {
|
const memoizedItems = React.useMemo<RenderedItem<RecordType>[]>(() => {
|
||||||
const mergedPagination = parsePagination(pagination);
|
|
||||||
const displayItems = mergedPagination
|
const displayItems = mergedPagination
|
||||||
? filteredRenderItems.slice(
|
? filteredRenderItems.slice((current - 1) * pageSize!, current * pageSize!)
|
||||||
(current - 1) * mergedPagination.pageSize!,
|
|
||||||
current * mergedPagination.pageSize!,
|
|
||||||
)
|
|
||||||
: filteredRenderItems;
|
: filteredRenderItems;
|
||||||
return displayItems;
|
return displayItems;
|
||||||
}, [current, filteredRenderItems, pagination]);
|
}, [current, filteredRenderItems, mergedPagination, pageSize]);
|
||||||
|
|
||||||
React.useImperativeHandle(ref, () => ({ items: memoizedItems }));
|
React.useImperativeHandle(ref, () => ({ items: memoizedItems }));
|
||||||
|
|
||||||
const mergedPagination = parsePagination(pagination);
|
|
||||||
|
|
||||||
const paginationNode: React.ReactNode = mergedPagination ? (
|
const paginationNode: React.ReactNode = mergedPagination ? (
|
||||||
<Pagination
|
<Pagination
|
||||||
size="small"
|
size="small"
|
||||||
disabled={globalDisabled}
|
disabled={globalDisabled}
|
||||||
simple={mergedPagination.simple}
|
simple={mergedPagination.simple}
|
||||||
pageSize={mergedPagination.pageSize}
|
pageSize={pageSize}
|
||||||
showLessItems={mergedPagination.showLessItems}
|
showLessItems={mergedPagination.showLessItems}
|
||||||
showSizeChanger={mergedPagination.showSizeChanger}
|
showSizeChanger={mergedPagination.showSizeChanger}
|
||||||
className={`${prefixCls}-pagination`}
|
className={`${prefixCls}-pagination`}
|
||||||
total={filteredRenderItems.length}
|
total={filteredRenderItems.length}
|
||||||
current={current}
|
current={current}
|
||||||
onChange={onPageChange}
|
onChange={onPageChange}
|
||||||
|
onShowSizeChange={onSizeChange}
|
||||||
/>
|
/>
|
||||||
) : null;
|
) : null;
|
||||||
|
|
||||||
|
@ -73,6 +73,19 @@ const searchTransferProps = {
|
|||||||
targetKeys: ['3', '4'],
|
targetKeys: ['3', '4'],
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const generateData = (n = 20) => {
|
||||||
|
const data = [];
|
||||||
|
for (let i = 0; i < n; i++) {
|
||||||
|
data.push({
|
||||||
|
key: `${i}`,
|
||||||
|
title: `content${i}`,
|
||||||
|
description: `description of content${i}`,
|
||||||
|
chosen: false,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return data;
|
||||||
|
};
|
||||||
|
|
||||||
describe('Transfer', () => {
|
describe('Transfer', () => {
|
||||||
mountTest(Transfer);
|
mountTest(Transfer);
|
||||||
rtlTest(Transfer);
|
rtlTest(Transfer);
|
||||||
@ -595,6 +608,32 @@ describe('Transfer', () => {
|
|||||||
);
|
);
|
||||||
await waitFor(() => expect(getAllByTitle('1/1')).toHaveLength(2));
|
await waitFor(() => expect(getAllByTitle('1/1')).toHaveLength(2));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should support change pageSize', () => {
|
||||||
|
const dataSource = generateData();
|
||||||
|
const { container } = render(
|
||||||
|
<Transfer dataSource={dataSource} pagination={{ showSizeChanger: true, simple: false }} />,
|
||||||
|
);
|
||||||
|
|
||||||
|
fireEvent.mouseDown(container.querySelector('.ant-select-selector')!);
|
||||||
|
fireEvent.click(container.querySelectorAll('.ant-select-item-option')[1]);
|
||||||
|
expect(container.querySelectorAll('.ant-transfer-list-content-item').length).toBe(20);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be used first when pagination has pagesize', () => {
|
||||||
|
const dataSource = generateData(30);
|
||||||
|
|
||||||
|
const { container } = render(
|
||||||
|
<Transfer
|
||||||
|
dataSource={dataSource}
|
||||||
|
pagination={{ showSizeChanger: true, simple: false, pageSize: 20 }}
|
||||||
|
/>,
|
||||||
|
);
|
||||||
|
|
||||||
|
fireEvent.mouseDown(container.querySelector('.ant-select-selector')!);
|
||||||
|
fireEvent.click(container.querySelectorAll('.ant-select-item-option')[2]);
|
||||||
|
expect(container.querySelectorAll('.ant-transfer-list-content-item').length).toBe(20);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('remove by click icon', () => {
|
it('remove by click icon', () => {
|
||||||
|
@ -110,7 +110,6 @@ const TransferList = <RecordType extends KeyWiseTransferItem>(
|
|||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
const [filterValue, setFilterValue] = useState<string>('');
|
const [filterValue, setFilterValue] = useState<string>('');
|
||||||
|
|
||||||
const listBodyRef = useRef<ListBodyRef<RecordType>>({});
|
const listBodyRef = useRef<ListBodyRef<RecordType>>({});
|
||||||
|
|
||||||
const internalHandleFilter = (e: React.ChangeEvent<HTMLInputElement>) => {
|
const internalHandleFilter = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
|
@ -101,6 +101,7 @@ const genTransferListStyle: GenerateStyle<TransferToken> = (token: TransferToken
|
|||||||
marginXS,
|
marginXS,
|
||||||
paddingSM,
|
paddingSM,
|
||||||
lineType,
|
lineType,
|
||||||
|
antCls,
|
||||||
iconCls,
|
iconCls,
|
||||||
motionDurationSlow,
|
motionDurationSlow,
|
||||||
controlItemBgHover,
|
controlItemBgHover,
|
||||||
@ -174,8 +175,9 @@ const genTransferListStyle: GenerateStyle<TransferToken> = (token: TransferToken
|
|||||||
display: 'flex',
|
display: 'flex',
|
||||||
flex: 'auto',
|
flex: 'auto',
|
||||||
flexDirection: 'column',
|
flexDirection: 'column',
|
||||||
overflow: 'hidden',
|
|
||||||
fontSize: token.fontSize,
|
fontSize: token.fontSize,
|
||||||
|
// https://blog.csdn.net/qq449245884/article/details/107373672/
|
||||||
|
minHeight: 0,
|
||||||
|
|
||||||
'&-search-wrapper': {
|
'&-search-wrapper': {
|
||||||
position: 'relative',
|
position: 'relative',
|
||||||
@ -262,6 +264,10 @@ const genTransferListStyle: GenerateStyle<TransferToken> = (token: TransferToken
|
|||||||
padding: `${token.paddingXS}px 0`,
|
padding: `${token.paddingXS}px 0`,
|
||||||
textAlign: 'end',
|
textAlign: 'end',
|
||||||
borderTop: `${lineWidth}px ${lineType} ${colorSplit}`,
|
borderTop: `${lineWidth}px ${lineType} ${colorSplit}`,
|
||||||
|
|
||||||
|
[`${antCls}-pagination-options`]: {
|
||||||
|
paddingInlineEnd: token.paddingXS,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
'&-body-not-found': {
|
'&-body-not-found': {
|
||||||
|
Loading…
Reference in New Issue
Block a user