ant-design-vue/components/transfer/ListBody.tsx

166 lines
4.2 KiB
Vue

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: String,
filteredRenderItems: PropTypes.array.def([]),
selectedKeys: PropTypes.array,
disabled: { type: Boolean, default: undefined },
showRemove: { type: Boolean, default: undefined },
pagination: PropTypes.any,
onItemSelect: Function,
onScroll: Function,
onItemRemove: Function,
};
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;