{"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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"}