'use strict';

Object.defineProperty(exports, '__esModule', { value: true });

var vue = require('vue');
var core = require('@vueuse/core');
var warning = require('../vc-util/warning.js');
var isVisible = require('../vc-util/Dom/isVisible.js');
var index$4 = require('../vc-resize-observer/index.js');
require('../hooks/index.js');
var util = require('../_util/util.js');
var getScrollBarSize = require('../_util/getScrollBarSize.js');
var classNames = require('../_util/classNames.js');
var pickAttrs = require('../_util/pickAttrs.js');
var Header = require('./Header/Header.js');
var index = require('./Body/index.js');
var useColumns = require('./hooks/useColumns.js');
var useFrame = require('./hooks/useFrame.js');
var valueUtil = require('./utils/valueUtil.js');
var useStickyOffsets = require('./hooks/useStickyOffsets.js');
var ColGroup = require('./ColGroup.js');
var index$3 = require('./Panel/index.js');
var index$1 = require('./Footer/index.js');
var expandUtil = require('./utils/expandUtil.js');
var fixUtil = require('./utils/fixUtil.js');
var stickyScrollBar = require('./stickyScrollBar.js');
var useSticky = require('./hooks/useSticky.js');
var index$2 = require('./FixedHolder/index.js');
var TableContext = require('./context/TableContext.js');
var BodyContext = require('./context/BodyContext.js');
var ResizeContext = require('./context/ResizeContext.js');
var StickyContext = require('./context/StickyContext.js');
var ExpandedRowContext = require('./context/ExpandedRowContext.js');
var useState = require('../hooks/useState.js');

