| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467 |
- import _objectSpread from "@babel/runtime/helpers/esm/objectSpread2";
- import _extends from "@babel/runtime/helpers/esm/extends";
- import { resolveDirective as _resolveDirective, createVNode as _createVNode } from "vue";
- import RcTable from '../vc-table';
- import { INTERNAL_HOOKS } from '../vc-table/Table';
- import Spin from '../spin';
- import Pagination from '../pagination';
- import usePagination, { DEFAULT_PAGE_SIZE, getPaginationParam } from './hooks/usePagination';
- import useLazyKVMap from './hooks/useLazyKVMap';
- import useSelection from './hooks/useSelection';
- import useSorter, { getSortData } from './hooks/useSorter';
- import useFilter, { getFilterData } from './hooks/useFilter';
- import useTitleColumns from './hooks/useTitleColumns';
- import renderExpandIcon from './ExpandIcon';
- import scrollTo from '../_util/scrollTo';
- import defaultLocale from '../locale/en_US';
- import devWarning from '../vc-util/devWarning';
- import { nextTick, reactive, ref, computed, defineComponent, toRef, watchEffect, watch } from 'vue';
- import useBreakpoint from '../_util/hooks/useBreakpoint';
- import useConfigInject from '../config-provider/hooks/useConfigInject';
- import { useLocaleReceiver } from '../locale-provider/LocaleReceiver';
- import classNames from '../_util/classNames';
- import omit from '../_util/omit';
- import { initDefaultProps } from '../_util/props-util';
- import { useProvideSlots, useProvideTableContext } from './context';
- import useColumns from './hooks/useColumns';
- import { convertChildrenToColumns } from './util';
- import { stringType, booleanType, arrayType, someType, functionType, objectType } from '../_util/type';
- // CSSINJS
- import useStyle from './style';
- const EMPTY_LIST = [];
- export const tableProps = () => {
- return {
- prefixCls: stringType(),
- columns: arrayType(),
- rowKey: someType([String, Function]),
- tableLayout: stringType(),
- rowClassName: someType([String, Function]),
- title: functionType(),
- footer: functionType(),
- id: stringType(),
- showHeader: booleanType(),
- components: objectType(),
- customRow: functionType(),
- customHeaderRow: functionType(),
- direction: stringType(),
- expandFixed: someType([Boolean, String]),
- expandColumnWidth: Number,
- expandedRowKeys: arrayType(),
- defaultExpandedRowKeys: arrayType(),
- expandedRowRender: functionType(),
- expandRowByClick: booleanType(),
- expandIcon: functionType(),
- onExpand: functionType(),
- onExpandedRowsChange: functionType(),
- 'onUpdate:expandedRowKeys': functionType(),
- defaultExpandAllRows: booleanType(),
- indentSize: Number,
- /** @deprecated Please use `EXPAND_COLUMN` in `columns` directly */
- expandIconColumnIndex: Number,
- showExpandColumn: booleanType(),
- expandedRowClassName: functionType(),
- childrenColumnName: stringType(),
- rowExpandable: functionType(),
- sticky: someType([Boolean, Object]),
- dropdownPrefixCls: String,
- dataSource: arrayType(),
- pagination: someType([Boolean, Object]),
- loading: someType([Boolean, Object]),
- size: stringType(),
- bordered: booleanType(),
- locale: objectType(),
- onChange: functionType(),
- onResizeColumn: functionType(),
- rowSelection: objectType(),
- getPopupContainer: functionType(),
- scroll: objectType(),
- sortDirections: arrayType(),
- showSorterTooltip: someType([Boolean, Object], true),
- transformCellText: functionType()
- };
- };
- const InternalTable = defineComponent({
- name: 'InternalTable',
- inheritAttrs: false,
- props: initDefaultProps(_extends(_extends({}, tableProps()), {
- contextSlots: objectType()
- }), {
- rowKey: 'key'
- }),
- setup(props, _ref) {
- let {
- attrs,
- slots,
- expose,
- emit
- } = _ref;
- devWarning(!(typeof props.rowKey === 'function' && props.rowKey.length > 1), 'Table', '`index` parameter of `rowKey` function is deprecated. There is no guarantee that it will work as expected.');
- useProvideSlots(computed(() => props.contextSlots));
- useProvideTableContext({
- onResizeColumn: (w, col) => {
- emit('resizeColumn', w, col);
- }
- });
- const screens = useBreakpoint();
- const mergedColumns = computed(() => {
- const matched = new Set(Object.keys(screens.value).filter(m => screens.value[m]));
- return props.columns.filter(c => !c.responsive || c.responsive.some(r => matched.has(r)));
- });
- const {
- size: mergedSize,
- renderEmpty,
- direction,
- prefixCls,
- configProvider
- } = useConfigInject('table', props);
- // Style
- const [wrapSSR, hashId] = useStyle(prefixCls);
- const transformCellText = computed(() => {
- var _a;
- return props.transformCellText || ((_a = configProvider.transformCellText) === null || _a === void 0 ? void 0 : _a.value);
- });
- const [tableLocale] = useLocaleReceiver('Table', defaultLocale.Table, toRef(props, 'locale'));
- const rawData = computed(() => props.dataSource || EMPTY_LIST);
- const dropdownPrefixCls = computed(() => configProvider.getPrefixCls('dropdown', props.dropdownPrefixCls));
- const childrenColumnName = computed(() => props.childrenColumnName || 'children');
- const expandType = computed(() => {
- if (rawData.value.some(item => item === null || item === void 0 ? void 0 : item[childrenColumnName.value])) {
- return 'nest';
- }
- if (props.expandedRowRender) {
- return 'row';
- }
- return null;
- });
- const internalRefs = reactive({
- body: null
- });
- const updateInternalRefs = refs => {
- _extends(internalRefs, refs);
- };
- // ============================ RowKey ============================
- const getRowKey = computed(() => {
- if (typeof props.rowKey === 'function') {
- return props.rowKey;
- }
- return record => record === null || record === void 0 ? void 0 : record[props.rowKey];
- });
- const [getRecordByKey] = useLazyKVMap(rawData, childrenColumnName, getRowKey);
- // ============================ Events =============================
- const changeEventInfo = {};
- const triggerOnChange = function (info, action) {
- let reset = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
- const {
- pagination,
- scroll,
- onChange
- } = props;
- const changeInfo = _extends(_extends({}, changeEventInfo), info);
- if (reset) {
- changeEventInfo.resetPagination();
- // Reset event param
- if (changeInfo.pagination.current) {
- changeInfo.pagination.current = 1;
- }
- // Trigger pagination events
- if (pagination && pagination.onChange) {
- pagination.onChange(1, changeInfo.pagination.pageSize);
- }
- }
- if (scroll && scroll.scrollToFirstRowOnChange !== false && internalRefs.body) {
- scrollTo(0, {
- getContainer: () => internalRefs.body
- });
- }
- onChange === null || onChange === void 0 ? void 0 : onChange(changeInfo.pagination, changeInfo.filters, changeInfo.sorter, {
- currentDataSource: getFilterData(getSortData(rawData.value, changeInfo.sorterStates, childrenColumnName.value), changeInfo.filterStates),
- action
- });
- };
- /**
- * Controlled state in `columns` is not a good idea that makes too many code (1000+ line?) to read
- * state out and then put it back to title render. Move these code into `hooks` but still too
- * complex. We should provides Table props like `sorter` & `filter` to handle control in next big version.
- */
- // ============================ Sorter =============================
- const onSorterChange = (sorter, sorterStates) => {
- triggerOnChange({
- sorter,
- sorterStates
- }, 'sort', false);
- };
- const [transformSorterColumns, sortStates, sorterTitleProps, sorters] = useSorter({
- prefixCls,
- mergedColumns,
- onSorterChange,
- sortDirections: computed(() => props.sortDirections || ['ascend', 'descend']),
- tableLocale,
- showSorterTooltip: toRef(props, 'showSorterTooltip')
- });
- const sortedData = computed(() => getSortData(rawData.value, sortStates.value, childrenColumnName.value));
- // ============================ Filter ============================
- const onFilterChange = (filters, filterStates) => {
- triggerOnChange({
- filters,
- filterStates
- }, 'filter', true);
- };
- const [transformFilterColumns, filterStates, filters] = useFilter({
- prefixCls,
- locale: tableLocale,
- dropdownPrefixCls,
- mergedColumns,
- onFilterChange,
- getPopupContainer: toRef(props, 'getPopupContainer')
- });
- const mergedData = computed(() => getFilterData(sortedData.value, filterStates.value));
- // ============================ Column ============================
- const [transformBasicColumns] = useColumns(toRef(props, 'contextSlots'));
- const columnTitleProps = computed(() => {
- const mergedFilters = {};
- const filtersValue = filters.value;
- Object.keys(filtersValue).forEach(filterKey => {
- if (filtersValue[filterKey] !== null) {
- mergedFilters[filterKey] = filtersValue[filterKey];
- }
- });
- return _extends(_extends({}, sorterTitleProps.value), {
- filters: mergedFilters
- });
- });
- const [transformTitleColumns] = useTitleColumns(columnTitleProps);
- // ========================== Pagination ==========================
- const onPaginationChange = (current, pageSize) => {
- triggerOnChange({
- pagination: _extends(_extends({}, changeEventInfo.pagination), {
- current,
- pageSize
- })
- }, 'paginate');
- };
- const [mergedPagination, resetPagination] = usePagination(computed(() => mergedData.value.length), toRef(props, 'pagination'), onPaginationChange);
- watchEffect(() => {
- changeEventInfo.sorter = sorters.value;
- changeEventInfo.sorterStates = sortStates.value;
- changeEventInfo.filters = filters.value;
- changeEventInfo.filterStates = filterStates.value;
- changeEventInfo.pagination = props.pagination === false ? {} : getPaginationParam(mergedPagination.value, props.pagination);
- changeEventInfo.resetPagination = resetPagination;
- });
- // ============================= Data =============================
- const pageData = computed(() => {
- if (props.pagination === false || !mergedPagination.value.pageSize) {
- return mergedData.value;
- }
- const {
- current = 1,
- total,
- pageSize = DEFAULT_PAGE_SIZE
- } = mergedPagination.value;
- devWarning(current > 0, 'Table', '`current` should be positive number.');
- // Dynamic table data
- if (mergedData.value.length < total) {
- if (mergedData.value.length > pageSize) {
- return mergedData.value.slice((current - 1) * pageSize, current * pageSize);
- }
- return mergedData.value;
- }
- return mergedData.value.slice((current - 1) * pageSize, current * pageSize);
- });
- watchEffect(() => {
- nextTick(() => {
- const {
- total,
- pageSize = DEFAULT_PAGE_SIZE
- } = mergedPagination.value;
- // Dynamic table data
- if (mergedData.value.length < total) {
- if (mergedData.value.length > pageSize) {
- devWarning(false, 'Table', '`dataSource` length is less than `pagination.total` but large than `pagination.pageSize`. Please make sure your config correct data with async mode.');
- }
- }
- });
- }, {
- flush: 'post'
- });
- const expandIconColumnIndex = computed(() => {
- if (props.showExpandColumn === false) return -1;
- // Adjust expand icon index, no overwrite expandIconColumnIndex if set.
- if (expandType.value === 'nest' && props.expandIconColumnIndex === undefined) {
- return props.rowSelection ? 1 : 0;
- } else if (props.expandIconColumnIndex > 0 && props.rowSelection) {
- return props.expandIconColumnIndex - 1;
- }
- return props.expandIconColumnIndex;
- });
- const rowSelection = ref();
- watch(() => props.rowSelection, () => {
- rowSelection.value = props.rowSelection ? _extends({}, props.rowSelection) : props.rowSelection;
- }, {
- deep: true,
- immediate: true
- });
- // ========================== Selections ==========================
- const [transformSelectionColumns, selectedKeySet] = useSelection(rowSelection, {
- prefixCls,
- data: mergedData,
- pageData,
- getRowKey,
- getRecordByKey,
- expandType,
- childrenColumnName,
- locale: tableLocale,
- getPopupContainer: computed(() => props.getPopupContainer)
- });
- const internalRowClassName = (record, index, indent) => {
- let mergedRowClassName;
- const {
- rowClassName
- } = props;
- if (typeof rowClassName === 'function') {
- mergedRowClassName = classNames(rowClassName(record, index, indent));
- } else {
- mergedRowClassName = classNames(rowClassName);
- }
- return classNames({
- [`${prefixCls.value}-row-selected`]: selectedKeySet.value.has(getRowKey.value(record, index))
- }, mergedRowClassName);
- };
- expose({
- selectedKeySet
- });
- const indentSize = computed(() => {
- // Indent size
- return typeof props.indentSize === 'number' ? props.indentSize : 15;
- });
- const transformColumns = innerColumns => {
- const res = transformTitleColumns(transformSelectionColumns(transformFilterColumns(transformSorterColumns(transformBasicColumns(innerColumns)))));
- return res;
- };
- return () => {
- var _a;
- const {
- expandIcon = slots.expandIcon || renderExpandIcon(tableLocale.value),
- pagination,
- loading,
- bordered
- } = props;
- let topPaginationNode;
- let bottomPaginationNode;
- if (pagination !== false && ((_a = mergedPagination.value) === null || _a === void 0 ? void 0 : _a.total)) {
- let paginationSize;
- if (mergedPagination.value.size) {
- paginationSize = mergedPagination.value.size;
- } else {
- paginationSize = mergedSize.value === 'small' || mergedSize.value === 'middle' ? 'small' : undefined;
- }
- const renderPagination = position => _createVNode(Pagination, _objectSpread(_objectSpread({}, mergedPagination.value), {}, {
- "class": [`${prefixCls.value}-pagination ${prefixCls.value}-pagination-${position}`, mergedPagination.value.class],
- "size": paginationSize
- }), null);
- const defaultPosition = direction.value === 'rtl' ? 'left' : 'right';
- const {
- position
- } = mergedPagination.value;
- if (position !== null && Array.isArray(position)) {
- const topPos = position.find(p => p.includes('top'));
- const bottomPos = position.find(p => p.includes('bottom'));
- const isDisable = position.every(p => `${p}` === 'none');
- if (!topPos && !bottomPos && !isDisable) {
- bottomPaginationNode = renderPagination(defaultPosition);
- }
- if (topPos) {
- topPaginationNode = renderPagination(topPos.toLowerCase().replace('top', ''));
- }
- if (bottomPos) {
- bottomPaginationNode = renderPagination(bottomPos.toLowerCase().replace('bottom', ''));
- }
- } else {
- bottomPaginationNode = renderPagination(defaultPosition);
- }
- }
- // >>>>>>>>> Spinning
- let spinProps;
- if (typeof loading === 'boolean') {
- spinProps = {
- spinning: loading
- };
- } else if (typeof loading === 'object') {
- spinProps = _extends({
- spinning: true
- }, loading);
- }
- const wrapperClassNames = classNames(`${prefixCls.value}-wrapper`, {
- [`${prefixCls.value}-wrapper-rtl`]: direction.value === 'rtl'
- }, attrs.class, hashId.value);
- const tableProps = omit(props, ['columns']);
- return wrapSSR(_createVNode("div", {
- "class": wrapperClassNames,
- "style": attrs.style
- }, [_createVNode(Spin, _objectSpread({
- "spinning": false
- }, spinProps), {
- default: () => [topPaginationNode, _createVNode(RcTable, _objectSpread(_objectSpread(_objectSpread({}, attrs), tableProps), {}, {
- "expandedRowKeys": props.expandedRowKeys,
- "defaultExpandedRowKeys": props.defaultExpandedRowKeys,
- "expandIconColumnIndex": expandIconColumnIndex.value,
- "indentSize": indentSize.value,
- "expandIcon": expandIcon,
- "columns": mergedColumns.value,
- "direction": direction.value,
- "prefixCls": prefixCls.value,
- "class": classNames({
- [`${prefixCls.value}-middle`]: mergedSize.value === 'middle',
- [`${prefixCls.value}-small`]: mergedSize.value === 'small',
- [`${prefixCls.value}-bordered`]: bordered,
- [`${prefixCls.value}-empty`]: rawData.value.length === 0
- }),
- "data": pageData.value,
- "rowKey": getRowKey.value,
- "rowClassName": internalRowClassName,
- "internalHooks": INTERNAL_HOOKS,
- "internalRefs": internalRefs,
- "onUpdateInternalRefs": updateInternalRefs,
- "transformColumns": transformColumns,
- "transformCellText": transformCellText.value
- }), _extends(_extends({}, slots), {
- emptyText: () => {
- var _a, _b;
- return ((_a = slots.emptyText) === null || _a === void 0 ? void 0 : _a.call(slots)) || ((_b = props.locale) === null || _b === void 0 ? void 0 : _b.emptyText) || renderEmpty('Table');
- }
- })), bottomPaginationNode]
- })]));
- };
- }
- });
- const Table = defineComponent({
- name: 'ATable',
- inheritAttrs: false,
- props: initDefaultProps(tableProps(), {
- rowKey: 'key'
- }),
- slots: Object,
- setup(props, _ref2) {
- let {
- attrs,
- slots,
- expose
- } = _ref2;
- const table = ref();
- expose({
- table
- });
- return () => {
- var _a;
- const columns = props.columns || convertChildrenToColumns((_a = slots.default) === null || _a === void 0 ? void 0 : _a.call(slots));
- return _createVNode(InternalTable, _objectSpread(_objectSpread(_objectSpread({
- "ref": table
- }, attrs), props), {}, {
- "columns": columns || [],
- "expandedRowRender": slots.expandedRowRender || props.expandedRowRender,
- "contextSlots": _extends({}, slots)
- }), slots);
- };
- }
- });
- export default Table;
|