import { defineComponent, computed, shallowRef, inject, ref, onMounted, watchEffect, watch, unref, createVNode, Fragment, Teleport } from 'vue';
import { uniq } from 'lodash-es';
import { EllipsisOutlined } from '@ant-design/icons-vue';
import '../../../utils/index.mjs';
import '../../../vue-components/vc-overflow/index.mjs';
import '../../../vue-components/transition/index.mjs';
import useStyle from '../style/index.mjs';
import useConfigInject from '../../config-provider/src/hooks/useConfigInject.mjs';
import { SiderCollapsedKey } from '../../layout/src/injectionKey.mjs';
import { useInjectOverride } from './OverrideContext.mjs';
import useItems from './hooks/useItems.mjs';
import { OVERFLOW_KEY, PathContext } from './hooks/useKeyPath.mjs';
import ASubMenu from './SubMenu.mjs';
import AMenuItem from './MenuItem.mjs';
import { useProvideFirstLevel, useProvideMenu, MenuContextProvider } from './hooks/useMenuContext.mjs';
import { menuProps } from './props.mjs';
import { devWarning } from '../../../utils/log.mjs';
import { shallowEqual } from '../../../utils/lang/shallowEqual.mjs';
import { collapseMotion } from '../../../vue-components/transition/src/collapseMotion.mjs';
import { cloneElement } from '../../../utils/vue/vnode.mjs';
import { flattenChildren } from '../../../utils/vue/props.mjs';
import Overflow from '../../../vue-components/vc-overflow/src/Overflow.mjs';

