Skip to content

Commit 03e3ff3

Browse files
committed
chore: add _internalRenderSubMenuItem
1 parent 102534e commit 03e3ff3

File tree

4 files changed

+90
-47
lines changed

4 files changed

+90
-47
lines changed

src/Menu.tsx

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,14 @@ export interface MenuProps
121121
originNode: React.ReactElement,
122122
menuItemProps: any,
123123
) => React.ReactElement;
124+
/***
125+
* @private Only used for `pro-layout`. Do not use in your prod directly
126+
* and we do not promise any compatibility for this.
127+
*/
128+
_internalRenderSubMenuItem?: (
129+
originNode: React.ReactElement,
130+
subMenuItemProps: any,
131+
) => React.ReactElement;
124132
}
125133

126134
interface LegacyMenuProps extends MenuProps {
@@ -197,6 +205,7 @@ const Menu: React.FC<MenuProps> = props => {
197205

198206
// Internal
199207
_internalRenderMenuItem,
208+
_internalRenderSubMenuItem,
200209

201210
...restProps
202211
} = props as LegacyMenuProps;
@@ -444,8 +453,9 @@ const Menu: React.FC<MenuProps> = props => {
444453
const privateContext = React.useMemo(
445454
() => ({
446455
_internalRenderMenuItem,
456+
_internalRenderSubMenuItem,
447457
}),
448-
[_internalRenderMenuItem],
458+
[_internalRenderMenuItem, _internalRenderSubMenuItem],
449459
);
450460

451461
// ======================== Render ========================

src/SubMenu/index.tsx

Lines changed: 58 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import {
2626
useMeasure,
2727
} from '../context/PathContext';
2828
import { useMenuId } from '../context/IdContext';
29+
import PrivateContext from '../context/PrivateContext';
2930

3031
export interface SubMenuProps {
3132
style?: React.CSSProperties;
@@ -127,6 +128,8 @@ const InternalSubMenu = (props: SubMenuProps) => {
127128
onActive,
128129
} = React.useContext(MenuContext);
129130

131+
const { _internalRenderSubMenuItem } = React.useContext(PrivateContext);
132+
130133
const { isSubPathKey } = React.useContext(PathUserContext);
131134
const connectedPath = useFullPath();
132135

@@ -168,25 +171,27 @@ const InternalSubMenu = (props: SubMenuProps) => {
168171
}
169172
};
170173

171-
const onInternalMouseEnter: React.MouseEventHandler<HTMLLIElement> =
172-
domEvent => {
173-
triggerChildrenActive(true);
174+
const onInternalMouseEnter: React.MouseEventHandler<
175+
HTMLLIElement
176+
> = domEvent => {
177+
triggerChildrenActive(true);
174178

175-
onMouseEnter?.({
176-
key: eventKey,
177-
domEvent,
178-
});
179-
};
179+
onMouseEnter?.({
180+
key: eventKey,
181+
domEvent,
182+
});
183+
};
180184

181-
const onInternalMouseLeave: React.MouseEventHandler<HTMLLIElement> =
182-
domEvent => {
183-
triggerChildrenActive(false);
185+
const onInternalMouseLeave: React.MouseEventHandler<
186+
HTMLLIElement
187+
> = domEvent => {
188+
triggerChildrenActive(false);
184189

185-
onMouseLeave?.({
186-
key: eventKey,
187-
domEvent,
188-
});
189-
};
190+
onMouseLeave?.({
191+
key: eventKey,
192+
domEvent,
193+
});
194+
};
190195

191196
const mergedActive = React.useMemo(() => {
192197
if (active) {
@@ -317,6 +322,42 @@ const InternalSubMenu = (props: SubMenuProps) => {
317322
);
318323
}
319324

325+
// >>>>> List node
326+
let listNode = (
327+
<Overflow.Item
328+
role="none"
329+
{...restProps}
330+
component="li"
331+
style={style}
332+
className={classNames(
333+
subMenuPrefixCls,
334+
`${subMenuPrefixCls}-${mode}`,
335+
className,
336+
{
337+
[`${subMenuPrefixCls}-open`]: open,
338+
[`${subMenuPrefixCls}-active`]: mergedActive,
339+
[`${subMenuPrefixCls}-selected`]: childrenSelected,
340+
[`${subMenuPrefixCls}-disabled`]: mergedDisabled,
341+
},
342+
)}
343+
onMouseEnter={onInternalMouseEnter}
344+
onMouseLeave={onInternalMouseLeave}
345+
>
346+
{titleNode}
347+
348+
{/* Inline mode */}
349+
{!overflowDisabled && (
350+
<InlineSubMenuList id={popupId} open={open} keyPath={connectedPath}>
351+
{children}
352+
</InlineSubMenuList>
353+
)}
354+
</Overflow.Item>
355+
);
356+
357+
if (_internalRenderSubMenuItem) {
358+
listNode = _internalRenderSubMenuItem(listNode, props);
359+
}
360+
320361
// >>>>> Render
321362
return (
322363
<MenuContextProvider
@@ -325,34 +366,7 @@ const InternalSubMenu = (props: SubMenuProps) => {
325366
itemIcon={mergedItemIcon}
326367
expandIcon={mergedExpandIcon}
327368
>
328-
<Overflow.Item
329-
role="none"
330-
{...restProps}
331-
component="li"
332-
style={style}
333-
className={classNames(
334-
subMenuPrefixCls,
335-
`${subMenuPrefixCls}-${mode}`,
336-
className,
337-
{
338-
[`${subMenuPrefixCls}-open`]: open,
339-
[`${subMenuPrefixCls}-active`]: mergedActive,
340-
[`${subMenuPrefixCls}-selected`]: childrenSelected,
341-
[`${subMenuPrefixCls}-disabled`]: mergedDisabled,
342-
},
343-
)}
344-
onMouseEnter={onInternalMouseEnter}
345-
onMouseLeave={onInternalMouseLeave}
346-
>
347-
{titleNode}
348-
349-
{/* Inline mode */}
350-
{!overflowDisabled && (
351-
<InlineSubMenuList id={popupId} open={open} keyPath={connectedPath}>
352-
{children}
353-
</InlineSubMenuList>
354-
)}
355-
</Overflow.Item>
369+
{listNode}
356370
</MenuContextProvider>
357371
);
358372
};

src/context/PrivateContext.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import type { MenuProps } from '../Menu';
33

44
export interface PrivateContextProps {
55
_internalRenderMenuItem?: MenuProps['_internalRenderMenuItem'];
6+
_internalRenderSubMenuItem?: MenuProps['_internalRenderSubMenuItem'];
67
}
78

89
const PrivateContext = React.createContext<PrivateContextProps>({});

tests/Private.spec.js

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
import React from 'react';
33
import { mount } from 'enzyme';
44
import classnames from 'classnames';
5-
import Menu, { MenuItem } from '../src';
5+
import Menu, { MenuItem, SubMenu } from '../src';
66

77
describe('Private Props', () => {
88
it('_internalRenderMenuItem', () => {
@@ -18,7 +18,25 @@ describe('Private Props', () => {
1818
</Menu>,
1919
);
2020

21-
console.log(wrapper.html());
21+
expect(wrapper.exists('.inject-cls')).toBeTruthy();
22+
});
23+
24+
it('_internalRenderSubMenuItem', () => {
25+
const wrapper = mount(
26+
<Menu
27+
mode="inline"
28+
openKeys={['1']}
29+
_internalRenderSubMenuItem={node =>
30+
React.cloneElement(node, {
31+
className: classnames(node.props.className, 'inject-cls'),
32+
})
33+
}
34+
>
35+
<SubMenu key="1" title="1">
36+
<MenuItem key="1-1">1-1</MenuItem>
37+
</SubMenu>
38+
</Menu>,
39+
);
2240

2341
expect(wrapper.exists('.inject-cls')).toBeTruthy();
2442
});

0 commit comments

Comments
 (0)