function _isSlot(s) {
  return typeof s === "function" || Object.prototype.toString.call(s) === "[object Object]" && !vue.isVNode(s);
}
const EMPTY_DATA = [];
const EMPTY_SCROLL_TARGET = {};
const INTERNAL_HOOKS = "rc-table-internal-hook";
var Table = /* @__PURE__ */ vue.defineComponent({
  name: "Table",
  inheritAttrs: false,
  props: ["prefixCls", "data", "columns", "rowKey", "tableLayout", "scroll", "rowClassName", "title", "footer", "id", "showHeader", "components", "customRow", "customHeaderRow", "direction", "expandFixed", "expandColumnWidth", "expandedRowKeys", "defaultExpandedRowKeys", "expandedRowRender", "expandRowByClick", "expandIcon", "onExpand", "onExpandedRowsChange", "onUpdate:expandedRowKeys", "defaultExpandAllRows", "indentSize", "expandIconColumnIndex", "expandedRowClassName", "childrenColumnName", "rowExpandable", "sticky", "transformColumns", "internalHooks", "internalRefs", "canExpandable", "onUpdateInternalRefs", "transformCellText"],
  emits: ["expand", "expandedRowsChange", "updateInternalRefs", "update:expandedRowKeys"],
  setup(props, {
    attrs,
    slots,
    emit
  }) {
    const mergedData = vue.computed(() => props.data || EMPTY_DATA);
    const hasData = vue.computed(() => !!mergedData.value.length);
    const mergedComponents = vue.computed(() => valueUtil.mergeObject(props.components, {}));
    const getComponent = (path, defaultComponent) => valueUtil.getPathValue(mergedComponents.value, path) || defaultComponent;
    const getRowKey = vue.computed(() => {
      const rowKey = props.rowKey;
      if (typeof rowKey === "function")
        return rowKey;
      return (record) => {
        const key = record && record[rowKey];
        if (process.env.NODE_ENV !== "production") {
          warning.warning(key !== void 0, "Each record in table should have a unique `key` prop, or set `rowKey` to an unique primary key.");
        }
        return key;
      };
    });
    const mergedExpandIcon = vue.computed(() => props.expandIcon || expandUtil.renderExpandIcon);
    const mergedChildrenColumnName = vue.computed(() => props.childrenColumnName || "children");
    const expandableType = vue.computed(() => {
      if (props.expandedRowRender)
        return "row";
      if (props.canExpandable || mergedData.value.some((record) => record && typeof record === "object" && record[mergedChildrenColumnName.value]))
        return "nest";
      return false;
    });
    const innerExpandedKeys = vue.shallowRef([]);
    const stop = vue.watchEffect(() => {
      if (props.defaultExpandedRowKeys)
        innerExpandedKeys.value = props.defaultExpandedRowKeys;
      if (props.defaultExpandAllRows) {
        innerExpandedKeys.value = expandUtil.findAllChildrenKeys(mergedData.value, getRowKey.value, mergedChildrenColumnName.value);
      }
    });
    stop();
    const mergedExpandedKeys = vue.computed(() => new Set(props.expandedRowKeys || innerExpandedKeys.value || []));
    const onTriggerExpand = (record) => {
      const key = getRowKey.value(record, mergedData.value.indexOf(record));
      let newExpandedKeys;
      const hasKey = mergedExpandedKeys.value.has(key);
      if (hasKey) {
        mergedExpandedKeys.value.delete(key);
        newExpandedKeys = [...mergedExpandedKeys.value];
      } else {
        newExpandedKeys = [...mergedExpandedKeys.value, key];
      }
      innerExpandedKeys.value = newExpandedKeys;
      emit("expand", !hasKey, record);
      emit("update:expandedRowKeys", newExpandedKeys);
      emit("expandedRowsChange", newExpandedKeys);
    };
    if (process.env.NODE_ENV !== "production" && props.expandedRowRender && mergedData.value.some((record) => {
      return Array.isArray(record == null ? void 0 : record[mergedChildrenColumnName.value]);
    }))
      warning.warning(false, "`expandedRowRender` should not use with nested Table");
    const componentWidth = vue.ref(0);
    const [columns, flattenColumns] = useColumns.default({
      ...vue.toRefs(props),
      // children,
      expandable: vue.computed(() => !!props.expandedRowRender),
      expandedKeys: mergedExpandedKeys,
      getRowKey,
      onTriggerExpand,
      expandIcon: mergedExpandIcon
    }, vue.computed(() => props.internalHooks === INTERNAL_HOOKS ? props.transformColumns : null));
    const columnContext = vue.computed(() => ({
      columns: columns.value,
      flattenColumns: flattenColumns.value
    }));
    const fullTableRef = vue.ref();
    const scrollHeaderRef = vue.ref();
    const scrollBodyRef = vue.ref();
    const scrollBodySizeInfo = vue.ref({
      scrollWidth: 0,
      clientWidth: 0
    });
    const scrollSummaryRef = vue.ref();
    const [pingedLeft, setPingedLeft] = useState.useState(false);
    const [pingedRight, setPingedRight] = useState.useState(false);
    const [colsWidths, updateColsWidths] = useFrame.useLayoutState(/* @__PURE__ */ new Map());
    const colsKeys = vue.computed(() => valueUtil.getColumnsKey(flattenColumns.value));
    const colWidths = vue.computed(() => colsKeys.value.map((columnKey) => colsWidths.value.get(columnKey)));
    const columnCount = vue.computed(() => flattenColumns.value.length);
    const stickyOffsets = useStickyOffsets.default(colWidths, columnCount, vue.toRef(props, "direction"));
    const fixHeader = vue.computed(() => props.scroll && valueUtil.validateValue(props.scroll.y));
    const horizonScroll = vue.computed(() => props.scroll && valueUtil.validateValue(props.scroll.x) || Boolean(props.expandFixed));
    const fixColumn = vue.computed(() => horizonScroll.value && flattenColumns.value.some(({
      fixed
    }) => fixed));
    const stickyRef = vue.ref();
    const stickyState = useSticky.default(vue.toRef(props, "sticky"), vue.toRef(props, "prefixCls"));
    const summaryFixedInfos = vue.reactive({});
    const fixFooter = vue.computed(() => {
      const info = Object.values(summaryFixedInfos)[0];
      return (fixHeader.value || stickyState.value.isSticky) && info;
    });
    const summaryCollect = (uniKey, fixed) => {
      if (fixed)
        summaryFixedInfos[uniKey] = fixed;
      else
        delete summaryFixedInfos[uniKey];
    };
    const scrollXStyle = vue.ref({});
    const scrollYStyle = vue.ref({});
    const scrollTableStyle = vue.ref({});
    vue.watchEffect(() => {
      if (fixHeader.value) {
        scrollYStyle.value = {
          overflowY: "scroll",
          maxHeight: util.toPx(props.scroll.y)
        };
      }
      if (horizonScroll.value) {
        scrollXStyle.value = {
          overflowX: "auto"
        };
        if (!fixHeader.value)
          scrollYStyle.value = {
            overflowY: "hidden"
          };
        scrollTableStyle.value = {
          width: props.scroll.x === true ? "auto" : util.toPx(props.scroll.x),
          minWidth: "100%"
        };
      }
    });
    const onColumnResize = (columnKey, width) => {
      if (isVisible.default(fullTableRef.value)) {
        updateColsWidths((widths) => {
          if (widths.get(columnKey) !== width) {
            const newWidths = new Map(widths);
            newWidths.set(columnKey, width);
            return newWidths;
          }
          return widths;
        });
      }
    };
    const [setScrollTarget, getScrollTarget] = useFrame.useTimeoutLock(null);
    function forceScroll(scrollLeft, target) {
      if (!target)
        return;
      if (typeof target === "function") {
        target(scrollLeft);
        return;
      }
      const domTarget = target.$el || target;
      if (domTarget.scrollLeft !== scrollLeft)
        domTarget.scrollLeft = scrollLeft;
    }
    const onScroll = ({
      currentTarget,
      scrollLeft
    }) => {
      var _a;
      const isRTL = props.direction === "rtl";
      const mergedScrollLeft = typeof scrollLeft === "number" ? scrollLeft : currentTarget.scrollLeft;
      const compareTarget = currentTarget || EMPTY_SCROLL_TARGET;
      if (!getScrollTarget() || getScrollTarget() === compareTarget) {
        setScrollTarget(compareTarget);
        forceScroll(mergedScrollLeft, scrollHeaderRef.value);
        forceScroll(mergedScrollLeft, scrollBodyRef.value);
        forceScroll(mergedScrollLeft, scrollSummaryRef.value);
        forceScroll(mergedScrollLeft, (_a = stickyRef.value) == null ? void 0 : _a.setScrollLeft);
      }
      if (currentTarget) {
        const {
          scrollWidth,
          clientWidth
        } = currentTarget;
        if (isRTL) {
          setPingedLeft(-mergedScrollLeft < scrollWidth - clientWidth);
          setPingedRight(-mergedScrollLeft > 0);
        } else {
          setPingedLeft(mergedScrollLeft > 0);
          setPingedRight(mergedScrollLeft < scrollWidth - clientWidth);
        }
      }
    };
    const triggerOnScroll = () => {
      if (horizonScroll.value && scrollBodyRef.value) {
        onScroll({
          currentTarget: scrollBodyRef.value
        });
      } else {
        setPingedLeft(false);
        setPingedRight(false);
      }
    };
    let timtout;
    const updateWidth = (width) => {
      if (width !== componentWidth.value) {
        triggerOnScroll();
        componentWidth.value = fullTableRef.value ? fullTableRef.value.offsetWidth : width;
      }
    };
    const onFullTableResize = ({
      width
    }) => {
      clearTimeout(timtout);
      if (componentWidth.value === 0) {
        updateWidth(width);
        return;
      }
      timtout = setTimeout(() => {
        updateWidth(width);
      }, 100);
    };
    vue.watch([horizonScroll, () => props.data, () => props.columns], () => {
      if (horizonScroll.value)
        triggerOnScroll();
    }, {
      flush: "post"
    });
    const [scrollbarSize, setScrollbarSize] = useState.useState(0);
    StickyContext.useProvideSticky();
    vue.onMounted(() => {
      vue.nextTick(() => {
        var _a, _b;
        triggerOnScroll();
        setScrollbarSize(getScrollBarSize.getTargetScrollBarSize(scrollBodyRef.value).width);
        scrollBodySizeInfo.value = {
          scrollWidth: ((_a = scrollBodyRef.value) == null ? void 0 : _a.scrollWidth) || 0,
          clientWidth: ((_b = scrollBodyRef.value) == null ? void 0 : _b.clientWidth) || 0
        };
      });
    });
    vue.onUpdated(() => {
      vue.nextTick(() => {
        var _a, _b;
        const scrollWidth = ((_a = scrollBodyRef.value) == null ? void 0 : _a.scrollWidth) || 0;
        const clientWidth = ((_b = scrollBodyRef.value) == null ? void 0 : _b.clientWidth) || 0;
        if (scrollBodySizeInfo.value.scrollWidth !== scrollWidth || scrollBodySizeInfo.value.clientWidth !== clientWidth) {
          scrollBodySizeInfo.value = {
            scrollWidth,
            clientWidth
          };
        }
      });
    });
    vue.watchEffect(() => {
      if (props.internalHooks === INTERNAL_HOOKS && props.internalRefs) {
        props.onUpdateInternalRefs({
          body: scrollBodyRef.value ? scrollBodyRef.value.$el || scrollBodyRef.value : null
        });
      }
    }, {
      flush: "post"
    });
    const mergedTableLayout = vue.computed(() => {
      if (props.tableLayout)
        return props.tableLayout;
      if (fixColumn.value)
        return props.scroll.x === "max-content" ? "auto" : "fixed";
      if (fixHeader.value || stickyState.value.isSticky || flattenColumns.value.some(({
        ellipsis
      }) => ellipsis))
        return "fixed";
      return "auto";
    });
    const emptyNode = () => {
      var _a;
      return hasData.value ? null : ((_a = slots.emptyText) == null ? void 0 : _a.call(slots)) || "No Data";
    };
    TableContext.useProvideTable(vue.reactive({
      ...vue.toRefs(core.reactivePick(props, "prefixCls", "direction", "transformCellText")),
      getComponent,
      scrollbarSize,
      fixedInfoList: vue.computed(() => flattenColumns.value.map((_, colIndex) => fixUtil.getCellFixedInfo(colIndex, colIndex, flattenColumns.value, stickyOffsets.value, props.direction))),
      isSticky: vue.computed(() => stickyState.value.isSticky),
      summaryCollect
    }));
    BodyContext.useProvideBody(vue.reactive({
      ...vue.toRefs(core.reactivePick(props, "rowClassName", "expandedRowClassName", "expandRowByClick", "expandedRowRender", "expandIconColumnIndex", "indentSize")),
      columns,
      flattenColumns,
      tableLayout: mergedTableLayout,
      expandIcon: mergedExpandIcon,
      expandableType,
      onTriggerExpand
    }));
    ResizeContext.useProvideResize({
      onColumnResize
    });
    ExpandedRowContext.useProvideExpandedRow({
      componentWidth,
      fixHeader,
      fixColumn,
      horizonScroll
    });
    const bodyTable = () => vue.createVNode(index.default, {
      "data": mergedData.value,
      "measureColumnWidth": fixHeader.value || horizonScroll.value || stickyState.value.isSticky,
      "expandedKeys": mergedExpandedKeys.value,
      "rowExpandable": props.rowExpandable,
      "getRowKey": getRowKey.value,
      "customRow": props.customRow,
      "childrenColumnName": mergedChildrenColumnName.value
    }, {
      emptyNode
    });
    const bodyColGroup = () => vue.createVNode(ColGroup.default, {
      "colWidths": flattenColumns.value.map(({
        width
      }) => width),
      "columns": flattenColumns.value
    }, null);
    return () => {
      var _a;
      const {
        prefixCls,
        scroll,
        tableLayout,
        direction,
        // Additional Part
        title = slots.title,
        footer = slots.footer,
        // Customize
        id,
        showHeader,
        customHeaderRow
      } = props;
      const {
        isSticky,
        offsetHeader,
        offsetSummary,
        offsetScroll,
        stickyClassName,
        container
      } = stickyState.value;
      const TableComponent = getComponent(["table"], "table");
      const customizeScrollBody = getComponent(["body"]);
      const summaryNode = (_a = slots.summary) == null ? void 0 : _a.call(slots, {
        pageData: mergedData.value
      });
      let groupTableNode = () => null;
      const headerProps = {
        colWidths: colWidths.value,
        columCount: flattenColumns.value.length,
        stickyOffsets: stickyOffsets.value,
        customHeaderRow,
        fixHeader: fixHeader.value,
        scroll
      };
      if (process.env.NODE_ENV !== "production" && typeof customizeScrollBody === "function" && hasData.value && !fixHeader.value)
        warning.warning(false, "`components.body` with render props is only work on `scroll.y`.");
      if (fixHeader.value || isSticky) {
        let bodyContent = () => null;
        if (typeof customizeScrollBody === "function") {
          bodyContent = () => customizeScrollBody(mergedData.value, {
            scrollbarSize: scrollbarSize.value,
            ref: scrollBodyRef,
            onScroll
          });
          headerProps.colWidths = flattenColumns.value.map(({
            width
          }, index) => {
            const colWidth = index === columns.value.length - 1 ? width - scrollbarSize.value : width;
            if (typeof colWidth === "number" && !Number.isNaN(colWidth))
              return colWidth;
            warning.warning(false, "When use `components.body` with render props. Each column should have a fixed `width` value.");
            return 0;
          });
        } else {
          bodyContent = () => vue.createVNode("div", {
            "style": {
              ...scrollXStyle.value,
              ...scrollYStyle.value
            },
            "onScroll": onScroll,
            "ref": scrollBodyRef,
            "class": classNames.default(`${prefixCls}-body`)
          }, [vue.createVNode(TableComponent, {
            "style": {
              ...scrollTableStyle.value,
              tableLayout: mergedTableLayout.value
            }
          }, {
            default: () => [bodyColGroup(), bodyTable(), !fixFooter.value && summaryNode && vue.createVNode(index$1.default, {
              "stickyOffsets": stickyOffsets.value,
              "flattenColumns": flattenColumns.value
            }, _isSlot(summaryNode) ? summaryNode : {
              default: () => [summaryNode]
            })]
          })]);
        }
        const fixedHolderProps = {
          noData: !mergedData.value.length,
          maxContentScroll: horizonScroll.value && scroll.x === "max-content",
          ...headerProps,
          ...columnContext.value,
          direction,
          stickyClassName,
          onScroll
        };
        groupTableNode = () => vue.createVNode(vue.Fragment, null, [showHeader !== false && vue.createVNode(index$2.default, vue.mergeProps(fixedHolderProps, {
          "stickyTopOffset": offsetHeader,
          "class": `${prefixCls}-header`,
          "ref": scrollHeaderRef
        }), {
          default: (fixedHolderPassProps) => vue.createVNode(vue.Fragment, null, [vue.createVNode(Header.default, fixedHolderPassProps, null), fixFooter.value === "top" && vue.createVNode(index$1.default, fixedHolderPassProps, _isSlot(summaryNode) ? summaryNode : {
            default: () => [summaryNode]
          })])
        }), bodyContent(), fixFooter.value && fixFooter.value !== "top" && vue.createVNode(index$2.default, vue.mergeProps(fixedHolderProps, {
          "stickyBottomOffset": offsetSummary,
          "class": `${prefixCls}-summary`,
          "ref": scrollSummaryRef
        }), {
          default: (fixedHolderPassProps) => vue.createVNode(index$1.default, fixedHolderPassProps, _isSlot(summaryNode) ? summaryNode : {
            default: () => [summaryNode]
          })
        }), isSticky && scrollBodyRef.value && vue.createVNode(stickyScrollBar.default, {
          "ref": stickyRef,
          "offsetScroll": offsetScroll,
          "scrollBodyRef": scrollBodyRef,
          "onScroll": onScroll,
          "container": container,
          "scrollBodySizeInfo": scrollBodySizeInfo.value
        }, null)]);
      } else {
        groupTableNode = () => vue.createVNode("div", {
          "style": {
            ...scrollXStyle.value,
            ...scrollYStyle.value
          },
          "class": classNames.default(`${prefixCls}-content`),
          "onScroll": onScroll,
          "ref": scrollBodyRef
        }, [vue.createVNode(TableComponent, {
          "style": {
            ...scrollTableStyle.value,
            tableLayout: mergedTableLayout.value
          }
        }, {
          default: () => [bodyColGroup(), showHeader !== false && vue.createVNode(Header.default, vue.mergeProps(headerProps, columnContext.value), null), bodyTable(), summaryNode && vue.createVNode(index$1.default, {
            "stickyOffsets": stickyOffsets.value,
            "flattenColumns": flattenColumns.value
          }, _isSlot(summaryNode) ? summaryNode : {
            default: () => [summaryNode]
          })]
        })]);
      }
      const ariaProps = pickAttrs.default(attrs, {
        aria: true,
        data: true
      });
      const fullTable = () => {
        let _slot, _slot2;
        return vue.createVNode("div", vue.mergeProps(ariaProps, {
          "class": classNames.default(prefixCls, {
            [`${prefixCls}-rtl`]: direction === "rtl",
            [`${prefixCls}-ping-left`]: pingedLeft.value,
            [`${prefixCls}-ping-right`]: pingedRight.value,
            [`${prefixCls}-layout-fixed`]: tableLayout === "fixed",
            [`${prefixCls}-fixed-header`]: fixHeader.value,
            /** No used but for compatible */
            [`${prefixCls}-fixed-column`]: fixColumn.value,
            [`${prefixCls}-scroll-horizontal`]: horizonScroll.value,
            [`${prefixCls}-has-fix-left`]: flattenColumns.value[0] && flattenColumns.value[0].fixed,
            [`${prefixCls}-has-fix-right`]: flattenColumns.value[columnCount.value - 1] && flattenColumns.value[columnCount.value - 1].fixed === "right",
            [attrs.class]: attrs.class
          }),
          "style": attrs.style,
          "id": id,
          "ref": fullTableRef
        }), [title && vue.createVNode(index$3.default, {
          "class": `${prefixCls}-title`
        }, _isSlot(_slot = title(mergedData.value)) ? _slot : {
          default: () => [_slot]
        }), vue.createVNode("div", {
          "class": `${prefixCls}-container`
        }, [groupTableNode()]), footer && vue.createVNode(index$3.default, {
          "class": `${prefixCls}-footer`
        }, _isSlot(_slot2 = footer(mergedData.value)) ? _slot2 : {
          default: () => [_slot2]
        })]);
      };
      if (horizonScroll.value) {
        return vue.createVNode(index$4.default, {
          "onResize": onFullTableResize
        }, {
          default: fullTable
        });
      }
      return fullTable();
    };
  }
});

exports.INTERNAL_HOOKS = INTERNAL_HOOKS;
exports.default = Table;
//# sourceMappingURL=Table.js.map
