166 lines
4.2 KiB
Vue
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: 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;
|