naive-ui
Version:
A Vue 3 Component Library. Fairly Complete, Theme Customizable, Uses TypeScript, Fast
453 lines • 16 kB
JavaScript
import { Transition, computed, defineComponent, h, provide, ref, toRef, watchEffect } from 'vue';
import { createId } from 'seemly';
import { useConfig, useLocale, useRtl, useTheme, useThemeClass } from "../../_mixins/index.mjs";
import { NBaseLoading } from "../../_internal/index.mjs";
import { NPagination } from "../../pagination/index.mjs";
import { createKey, download, resolveSlot, warnOnce } from "../../_utils/index.mjs";
import { dataTableLight } from "../styles/index.mjs";
import MainTable from "./MainTable.mjs";
import { useCheck } from "./use-check.mjs";
import { useTableData } from "./use-table-data.mjs";
import { useScroll } from "./use-scroll.mjs";
import { useResizable } from "./use-resizable.mjs";
import { dataTableInjectionKey, dataTableProps } from "./interface.mjs";
import { useGroupHeader } from "./use-group-header.mjs";
import { useExpand } from "./use-expand.mjs";
import style from "./styles/index.cssr.mjs";
import { generateCsv } from "./utils.mjs";
export default defineComponent({
name: 'DataTable',
alias: ['AdvancedTable'],
props: dataTableProps,
setup(props, {
slots
}) {
if (process.env.NODE_ENV !== 'production') {
watchEffect(() => {
if (props.onPageChange !== undefined) {
warnOnce('data-table', '`on-page-change` is deprecated, please use `on-update:page` instead.');
}
if (props.onPageSizeChange !== undefined) {
warnOnce('data-table', '`on-page-size-change` is deprecated, please use `on-update:page-size` instead.');
}
if (props.onSorterChange !== undefined) {
warnOnce('data-table', '`on-sorter-change` is deprecated, please use `on-update:sorter` instead.');
}
if (props.onFiltersChange !== undefined) {
warnOnce('data-table', '`on-filters-change` is deprecated, please use `on-update:filters` instead.');
}
if (props.onCheckedRowKeysChange !== undefined) {
warnOnce('data-table', '`on-checked-row-keys-change` is deprecated, please use `on-update:checked-row-keys` instead.');
}
});
}
const {
mergedBorderedRef,
mergedClsPrefixRef,
inlineThemeDisabled,
mergedRtlRef
} = useConfig(props);
const rtlEnabledRef = useRtl('DataTable', mergedRtlRef, mergedClsPrefixRef);
const mergedBottomBorderedRef = computed(() => {
const {
bottomBordered
} = props;
// do not add bottom bordered class if bordered is true
// since border is displayed on wrapper
if (mergedBorderedRef.value) return false;
if (bottomBordered !== undefined) return bottomBordered;
return true;
});
const themeRef = useTheme('DataTable', '-data-table', style, dataTableLight, props, mergedClsPrefixRef);
const bodyWidthRef = ref(null);
const mainTableInstRef = ref(null);
const {
getResizableWidth,
clearResizableWidth,
doUpdateResizableWidth
} = useResizable();
const {
rowsRef,
colsRef,
dataRelatedColsRef,
hasEllipsisRef
} = useGroupHeader(props, getResizableWidth);
const {
treeMateRef,
mergedCurrentPageRef,
paginatedDataRef,
rawPaginatedDataRef,
selectionColumnRef,
hoverKeyRef,
mergedPaginationRef,
mergedFilterStateRef,
mergedSortStateRef,
childTriggerColIndexRef,
doUpdatePage,
doUpdateFilters,
onUnstableColumnResize,
deriveNextSorter,
filter,
filters,
clearFilter,
clearFilters,
clearSorter,
page,
sort
} = useTableData(props, {
dataRelatedColsRef
});
const downloadCsv = options => {
const {
fileName = 'data.csv',
keepOriginalData = false
} = options || {};
const data = keepOriginalData ? props.data : rawPaginatedDataRef.value;
const csvData = generateCsv(props.columns, data);
const blob = new Blob([csvData], {
type: 'text/csv;charset=utf-8'
});
const downloadUrl = URL.createObjectURL(blob);
download(downloadUrl, fileName.endsWith('.csv') ? fileName : `${fileName}.csv`);
URL.revokeObjectURL(downloadUrl);
};
const {
doCheckAll,
doUncheckAll,
doCheck,
doUncheck,
headerCheckboxDisabledRef,
someRowsCheckedRef,
allRowsCheckedRef,
mergedCheckedRowKeySetRef,
mergedInderminateRowKeySetRef
} = useCheck(props, {
selectionColumnRef,
treeMateRef,
paginatedDataRef
});
const {
stickyExpandedRowsRef,
mergedExpandedRowKeysRef,
renderExpandRef,
expandableRef,
doUpdateExpandedRowKeys
} = useExpand(props, treeMateRef);
const {
handleTableBodyScroll,
handleTableHeaderScroll,
syncScrollState,
setHeaderScrollLeft,
leftActiveFixedColKeyRef,
leftActiveFixedChildrenColKeysRef,
rightActiveFixedColKeyRef,
rightActiveFixedChildrenColKeysRef,
leftFixedColumnsRef,
rightFixedColumnsRef,
fixedColumnLeftMapRef,
fixedColumnRightMapRef
} = useScroll(props, {
bodyWidthRef,
mainTableInstRef,
mergedCurrentPageRef
});
const {
localeRef
} = useLocale('DataTable');
const mergedTableLayoutRef = computed(() => {
// Layout
// virtual |descrete header | ellpisis => fixed
// = virtual | maxHeight | ellpisis => fixed
if (props.virtualScroll || props.flexHeight || props.maxHeight !== undefined || hasEllipsisRef.value) {
return 'fixed';
}
return props.tableLayout;
});
provide(dataTableInjectionKey, {
props,
treeMateRef,
renderExpandIconRef: toRef(props, 'renderExpandIcon'),
loadingKeySetRef: ref(new Set()),
slots,
indentRef: toRef(props, 'indent'),
childTriggerColIndexRef,
bodyWidthRef,
componentId: createId(),
hoverKeyRef,
mergedClsPrefixRef,
mergedThemeRef: themeRef,
scrollXRef: computed(() => props.scrollX),
rowsRef,
colsRef,
paginatedDataRef,
leftActiveFixedColKeyRef,
leftActiveFixedChildrenColKeysRef,
rightActiveFixedColKeyRef,
rightActiveFixedChildrenColKeysRef,
leftFixedColumnsRef,
rightFixedColumnsRef,
fixedColumnLeftMapRef,
fixedColumnRightMapRef,
mergedCurrentPageRef,
someRowsCheckedRef,
allRowsCheckedRef,
mergedSortStateRef,
mergedFilterStateRef,
loadingRef: toRef(props, 'loading'),
rowClassNameRef: toRef(props, 'rowClassName'),
mergedCheckedRowKeySetRef,
mergedExpandedRowKeysRef,
mergedInderminateRowKeySetRef,
localeRef,
expandableRef,
stickyExpandedRowsRef,
rowKeyRef: toRef(props, 'rowKey'),
renderExpandRef,
summaryRef: toRef(props, 'summary'),
virtualScrollRef: toRef(props, 'virtualScroll'),
virtualScrollXRef: toRef(props, 'virtualScrollX'),
heightForRowRef: toRef(props, 'heightForRow'),
minRowHeightRef: toRef(props, 'minRowHeight'),
virtualScrollHeaderRef: toRef(props, 'virtualScrollHeader'),
headerHeightRef: toRef(props, 'headerHeight'),
rowPropsRef: toRef(props, 'rowProps'),
stripedRef: toRef(props, 'striped'),
checkOptionsRef: computed(() => {
const {
value: selectionColumn
} = selectionColumnRef;
return selectionColumn === null || selectionColumn === void 0 ? void 0 : selectionColumn.options;
}),
rawPaginatedDataRef,
filterMenuCssVarsRef: computed(() => {
const {
self: {
actionDividerColor,
actionPadding,
actionButtonMargin
}
} = themeRef.value;
return {
'--n-action-padding': actionPadding,
'--n-action-button-margin': actionButtonMargin,
'--n-action-divider-color': actionDividerColor
};
}),
onLoadRef: toRef(props, 'onLoad'),
mergedTableLayoutRef,
maxHeightRef: toRef(props, 'maxHeight'),
minHeightRef: toRef(props, 'minHeight'),
flexHeightRef: toRef(props, 'flexHeight'),
headerCheckboxDisabledRef,
paginationBehaviorOnFilterRef: toRef(props, 'paginationBehaviorOnFilter'),
summaryPlacementRef: toRef(props, 'summaryPlacement'),
filterIconPopoverPropsRef: toRef(props, 'filterIconPopoverProps'),
scrollbarPropsRef: toRef(props, 'scrollbarProps'),
syncScrollState,
doUpdatePage,
doUpdateFilters,
getResizableWidth,
onUnstableColumnResize,
clearResizableWidth,
doUpdateResizableWidth,
deriveNextSorter,
doCheck,
doUncheck,
doCheckAll,
doUncheckAll,
doUpdateExpandedRowKeys,
handleTableHeaderScroll,
handleTableBodyScroll,
setHeaderScrollLeft,
renderCell: toRef(props, 'renderCell')
});
const exposedMethods = {
filter,
filters,
clearFilters,
clearSorter,
page,
sort,
clearFilter,
downloadCsv,
scrollTo: (arg0, arg1) => {
var _a;
(_a = mainTableInstRef.value) === null || _a === void 0 ? void 0 : _a.scrollTo(arg0, arg1);
}
};
const cssVarsRef = computed(() => {
const {
size
} = props;
const {
common: {
cubicBezierEaseInOut
},
self: {
borderColor,
tdColorHover,
tdColorSorting,
tdColorSortingModal,
tdColorSortingPopover,
thColorSorting,
thColorSortingModal,
thColorSortingPopover,
thColor,
thColorHover,
tdColor,
tdTextColor,
thTextColor,
thFontWeight,
thButtonColorHover,
thIconColor,
thIconColorActive,
filterSize,
borderRadius,
lineHeight,
tdColorModal,
thColorModal,
borderColorModal,
thColorHoverModal,
tdColorHoverModal,
borderColorPopover,
thColorPopover,
tdColorPopover,
tdColorHoverPopover,
thColorHoverPopover,
paginationMargin,
emptyPadding,
boxShadowAfter,
boxShadowBefore,
sorterSize,
resizableContainerSize,
resizableSize,
loadingColor,
loadingSize,
opacityLoading,
tdColorStriped,
tdColorStripedModal,
tdColorStripedPopover,
[createKey('fontSize', size)]: fontSize,
[createKey('thPadding', size)]: thPadding,
[createKey('tdPadding', size)]: tdPadding
}
} = themeRef.value;
return {
'--n-font-size': fontSize,
'--n-th-padding': thPadding,
'--n-td-padding': tdPadding,
'--n-bezier': cubicBezierEaseInOut,
'--n-border-radius': borderRadius,
'--n-line-height': lineHeight,
'--n-border-color': borderColor,
'--n-border-color-modal': borderColorModal,
'--n-border-color-popover': borderColorPopover,
'--n-th-color': thColor,
'--n-th-color-hover': thColorHover,
'--n-th-color-modal': thColorModal,
'--n-th-color-hover-modal': thColorHoverModal,
'--n-th-color-popover': thColorPopover,
'--n-th-color-hover-popover': thColorHoverPopover,
'--n-td-color': tdColor,
'--n-td-color-hover': tdColorHover,
'--n-td-color-modal': tdColorModal,
'--n-td-color-hover-modal': tdColorHoverModal,
'--n-td-color-popover': tdColorPopover,
'--n-td-color-hover-popover': tdColorHoverPopover,
'--n-th-text-color': thTextColor,
'--n-td-text-color': tdTextColor,
'--n-th-font-weight': thFontWeight,
'--n-th-button-color-hover': thButtonColorHover,
'--n-th-icon-color': thIconColor,
'--n-th-icon-color-active': thIconColorActive,
'--n-filter-size': filterSize,
'--n-pagination-margin': paginationMargin,
'--n-empty-padding': emptyPadding,
'--n-box-shadow-before': boxShadowBefore,
'--n-box-shadow-after': boxShadowAfter,
'--n-sorter-size': sorterSize,
'--n-resizable-container-size': resizableContainerSize,
'--n-resizable-size': resizableSize,
'--n-loading-size': loadingSize,
'--n-loading-color': loadingColor,
'--n-opacity-loading': opacityLoading,
'--n-td-color-striped': tdColorStriped,
'--n-td-color-striped-modal': tdColorStripedModal,
'--n-td-color-striped-popover': tdColorStripedPopover,
'n-td-color-sorting': tdColorSorting,
'n-td-color-sorting-modal': tdColorSortingModal,
'n-td-color-sorting-popover': tdColorSortingPopover,
'n-th-color-sorting': thColorSorting,
'n-th-color-sorting-modal': thColorSortingModal,
'n-th-color-sorting-popover': thColorSortingPopover
};
});
const themeClassHandle = inlineThemeDisabled ? useThemeClass('data-table', computed(() => props.size[0]), cssVarsRef, props) : undefined;
const mergedShowPaginationRef = computed(() => {
if (!props.pagination) return false;
if (props.paginateSinglePage) return true;
const mergedPagination = mergedPaginationRef.value;
const {
pageCount
} = mergedPagination;
if (pageCount !== undefined) return pageCount > 1;
return mergedPagination.itemCount && mergedPagination.pageSize && mergedPagination.itemCount > mergedPagination.pageSize;
});
return Object.assign({
mainTableInstRef,
mergedClsPrefix: mergedClsPrefixRef,
rtlEnabled: rtlEnabledRef,
mergedTheme: themeRef,
paginatedData: paginatedDataRef,
mergedBordered: mergedBorderedRef,
mergedBottomBordered: mergedBottomBorderedRef,
mergedPagination: mergedPaginationRef,
mergedShowPagination: mergedShowPaginationRef,
cssVars: inlineThemeDisabled ? undefined : cssVarsRef,
themeClass: themeClassHandle === null || themeClassHandle === void 0 ? void 0 : themeClassHandle.themeClass,
onRender: themeClassHandle === null || themeClassHandle === void 0 ? void 0 : themeClassHandle.onRender
}, exposedMethods);
},
render() {
const {
mergedClsPrefix,
themeClass,
onRender,
$slots,
spinProps
} = this;
onRender === null || onRender === void 0 ? void 0 : onRender();
return h("div", {
class: [`${mergedClsPrefix}-data-table`, this.rtlEnabled && `${mergedClsPrefix}-data-table--rtl`, themeClass, {
[`${mergedClsPrefix}-data-table--bordered`]: this.mergedBordered,
[`${mergedClsPrefix}-data-table--bottom-bordered`]: this.mergedBottomBordered,
[`${mergedClsPrefix}-data-table--single-line`]: this.singleLine,
[`${mergedClsPrefix}-data-table--single-column`]: this.singleColumn,
[`${mergedClsPrefix}-data-table--loading`]: this.loading,
[`${mergedClsPrefix}-data-table--flex-height`]: this.flexHeight
}],
style: this.cssVars
}, h("div", {
class: `${mergedClsPrefix}-data-table-wrapper`
}, h(MainTable, {
ref: "mainTableInstRef"
})), this.mergedShowPagination ? h("div", {
class: `${mergedClsPrefix}-data-table__pagination`
}, h(NPagination, Object.assign({
theme: this.mergedTheme.peers.Pagination,
themeOverrides: this.mergedTheme.peerOverrides.Pagination,
disabled: this.loading
}, this.mergedPagination))) : null, h(Transition, {
name: "fade-in-scale-up-transition"
}, {
default: () => {
return this.loading ? h("div", {
class: `${mergedClsPrefix}-data-table-loading-wrapper`
}, resolveSlot($slots.loading, () => [h(NBaseLoading, Object.assign({
clsPrefix: mergedClsPrefix,
strokeWidth: 20
}, spinProps))])) : null;
}
}));
}
});