UNPKG

element-plus

Version:

A Component Library for Vue 3

1 lines 15.1 kB
{"version":3,"file":"table-layout.mjs","sources":["../../../../../../packages/components/table/src/table-layout.ts"],"sourcesContent":["import { nextTick, ref, isRef } from 'vue'\nimport { hasOwn } from '@vue/shared'\nimport scrollbarWidth from '@element-plus/utils/scrollbar-width'\nimport isServer from '@element-plus/utils/isServer'\nimport { parseHeight } from './util'\nimport type { Ref } from 'vue'\n\nimport type { TableColumnCtx } from './table-column/defaults'\nimport type { TableHeader } from './table-header'\nimport type { Table } from './table/defaults'\nimport type { Store } from './store'\nclass TableLayout<T> {\n observers: TableHeader[]\n table: Table<T>\n store: Store<T>\n columns: TableColumnCtx<T>[]\n fit: boolean\n showHeader: boolean\n\n height: Ref<null | number>\n scrollX: Ref<boolean>\n scrollY: Ref<boolean>\n bodyWidth: Ref<null | number>\n fixedWidth: Ref<null | number>\n rightFixedWidth: Ref<null | number>\n tableHeight: Ref<null | number>\n headerHeight: Ref<null | number> // Table Header Height\n appendHeight: Ref<null | number> // Append Slot Height\n footerHeight: Ref<null | number> // Table Footer Height\n viewportHeight: Ref<null | number> // Table Height - Scroll Bar Height\n bodyHeight: Ref<null | number> // Table Height - Table Header Height\n fixedBodyHeight: Ref<null | number> // Table Height - Table Header Height - Scroll Bar Height\n gutterWidth: number\n constructor(options: Record<string, any>) {\n this.observers = []\n this.table = null\n this.store = null\n this.columns = []\n this.fit = true\n this.showHeader = true\n this.height = ref(null)\n this.scrollX = ref(false)\n this.scrollY = ref(false)\n this.bodyWidth = ref(null)\n this.fixedWidth = ref(null)\n this.rightFixedWidth = ref(null)\n this.tableHeight = ref(null)\n this.headerHeight = ref(44)\n this.appendHeight = ref(0)\n this.footerHeight = ref(44)\n this.viewportHeight = ref(null)\n this.bodyHeight = ref(null)\n this.fixedBodyHeight = ref(null)\n this.gutterWidth = scrollbarWidth()\n for (const name in options) {\n if (hasOwn(options, name)) {\n if (isRef(this[name])) {\n this[name as string].value = options[name]\n } else {\n this[name as string] = options[name]\n }\n }\n }\n if (!this.table) {\n throw new Error('Table is required for Table Layout')\n }\n if (!this.store) {\n throw new Error('Store is required for Table Layout')\n }\n }\n\n updateScrollY() {\n const height = this.height.value\n /**\n * When the height is not initialized, it is null.\n * After the table is initialized, when the height is not configured, the height is 0.\n */\n if (height === null) return false\n const bodyWrapper = this.table.refs.bodyWrapper as HTMLElement\n if (this.table.vnode.el && bodyWrapper) {\n let scrollY = true\n const prevScrollY = this.scrollY.value\n /**\n * When bodyHeight has no value,\n * it means that the table height is not set,\n * and the scroll bar will never appear\n */\n if (this.bodyHeight.value === null) {\n scrollY = false\n } else {\n const body = bodyWrapper.querySelector('.el-table__body') as HTMLElement\n scrollY = body.offsetHeight > this.bodyHeight.value\n }\n this.scrollY.value = scrollY\n return prevScrollY !== scrollY\n }\n return false\n }\n\n setHeight(value: string | number, prop = 'height') {\n if (isServer) return\n const el = this.table.vnode.el\n value = parseHeight(value)\n this.height.value = Number(value)\n\n if (!el && (value || value === 0))\n return nextTick(() => this.setHeight(value, prop))\n\n if (typeof value === 'number') {\n el.style[prop] = `${value}px`\n this.updateElsHeight()\n } else if (typeof value === 'string') {\n el.style[prop] = value\n this.updateElsHeight()\n }\n }\n\n setMaxHeight(value: string | number) {\n this.setHeight(value, 'max-height')\n }\n\n getFlattenColumns(): TableColumnCtx<T>[] {\n const flattenColumns = []\n const columns = this.table.store.states.columns.value\n columns.forEach((column) => {\n if (column.isColumnGroup) {\n // eslint-disable-next-line prefer-spread\n flattenColumns.push.apply(flattenColumns, column.columns)\n } else {\n flattenColumns.push(column)\n }\n })\n\n return flattenColumns\n }\n\n updateElsHeight() {\n if (!this.table.$ready) return nextTick(() => this.updateElsHeight())\n const { headerWrapper, appendWrapper, footerWrapper } = this.table.refs\n this.appendHeight.value = appendWrapper ? appendWrapper.offsetHeight : 0\n if (this.showHeader && !headerWrapper) return\n\n const headerTrElm: HTMLElement = headerWrapper\n ? headerWrapper.querySelector('.el-table__header tr')\n : null\n const noneHeader = this.headerDisplayNone(headerTrElm)\n\n const headerHeight = (this.headerHeight.value = !this.showHeader\n ? 0\n : headerWrapper.offsetHeight)\n if (\n this.showHeader &&\n !noneHeader &&\n headerWrapper.offsetWidth > 0 &&\n (this.table.store.states.columns.value || []).length > 0 &&\n headerHeight < 2\n ) {\n return nextTick(() => this.updateElsHeight())\n }\n const tableHeight = (this.tableHeight.value =\n this.table.vnode.el.clientHeight)\n const footerHeight = (this.footerHeight.value = footerWrapper\n ? footerWrapper.offsetHeight\n : 0)\n if (this.height.value !== null) {\n this.bodyHeight.value =\n tableHeight - headerHeight - footerHeight + (footerWrapper ? 1 : 0)\n }\n this.fixedBodyHeight.value = this.scrollX.value\n ? this.bodyHeight.value - this.gutterWidth\n : this.bodyHeight.value\n\n this.viewportHeight.value = this.scrollX.value\n ? tableHeight - this.gutterWidth\n : tableHeight\n\n this.updateScrollY()\n this.notifyObservers('scrollable')\n }\n\n headerDisplayNone(elm: HTMLElement) {\n if (!elm) return true\n let headerChild = elm\n while (headerChild.tagName !== 'DIV') {\n if (getComputedStyle(headerChild).display === 'none') {\n return true\n }\n headerChild = headerChild.parentElement\n }\n return false\n }\n\n updateColumnsWidth() {\n if (isServer) return\n const fit = this.fit\n const bodyWidth = this.table.vnode.el.clientWidth\n let bodyMinWidth = 0\n\n const flattenColumns = this.getFlattenColumns()\n const flexColumns = flattenColumns.filter(\n (column) => typeof column.width !== 'number'\n )\n flattenColumns.forEach((column) => {\n // Clean those columns whose width changed from flex to unflex\n if (typeof column.width === 'number' && column.realWidth)\n column.realWidth = null\n })\n if (flexColumns.length > 0 && fit) {\n flattenColumns.forEach((column) => {\n bodyMinWidth += Number(column.width || column.minWidth || 80)\n })\n\n const scrollYWidth = this.scrollY.value ? this.gutterWidth : 0\n\n if (bodyMinWidth <= bodyWidth - scrollYWidth) {\n // DON'T HAVE SCROLL BAR\n this.scrollX.value = false\n\n const totalFlexWidth = bodyWidth - scrollYWidth - bodyMinWidth\n\n if (flexColumns.length === 1) {\n flexColumns[0].realWidth =\n Number(flexColumns[0].minWidth || 80) + totalFlexWidth\n } else {\n const allColumnsWidth = flexColumns.reduce(\n (prev, column) => prev + Number(column.minWidth || 80),\n 0\n )\n const flexWidthPerPixel = totalFlexWidth / allColumnsWidth\n let noneFirstWidth = 0\n\n flexColumns.forEach((column, index) => {\n if (index === 0) return\n const flexWidth = Math.floor(\n Number(column.minWidth || 80) * flexWidthPerPixel\n )\n noneFirstWidth += flexWidth\n column.realWidth = Number(column.minWidth || 80) + flexWidth\n })\n\n flexColumns[0].realWidth =\n Number(flexColumns[0].minWidth || 80) +\n totalFlexWidth -\n noneFirstWidth\n }\n } else {\n // HAVE HORIZONTAL SCROLL BAR\n this.scrollX.value = true\n flexColumns.forEach(function (column) {\n column.realWidth = Number(column.minWidth)\n })\n }\n\n this.bodyWidth.value = Math.max(bodyMinWidth, bodyWidth)\n this.table.state.resizeState.value.width = this.bodyWidth.value\n } else {\n flattenColumns.forEach((column) => {\n if (!column.width && !column.minWidth) {\n column.realWidth = 80\n } else {\n column.realWidth = Number(column.width || column.minWidth)\n }\n bodyMinWidth += column.realWidth\n })\n this.scrollX.value = bodyMinWidth > bodyWidth\n\n this.bodyWidth.value = bodyMinWidth\n }\n\n const fixedColumns = this.store.states.fixedColumns.value\n\n if (fixedColumns.length > 0) {\n let fixedWidth = 0\n fixedColumns.forEach(function (column) {\n fixedWidth += Number(column.realWidth || column.width)\n })\n\n this.fixedWidth.value = fixedWidth\n }\n\n const rightFixedColumns = this.store.states.rightFixedColumns.value\n if (rightFixedColumns.length > 0) {\n let rightFixedWidth = 0\n rightFixedColumns.forEach(function (column) {\n rightFixedWidth += Number(column.realWidth || column.width)\n })\n\n this.rightFixedWidth.value = rightFixedWidth\n }\n this.notifyObservers('columns')\n }\n\n addObserver(observer: TableHeader) {\n this.observers.push(observer)\n }\n\n removeObserver(observer: TableHeader) {\n const index = this.observers.indexOf(observer)\n if (index !== -1) {\n this.observers.splice(index, 1)\n }\n }\n\n notifyObservers(event: string) {\n const observers = this.observers\n observers.forEach((observer) => {\n switch (event) {\n case 'columns':\n observer.state?.onColumnsChange(this)\n break\n case 'scrollable':\n observer.state?.onScrollableChange(this)\n break\n default:\n throw new Error(`Table Layout don't have event ${event}.`)\n }\n })\n }\n}\n\nexport default TableLayout\n"],"names":[],"mappings":"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"}