/**
 * ldesign v0.2.14
 * (c) 2022/11/2 16:16 built by swimly
 * @license MIT
 */

import { toRefs, ref, reactive, computed, watch, onMounted, onBeforeMount } from '@vue/composition-api';
import get from 'lodash/get';
import debounce from 'lodash/debounce';
import { l as log } from '../../../_chunks/dep-70c789e5.js';
import { g as getIEVersion } from '../../../_chunks/dep-47d77fc8.js';
import { on, off } from '../../../utils/dom.js';
import '../../../_chunks/dep-5210251b.js';
import 'vue';
import 'raf';
import 'lodash/isString';
import '../../../utils/easing.js';

function getScrollbarWidth() {
  var defaultScrollbarWidth = 6;
  if (!navigator) return defaultScrollbarWidth;
  if (/(Chrome|Safari)/i.test(navigator.userAgent)) return defaultScrollbarWidth;
  var scrollDiv = document.createElement("div");
  scrollDiv.style.cssText = "width: 99px; height: 99px; overflow: scroll; position: absolute; top: -9999px;";
  document.body.appendChild(scrollDiv);
  var scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth;
  document.body.removeChild(scrollDiv);
  if (/Firefox/.test(navigator.userAgent)) scrollbarWidth -= 4;
  if (getIEVersion() <= 11) scrollbarWidth = 12;
  return scrollbarWidth;
}

