"use strict";
Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toStringTag]: { value: "Module" } });
const aria = require("../../../constants/aria.js");
const event = require("../../../utils/dom/event.js");
const raf = require("../../../utils/raf.js");
const error = require("../../../utils/error.js");
const runtime = require("../../../utils/vue/props/runtime.js");
const typescript = require("../../../utils/typescript.js");
const numbers = require("../../../utils/numbers.js");
const index = require("../../../hooks/use-namespace/index.js");
const index$2 = require("../../icon/index.js");
const useWheel = require("../../virtual-list/src/hooks/use-wheel.js");
const constants = require("./constants.js");
const tabBar2 = require("./tab-bar2.js");
const index$1 = require("../../../../node_modules/@vueuse/core/index.js");
const index$3 = require("../../../../../@element-plus/icons-vue/dist/index.js");
const vue = require("vue");
const clamp = require("../../../../../lodash-es/clamp.js");
const tabNavProps = runtime.buildProps({
  panes: {
    type: runtime.definePropType(Array),
    default: () => typescript.mutable([])
  },
  currentName: {
    type: [String, Number],
    default: ""
  },
  editable: Boolean,
  type: {
    type: String,
    values: [
      "card",
      "border-card",
      ""
    ],
    default: ""
  },
  stretch: Boolean,
  tabindex: {
    type: [String, Number],
    default: void 0
  }
});
const tabNavEmits = {
  tabClick: (tab, tabName, ev) => ev instanceof Event,
  tabRemove: (tab, ev) => ev instanceof Event
};
const COMPONENT_NAME = "ElTabNav";
const TabNav = /* @__PURE__ */ vue.defineComponent({
  name: COMPONENT_NAME,
  props: tabNavProps,
  emits: tabNavEmits,
  setup(props, { expose, emit }) {
    const rootTabs = vue.inject(constants.tabsRootContextKey);
    if (!rootTabs) error.throwError(COMPONENT_NAME, `<el-tabs><tab-nav /></el-tabs>`);
    const ns = index.useNamespace("tabs");
    const visibility = index$1.useDocumentVisibility();
    const focused = index$1.useWindowFocus();
    const navScroll$ = vue.ref();
    const nav$ = vue.ref();
    const el$ = vue.ref();
    const tabRefsMap = vue.ref({});
    const tabBarRef = vue.ref();
    const scrollable = vue.ref(false);
    const navOffset = vue.ref(0);
    const isFocus = vue.ref(false);
    const focusable = vue.ref(true);
    const isWheelScrolling = vue.ref(false);
    const tracker = vue.shallowRef();
    const isHorizontal = vue.computed(() => ["top", "bottom"].includes(rootTabs.props.tabPosition));
    const sizeName = vue.computed(() => isHorizontal.value ? "width" : "height");
    const navStyle = vue.computed(() => {
      const dir = sizeName.value === "width" ? "X" : "Y";
      return {
        transition: isWheelScrolling.value ? "none" : void 0,
        transform: `translate${dir}(-${navOffset.value}px)`
      };
    });
    const { width: navContainerWidth, height: navContainerHeight } = index$1.useElementSize(navScroll$);
    const { width: navWidth, height: navHeight } = index$1.useElementSize(nav$, {
      width: 0,
      height: 0
    }, { box: "border-box" });
    const navContainerSize = vue.computed(() => isHorizontal.value ? navContainerWidth.value : navContainerHeight.value);
    const navSize = vue.computed(() => isHorizontal.value ? navWidth.value : navHeight.value);
    const { onWheel } = useWheel.default({
      atStartEdge: vue.computed(() => navOffset.value <= 0),
      atEndEdge: vue.computed(() => navSize.value - navOffset.value <= navContainerSize.value),
      layout: vue.computed(() => isHorizontal.value ? "horizontal" : "vertical")
    }, (offset) => {
      navOffset.value = clamp.default(navOffset.value + offset, 0, navSize.value - navContainerSize.value);
    });
    const handleWheel = (event2) => {
      isWheelScrolling.value = true;
      onWheel(event2);
      raf.rAF(() => {
        isWheelScrolling.value = false;
      });
    };
    const scrollPrev = () => {
      if (!navScroll$.value) return;
      const containerSize = navScroll$.value.getBoundingClientRect()[sizeName.value];
      const currentOffset = navOffset.value;
      if (!currentOffset) return;
      navOffset.value = currentOffset > containerSize ? currentOffset - containerSize : 0;
    };
    const scrollNext = () => {
      if (!navScroll$.value || !nav$.value) return;
      const navSize2 = nav$.value.getBoundingClientRect()[sizeName.value];
      const containerSize = navScroll$.value.getBoundingClientRect()[sizeName.value];
      const currentOffset = navOffset.value;
      if (!numbers.isGreaterThan(navSize2 - currentOffset, containerSize)) return;
      navOffset.value = navSize2 - currentOffset > containerSize * 2 ? currentOffset + containerSize : navSize2 - containerSize;
    };
    const scrollToActiveTab = async () => {
      const nav = nav$.value;
      if (!scrollable.value || !el$.value || !navScroll$.value || !nav) return;
      await vue.nextTick();
      const activeTab = tabRefsMap.value[props.currentName];
      if (!activeTab) return;
      const navScroll = navScroll$.value;
      const activeTabBounding = activeTab.getBoundingClientRect();
      const navScrollBounding = navScroll.getBoundingClientRect();
      const navScrollLeft = navScrollBounding.left + 1;
      const navScrollRight = navScrollBounding.right - 1;
      const navBounding = nav.getBoundingClientRect();
      const maxOffset = isHorizontal.value ? navBounding.width - navScrollBounding.width : navBounding.height - navScrollBounding.height;
      const currentOffset = navOffset.value;
      let newOffset = currentOffset;
      if (isHorizontal.value) {
        if (activeTabBounding.left < navScrollLeft) newOffset = currentOffset - (navScrollLeft - activeTabBounding.left);
        if (activeTabBounding.right > navScrollRight) newOffset = currentOffset + activeTabBounding.right - navScrollRight;
      } else {
        if (activeTabBounding.top < navScrollBounding.top) newOffset = currentOffset - (navScrollBounding.top - activeTabBounding.top);
        if (activeTabBounding.bottom > navScrollBounding.bottom) newOffset = currentOffset + (activeTabBounding.bottom - navScrollBounding.bottom);
      }
      newOffset = Math.max(newOffset, 0);
      navOffset.value = Math.min(newOffset, maxOffset);
    };
    const update = () => {
      var _a;
      if (!nav$.value || !navScroll$.value) return;
      props.stretch && ((_a = tabBarRef.value) == null ? void 0 : _a.update());
      const navSize2 = nav$.value.getBoundingClientRect()[sizeName.value];
      const containerSize = navScroll$.value.getBoundingClientRect()[sizeName.value];
      const currentOffset = navOffset.value;
      if (containerSize < navSize2) {
        scrollable.value = scrollable.value || {};
        scrollable.value.prev = currentOffset;
        scrollable.value.next = numbers.isGreaterThan(navSize2, currentOffset + containerSize);
        if (numbers.isGreaterThan(containerSize, navSize2 - currentOffset)) navOffset.value = navSize2 - containerSize;
      } else {
        scrollable.value = false;
        if (currentOffset > 0) navOffset.value = 0;
      }
    };
    const changeTab = (event$1) => {
      const code = event.getEventCode(event$1);
      let step = 0;
      switch (code) {
        case aria.EVENT_CODE.left:
        case aria.EVENT_CODE.up:
          step = -1;
          break;
        case aria.EVENT_CODE.right:
        case aria.EVENT_CODE.down:
          step = 1;
          break;
        default:
          return;
      }
      const tabList = Array.from(event$1.currentTarget.querySelectorAll("[role=tab]:not(.is-disabled)"));
      let nextIndex = tabList.indexOf(event$1.target) + step;
      if (nextIndex < 0) nextIndex = tabList.length - 1;
      else if (nextIndex >= tabList.length) nextIndex = 0;
      tabList[nextIndex].focus({ preventScroll: true });
      tabList[nextIndex].click();
      setFocus();
    };
    const setFocus = () => {
      if (focusable.value) isFocus.value = true;
    };
    const removeFocus = () => isFocus.value = false;
    const setRefs = (el, key) => {
      tabRefsMap.value[key] = el;
    };
    const focusActiveTab = async () => {
      var _a;
      await vue.nextTick();
      (_a = tabRefsMap.value[props.currentName]) == null ? void 0 : _a.focus({ preventScroll: true });
    };
    vue.watch(visibility, (visibility2) => {
      if (visibility2 === "hidden") focusable.value = false;
      else if (visibility2 === "visible") setTimeout(() => focusable.value = true, 50);
    });
    vue.watch(focused, (focused2) => {
      if (focused2) setTimeout(() => focusable.value = true, 50);
      else focusable.value = false;
    });
    index$1.useResizeObserver(el$, () => {
      raf.rAF(update);
    });
    vue.onMounted(() => setTimeout(() => scrollToActiveTab(), 0));
    vue.onUpdated(() => update());
    expose({
      scrollToActiveTab,
      removeFocus,
      focusActiveTab,
      tabListRef: nav$,
      tabBarRef,
      scheduleRender: () => vue.triggerRef(tracker)
    });
    return () => {
      const scrollBtn = scrollable.value ? [vue.createVNode("span", {
        "class": [ns.e("nav-prev"), ns.is("disabled", !scrollable.value.prev)],
        "onClick": scrollPrev
      }, [vue.createVNode(index$2.ElIcon, null, { default: () => [vue.createVNode(index$3.ArrowLeft, null, null)] })]), vue.createVNode("span", {
        "class": [ns.e("nav-next"), ns.is("disabled", !scrollable.value.next)],
        "onClick": scrollNext
      }, [vue.createVNode(index$2.ElIcon, null, { default: () => [vue.createVNode(index$3.ArrowRight, null, null)] })])] : null;
      const tabs = props.panes.map((pane, index2) => {
        var _a, _b;
        const uid = pane.uid;
        const disabled = pane.props.disabled;
        const tabName = pane.props.name ?? pane.index ?? `${index2}`;
        const closable = !disabled && (pane.isClosable || pane.props.closable !== false && props.editable);
        pane.index = `${index2}`;
        const btnClose = closable ? vue.createVNode(index$2.ElIcon, {
          "class": "is-icon-close",
          "onClick": (ev) => emit("tabRemove", pane, ev)
        }, { default: () => [vue.createVNode(index$3.Close, null, null)] }) : null;
        const tabLabelContent = ((_b = (_a = pane.slots).label) == null ? void 0 : _b.call(_a)) || pane.props.label;
        const tabindex = !disabled && pane.active ? props.tabindex ?? rootTabs.props.tabindex : -1;
        return vue.createVNode("div", {
          "ref": (el) => setRefs(el, tabName),
          "class": [
            ns.e("item"),
            ns.is(rootTabs.props.tabPosition),
            ns.is("active", pane.active),
            ns.is("disabled", disabled),
            ns.is("closable", closable),
            ns.is("focus", isFocus.value)
          ],
          "id": `tab-${tabName}`,
          "key": `tab-${uid}`,
          "aria-controls": `pane-${tabName}`,
          "role": "tab",
          "aria-selected": pane.active,
          "tabindex": tabindex,
          "onFocus": () => setFocus(),
          "onBlur": () => removeFocus(),
          "onClick": (ev) => {
            removeFocus();
            emit("tabClick", pane, tabName, ev);
          },
          "onKeydown": (ev) => {
            const code = event.getEventCode(ev);
            if (closable && (code === aria.EVENT_CODE.delete || code === aria.EVENT_CODE.backspace)) emit("tabRemove", pane, ev);
          }
        }, [...[tabLabelContent, btnClose]]);
      });
      tracker.value;
      return vue.createVNode("div", {
        "ref": el$,
        "class": [
          ns.e("nav-wrap"),
          ns.is("scrollable", !!scrollable.value),
          ns.is(rootTabs.props.tabPosition)
        ]
      }, [scrollBtn, vue.createVNode("div", {
        "class": ns.e("nav-scroll"),
        "ref": navScroll$
      }, [props.panes.length > 0 ? vue.createVNode("div", {
        "class": [
          ns.e("nav"),
          ns.is(rootTabs.props.tabPosition),
          ns.is("stretch", props.stretch && ["top", "bottom"].includes(rootTabs.props.tabPosition))
        ],
        "ref": nav$,
        "style": navStyle.value,
        "role": "tablist",
        "onKeydown": changeTab,
        "onWheel": handleWheel
      }, [...[!props.type ? vue.createVNode(tabBar2.default, {
        "ref": tabBarRef,
        "tabs": [...props.panes],
        "tabRefs": tabRefsMap.value
      }, null) : null, tabs]]) : null])]);
    };
  }
});
exports.default = TabNav;
exports.tabNavEmits = tabNavEmits;
exports.tabNavProps = tabNavProps;