const EMPTY_LIST = [];
var AMenu = /* @__PURE__ */ defineComponent({
  compatConfig: {
    MODE: 3
  },
  name: "AMenu",
  inheritAttrs: false,
  props: menuProps(),
  slots: Object,
  setup(props, {
    slots,
    emit,
    attrs
  }) {
    const {
      direction,
      getPrefixCls
    } = useConfigInject("menu", props);
    const override = useInjectOverride();
    const prefixCls = computed(() => {
      var _a;
      return getPrefixCls("menu", props.prefixCls || ((_a = override == null ? void 0 : override.prefixCls) == null ? void 0 : _a.value));
    });
    const [wrapSSR, hashId] = useStyle(prefixCls, computed(() => {
      return !override;
    }));
    const store = shallowRef(/* @__PURE__ */ new Map());
    const siderCollapsed = inject(SiderCollapsedKey, ref(void 0));
    const inlineCollapsed = computed(() => {
      if (siderCollapsed.value !== void 0)
        return siderCollapsed.value;
      return props.inlineCollapsed;
    });
    const {
      itemsNodes
    } = useItems(props);
    const isMounted = shallowRef(false);
    onMounted(() => {
      isMounted.value = true;
    });
    watchEffect(() => {
      devWarning(!(props.inlineCollapsed === true && props.mode !== "inline"), "Menu", "`inlineCollapsed` should only be used when `mode` is inline.");
      devWarning(!(siderCollapsed.value !== void 0 && props.inlineCollapsed === true), "Menu", "`inlineCollapsed` not control Menu under Sider. Should set `collapsed` on Sider instead.");
    });
    const activeKeys = ref([]);
    const mergedSelectedKeys = ref([]);
    const keyMapStore = ref({});
    watch(store, () => {
      const newKeyMapStore = {};
      for (const menuInfo of store.value.values())
        newKeyMapStore[menuInfo.key] = menuInfo;
      keyMapStore.value = newKeyMapStore;
    }, {
      flush: "post"
    });
    watchEffect(() => {
      if (props.activeKey !== void 0) {
        let keys = [];
        const menuInfo = props.activeKey ? keyMapStore.value[props.activeKey] : void 0;
        if (menuInfo && props.activeKey !== void 0)
          keys = uniq([].concat(unref(menuInfo.parentKeys), props.activeKey));
        else
          keys = [];
        if (!shallowEqual(activeKeys.value, keys))
          activeKeys.value = keys;
      }
    });
    watch(() => props.selectedKeys, (selectedKeys) => {
      if (selectedKeys)
        mergedSelectedKeys.value = selectedKeys.slice();
    }, {
      immediate: true,
      deep: true
    });
    const selectedSubMenuKeys = ref([]);
    watch([keyMapStore, mergedSelectedKeys], () => {
      let subMenuParentKeys = [];
      mergedSelectedKeys.value.forEach((key) => {
        const menuInfo = keyMapStore.value[key];
        if (menuInfo)
          subMenuParentKeys = subMenuParentKeys.concat(unref(menuInfo.parentKeys));
      });
      subMenuParentKeys = uniq(subMenuParentKeys);
      if (!shallowEqual(selectedSubMenuKeys.value, subMenuParentKeys))
        selectedSubMenuKeys.value = subMenuParentKeys;
    }, {
      immediate: true
    });
    const mergedOpenKeys = ref([]);
    const mergedMode = ref("vertical");
    const triggerOpenKeys = (keys) => {
      mergedOpenKeys.value = keys;
      emit("update:openKeys", keys);
      emit("openChange", keys);
    };
    const triggerSelection = (info) => {
      if (props.selectable) {
        const {
          key: targetKey
        } = info;
        const exist = mergedSelectedKeys.value.includes(targetKey);
        let newSelectedKeys;
        if (props.multiple) {
          if (exist)
            newSelectedKeys = mergedSelectedKeys.value.filter((key) => key !== targetKey);
          else
            newSelectedKeys = [...mergedSelectedKeys.value, targetKey];
        } else {
          newSelectedKeys = [targetKey];
        }
        const selectInfo = {
          ...info,
          selectedKeys: newSelectedKeys
        };
        if (!shallowEqual(newSelectedKeys, mergedSelectedKeys.value)) {
          if (props.selectedKeys === void 0)
            mergedSelectedKeys.value = newSelectedKeys;
          emit("update:selectedKeys", newSelectedKeys);
          if (exist && props.multiple)
            emit("deselect", selectInfo);
          else
            emit("select", selectInfo);
        }
      }
      if (mergedMode.value !== "inline" && !props.multiple && mergedOpenKeys.value.length)
        triggerOpenKeys(EMPTY_LIST);
    };
    watch(() => props.openKeys, (openKeys = mergedOpenKeys.value) => {
      if (!shallowEqual(mergedOpenKeys.value, openKeys))
        mergedOpenKeys.value = openKeys.slice();
    }, {
      immediate: true,
      deep: true
    });
    let timeout;
    const changeActiveKeys = (keys) => {
      clearTimeout(timeout);
      timeout = setTimeout(() => {
        if (props.activeKey === void 0)
          activeKeys.value = keys;
        emit("update:activeKey", keys[keys.length - 1]);
      });
    };
    const disabled = computed(() => !!props.disabled);
    const isRtl = computed(() => direction.value === "rtl");
    const mergedInlineCollapsed = shallowRef(false);
    watchEffect(() => {
      var _a;
      if ((props.mode === "inline" || props.mode === "vertical") && inlineCollapsed.value) {
        mergedMode.value = "vertical";
        mergedInlineCollapsed.value = inlineCollapsed.value;
      } else {
        mergedMode.value = props.mode;
        mergedInlineCollapsed.value = false;
      }
      if ((_a = override == null ? void 0 : override.mode) == null ? void 0 : _a.value)
        mergedMode.value = override.mode.value;
    });
    const isInlineMode = computed(() => mergedMode.value === "inline");
    const inlineCacheOpenKeys = ref(mergedOpenKeys.value);
    const mountRef = shallowRef(false);
    watch(mergedOpenKeys, () => {
      if (isInlineMode.value)
        inlineCacheOpenKeys.value = mergedOpenKeys.value;
    }, {
      immediate: true
    });
    watch(isInlineMode, () => {
      if (!mountRef.value) {
        mountRef.value = true;
        return;
      }
      if (isInlineMode.value) {
        mergedOpenKeys.value = inlineCacheOpenKeys.value;
      } else {
        triggerOpenKeys(EMPTY_LIST);
      }
    }, {
      immediate: true
    });
    const className = computed(() => {
      return {
        [`${prefixCls.value}`]: true,
        [`${prefixCls.value}-root`]: true,
        [`${prefixCls.value}-${mergedMode.value}`]: true,
        [`${prefixCls.value}-inline-collapsed`]: mergedInlineCollapsed.value,
        [`${prefixCls.value}-rtl`]: isRtl.value,
        [`${prefixCls.value}-${props.theme}`]: true
      };
    });
    const rootPrefixCls = computed(() => getPrefixCls());
    const defaultMotions = computed(() => ({
      horizontal: {
        name: `${rootPrefixCls.value}-slide-up`
      },
      inline: collapseMotion(`${rootPrefixCls.value}-motion-collapse`),
      other: {
        name: `${rootPrefixCls.value}-zoom-big`
      }
    }));
    useProvideFirstLevel(true);
    const getChildrenKeys = (eventKeys = []) => {
      const keys = [];
      const storeValue = store.value;
      eventKeys.forEach((eventKey) => {
        const {
          key,
          childrenEventKeys
        } = storeValue.get(eventKey);
        keys.push(key, ...getChildrenKeys(unref(childrenEventKeys)));
      });
      return keys;
    };
    const onInternalClick = (info) => {
      var _a;
      emit("click", info);
      triggerSelection(info);
      (_a = override == null ? void 0 : override.onClick) == null ? void 0 : _a.call(override);
    };
    const onInternalOpenChange = (key, open) => {
      var _a;
      const childrenEventKeys = ((_a = keyMapStore.value[key]) == null ? void 0 : _a.childrenEventKeys) || [];
      let newOpenKeys = mergedOpenKeys.value.filter((k) => k !== key);
      if (open) {
        newOpenKeys.push(key);
      } else if (mergedMode.value !== "inline") {
        const subPathKeys = getChildrenKeys(unref(childrenEventKeys));
        newOpenKeys = uniq(newOpenKeys.filter((k) => !subPathKeys.includes(k)));
      }
      if (!shallowEqual(mergedOpenKeys, newOpenKeys))
        triggerOpenKeys(newOpenKeys);
    };
    const registerMenuInfo = (key, info) => {
      store.value.set(key, info);
      store.value = new Map(store.value);
    };
    const unRegisterMenuInfo = (key) => {
      store.value.delete(key);
      store.value = new Map(store.value);
    };
    const lastVisibleIndex = ref(0);
    const expandIcon = computed(() => {
      var _a;
      return props.expandIcon || slots.expandIcon || ((_a = override == null ? void 0 : override.expandIcon) == null ? void 0 : _a.value) ? (opt) => {
        let icon = props.expandIcon || slots.expandIcon;
        icon = typeof icon === "function" ? icon(opt) : icon;
        return cloneElement(icon, {
          class: `${prefixCls.value}-submenu-expand-icon`
        }, false);
      } : null;
    });
    useProvideMenu({
      prefixCls,
      activeKeys,
      openKeys: mergedOpenKeys,
      selectedKeys: mergedSelectedKeys,
      changeActiveKeys,
      disabled,
      rtl: isRtl,
      mode: mergedMode,
      inlineIndent: computed(() => props.inlineIndent),
      subMenuCloseDelay: computed(() => props.subMenuCloseDelay),
      subMenuOpenDelay: computed(() => props.subMenuOpenDelay),
      builtinPlacements: computed(() => props.builtinPlacements),
      triggerSubMenuAction: computed(() => props.triggerSubMenuAction),
      getPopupContainer: computed(() => props.getPopupContainer),
      inlineCollapsed: mergedInlineCollapsed,
      theme: computed(() => props.theme),
      siderCollapsed,
      defaultMotions: computed(() => isMounted.value ? defaultMotions.value : null),
      motion: computed(() => isMounted.value ? props.motion : null),
      overflowDisabled: shallowRef(void 0),
      onOpenChange: onInternalOpenChange,
      onItemClick: onInternalClick,
      registerMenuInfo,
      unRegisterMenuInfo,
      selectedSubMenuKeys,
      expandIcon,
      forceSubMenuRender: computed(() => props.forceSubMenuRender),
      rootClassName: hashId
    });
    return () => {
      var _a, _b;
      const childList = itemsNodes.value || flattenChildren((_a = slots.default) == null ? void 0 : _a.call(slots));
      const allVisible = lastVisibleIndex.value >= childList.length - 1 || mergedMode.value !== "horizontal" || props.disabledOverflow;
      const wrappedChildList = mergedMode.value !== "horizontal" || props.disabledOverflow ? childList : childList.map((child, index) => {
        return (
          // Always wrap provider to avoid sub node re-mount
          createVNode(MenuContextProvider, {
            "key": child.key,
            "overflowDisabled": index > lastVisibleIndex.value
          }, {
            default: () => child
          })
        );
      });
      const overflowedIndicator = ((_b = slots.overflowedIndicator) == null ? void 0 : _b.call(slots)) || createVNode(EllipsisOutlined, null, null);
      return wrapSSR(createVNode(Overflow, {
        ...attrs,
        "onMousedown": props.onMousedown,
        "prefixCls": `${prefixCls.value}-overflow`,
        "component": "ul",
        "itemComponent": AMenuItem,
        "class": [className.value, attrs.class, hashId.value],
        "role": "menu",
        "id": props.id,
        "data": wrappedChildList,
        "renderRawItem": (node) => node,
        "renderRawRest": (omitItems) => {
          const len = omitItems.length;
          const originOmitItems = len ? childList.slice(-len) : null;
          return createVNode(Fragment, null, [createVNode(ASubMenu, {
            "eventKey": OVERFLOW_KEY,
            "key": OVERFLOW_KEY,
            "title": overflowedIndicator,
            "disabled": allVisible,
            "internalPopupClose": len === 0
          }, {
            default: () => originOmitItems
          }), createVNode(PathContext, null, {
            default: () => [createVNode(ASubMenu, {
              "eventKey": OVERFLOW_KEY,
              "key": OVERFLOW_KEY,
              "title": overflowedIndicator,
              "disabled": allVisible,
              "internalPopupClose": len === 0
            }, {
              default: () => originOmitItems
            })]
          })]);
        },
        "maxCount": mergedMode.value !== "horizontal" || props.disabledOverflow ? Overflow.INVALIDATE : Overflow.RESPONSIVE,
        "ssr": "full",
        "data-menu-list": true,
        "onVisibleChange": (newLastIndex) => {
          lastVisibleIndex.value = newLastIndex;
        }
      }, {
        default: () => [createVNode(Teleport, {
          "to": "body"
        }, {
          default: () => [createVNode("div", {
            "style": {
              display: "none"
            },
            "aria-hidden": true
          }, [createVNode(PathContext, null, {
            default: () => [wrappedChildList]
          })])]
        })]
      }));
    };
  }
});

export { AMenu as default };
//# sourceMappingURL=Menu.mjs.map
