{"version":3,"file":"table-layout.mjs","names":[],"sources":["../../../../../../packages/components/table/src/table-layout.ts"],"sourcesContent":["import { isRef, nextTick, ref } from 'vue'\nimport { isNull } from 'lodash-unified'\nimport { hasOwn, isClient, isNumber, isString } from '@element-plus/utils'\nimport { parseHeight } from './util'\n\nimport type { Ref } from 'vue'\nimport type { TableColumnCtx } from './table-column/defaults'\nimport type { TableHeader } from './table-header'\nimport type { DefaultRow, Table } from './table/defaults'\nimport type { Store } from './store'\n\nclass TableLayout<T extends DefaultRow> {\n  observers: TableHeader[]\n  table: Table<T>\n  store: Store<T>\n  columns: TableColumnCtx<T>[]\n  fit: boolean\n  showHeader: boolean\n  heightMap: Record<string, string | number | null>\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  gutterWidth: number\n  constructor(options: Record<string, any>) {\n    this.observers = []\n    this.table = null as unknown as Table<T>\n    this.store = null as unknown as Store<T>\n    this.columns = []\n    this.fit = true\n    this.showHeader = true\n    this.heightMap = {}\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.gutterWidth = 0\n    for (const name in options) {\n      if (hasOwn(options, name)) {\n        if (isRef(this[name])) {\n          ;(this[name] as Ref).value = options[name]\n        } else {\n          this[name as keyof typeof this] = 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 (isNull(height)) return false\n    const scrollBarRef = this.table.refs.scrollBarRef\n    if (this.table.vnode.el && scrollBarRef?.wrapRef) {\n      let scrollY = true\n      const prevScrollY = this.scrollY.value\n      scrollY =\n        scrollBarRef.wrapRef.scrollHeight > scrollBarRef.wrapRef.clientHeight\n      this.scrollY.value = scrollY\n      return prevScrollY !== scrollY\n    }\n    return false\n  }\n\n  setHeight(value: string | number | null, prop = 'height') {\n    if (!isClient) return\n    const el = this.table.vnode.el\n    value = parseHeight(value)\n    this.height.value = Number(value)\n    this.heightMap[prop] = value\n\n    if (!el && (value || value === 0)) {\n      nextTick(() => {\n        if (this.heightMap[prop] === value) {\n          this.setHeight(value, prop)\n        }\n      })\n      return\n    }\n\n    if (el && isNumber(value)) {\n      el.style[prop] = `${value}px`\n      this.updateElsHeight()\n    } else if (el && isString(value)) {\n      el.style[prop] = value\n      this.updateElsHeight()\n    }\n  }\n\n  setMaxHeight(value: string | number | null) {\n    this.setHeight(value, 'max-height')\n  }\n\n  getFlattenColumns(): TableColumnCtx<T>[] {\n    const flattenColumns: TableColumnCtx<T>[] = []\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    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 (!isClient) 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) => !isNumber(column.width)\n    )\n    flattenColumns.forEach((column) => {\n      // Clean those columns whose width changed from flex to unflex\n      if (isNumber(column.width) && column.realWidth) column.realWidth = null\n    })\n    if (flexColumns.length > 0 && fit) {\n      flattenColumns.forEach((column) => {\n        bodyMinWidth += Number(column.width || column.minWidth || 80)\n      })\n      if (bodyMinWidth <= bodyWidth) {\n        // DON'T HAVE SCROLL BAR\n        this.scrollX.value = false\n\n        const totalFlexWidth = bodyWidth - 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((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((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((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 as TableLayout<DefaultRow>)\n          break\n        case 'scrollable':\n          observer.state?.onScrollableChange(this as TableLayout<DefaultRow>)\n          break\n        default:\n          throw new Error(`Table Layout don't have event ${event}.`)\n      }\n    })\n  }\n}\n\nexport default TableLayout\n"],"mappings":"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"}