import type { ExtractPropTypes } from 'vue'; import { defineComponent, computed, ref, watch } from 'vue'; import classNames from '../_util/classNames'; import ListItem from './ListItem'; import Pagination from '../pagination'; import PropTypes from '../_util/vue-types'; import type { TransferItem } from '.'; export const transferListBodyProps = { prefixCls: PropTypes.string, filteredRenderItems: PropTypes.array.def([]), selectedKeys: PropTypes.array, disabled: PropTypes.looseBool, showRemove: PropTypes.looseBool, pagination: PropTypes.any, onItemSelect: PropTypes.func, onScroll: PropTypes.func, onItemRemove: PropTypes.func, }; export type TransferListBodyProps = Partial<ExtractPropTypes<typeof transferListBodyProps>>; function parsePagination(pagination) { if (!pagination) { return null; } const defaultPagination = { pageSize: 10, }; if (typeof pagination === 'object') { return { ...defaultPagination, ...pagination, }; } return defaultPagination; } const ListBody = defineComponent({ name: 'ListBody', inheritAttrs: false, props: transferListBodyProps, emits: ['itemSelect', 'itemRemove', 'scroll'], setup(props, { emit, expose }) { const current = ref(1); const handleItemSelect = (item: TransferItem) => { const { selectedKeys } = props; const checked = selectedKeys.indexOf(item.key) >= 0; emit('itemSelect', item.key, !checked); }; const handleItemRemove = (item: TransferItem) => { emit('itemRemove', item.key); }; const handleScroll = (e: Event) => { emit('scroll', e); }; const mergedPagination = computed(() => parsePagination(props.pagination)); watch( [mergedPagination, () => props.filteredRenderItems], () => { if (mergedPagination.value) { // Calculate the page number const maxPageCount = Math.ceil( props.filteredRenderItems.length / mergedPagination.value.pageSize, ); if (current.value > maxPageCount) { current.value = maxPageCount; } } }, { immediate: true }, ); const items = computed(() => { const { filteredRenderItems } = props; let displayItems = filteredRenderItems; if (mergedPagination.value) { displayItems = filteredRenderItems.slice( (current.value - 1) * mergedPagination.value.pageSize, current.value * mergedPagination.value.pageSize, ); } return displayItems; }); const onPageChange = (cur: number) => { current.value = cur; }; expose({ items }); return () => { const { prefixCls, filteredRenderItems, selectedKeys, disabled: globalDisabled, showRemove, } = props; let paginationNode = null; if (mergedPagination.value) { paginationNode = ( <Pagination simple size="small" disabled={globalDisabled} class={`${prefixCls}-pagination`} total={filteredRenderItems.length} pageSize={mergedPagination.value.pageSize} current={current.value} onChange={onPageChange} /> ); } const itemsList = items.value.map(({ renderedEl, renderedText, item }: any) => { const { disabled } = item; const checked = selectedKeys.indexOf(item.key) >= 0; return ( <ListItem disabled={globalDisabled || disabled} key={item.key} item={item} renderedText={renderedText} renderedEl={renderedEl} checked={checked} prefixCls={prefixCls} onClick={handleItemSelect} onRemove={handleItemRemove} showRemove={showRemove} /> ); }); return ( <> <ul class={classNames(`${prefixCls}-content`, { [`${prefixCls}-content-show-remove`]: showRemove, })} onScroll={handleScroll} > {itemsList} </ul> {paginationNode} </> ); }; }, }); export default ListBody;