function getColumnFixedStyles(col, index, rowAndColFixedPosition, tableColFixedClasses) {
  const fixedPos = rowAndColFixedPosition === null || rowAndColFixedPosition === void 0 ? void 0 : rowAndColFixedPosition.get(col.colKey || index);
  if (!fixedPos) return {};
  const thClasses = {
    [tableColFixedClasses.left]: col.fixed === "left",
    [tableColFixedClasses.right]: col.fixed === "right",
    [tableColFixedClasses.lastLeft]: col.fixed === "left" && fixedPos.lastLeftFixedCol,
    [tableColFixedClasses.firstRight]: col.fixed === "right" && fixedPos.firstRightFixedCol
  };
  const thStyles = {
    left: col.fixed === "left" ? `${fixedPos.left}px` : void 0,
    right: col.fixed === "right" ? `${fixedPos.right}px` : void 0
  };
  return {
    style: thStyles,
    classes: thClasses
  };
}
function getRowFixedStyles(rowId, rowIndex, rowLength, fixedRows, rowAndColFixedPosition, tableRowFixedClasses) {
  if (!fixedRows || !fixedRows.length) return {
    style: void 0,
    classes: void 0
  };
  const fixedTop = rowIndex < fixedRows[0];
  const fixedBottom = rowIndex > rowLength - 1 - fixedRows[1];
  const firstFixedBottomRow = rowLength - fixedRows[1];
  const fixedPos = (rowAndColFixedPosition === null || rowAndColFixedPosition === void 0 ? void 0 : rowAndColFixedPosition.get(rowId)) || {};
  const rowClasses = {
    [tableRowFixedClasses.top]: fixedTop,
    [tableRowFixedClasses.bottom]: fixedBottom,
    [tableRowFixedClasses.firstBottom]: rowIndex === firstFixedBottomRow,
    [tableRowFixedClasses.withoutBorderBottom]: rowIndex === firstFixedBottomRow - 1
  };
  const rowStyles = {
    top: fixedTop ? `${fixedPos.top}px` : void 0,
    bottom: fixedBottom ? `${fixedPos.bottom}px` : void 0
  };
  return {
    style: rowStyles,
    classes: rowClasses
  };
}
function useFixed(props, context, finalColumns, affixRef) {
  const {
    columns,
    tableLayout,
    tableContentWidth,
    fixedRows,
    firstFullRow,
    lastFullRow,
    maxHeight,
    headerAffixedTop,
    footerAffixedBottom,
    bordered,
    resizable,
    allowResizeColumnWidth
  } = toRefs(props);
  const data = ref([]);
  const tableRef = ref();
  const tableContentRef = ref();
  const isFixedHeader = ref(false);
  const isWidthOverflow = ref(false);
  const tableElmRef = ref();
  const scrollbarWidth = ref(6);
  const rowAndColFixedPosition = ref( /* @__PURE__ */new Map());
  const showColumnShadow = reactive({
    left: false,
    right: false
  });
  const virtualScrollHeaderPos = ref({
    left: 0,
    top: 0
  });
  const tableWidth = ref(0);
  const tableElmWidth = ref(0);
  const thWidthList = ref({});
  const isFixedColumn = ref(false);
  const isFixedRightColumn = ref(false);
  const isFixedLeftColumn = ref(false);
  const columnResizable = computed(() => resizable.value || allowResizeColumnWidth.value || false);
  const notNeedThWidthList = computed(() => {
    var _props$scroll;
    return !(props.headerAffixedTop || props.footerAffixedBottom || props.horizontalScrollAffixedBottom || ((_props$scroll = props.scroll) === null || _props$scroll === void 0 ? void 0 : _props$scroll.type) === "virtual");
  });
  const recalculateColWidth = ref(() => {});
  function setUseFixedTableElmRef(val) {
    tableElmRef.value = val;
  }
  function setRecalculateColWidthFuncRef(val) {
    recalculateColWidth.value = val;
  }
  function getColumnMap(columns2) {
    let map = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : /* @__PURE__ */new Map();
    let levelNodes = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : [];
    let level = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 0;
    let parent = arguments.length > 4 ? arguments[4] : undefined;
    for (let i = 0, len = columns2.length; i < len; i++) {
      var _col$children;
      const col = columns2[i];
      if (["left", "right"].includes(col.fixed)) isFixedColumn.value = true;
      if (col.fixed === "right") isFixedRightColumn.value = true;
      if (col.fixed === "left") isFixedLeftColumn.value = true;
      const key = col.colKey || i;
      const columnInfo = {
        col,
        parent,
        index: i
      };
      map.set(key, columnInfo);
      if ((_col$children = col.children) !== null && _col$children !== void 0 && _col$children.length) getColumnMap(col.children, map, levelNodes, level + 1, columnInfo);
      if (levelNodes[level]) levelNodes[level].push(columnInfo);else levelNodes[level] = [columnInfo];
    }
    return {
      newColumnsMap: map,
      levelNodes
    };
  }
  const setFixedLeftPos = function (columns2, initialColumnMap) {
    let parent = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
    for (let i = 0, len = columns2.length; i < len; i++) {
      var _col$children2;
      const col = columns2[i];
      if (col.fixed === "right") return;
      const colInfo = initialColumnMap.get(col.colKey || i);
      let lastColIndex = i - 1;
      while (lastColIndex >= 0 && columns2[lastColIndex].fixed !== "left") lastColIndex -= 1;
      const lastCol = columns2[lastColIndex];
      const defaultWidth = i === 0 ? (parent === null || parent === void 0 ? void 0 : parent.left) || 0 : 0;
      const lastColInfo = initialColumnMap.get((lastCol === null || lastCol === void 0 ? void 0 : lastCol.colKey) || i - 1);
      colInfo.left = ((lastColInfo === null || lastColInfo === void 0 ? void 0 : lastColInfo.left) || defaultWidth) + ((lastColInfo === null || lastColInfo === void 0 ? void 0 : lastColInfo.width) || 0);
      if ((_col$children2 = col.children) !== null && _col$children2 !== void 0 && _col$children2.length) setFixedLeftPos(col.children, initialColumnMap, colInfo);
    }
  };
  const setFixedRightPos = function (columns2, initialColumnMap) {
    let parent = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
    for (let i = columns2.length - 1; i >= 0; i--) {
      var _col$children3;
      const col = columns2[i];
      if (col.fixed === "left") return;
      const colInfo = initialColumnMap.get(col.colKey || i);
      let lastColIndex = i + 1;
      while (lastColIndex < columns2.length && columns2[lastColIndex].fixed !== "right") lastColIndex += 1;
      const lastCol = columns2[lastColIndex];
      const defaultWidth = i === columns2.length - 1 ? (parent === null || parent === void 0 ? void 0 : parent.right) || 0 : 0;
      const lastColInfo = initialColumnMap.get((lastCol === null || lastCol === void 0 ? void 0 : lastCol.colKey) || i + 1);
      colInfo.right = ((lastColInfo === null || lastColInfo === void 0 ? void 0 : lastColInfo.right) || defaultWidth) + ((lastColInfo === null || lastColInfo === void 0 ? void 0 : lastColInfo.width) || 0);
      if ((_col$children3 = col.children) !== null && _col$children3 !== void 0 && _col$children3.length) setFixedRightPos(col.children, initialColumnMap, colInfo);
    }
  };
  const setFixedColPosition = (trList, initialColumnMap) => {
    if (!trList) return;
    for (let i = 0, len = trList.length; i < len; i++) {
      const thList = trList[i].children;
      for (let j = 0, thLen = thList.length; j < thLen; j++) {
        var _obj$col;
        const th = thList[j];
        const colKey = th.dataset.colkey;
        if (!colKey) log.warn("TDesign Table", `${th.innerText} missing colKey. colKey is required for fixed column feature.`);
        const obj = initialColumnMap.get(colKey || j);
        if (obj !== null && obj !== void 0 && (_obj$col = obj.col) !== null && _obj$col !== void 0 && _obj$col.fixed) initialColumnMap.set(colKey, {
          ...obj,
          width: th.getBoundingClientRect().width
        });
      }
    }
    setFixedLeftPos(columns.value, initialColumnMap);
    setFixedRightPos(columns.value, initialColumnMap);
  };
  const setFixedRowPosition = (trList, initialColumnMap, thead, tfoot) => {
    const [fixedTopRows, fixedBottomRows] = fixedRows.value || [];
    const {
      data: data2,
      rowKey = "id"
    } = props;
    for (let i = 0; i < fixedTopRows; i++) {
      const tr = trList[i];
      const rowId = get(data2[i], rowKey);
      const thisRowInfo = initialColumnMap.get(rowId) || {};
      const lastRowId = get(data2[i - 1], rowKey);
      const lastRowInfo = initialColumnMap.get(lastRowId) || {};
      let defaultBottom = 0;
      if (i === 0) defaultBottom = (thead === null || thead === void 0 ? void 0 : thead.getBoundingClientRect().height) || 0;
      thisRowInfo.top = (lastRowInfo.top || defaultBottom) + (lastRowInfo.height || 0);
      initialColumnMap.set(rowId, {
        ...thisRowInfo,
        height: tr.getBoundingClientRect().height
      });
    }
    for (let i = data2.length - 1; i >= data2.length - fixedBottomRows; i--) {
      const tr = trList[i];
      const rowId = get(data2[i], rowKey);
      const thisRowInfo = initialColumnMap.get(rowId) || {};
      const lastRowId = get(data2[i + 1], rowKey);
      const lastRowInfo = initialColumnMap.get(lastRowId) || {};
      let defaultBottom = 0;
      if (i === data2.length - 1) defaultBottom = (tfoot === null || tfoot === void 0 ? void 0 : tfoot.getBoundingClientRect().height) || 0;
      thisRowInfo.bottom = (lastRowInfo.bottom || defaultBottom) + (lastRowInfo.height || 0);
      initialColumnMap.set(rowId, {
        ...thisRowInfo,
        height: tr.getBoundingClientRect().height
      });
    }
  };
  const updateRowAndColFixedPosition = (tableContentElm, initialColumnMap) => {
    rowAndColFixedPosition.value.clear();
    if (!tableContentElm) return;
    const thead = tableContentElm.querySelector("thead");
    thead && setFixedColPosition(thead.children, initialColumnMap);
    const tbody = tableContentElm.querySelector("tbody");
    const tfoot = tableContentElm.querySelector("tfoot");
    tbody && setFixedRowPosition(tbody.children, initialColumnMap, thead, tfoot);
    rowAndColFixedPosition.value = initialColumnMap;
  };
  let shadowLastScrollLeft;
  const updateColumnFixedShadow = (target, extra) => {
    if (!isFixedColumn.value || !target) return;
    const {
      scrollLeft
    } = target;
    if (shadowLastScrollLeft === scrollLeft && (!extra || !extra.skipScrollLimit)) return;
    shadowLastScrollLeft = scrollLeft;
    const isShowRight = target.clientWidth + scrollLeft < target.scrollWidth;
    showColumnShadow.left = scrollLeft > 0;
    showColumnShadow.right = isShowRight;
  };
  const setIsLastOrFirstFixedCol = levelNodes => {
    for (let t = 0; t < levelNodes.length; t++) {
      const nodes = levelNodes[t];
      for (let i = 0, len = nodes.length; i < len; i++) {
        const colMapInfo = nodes[i];
        const nextColMapInfo = nodes[i + 1];
        const {
          parent
        } = colMapInfo;
        const isParentLastLeftFixedCol = !parent || (parent === null || parent === void 0 ? void 0 : parent.lastLeftFixedCol);
        if (isParentLastLeftFixedCol && colMapInfo.col.fixed === "left" && (nextColMapInfo === null || nextColMapInfo === void 0 ? void 0 : nextColMapInfo.col.fixed) !== "left") colMapInfo.lastLeftFixedCol = true;
        const lastColMapInfo = nodes[i - 1];
        const isParentFirstRightFixedCol = !parent || (parent === null || parent === void 0 ? void 0 : parent.firstRightFixedCol);
        if (isParentFirstRightFixedCol && colMapInfo.col.fixed === "right" && (lastColMapInfo === null || lastColMapInfo === void 0 ? void 0 : lastColMapInfo.col.fixed) !== "right") colMapInfo.firstRightFixedCol = true;
      }
    }
  };
  const updateFixedStatus = () => {
    const {
      newColumnsMap,
      levelNodes
    } = getColumnMap(columns.value);
    setIsLastOrFirstFixedCol(levelNodes);
    const timer = setTimeout(() => {
      var _fixedRows$value;
      if (isFixedColumn.value || (_fixedRows$value = fixedRows.value) !== null && _fixedRows$value !== void 0 && _fixedRows$value.length) updateRowAndColFixedPosition(tableContentRef.value, newColumnsMap);
      clearTimeout(timer);
    }, 0);
    return () => {
      clearTimeout(timer);
    };
  };
  const updateFixedHeader = () => {
    const timer = setTimeout(() => {
      if (!tableContentRef.value) return;
      isFixedHeader.value = tableContentRef.value.scrollHeight > tableContentRef.value.clientHeight;
      isWidthOverflow.value = tableContentRef.value.scrollWidth > tableContentRef.value.clientWidth;
      const pos = tableContentRef.value.getBoundingClientRect();
      virtualScrollHeaderPos.value = {
        top: pos.top,
        left: pos.left
      };
      clearTimeout(timer);
    }, 0);
  };
  const updateTableWidth = () => {
    var _tableContentRef$valu, _tableElmRef$value;
    const rect = (_tableContentRef$valu = tableContentRef.value) === null || _tableContentRef$valu === void 0 ? void 0 : _tableContentRef$valu.getBoundingClientRect();
    if (!rect) return;
    const reduceWidth = isFixedHeader.value ? scrollbarWidth.value : 0;
    tableWidth.value = rect.width - reduceWidth - (props.bordered ? 1 : 0);
    const elmRect = tableElmRef === null || tableElmRef === void 0 ? void 0 : (_tableElmRef$value = tableElmRef.value) === null || _tableElmRef$value === void 0 ? void 0 : _tableElmRef$value.getBoundingClientRect();
    tableElmWidth.value = elmRect === null || elmRect === void 0 ? void 0 : elmRect.width;
  };
  const updateAffixPosition = () => {
    var _affixRef$paginationA, _affixRef$paginationA2, _affixRef$horizontalS, _affixRef$horizontalS2, _affixRef$headerTopAf, _affixRef$headerTopAf2, _affixRef$footerBotto, _affixRef$footerBotto2;
    (_affixRef$paginationA = affixRef.paginationAffixRef.value) === null || _affixRef$paginationA === void 0 ? void 0 : (_affixRef$paginationA2 = _affixRef$paginationA.handleScroll) === null || _affixRef$paginationA2 === void 0 ? void 0 : _affixRef$paginationA2.call(_affixRef$paginationA);
    (_affixRef$horizontalS = affixRef.horizontalScrollAffixRef.value) === null || _affixRef$horizontalS === void 0 ? void 0 : (_affixRef$horizontalS2 = _affixRef$horizontalS.handleScroll) === null || _affixRef$horizontalS2 === void 0 ? void 0 : _affixRef$horizontalS2.call(_affixRef$horizontalS);
    (_affixRef$headerTopAf = affixRef.headerTopAffixRef.value) === null || _affixRef$headerTopAf === void 0 ? void 0 : (_affixRef$headerTopAf2 = _affixRef$headerTopAf.handleScroll) === null || _affixRef$headerTopAf2 === void 0 ? void 0 : _affixRef$headerTopAf2.call(_affixRef$headerTopAf);
    (_affixRef$footerBotto = affixRef.footerBottomAffixRef.value) === null || _affixRef$footerBotto === void 0 ? void 0 : (_affixRef$footerBotto2 = _affixRef$footerBotto.handleScroll) === null || _affixRef$footerBotto2 === void 0 ? void 0 : _affixRef$footerBotto2.call(_affixRef$footerBotto);
  };
  const updateThWidthList = trList => {
    if (trList instanceof HTMLCollection) {
      if (columnResizable.value) return;
      const widthMap = {};
      for (let i = 0, len = trList.length; i < len; i++) {
        const thList = trList[i].children;
        for (let j = 0, thLen = thList.length; j < thLen; j++) {
          const th = thList[j];
          const colKey = th.dataset.colkey;
          widthMap[colKey] = th.getBoundingClientRect().width;
        }
      }
      thWidthList.value = widthMap;
    } else {
      if (!thWidthList.value) thWidthList.value = {};
      Object.entries(trList).forEach(_ref => {
        let [colKey, width] = _ref;
        thWidthList.value[colKey] = width;
      });
    }
  };
  const updateThWidthListHandler = () => {
    if (columnResizable.value) recalculateColWidth.value(finalColumns.value, thWidthList.value, tableLayout.value, tableElmWidth.value);
    if (notNeedThWidthList.value) return;
    const timer = setTimeout(() => {
      var _tableContentRef$valu2;
      updateTableWidth();
      const thead = (_tableContentRef$valu2 = tableContentRef.value) === null || _tableContentRef$valu2 === void 0 ? void 0 : _tableContentRef$valu2.querySelector("thead");
      if (!thead) return;
      updateThWidthList(thead.children);
      clearTimeout(timer);
    }, 0);
  };
  const resetThWidthList = () => {
    thWidthList.value = {};
  };
  const emitScrollEvent = e => {
    var _props$onScrollX, _props$onScrollY, _props$onScroll;
    (_props$onScrollX = props.onScrollX) === null || _props$onScrollX === void 0 ? void 0 : _props$onScrollX.call(props, {
      e
    });
    context.emit("scroll-x", {
      e
    });
    (_props$onScrollY = props.onScrollY) === null || _props$onScrollY === void 0 ? void 0 : _props$onScrollY.call(props, {
      e
    });
    context.emit("scroll-y", {
      e
    });
    (_props$onScroll = props.onScroll) === null || _props$onScroll === void 0 ? void 0 : _props$onScroll.call(props, {
      e
    });
    context.emit("scroll", {
      e
    });
  };
  const getThWidthList = () => {
    if (!thWidthList.value) thWidthList.value = {};
    return thWidthList.value;
  };
  watch([data, columns, bordered, tableLayout, tableContentWidth, isFixedHeader, isWidthOverflow, isFixedColumn, fixedRows, firstFullRow, lastFullRow], updateFixedStatus, {
    immediate: true
  });
  watch([isFixedColumn, columns], () => {
    const timer = setTimeout(() => {
      if (isFixedColumn.value) updateColumnFixedShadow(tableContentRef.value);
      clearTimeout(timer);
    }, 0);
  }, {
    immediate: true
  });
  watch([maxHeight, data, columns, bordered], updateFixedHeader, {
    immediate: true
  });
  watch(finalColumns, () => {
    resetThWidthList();
    if (columnResizable.value) recalculateColWidth.value(finalColumns.value, thWidthList.value, tableLayout.value, tableElmWidth.value);
  });
  watch([data, columns, bordered, tableLayout, fixedRows, isFixedHeader, headerAffixedTop, footerAffixedBottom, tableContentWidth], () => {
    updateThWidthListHandler();
    updateAffixPosition();
  }, {
    immediate: true
  });
  const refreshTable = debounce(() => {
    updateTableWidth();
    updateFixedHeader();
    updateThWidthListHandler();
    updateAffixPosition();
    if (isFixedColumn.value || isFixedHeader.value) {
      updateFixedStatus();
      updateColumnFixedShadow(tableContentRef.value, {
        skipScrollLimit: true
      });
    }
  }, 30);
  const onResize = refreshTable;
  let resizeObserver = null;
  function addTableResizeObserver(tableElement) {
    if (getIEVersion() < 11 || typeof window.ResizeObserver === "undefined") return;
    off(window, "resize", onResize);
    resizeObserver = new window.ResizeObserver(() => {
      refreshTable();
    });
    resizeObserver.observe(tableElement);
    tableRef.value = tableElement;
  }
  onMounted(() => {
    const scrollWidth = getScrollbarWidth();
    scrollbarWidth.value = scrollWidth;
    const timer = setTimeout(() => {
      updateTableWidth();
      if (columnResizable.value) recalculateColWidth.value(finalColumns.value, thWidthList.value, tableLayout.value, tableElmWidth.value);
      clearTimeout(timer);
    });
    const isWatchResize = isFixedColumn.value || isFixedHeader.value || !notNeedThWidthList.value || !data.value.length;
    if (isWatchResize && getIEVersion() < 11 || typeof window.ResizeObserver === "undefined") on(window, "resize", onResize);
  });
  onBeforeMount(() => {
    var _resizeObserver, _resizeObserver2;
    off(window, "resize", onResize);
    (_resizeObserver = resizeObserver) === null || _resizeObserver === void 0 ? void 0 : _resizeObserver.unobserve(tableRef.value);
    (_resizeObserver2 = resizeObserver) === null || _resizeObserver2 === void 0 ? void 0 : _resizeObserver2.disconnect();
  });
  const setData = dataSource => {
    data.value = dataSource;
  };
  return {
    tableWidth,
    tableElmWidth,
    thWidthList,
    isFixedHeader,
    isWidthOverflow,
    tableContentRef,
    isFixedColumn,
    showColumnShadow,
    rowAndColFixedPosition,
    virtualScrollHeaderPos,
    scrollbarWidth,
    setData,
    refreshTable,
    emitScrollEvent,
    updateThWidthListHandler,
    updateColumnFixedShadow,
    setUseFixedTableElmRef,
    getThWidthList,
    updateThWidthList,
    setRecalculateColWidthFuncRef,
    addTableResizeObserver
  };
}

export { useFixed as default, getColumnFixedStyles, getRowFixedStyles };
//# sourceMappingURL=useFixed.js.map
