"use strict";
Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toStringTag]: { value: "Module" } });
const vue = require("vue");
const comp = require("../../ui/src/comp.js");
const XEUtils = require("xe-utils");
require("../../ui/index.js");
const dom = require("../../ui/src/dom.js");
const utils = require("../../ui/src/utils.js");
const vn = require("../../ui/src/vn.js");
const log = require("../../ui/src/log.js");
const index = require("../../loading/index.js");
const index_esm = require("../../../../@vxe-ui/core/es/index.esm.js");
const useFns = require("../../../../@vxe-ui/core/es/src/useFns.js");
const event = require("../../../../@vxe-ui/core/es/src/event.js");
const permission = require("../../../../@vxe-ui/core/es/src/permission.js");
const { menus, getConfig, getIcon } = index_esm.VxeUI;
const VxeMenuComponent = comp.defineVxeComponent({
  name: "VxeMenu",
  props: {
    modelValue: [String, Number],
    expandAll: Boolean,
    accordion: {
      type: Boolean,
      default: () => getConfig().menu.accordion
    },
    collapsed: {
      type: Boolean,
      default: null
    },
    collapseFixed: Boolean,
    loading: Boolean,
    options: {
      type: Array,
      default: () => []
    },
    size: {
      type: String,
      default: () => getConfig().menu.size || getConfig().size
    },
    menuConfig: Object
  },
  emits: [
    "update:modelValue",
    "click",
    "option-menu",
    "menu-click"
  ],
  setup(props, context) {
    const { emit, slots } = context;
    const xID = XEUtils.uniqueId();
    const $xeLayoutAside = vue.inject("$xeLayoutAside", null);
    const refElem = vue.ref();
    const refCollapseElem = vue.ref();
    const { computeSize } = useFns.useSize(props);
    const reactData = vue.reactive({
      initialized: !!props.collapsed,
      isEnterCollapse: false,
      collapseStyle: {},
      collapseZindex: 0,
      activeName: props.modelValue,
      menuList: [],
      itemHeight: 1
    });
    const refMaps = {
      refElem
    };
    const computeMenuOpts = vue.computed(() => {
      return Object.assign({}, getConfig().menu.menuConfig, props.menuConfig);
    });
    const computeIsCollapsed = vue.computed(() => {
      const { collapsed } = props;
      if (XEUtils.isBoolean(collapsed)) {
        return collapsed;
      }
      if ($xeLayoutAside) {
        return !!$xeLayoutAside.props.collapsed;
      }
      return false;
    });
    const computeCollapseWidth = vue.computed(() => {
      let collapseWidth = "";
      if ($xeLayoutAside) {
        collapseWidth = $xeLayoutAside.props.collapseWidth || "";
      }
      return collapseWidth;
    });
    const computeCollapseEnterWidth = vue.computed(() => {
      let width = "";
      if ($xeLayoutAside) {
        width = $xeLayoutAside.props.width || "";
      }
      return width;
    });
    const computeMaps = {
      computeSize
    };
    const $xeMenu = {
      xID,
      props,
      context,
      reactData,
      getRefMaps: () => refMaps,
      getComputeMaps: () => computeMaps
    };
    const getMenuTitle = (item) => {
      return `${item.title || item.name}`;
    };
    const updateZindex = () => {
      if (reactData.collapseZindex < utils.getLastZIndex()) {
        reactData.collapseZindex = utils.nextZIndex();
      }
    };
    const updateActiveMenu = (isDefExpand) => {
      const { activeName } = reactData;
      XEUtils.eachTree(reactData.menuList, (item, index2, items, path, parent, nodes) => {
        if (item.itemKey === activeName) {
          nodes.forEach((obj) => {
            obj.isActive = true;
            {
              obj.isExpand = true;
            }
          });
          item.isExactActive = true;
        } else {
          item.isExactActive = false;
          item.isActive = false;
        }
      }, { children: "childList" });
    };
    const updateMenuConfig = () => {
      const { options, expandAll } = props;
      reactData.menuList = XEUtils.mapTree(options, (item, index2, items, path, parent) => {
        const objItem = Object.assign(Object.assign({}, item), { parentKey: parent ? parent.name || path.slice(0, path.length - 1).join(",") : "", level: path.length, itemKey: item.name || path.join(","), isExactActive: false, isActive: false, isExpand: XEUtils.isBoolean(item.expanded) ? item.expanded : !!expandAll, hasChild: item.children && item.children.length > 0 });
        return objItem;
      }, { children: "children", mapChildren: "childList" });
    };
    const updateCollapseStyle = () => {
      const { collapseFixed } = props;
      if (collapseFixed) {
        vue.nextTick(() => {
          const { isEnterCollapse } = reactData;
          const isCollapsed = computeIsCollapsed.value;
          const collapseEnterWidth = computeCollapseEnterWidth.value;
          const collapseWidth = computeCollapseWidth.value;
          const el = refElem.value;
          if (el) {
            const clientRect = el.getBoundingClientRect();
            const parentNode = el.parentNode;
            reactData.collapseStyle = isCollapsed ? {
              top: dom.toCssUnit(clientRect.top),
              left: dom.toCssUnit(clientRect.left),
              height: dom.toCssUnit(parentNode.clientHeight),
              width: isEnterCollapse ? collapseEnterWidth ? dom.toCssUnit(collapseEnterWidth) : "" : collapseWidth ? dom.toCssUnit(collapseWidth) : "",
              zIndex: reactData.collapseZindex
            } : {};
          }
        });
      }
    };
    const handleCollapseMenu = () => {
      const { collapseFixed } = props;
      if (collapseFixed) {
        const { initialized } = reactData;
        const isCollapsed = computeIsCollapsed.value;
        if (isCollapsed) {
          if (!initialized) {
            reactData.initialized = true;
            vue.nextTick(() => {
              const collapseEl = refCollapseElem.value;
              if (collapseEl) {
                document.body.appendChild(collapseEl);
              }
            });
          }
        }
        reactData.isEnterCollapse = false;
        updateZindex();
        updateCollapseStyle();
      }
    };
    const handleClickIconCollapse = (evnt, item, itemList) => {
      const { accordion } = props;
      const { hasChild, isExpand } = item;
      if (hasChild) {
        evnt.stopPropagation();
        evnt.preventDefault();
        if (accordion) {
          itemList.forEach((obj) => {
            if (obj !== item) {
              obj.isExpand = false;
            }
          });
        }
        item.isExpand = !isExpand;
      }
    };
    const emitModel = (value) => {
      reactData.activeName = value;
      emit("update:modelValue", value);
    };
    const handleContextmenuEvent = (evnt, item) => {
      const { menuConfig } = props;
      const menuOpts = computeMenuOpts.value;
      if (menuConfig ? utils.isEnableConf(menuOpts) : menuOpts.enabled) {
        const { options, visibleMethod } = menuOpts;
        if (!visibleMethod || visibleMethod({ $menu: $xeMenu, options, currentMenu: item })) {
          if (index_esm.VxeUI.contextMenu) {
            index_esm.VxeUI.contextMenu.openByEvent(evnt, {
              options,
              events: {
                optionClick(eventParams) {
                  const { option } = eventParams;
                  const gMenuOpts = menus.get(option.code);
                  const mmMethod = gMenuOpts ? gMenuOpts.menuMenuMethod : null;
                  const params = { menu: option, currentMenu: item, $event: evnt, $menu: $xeMenu };
                  if (mmMethod) {
                    mmMethod(params, evnt);
                  }
                  dispatchEvent("menu-click", params, eventParams.$event);
                }
              }
            });
          }
        }
      }
      dispatchEvent("option-menu", { currentMenu: item }, evnt);
    };
    const handleClickMenu = (evnt, item, itemList) => {
      const { itemKey, routerLink, hasChild } = item;
      if (routerLink) {
        emitModel(itemKey);
        handleMenuMouseleave();
      } else {
        if (hasChild) {
          handleClickIconCollapse(evnt, item, itemList);
        } else {
          emitModel(itemKey);
          handleMenuMouseleave();
        }
      }
      const params = {
        currentMenu: item,
        // 已废弃
        menu: item
      };
      dispatchEvent("click", params, evnt);
    };
    const handleMenuMouseenter = () => {
      const { collapseStyle } = reactData;
      const collapseEnterWidth = computeCollapseEnterWidth.value;
      reactData.collapseStyle = Object.assign({}, collapseStyle, {
        width: collapseEnterWidth ? dom.toCssUnit(collapseEnterWidth) : ""
      });
      reactData.isEnterCollapse = true;
    };
    const handleMenuMouseover = () => {
      const { isEnterCollapse } = reactData;
      if (!isEnterCollapse) {
        handleMenuMouseenter();
      }
    };
    const handleMenuMouseleave = () => {
      const { collapseStyle } = reactData;
      const el = refElem.value;
      reactData.collapseStyle = Object.assign({}, collapseStyle, {
        width: el ? dom.toCssUnit(el.offsetWidth) : ""
      });
      reactData.isEnterCollapse = false;
    };
    const callSlot = (slotFunc, params) => {
      if (slotFunc) {
        if (XEUtils.isString(slotFunc)) {
          slotFunc = slots[slotFunc] || null;
        }
        if (XEUtils.isFunction(slotFunc)) {
          return vn.getSlotVNs(slotFunc(params));
        }
      }
      return [];
    };
    const dispatchEvent = (type, params, evnt) => {
      emit(type, event.createEvent(evnt, { $menu: $xeMenu }, params));
    };
    const menuMethods = {
      dispatchEvent
    };
    const menuPrivateMethods = {};
    Object.assign($xeMenu, menuMethods, menuPrivateMethods);
    const renderMenuTitle = (item, itemList) => {
      const { icon, isExpand, hasChild } = item;
      const itemSlots = item.slots || {};
      const optionSlot = itemSlots.default || slots.option;
      const titleSlot = itemSlots.title || slots.optionTitle || slots["option-title"];
      const iconSlot = itemSlots.icon || slots.optionIcon || slots["option-icon"];
      const title = getMenuTitle(item);
      const isCollapsed = computeIsCollapsed.value;
      const params = {
        currentMenu: item,
        collapsed: isCollapsed,
        // 已废弃
        option: item
      };
      return [
        optionSlot ? index_esm.renderEmptyElement() : vue.h("div", {
          class: "vxe-menu--item-link-icon"
        }, iconSlot ? callSlot(iconSlot, params) : icon ? [vue.h("i", {
          class: icon
        })] : []),
        optionSlot ? vue.h("div", {
          class: "vxe-menu--item-custom-title"
        }, callSlot(optionSlot, params)) : vue.h("div", {
          class: "vxe-menu--item-link-title",
          title
        }, titleSlot ? callSlot(titleSlot, params) : title),
        hasChild ? vue.h("div", {
          class: "vxe-menu--item-link-collapse",
          onClick(evnt) {
            handleClickIconCollapse(evnt, item, itemList);
          }
        }, [
          vue.h("i", {
            class: isExpand ? getIcon().MENU_ITEM_EXPAND_OPEN : getIcon().MENU_ITEM_EXPAND_CLOSE
          })
        ]) : index_esm.renderEmptyElement()
      ];
    };
    const renderDefaultChildren = (item, itemList) => {
      const { itemKey, level, hasChild, isActive, isExactActive, isExpand, routerLink, childList } = item;
      const { isEnterCollapse } = reactData;
      const isCollapsed = computeIsCollapsed.value;
      if (item.permissionCode) {
        if (!permission.permission.checkVisible(item.permissionCode)) {
          return index_esm.renderEmptyElement();
        }
      }
      return vue.h("div", {
        key: itemKey,
        class: ["vxe-menu--item-wrapper", `vxe-menu--item-level${level}`, {
          "is--exact-active": isExactActive,
          "is--active": isActive,
          "is--expand": (!isCollapsed || isEnterCollapse) && isExpand
        }]
      }, [
        routerLink ? vue.h(vue.resolveComponent("router-link"), {
          class: "vxe-menu--item-link",
          to: routerLink,
          onContextmenu(evnt) {
            handleContextmenuEvent(evnt, item);
          },
          onClick(evnt) {
            handleClickMenu(evnt, item, itemList);
          }
        }, {
          default: () => renderMenuTitle(item, itemList)
        }) : vue.h("div", {
          class: "vxe-menu--item-link",
          onContextmenu(evnt) {
            handleContextmenuEvent(evnt, item);
          },
          onClick(evnt) {
            handleClickMenu(evnt, item, itemList);
          }
        }, renderMenuTitle(item, itemList)),
        hasChild ? vue.h("div", {
          class: "vxe-menu--item-group"
        }, childList.map((child) => renderDefaultChildren(child, childList))) : index_esm.renderEmptyElement()
      ]);
    };
    const renderCollapseChildren = (item, itemList) => {
      const { itemKey, level, hasChild, isActive, isExactActive, routerLink, childList } = item;
      if (item.permissionCode) {
        if (!permission.permission.checkVisible(item.permissionCode)) {
          return index_esm.renderEmptyElement();
        }
      }
      return vue.h("div", {
        key: itemKey,
        class: ["vxe-menu--item-wrapper", `vxe-menu--item-level${level}`, {
          "is--exact-active": isExactActive,
          "is--active": isActive
        }]
      }, [
        routerLink ? vue.h(vue.resolveComponent("router-link"), {
          class: "vxe-menu--item-link",
          to: routerLink,
          onContextmenu(evnt) {
            handleContextmenuEvent(evnt, item);
          },
          onClick(evnt) {
            handleClickMenu(evnt, item, itemList);
          }
        }, {
          default: () => renderMenuTitle(item, itemList)
        }) : vue.h("div", {
          class: "vxe-menu--item-link",
          onContextmenu(evnt) {
            handleContextmenuEvent(evnt, item);
          },
          onClick(evnt) {
            handleClickMenu(evnt, item, itemList);
          }
        }, renderMenuTitle(item, itemList)),
        hasChild ? vue.h("div", {
          class: "vxe-menu--item-group"
        }, childList.map((child) => renderDefaultChildren(child, childList))) : index_esm.renderEmptyElement()
      ]);
    };
    const renderVN = () => {
      const { loading, collapseFixed } = props;
      const { initialized, menuList, collapseStyle, isEnterCollapse } = reactData;
      const vSize = computeSize.value;
      const isCollapsed = computeIsCollapsed.value;
      let ons = {};
      if (collapseFixed) {
        ons = {
          onMouseenter: handleMenuMouseenter,
          onMouseover: handleMenuMouseover,
          onMouseleave: handleMenuMouseleave
        };
      }
      return vue.h("div", {
        ref: refElem,
        class: ["vxe-menu", {
          [`size--${vSize}`]: vSize,
          "is--collapsed": isCollapsed,
          "is--loading": loading
        }]
      }, [
        vue.h("div", {
          class: "vxe-menu--item-list"
        }, menuList.map((child) => isCollapsed ? renderCollapseChildren(child, menuList) : renderDefaultChildren(child, menuList))),
        initialized ? vue.h("div", Object.assign({ ref: refCollapseElem, class: ["vxe-menu--collapse-wrapper", {
          [`size--${vSize}`]: vSize,
          "is--collapsed": isCollapsed,
          "is--enter": isEnterCollapse,
          "is--loading": loading
        }], style: collapseStyle }, ons), [
          isCollapsed ? vue.h("div", {
            class: "vxe-menu--item-list"
          }, menuList.map((child) => renderDefaultChildren(child, menuList))) : index_esm.renderEmptyElement()
        ]) : index_esm.renderEmptyElement(),
        /**
         * 加载中
         */
        vue.h(index.VxeLoading, {
          class: "vxe-list-view--loading",
          modelValue: loading
        })
      ]);
    };
    const optFlag = vue.ref(0);
    vue.watch(() => props.options ? props.options.length : -1, () => {
      optFlag.value++;
    });
    vue.watch(() => props.options, () => {
      optFlag.value++;
    });
    vue.watch(optFlag, () => {
      updateMenuConfig();
      updateActiveMenu();
    });
    vue.watch(() => props.modelValue, (val) => {
      reactData.activeName = val;
    });
    vue.watch(() => reactData.activeName, () => {
      updateActiveMenu();
    });
    vue.watch(computeIsCollapsed, () => {
      handleCollapseMenu();
    });
    vue.onMounted(() => {
      const { menuConfig } = props;
      const VxeUIContextMenu = index_esm.VxeUI.getComponent("VxeContextMenu");
      if (menuConfig && !VxeUIContextMenu) {
        log.errLog("vxe.error.reqComp", ["vxe-context-menu"]);
      }
      event.globalEvents.on($xeMenu, "resize", updateCollapseStyle);
      updateCollapseStyle();
    });
    vue.onBeforeUnmount(() => {
      event.globalEvents.off($xeMenu, "resize");
      const collapseEl = refCollapseElem.value;
      if (collapseEl) {
        const parentNode = collapseEl.parentNode;
        if (parentNode) {
          parentNode.removeChild(collapseEl);
        }
      }
    });
    updateMenuConfig();
    updateActiveMenu();
    $xeMenu.renderVN = renderVN;
    return $xeMenu;
  },
  render() {
    return this.renderVN();
  }
});
exports.default = VxeMenuComponent;
