UNPKG

naive-ui

Version:

A Vue 3 Component Library. Fairly Complete, Theme Customizable, Uses TypeScript, Fast

453 lines 16 kB
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; } })); } });