diff --git a/components/menu/src/Menu.tsx b/components/menu/src/Menu.tsx
index f9e8e7ef0..26d7a2dc4 100644
--- a/components/menu/src/Menu.tsx
+++ b/components/menu/src/Menu.tsx
@@ -13,7 +13,11 @@ import {
UnwrapRef,
} from 'vue';
import shallowEqual from '../../_util/shallowequal';
-import useProvideMenu, { StoreMenuInfo, useProvideFirstLevel } from './hooks/useMenuContext';
+import useProvideMenu, {
+ MenuContextProvider,
+ StoreMenuInfo,
+ useProvideFirstLevel,
+} from './hooks/useMenuContext';
import useConfigInject from '../../_util/hooks/useConfigInject';
import {
MenuTheme,
@@ -27,12 +31,17 @@ import devWarning from '../../vc-util/devWarning';
import { collapseMotion, CSSMotionProps } from '../../_util/transition';
import uniq from 'lodash-es/uniq';
import { SiderCollapsedKey } from '../../layout/injectionKey';
+import { flattenChildren } from '../../_util/props-util';
+import Overflow from '../../vc-overflow';
+import MenuItem from './MenuItem';
+import SubMenu from './SubMenu';
+import EllipsisOutlined from '@ant-design/icons-vue/EllipsisOutlined';
export const menuProps = {
prefixCls: String,
disabled: Boolean,
inlineCollapsed: Boolean,
- overflowDisabled: Boolean,
+ disabledOverflow: Boolean,
openKeys: Array,
selectedKeys: Array,
activeKey: String, // 内部组件使用
@@ -341,6 +350,8 @@ export default defineComponent({
store.value = { ...store.value };
};
+ const lastVisibleIndex = ref(0);
+
useProvideMenu({
store,
prefixCls,
@@ -362,7 +373,7 @@ export default defineComponent({
siderCollapsed,
defaultMotions: computed(() => (isMounted.value ? defaultMotions : null)),
motion: computed(() => (isMounted.value ? props.motion : null)),
- overflowDisabled: computed(() => props.overflowDisabled),
+ overflowDisabled: computed(() => props.disabledOverflow),
onOpenChange: onInternalOpenChange,
onItemClick: onInternalClick,
registerMenuInfo,
@@ -371,11 +382,66 @@ export default defineComponent({
isRootMenu: true,
});
return () => {
+ const childList = flattenChildren(slots.default?.());
+ const allVisible =
+ lastVisibleIndex.value >= childList.length - 1 ||
+ mergedMode.value !== 'horizontal' ||
+ props.disabledOverflow;
+ // >>>>> Children
+ const wrappedChildList =
+ mergedMode.value !== 'horizontal' || props.disabledOverflow
+ ? childList
+ : // Need wrap for overflow dropdown that do not response for open
+ childList.map((child, index) => (
+ // Always wrap provider to avoid sub node re-mount
+ index > lastVisibleIndex.value) }}
+ >
+ {child}
+
+ ));
+ const overflowedIndicator = ;
+
// data-hack-store-update 初步判断是 vue bug,先用hack方式
return (
-
+ node}
+ renderRawRest={omitItems => {
+ // We use origin list since wrapped list use context to prevent open
+ const len = omitItems.length;
+
+ const originOmitItems = len ? childList.slice(-len) : null;
+
+ return (
+
+ {originOmitItems}
+
+ );
+ }}
+ maxCount={
+ mergedMode.value !== 'horizontal' || props.disabledOverflow
+ ? Overflow.INVALIDATE
+ : Overflow.RESPONSIVE
+ }
+ ssr="full"
+ data-menu-list
+ onVisibleChange={newLastIndex => {
+ lastVisibleIndex.value = newLastIndex;
+ }}
+ />
);
};
},
diff --git a/components/menu/src/MenuItem.tsx b/components/menu/src/MenuItem.tsx
index 33b5a6f75..4608128ad 100644
--- a/components/menu/src/MenuItem.tsx
+++ b/components/menu/src/MenuItem.tsx
@@ -16,6 +16,7 @@ import Tooltip from '../../tooltip';
import { MenuInfo } from './interface';
import KeyCode from '../../_util/KeyCode';
import useDirectionStyle from './hooks/useDirectionStyle';
+import Overflow from '../../vc-overflow';
let indexGuid = 0;
const menuItemProps = {
@@ -200,7 +201,8 @@ export default defineComponent({
placement={rtl.value ? 'left' : 'right'}
overlayClassName={`${prefixCls.value}-inline-collapsed-tooltip`}
>
-
+
);
};
diff --git a/components/menu/src/SubMenu.tsx b/components/menu/src/SubMenu.tsx
index 38b97b93e..a641ad69b 100644
--- a/components/menu/src/SubMenu.tsx
+++ b/components/menu/src/SubMenu.tsx
@@ -19,6 +19,7 @@ import SubMenuList from './SubMenuList';
import InlineSubMenuList from './InlineSubMenuList';
import Transition, { getTransitionProps } from '../../_util/transition';
import { cloneElement } from '../../_util/vnode';
+import Overflow from '../../vc-overflow';
let indexGuid = 0;
@@ -30,6 +31,7 @@ const subMenuProps = {
popupClassName: String,
popupOffset: Array as PropType,
internalPopupClose: Boolean,
+ eventKey: String,
};
export type SubMenuProps = Partial>;
@@ -48,9 +50,10 @@ export default defineComponent({
instance.vnode.key !== null ? instance.vnode.key : `sub_menu_${++indexGuid}_$$_not_set_key`;
const eventKey =
- instance.vnode.key !== null
+ props.eventKey ??
+ (instance.vnode.key !== null
? `sub_menu_${++indexGuid}_$$_${instance.vnode.key}`
- : (key as string);
+ : (key as string));
const { parentEventKeys, parentInfo, parentKeys } = useInjectKeyPath();
const keysPath = computed(() => [...parentKeys.value, key]);
const eventKeysPath = computed(() => [...parentEventKeys.value, eventKey]);
@@ -291,7 +294,8 @@ export default defineComponent({
}
return (
-
)}
-
+
);
};
diff --git a/components/vc-overflow/Item.tsx b/components/vc-overflow/Item.tsx
index 7090f02bc..a45dd7021 100644
--- a/components/vc-overflow/Item.tsx
+++ b/components/vc-overflow/Item.tsx
@@ -12,6 +12,8 @@ import classNames from '../_util/classNames';
import { Key, VueNode } from '../_util/type';
import PropTypes from '../_util/vue-types';
+const UNDEFINED = undefined;
+
export default defineComponent({
name: 'Item',
props: {
@@ -57,16 +59,17 @@ export default defineComponent({
} = props;
const children = slots.default?.();
// ================================ Render ================================
- const childNode = renderItem && item !== undefined ? renderItem(item) : children;
+ const childNode = renderItem && item !== UNDEFINED ? renderItem(item) : children;
let overflowStyle: CSSProperties | undefined;
if (!invalidate) {
overflowStyle = {
opacity: mergedHidden.value ? 0 : 1,
- height: mergedHidden.value ? 0 : undefined,
- overflowY: mergedHidden.value ? 'hidden' : undefined,
- order: responsive ? order : undefined,
- pointerEvents: mergedHidden.value ? 'none' : undefined,
+ height: mergedHidden.value ? 0 : UNDEFINED,
+ overflowY: mergedHidden.value ? 'hidden' : UNDEFINED,
+ order: responsive ? order : UNDEFINED,
+ pointerEvents: mergedHidden.value ? 'none' : UNDEFINED,
+ position: mergedHidden.value ? 'absolute' : UNDEFINED,
};
}
diff --git a/components/vc-overflow/Overflow.tsx b/components/vc-overflow/Overflow.tsx
index d47d95535..54659d237 100644
--- a/components/vc-overflow/Overflow.tsx
+++ b/components/vc-overflow/Overflow.tsx
@@ -64,7 +64,7 @@ const Overflow = defineComponent({
renderRawRest: Function as PropType<(items: any[]) => VueNode>,
suffix: PropTypes.any,
component: String,
- itemComponent: String,
+ itemComponent: PropTypes.any,
/** @private This API may be refactor since not well design */
onVisibleChange: Function as PropType<(visibleCount: number) => void>,
/** When set to `full`, ssr will render full items by default and remove at client side */
diff --git a/components/vc-overflow/RawItem.tsx b/components/vc-overflow/RawItem.tsx
index 34af10394..65a5c1115 100644
--- a/components/vc-overflow/RawItem.tsx
+++ b/components/vc-overflow/RawItem.tsx
@@ -9,6 +9,7 @@ export default defineComponent({
inheritAttrs: false,
props: {
component: PropTypes.any,
+ title: PropTypes.any,
},
setup(props, { slots, attrs }) {
const context = useInjectOverflowContext();
diff --git a/components/vc-overflow/assets/index.less b/components/vc-overflow/assets/index.less
new file mode 100644
index 000000000..3480ae66c
--- /dev/null
+++ b/components/vc-overflow/assets/index.less
@@ -0,0 +1,15 @@
+@overflow-prefix-cls: rc-overflow;
+
+.@{overflow-prefix-cls} {
+ display: flex;
+ flex-wrap: wrap;
+ max-width: 100%;
+ position: relative;
+
+ &-item {
+ background: rgba(0, 255, 0, 0.2);
+ box-shadow: 0 0 1px black;
+ flex: none;
+ max-width: 100%;
+ }
+}
diff --git a/components/vc-overflow/examples/basic.tsx b/components/vc-overflow/examples/basic.tsx
index 511f276cd..508757b16 100644
--- a/components/vc-overflow/examples/basic.tsx
+++ b/components/vc-overflow/examples/basic.tsx
@@ -54,7 +54,7 @@ export default defineComponent({