"use strict";
Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toStringTag]: { value: "Module" } });
const types = require("../../../utils/types.js");
const runtime = require("../../../utils/vue/props/runtime.js");
const icon = require("../../../utils/vue/icon.js");
const vnode = require("../../../utils/vue/vnode.js");
const typescript = require("../../../utils/typescript.js");
const index = require("../../../hooks/use-namespace/index.js");
const index$2 = require("../../icon/index.js");
const index$3 = require("../../../directives/click-outside/index.js");
const menuBar = require("./utils/menu-bar.js");
const menuCollapseTransition = require("./menu-collapse-transition.js");
const useMenuCssVar = require("./use-menu-css-var.js");
const tokens = require("./tokens.js");
const subMenu = require("./sub-menu.js");
const index$1 = require("../../../../node_modules/@vueuse/core/index.js");
const index$4 = require("../../../../../@element-plus/icons-vue/dist/index.js");
const Vue = require("vue");
const shared_esmBundler = require("../../../../../@vue/shared/dist/shared.esm-bundler.js");
const isNil = require("../../../../../lodash-es/isNil.js");
const menuProps = runtime.buildProps({
  mode: {
    type: String,
    values: ["horizontal", "vertical"],
    default: "vertical"
  },
  defaultActive: {
    type: String,
    default: ""
  },
  defaultOpeneds: {
    type: runtime.definePropType(Array),
    default: () => typescript.mutable([])
  },
  uniqueOpened: Boolean,
  router: Boolean,
  menuTrigger: {
    type: String,
    values: ["hover", "click"],
    default: "hover"
  },
  collapse: Boolean,
  backgroundColor: String,
  textColor: String,
  activeTextColor: String,
  closeOnClickOutside: Boolean,
  collapseTransition: {
    type: Boolean,
    default: true
  },
  ellipsis: {
    type: Boolean,
    default: true
  },
  popperOffset: {
    type: Number,
    default: 6
  },
  ellipsisIcon: {
    type: icon.iconPropType,
    default: () => index$4.More
  },
  popperEffect: {
    type: runtime.definePropType(String),
    default: "dark"
  },
  popperClass: String,
  popperStyle: { type: runtime.definePropType([String, Object]) },
  showTimeout: {
    type: Number,
    default: 300
  },
  hideTimeout: {
    type: Number,
    default: 300
  },
  persistent: {
    type: Boolean,
    default: true
  }
});
const checkIndexPath = (indexPath) => shared_esmBundler.isArray(indexPath) && indexPath.every((path) => shared_esmBundler.isString(path));
const menuEmits = {
  close: (index2, indexPath) => shared_esmBundler.isString(index2) && checkIndexPath(indexPath),
  open: (index2, indexPath) => shared_esmBundler.isString(index2) && checkIndexPath(indexPath),
  select: (index2, indexPath, item, routerResult) => shared_esmBundler.isString(index2) && checkIndexPath(indexPath) && shared_esmBundler.isObject(item) && (types.isUndefined(routerResult) || routerResult instanceof Promise)
};
const DEFAULT_MORE_ITEM_WIDTH = 64;
var menu_default = Vue.defineComponent({
  name: "ElMenu",
  props: menuProps,
  emits: menuEmits,
  setup(props, { emit, slots, expose }) {
    const instance = Vue.getCurrentInstance();
    const router = instance.appContext.config.globalProperties.$router;
    const menu = Vue.ref();
    const subMenu$1 = Vue.ref();
    const nsMenu = index.useNamespace("menu");
    const nsSubMenu = index.useNamespace("sub-menu");
    let moreItemWidth = DEFAULT_MORE_ITEM_WIDTH;
    const sliceIndex = Vue.ref(-1);
    const openedMenus = Vue.ref(props.defaultOpeneds && !props.collapse ? props.defaultOpeneds.slice(0) : []);
    const activeIndex = Vue.ref(props.defaultActive);
    const items = Vue.ref({});
    const subMenus = Vue.ref({});
    const isMenuPopup = Vue.computed(() => props.mode === "horizontal" || props.mode === "vertical" && props.collapse);
    const initMenu = () => {
      const activeItem = activeIndex.value && items.value[activeIndex.value];
      if (!activeItem || props.mode === "horizontal" || props.collapse) return;
      activeItem.indexPath.forEach((index2) => {
        const subMenu2 = subMenus.value[index2];
        subMenu2 && openMenu(index2, subMenu2.indexPath);
      });
    };
    const openMenu = (index2, indexPath) => {
      if (openedMenus.value.includes(index2)) return;
      if (props.uniqueOpened) openedMenus.value = openedMenus.value.filter((index3) => indexPath.includes(index3));
      openedMenus.value.push(index2);
      emit("open", index2, indexPath);
    };
    const close = (index2) => {
      const i = openedMenus.value.indexOf(index2);
      if (i !== -1) openedMenus.value.splice(i, 1);
    };
    const closeMenu = (index2, indexPath) => {
      close(index2);
      emit("close", index2, indexPath);
    };
    const handleSubMenuClick = ({ index: index2, indexPath }) => {
      openedMenus.value.includes(index2) ? closeMenu(index2, indexPath) : openMenu(index2, indexPath);
    };
    const handleMenuItemClick = (menuItem) => {
      if (props.mode === "horizontal" || props.collapse) openedMenus.value = [];
      const { index: index2, indexPath } = menuItem;
      if (isNil.default(index2) || isNil.default(indexPath)) return;
      if (props.router && router) {
        const route = menuItem.route || index2;
        const routerResult = router.push(route).then((res) => {
          if (!res) activeIndex.value = index2;
          return res;
        });
        emit("select", index2, indexPath, {
          index: index2,
          indexPath,
          route
        }, routerResult);
      } else {
        activeIndex.value = index2;
        emit("select", index2, indexPath, {
          index: index2,
          indexPath
        });
      }
    };
    const updateActiveIndex = (val) => {
      var _a;
      const itemsInData = items.value;
      activeIndex.value = ((_a = itemsInData[val] || activeIndex.value && itemsInData[activeIndex.value] || itemsInData[props.defaultActive]) == null ? void 0 : _a.index) ?? val;
    };
    const calcMenuItemWidth = (menuItem) => {
      const computedStyle = getComputedStyle(menuItem);
      const marginLeft = Number.parseInt(computedStyle.marginLeft, 10);
      const marginRight = Number.parseInt(computedStyle.marginRight, 10);
      return menuItem.offsetWidth + marginLeft + marginRight || 0;
    };
    const calcSliceIndex = () => {
      if (!menu.value) return -1;
      const items2 = Array.from(menu.value.childNodes).filter((item) => item.nodeName !== "#comment" && (item.nodeName !== "#text" || item.nodeValue));
      const computedMenuStyle = getComputedStyle(menu.value);
      const paddingLeft = Number.parseInt(computedMenuStyle.paddingLeft, 10);
      const paddingRight = Number.parseInt(computedMenuStyle.paddingRight, 10);
      const menuWidth = menu.value.clientWidth - paddingLeft - paddingRight;
      let calcWidth = 0;
      let sliceIndex2 = 0;
      items2.forEach((item, index2) => {
        calcWidth += calcMenuItemWidth(item);
        if (calcWidth <= menuWidth - moreItemWidth) sliceIndex2 = index2 + 1;
      });
      return sliceIndex2 === items2.length ? -1 : sliceIndex2;
    };
    const getIndexPath = (index2) => subMenus.value[index2].indexPath;
    const debounce = (fn, wait = 33.34) => {
      let timer;
      return () => {
        timer && clearTimeout(timer);
        timer = setTimeout(() => {
          fn();
        }, wait);
      };
    };
    let isFirstTimeRender = true;
    const handleResize = () => {
      const el = index$1.unrefElement(subMenu$1);
      if (el) moreItemWidth = calcMenuItemWidth(el) || DEFAULT_MORE_ITEM_WIDTH;
      if (sliceIndex.value === calcSliceIndex()) return;
      const callback = () => {
        sliceIndex.value = -1;
        Vue.nextTick(() => {
          sliceIndex.value = calcSliceIndex();
        });
      };
      isFirstTimeRender ? callback() : debounce(callback)();
      isFirstTimeRender = false;
    };
    Vue.watch(() => props.defaultActive, (currentActive) => {
      if (!items.value[currentActive]) activeIndex.value = "";
      updateActiveIndex(currentActive);
    });
    Vue.watch(() => props.collapse, (value) => {
      if (value) openedMenus.value = [];
    });
    Vue.watch(items.value, initMenu);
    let resizeStopper;
    Vue.watchEffect(() => {
      if (props.mode === "horizontal" && props.ellipsis) resizeStopper = index$1.useResizeObserver(menu, handleResize).stop;
      else resizeStopper == null ? void 0 : resizeStopper();
    });
    const mouseInChild = Vue.ref(false);
    {
      const addSubMenu = (item) => {
        subMenus.value[item.index] = item;
      };
      const removeSubMenu = (item) => {
        delete subMenus.value[item.index];
      };
      const addMenuItem = (item) => {
        items.value[item.index] = item;
      };
      const removeMenuItem = (item) => {
        delete items.value[item.index];
      };
      Vue.provide(tokens.MENU_INJECTION_KEY, Vue.reactive({
        props,
        openedMenus,
        items,
        subMenus,
        activeIndex,
        isMenuPopup,
        addMenuItem,
        removeMenuItem,
        addSubMenu,
        removeSubMenu,
        openMenu,
        closeMenu,
        handleMenuItemClick,
        handleSubMenuClick
      }));
      Vue.provide(`${tokens.SUB_MENU_INJECTION_KEY}${instance.uid}`, {
        addSubMenu,
        removeSubMenu,
        mouseInChild,
        level: 0
      });
    }
    Vue.onMounted(() => {
      if (props.mode === "horizontal") new menuBar.default(instance.vnode.el, nsMenu.namespace.value);
    });
    {
      const open = (index2) => {
        const { indexPath } = subMenus.value[index2];
        indexPath.forEach((i) => openMenu(i, indexPath));
      };
      expose({
        open,
        close,
        updateActiveIndex,
        handleResize
      });
    }
    const ulStyle = useMenuCssVar.useMenuCssVar(props, 0);
    return () => {
      var _a;
      let slot = ((_a = slots.default) == null ? void 0 : _a.call(slots)) ?? [];
      const vShowMore = [];
      if (props.mode === "horizontal" && menu.value) {
        const originalSlot = vnode.flattedChildren(slot).filter((vnode2) => {
          return (vnode2 == null ? void 0 : vnode2.shapeFlag) !== 8;
        });
        const slotDefault = sliceIndex.value === -1 ? originalSlot : originalSlot.slice(0, sliceIndex.value);
        const slotMore = sliceIndex.value === -1 ? [] : originalSlot.slice(sliceIndex.value);
        if ((slotMore == null ? void 0 : slotMore.length) && props.ellipsis) {
          slot = slotDefault;
          vShowMore.push(Vue.h(subMenu.default, {
            ref: subMenu$1,
            index: "sub-menu-more",
            class: nsSubMenu.e("hide-arrow"),
            popperOffset: props.popperOffset
          }, {
            title: () => Vue.h(index$2.ElIcon, { class: nsSubMenu.e("icon-more") }, { default: () => Vue.h(props.ellipsisIcon) }),
            default: () => slotMore
          }));
        }
      }
      const directives = props.closeOnClickOutside ? [[index$3.default, () => {
        if (!openedMenus.value.length) return;
        if (!mouseInChild.value) {
          openedMenus.value.forEach((openedMenu) => emit("close", openedMenu, getIndexPath(openedMenu)));
          openedMenus.value = [];
        }
      }]] : [];
      const vMenu = Vue.withDirectives(Vue.h("ul", {
        key: String(props.collapse),
        role: "menubar",
        ref: menu,
        style: ulStyle.value,
        class: {
          [nsMenu.b()]: true,
          [nsMenu.m(props.mode)]: true,
          [nsMenu.m("collapse")]: props.collapse
        }
      }, [...slot, ...vShowMore]), directives);
      if (props.collapseTransition && props.mode === "vertical") return Vue.h(menuCollapseTransition.default, () => vMenu);
      return vMenu;
    };
  }
});
exports.default = menu_default;
exports.menuEmits = menuEmits;
exports.menuProps = menuProps;
