@udixio/ui-react 2.9.22 → 2.9.24
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +32 -0
- package/dist/index.cjs +3 -3
- package/dist/index.js +2967 -2553
- package/dist/lib/components/AnchorPositioner.d.ts +2 -1
- package/dist/lib/components/AnchorPositioner.d.ts.map +1 -1
- package/dist/lib/components/ContextMenu.d.ts +15 -0
- package/dist/lib/components/ContextMenu.d.ts.map +1 -0
- package/dist/lib/components/Menu.d.ts +16 -0
- package/dist/lib/components/Menu.d.ts.map +1 -0
- package/dist/lib/components/MenuGroup.d.ts +12 -0
- package/dist/lib/components/MenuGroup.d.ts.map +1 -0
- package/dist/lib/components/MenuHeadline.d.ts +7 -0
- package/dist/lib/components/MenuHeadline.d.ts.map +1 -0
- package/dist/lib/components/MenuItem.d.ts +9 -0
- package/dist/lib/components/MenuItem.d.ts.map +1 -0
- package/dist/lib/components/TextField.d.ts +5 -1
- package/dist/lib/components/TextField.d.ts.map +1 -1
- package/dist/lib/components/index.d.ts +6 -2
- package/dist/lib/components/index.d.ts.map +1 -1
- package/dist/lib/interfaces/index.d.ts +1 -0
- package/dist/lib/interfaces/index.d.ts.map +1 -1
- package/dist/lib/interfaces/menu-group.interface.d.ts +13 -0
- package/dist/lib/interfaces/menu-group.interface.d.ts.map +1 -0
- package/dist/lib/interfaces/menu-item.interface.d.ts +34 -0
- package/dist/lib/interfaces/menu-item.interface.d.ts.map +1 -0
- package/dist/lib/interfaces/menu.interface.d.ts +17 -0
- package/dist/lib/interfaces/menu.interface.d.ts.map +1 -0
- package/dist/lib/interfaces/text-field.interface.d.ts +9 -1
- package/dist/lib/interfaces/text-field.interface.d.ts.map +1 -1
- package/dist/lib/styles/index.d.ts +3 -0
- package/dist/lib/styles/index.d.ts.map +1 -1
- package/dist/lib/styles/menu-group.style.d.ts +14 -0
- package/dist/lib/styles/menu-group.style.d.ts.map +1 -0
- package/dist/lib/styles/menu-headline.style.d.ts +19 -0
- package/dist/lib/styles/menu-headline.style.d.ts.map +1 -0
- package/dist/lib/styles/menu-item.style.d.ts +39 -0
- package/dist/lib/styles/menu-item.style.d.ts.map +1 -0
- package/dist/lib/styles/menu.style.d.ts +19 -0
- package/dist/lib/styles/menu.style.d.ts.map +1 -0
- package/dist/lib/styles/text-field.style.d.ts +19 -2
- package/dist/lib/styles/text-field.style.d.ts.map +1 -1
- package/package.json +3 -3
- package/src/lib/components/AnchorPositioner.tsx +61 -18
- package/src/lib/components/ContextMenu.tsx +111 -0
- package/src/lib/components/Menu.tsx +113 -0
- package/src/lib/components/MenuGroup.tsx +34 -0
- package/src/lib/components/MenuHeadline.tsx +9 -0
- package/src/lib/components/MenuItem.tsx +197 -0
- package/src/lib/components/TextField.tsx +206 -42
- package/src/lib/components/index.ts +7 -2
- package/src/lib/interfaces/index.ts +1 -0
- package/src/lib/interfaces/menu-group.interface.ts +13 -0
- package/src/lib/interfaces/menu-item.interface.ts +35 -0
- package/src/lib/interfaces/menu.interface.ts +20 -0
- package/src/lib/interfaces/text-field.interface.ts +9 -1
- package/src/lib/styles/index.ts +3 -0
- package/src/lib/styles/menu-group.style.ts +34 -0
- package/src/lib/styles/menu-headline.style.ts +20 -0
- package/src/lib/styles/menu-item.style.ts +53 -0
- package/src/lib/styles/menu.style.ts +32 -0
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import React, { useEffect, useRef, useState } from 'react';
|
|
2
|
+
import { AnchorPositioner } from './AnchorPositioner';
|
|
3
|
+
import { Menu } from './Menu';
|
|
4
|
+
// import { MenuProps } from '../interfaces/menu.interface'; // MenuProps is not exported from interface file usually, check file content
|
|
5
|
+
import { MenuInterface } from '../interfaces';
|
|
6
|
+
import { ReactProps } from '../utils';
|
|
7
|
+
|
|
8
|
+
// MenuInterface has props: MenuProps.
|
|
9
|
+
// But MenuProps might not be exported directly from the package index, so accessing it via MenuInterface['props'] is safer if we can't import it.
|
|
10
|
+
// Actually checking Step 1271, MenuProps IS exported.
|
|
11
|
+
|
|
12
|
+
export type ContextMenuProps = {
|
|
13
|
+
props: { trigger: React.ReactNode } & MenuInterface['props'];
|
|
14
|
+
type: 'div';
|
|
15
|
+
states: {
|
|
16
|
+
hasGroups: boolean;
|
|
17
|
+
};
|
|
18
|
+
elements: [''];
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export const ContextMenu = ({
|
|
22
|
+
trigger,
|
|
23
|
+
children,
|
|
24
|
+
onItemSelect,
|
|
25
|
+
...menuProps
|
|
26
|
+
}: ReactProps<ContextMenuProps>) => {
|
|
27
|
+
const [contextMenu, setContextMenu] = useState<{
|
|
28
|
+
mouseX: number;
|
|
29
|
+
mouseY: number;
|
|
30
|
+
} | null>(null);
|
|
31
|
+
const anchorRef = useRef<HTMLDivElement>(null);
|
|
32
|
+
|
|
33
|
+
const handleContextMenu = (event: React.MouseEvent) => {
|
|
34
|
+
event.preventDefault();
|
|
35
|
+
setContextMenu({
|
|
36
|
+
mouseX: event.clientX,
|
|
37
|
+
mouseY: event.clientY,
|
|
38
|
+
});
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
const handleClose = () => {
|
|
42
|
+
setContextMenu(null);
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
const handleSelect = (val: string | number) => {
|
|
46
|
+
handleClose();
|
|
47
|
+
onItemSelect?.(val);
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
useEffect(() => {
|
|
51
|
+
if (!contextMenu) return;
|
|
52
|
+
const handleOutsideInteraction = () => setContextMenu(null);
|
|
53
|
+
window.addEventListener('click', handleOutsideInteraction);
|
|
54
|
+
window.addEventListener('scroll', handleOutsideInteraction, true);
|
|
55
|
+
|
|
56
|
+
return () => {
|
|
57
|
+
window.removeEventListener('click', handleOutsideInteraction);
|
|
58
|
+
window.removeEventListener('scroll', handleOutsideInteraction, true);
|
|
59
|
+
};
|
|
60
|
+
}, [contextMenu]);
|
|
61
|
+
|
|
62
|
+
// Clone trigger if valid element to attach onContextMenu, otherwise wrap
|
|
63
|
+
const triggerElement = React.isValidElement(trigger) ? (
|
|
64
|
+
React.cloneElement(
|
|
65
|
+
trigger as React.ReactElement,
|
|
66
|
+
{
|
|
67
|
+
onContextMenu: (e: React.MouseEvent) => {
|
|
68
|
+
handleContextMenu(e);
|
|
69
|
+
// Call original handler if exists
|
|
70
|
+
(trigger as React.ReactElement).props.onContextMenu?.(e);
|
|
71
|
+
},
|
|
72
|
+
} as any,
|
|
73
|
+
)
|
|
74
|
+
) : (
|
|
75
|
+
<div onContextMenu={handleContextMenu} className="inline-block">
|
|
76
|
+
{trigger}
|
|
77
|
+
</div>
|
|
78
|
+
);
|
|
79
|
+
|
|
80
|
+
return (
|
|
81
|
+
<>
|
|
82
|
+
{triggerElement}
|
|
83
|
+
|
|
84
|
+
{/* Invisible anchor element positioned at cursor */}
|
|
85
|
+
<div
|
|
86
|
+
ref={anchorRef}
|
|
87
|
+
style={{
|
|
88
|
+
position: 'fixed',
|
|
89
|
+
top: contextMenu?.mouseY ?? 0,
|
|
90
|
+
left: contextMenu?.mouseX ?? 0,
|
|
91
|
+
width: 1,
|
|
92
|
+
height: 1,
|
|
93
|
+
pointerEvents: 'none',
|
|
94
|
+
visibility: 'hidden',
|
|
95
|
+
}}
|
|
96
|
+
/>
|
|
97
|
+
|
|
98
|
+
{contextMenu && (
|
|
99
|
+
<AnchorPositioner
|
|
100
|
+
anchorRef={anchorRef}
|
|
101
|
+
position="bottom right"
|
|
102
|
+
onClick={(e) => e.stopPropagation()}
|
|
103
|
+
>
|
|
104
|
+
<Menu onItemSelect={handleSelect} {...menuProps}>
|
|
105
|
+
{children}
|
|
106
|
+
</Menu>
|
|
107
|
+
</AnchorPositioner>
|
|
108
|
+
)}
|
|
109
|
+
</>
|
|
110
|
+
);
|
|
111
|
+
};
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import React, { useEffect, useRef } from 'react';
|
|
2
|
+
import { MenuInterface } from '../interfaces/menu.interface';
|
|
3
|
+
import { useMenuStyle } from '../styles/menu.style';
|
|
4
|
+
import { classNames } from '../utils';
|
|
5
|
+
import { ReactProps } from '../utils/component';
|
|
6
|
+
import { MenuItem } from './MenuItem';
|
|
7
|
+
import { Divider } from './Divider';
|
|
8
|
+
import { MenuHeadline } from './MenuHeadline';
|
|
9
|
+
import { MenuGroup } from './MenuGroup';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Menu displays a list of choices on a temporary surface.
|
|
13
|
+
* @status beta
|
|
14
|
+
* @category Selection
|
|
15
|
+
* @limitations
|
|
16
|
+
* - Don’t use MenuGroup in scrollable menus
|
|
17
|
+
* @devx
|
|
18
|
+
* - Used internally by `TextField` for `type="select"`.
|
|
19
|
+
* - Supports keyboard navigation and auto-scrolling to selected item.
|
|
20
|
+
* @a11y
|
|
21
|
+
* - `role="listbox"` with `aria-selected` management.
|
|
22
|
+
*/
|
|
23
|
+
export const Menu = ({
|
|
24
|
+
children,
|
|
25
|
+
selected,
|
|
26
|
+
onItemSelect,
|
|
27
|
+
className,
|
|
28
|
+
variant = 'standard',
|
|
29
|
+
...restProps
|
|
30
|
+
}: ReactProps<MenuInterface>) => {
|
|
31
|
+
/* pass restProps to include key such as variant */
|
|
32
|
+
const hasGroups = React.Children.toArray(children).some(
|
|
33
|
+
(child) => React.isValidElement(child) && child.type === MenuGroup,
|
|
34
|
+
);
|
|
35
|
+
const styles = useMenuStyle({
|
|
36
|
+
children,
|
|
37
|
+
selected,
|
|
38
|
+
onItemSelect,
|
|
39
|
+
className,
|
|
40
|
+
variant,
|
|
41
|
+
hasGroups,
|
|
42
|
+
...restProps,
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
const listRef = useRef<HTMLDivElement>(null);
|
|
46
|
+
|
|
47
|
+
// Scroll to selected item on open
|
|
48
|
+
useEffect(() => {
|
|
49
|
+
if (listRef.current) {
|
|
50
|
+
const selectedEl = listRef.current.querySelector(
|
|
51
|
+
'[aria-selected="true"]',
|
|
52
|
+
) as HTMLElement;
|
|
53
|
+
if (selectedEl) {
|
|
54
|
+
selectedEl.scrollIntoView({ block: 'nearest' });
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}, []);
|
|
58
|
+
|
|
59
|
+
const renderChildren = (nodes: React.ReactNode): React.ReactNode => {
|
|
60
|
+
return React.Children.map(nodes, (child) => {
|
|
61
|
+
if (!React.isValidElement(child)) return child;
|
|
62
|
+
|
|
63
|
+
// Handle MenuGroup: add surface styles if grouped
|
|
64
|
+
if (child.type === MenuGroup) {
|
|
65
|
+
const groupChildren = renderChildren((child.props as any).children);
|
|
66
|
+
return React.cloneElement(child, {
|
|
67
|
+
children: groupChildren,
|
|
68
|
+
variant: variant,
|
|
69
|
+
} as any);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
if (child.type === MenuItem) {
|
|
73
|
+
const childValue = (child.props as any).value;
|
|
74
|
+
const isSelected = Array.isArray(selected)
|
|
75
|
+
? selected.includes(childValue)
|
|
76
|
+
: selected === childValue;
|
|
77
|
+
|
|
78
|
+
return React.cloneElement(child, {
|
|
79
|
+
selected: isSelected,
|
|
80
|
+
variant: variant,
|
|
81
|
+
onItemSelect: (val: string | number) => {
|
|
82
|
+
onItemSelect?.(val);
|
|
83
|
+
},
|
|
84
|
+
} as any);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
if (child.type === MenuHeadline) {
|
|
88
|
+
return React.cloneElement(child, {
|
|
89
|
+
variant: variant,
|
|
90
|
+
} as any);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
if (child.type === Divider) {
|
|
94
|
+
return React.cloneElement(child, {
|
|
95
|
+
className: classNames('my-1', (child.props as any).className),
|
|
96
|
+
} as any);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
return child;
|
|
100
|
+
});
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
return (
|
|
104
|
+
<div ref={listRef} className={styles.menu} role="listbox" {...restProps}>
|
|
105
|
+
{renderChildren(children)}
|
|
106
|
+
{React.Children.count(children) === 0 && (
|
|
107
|
+
<div className="px-4 py-3 text-on-surface-variant opacity-60 italic text-body-medium">
|
|
108
|
+
No options
|
|
109
|
+
</div>
|
|
110
|
+
)}
|
|
111
|
+
</div>
|
|
112
|
+
);
|
|
113
|
+
};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { ReactProps } from '../utils/component';
|
|
3
|
+
import { useMenuGroupStyle } from '../styles/menu-group.style';
|
|
4
|
+
import { MenuGroupInterface } from '../interfaces/menu-group.interface';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* MenuGroup renders a group of menu items with persistent styling.
|
|
8
|
+
* It is primarily used to apply grouping logic or context to its children.
|
|
9
|
+
*
|
|
10
|
+
* @status beta
|
|
11
|
+
* @category Selection
|
|
12
|
+
*/
|
|
13
|
+
export const MenuGroup = ({
|
|
14
|
+
children,
|
|
15
|
+
className,
|
|
16
|
+
variant,
|
|
17
|
+
label,
|
|
18
|
+
...restProps
|
|
19
|
+
}: ReactProps<MenuGroupInterface> & React.HTMLAttributes<HTMLDivElement>) => {
|
|
20
|
+
const styles = useMenuGroupStyle({
|
|
21
|
+
children,
|
|
22
|
+
className,
|
|
23
|
+
variant,
|
|
24
|
+
label,
|
|
25
|
+
...restProps,
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
return (
|
|
29
|
+
<div className={styles.menuGroup} role="group" {...restProps}>
|
|
30
|
+
{label && <div className={styles.groupLabel}>{label}</div>}
|
|
31
|
+
{children}
|
|
32
|
+
</div>
|
|
33
|
+
);
|
|
34
|
+
};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { useMenuHeadlineStyle, MenuHeadlineInterface } from '../styles/menu-headline.style';
|
|
4
|
+
import { ReactProps } from '../utils';
|
|
5
|
+
|
|
6
|
+
export const MenuHeadline = ({ label, children, variant, className, ...restProps }: ReactProps<MenuHeadlineInterface> & { children?: React.ReactNode }) => {
|
|
7
|
+
const styles = useMenuHeadlineStyle({ variant, className });
|
|
8
|
+
return <div className={styles.headline} role="group" aria-label={label} {...restProps}>{children ?? label}</div>;
|
|
9
|
+
};
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
import React, { useRef, useState } from 'react';
|
|
2
|
+
import { Icon } from '../icon';
|
|
3
|
+
import { classNames, ReactProps } from '../utils';
|
|
4
|
+
import { MenuItemInterface } from '../interfaces/menu-item.interface';
|
|
5
|
+
import { useMenuItemStyle } from '../styles/menu-item.style';
|
|
6
|
+
import { faChevronRight } from '@fortawesome/free-solid-svg-icons';
|
|
7
|
+
import { AnchorPositioner } from './AnchorPositioner';
|
|
8
|
+
import { State } from '../effects';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Single item within a Menu.
|
|
12
|
+
* @status beta
|
|
13
|
+
* @category Selection
|
|
14
|
+
*/
|
|
15
|
+
export const MenuItem = ({
|
|
16
|
+
label,
|
|
17
|
+
children,
|
|
18
|
+
value,
|
|
19
|
+
leadingIcon,
|
|
20
|
+
trailingIcon,
|
|
21
|
+
disabled,
|
|
22
|
+
selected,
|
|
23
|
+
variant,
|
|
24
|
+
onClick,
|
|
25
|
+
onItemSelect, // Injected by Menu
|
|
26
|
+
className,
|
|
27
|
+
...restProps
|
|
28
|
+
}: ReactProps<MenuItemInterface>) => {
|
|
29
|
+
/* Extract subMenu from children if present */
|
|
30
|
+
let subMenuElement: React.ReactNode = null;
|
|
31
|
+
const contentChildren: React.ReactNode[] = [];
|
|
32
|
+
|
|
33
|
+
React.Children.forEach(children, (child) => {
|
|
34
|
+
// Check for Menu component via name (development) or if it has displayName 'Menu'
|
|
35
|
+
// We accept a child that is valid element and looks like a Menu.
|
|
36
|
+
if (
|
|
37
|
+
React.isValidElement(child) &&
|
|
38
|
+
((child.type as any)?.name === 'Menu' ||
|
|
39
|
+
(child.type as any)?.displayName === 'Menu')
|
|
40
|
+
) {
|
|
41
|
+
subMenuElement = child;
|
|
42
|
+
} else {
|
|
43
|
+
contentChildren.push(child);
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
const labelContent = contentChildren.length > 0 ? contentChildren : label;
|
|
48
|
+
|
|
49
|
+
const [isSubMenuOpen, setIsSubMenuOpen] = useState(false);
|
|
50
|
+
const itemRef = useRef<HTMLDivElement>(null);
|
|
51
|
+
const closeTimerRef = useRef<any>(null);
|
|
52
|
+
|
|
53
|
+
const styles = useMenuItemStyle({
|
|
54
|
+
variant,
|
|
55
|
+
disabled,
|
|
56
|
+
selected,
|
|
57
|
+
className,
|
|
58
|
+
value,
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
const handleClick = (e: React.MouseEvent) => {
|
|
62
|
+
if (disabled) {
|
|
63
|
+
e.preventDefault();
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
if (subMenuElement) {
|
|
68
|
+
e.stopPropagation();
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
onClick?.(e);
|
|
73
|
+
if (onItemSelect) {
|
|
74
|
+
onItemSelect(value);
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
const handleMouseEnter = () => {
|
|
79
|
+
if (closeTimerRef.current) {
|
|
80
|
+
clearTimeout(closeTimerRef.current);
|
|
81
|
+
closeTimerRef.current = null;
|
|
82
|
+
}
|
|
83
|
+
if (!disabled && subMenuElement) {
|
|
84
|
+
setIsSubMenuOpen(true);
|
|
85
|
+
}
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
const handleMouseLeave = () => {
|
|
89
|
+
if (subMenuElement) {
|
|
90
|
+
closeTimerRef.current = setTimeout(() => {
|
|
91
|
+
setIsSubMenuOpen(false);
|
|
92
|
+
}, 150); // Delay to allow diagonal movement
|
|
93
|
+
}
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
React.useEffect(() => {
|
|
97
|
+
return () => {
|
|
98
|
+
if (closeTimerRef.current) {
|
|
99
|
+
clearTimeout(closeTimerRef.current);
|
|
100
|
+
}
|
|
101
|
+
};
|
|
102
|
+
}, []);
|
|
103
|
+
|
|
104
|
+
const effectiveTrailingIcon =
|
|
105
|
+
trailingIcon ?? (subMenuElement ? faChevronRight : undefined);
|
|
106
|
+
|
|
107
|
+
return (
|
|
108
|
+
<div
|
|
109
|
+
ref={itemRef}
|
|
110
|
+
className={styles.menuItem} // Added relative and overflow-hidden for State
|
|
111
|
+
onClick={handleClick}
|
|
112
|
+
onMouseEnter={handleMouseEnter}
|
|
113
|
+
onMouseLeave={handleMouseLeave}
|
|
114
|
+
role="option"
|
|
115
|
+
aria-haspopup={!!subMenuElement}
|
|
116
|
+
aria-expanded={isSubMenuOpen}
|
|
117
|
+
aria-selected={selected}
|
|
118
|
+
tabIndex={disabled ? -1 : 0}
|
|
119
|
+
onKeyDown={(e) => {
|
|
120
|
+
// ... key handlers ...
|
|
121
|
+
if (e.key === 'Enter' || e.key === ' ') {
|
|
122
|
+
e.preventDefault();
|
|
123
|
+
if (subMenuElement) {
|
|
124
|
+
setIsSubMenuOpen(!isSubMenuOpen);
|
|
125
|
+
} else {
|
|
126
|
+
handleClick(e as any);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
if (e.key === 'ArrowRight' && subMenuElement) {
|
|
130
|
+
setIsSubMenuOpen(true);
|
|
131
|
+
e.stopPropagation();
|
|
132
|
+
}
|
|
133
|
+
if (e.key === 'ArrowLeft' && isSubMenuOpen) {
|
|
134
|
+
setIsSubMenuOpen(false);
|
|
135
|
+
e.stopPropagation();
|
|
136
|
+
}
|
|
137
|
+
}}
|
|
138
|
+
{...restProps}
|
|
139
|
+
>
|
|
140
|
+
<State
|
|
141
|
+
className="absolute inset-0 pointer-events-none"
|
|
142
|
+
colorName={classNames(
|
|
143
|
+
// Match text color for state layer usually
|
|
144
|
+
variant === 'vibrant' ? 'on-tertiary-container' : 'on-surface',
|
|
145
|
+
selected && 'on-secondary-container',
|
|
146
|
+
)}
|
|
147
|
+
stateClassName={'state-ripple-group-[menu-item]'}
|
|
148
|
+
/>
|
|
149
|
+
|
|
150
|
+
{leadingIcon && (
|
|
151
|
+
<div
|
|
152
|
+
className={classNames(
|
|
153
|
+
styles.itemIcon,
|
|
154
|
+
styles.leadingIcon,
|
|
155
|
+
'z-10 relative',
|
|
156
|
+
)}
|
|
157
|
+
>
|
|
158
|
+
{React.isValidElement(leadingIcon) ? (
|
|
159
|
+
leadingIcon
|
|
160
|
+
) : (
|
|
161
|
+
<Icon icon={leadingIcon} />
|
|
162
|
+
)}
|
|
163
|
+
</div>
|
|
164
|
+
)}
|
|
165
|
+
<span className={classNames(styles.itemLabel, 'z-10 relative')}>
|
|
166
|
+
{labelContent}
|
|
167
|
+
</span>
|
|
168
|
+
{effectiveTrailingIcon && (
|
|
169
|
+
<div
|
|
170
|
+
className={classNames(
|
|
171
|
+
styles.itemIcon,
|
|
172
|
+
styles.trailingIcon,
|
|
173
|
+
'z-10 relative',
|
|
174
|
+
)}
|
|
175
|
+
>
|
|
176
|
+
{React.isValidElement(effectiveTrailingIcon) ? (
|
|
177
|
+
effectiveTrailingIcon
|
|
178
|
+
) : (
|
|
179
|
+
<Icon icon={effectiveTrailingIcon} />
|
|
180
|
+
)}
|
|
181
|
+
</div>
|
|
182
|
+
)}
|
|
183
|
+
|
|
184
|
+
{subMenuElement && isSubMenuOpen && (
|
|
185
|
+
<AnchorPositioner
|
|
186
|
+
anchorRef={itemRef}
|
|
187
|
+
position="inline-end span-block-end"
|
|
188
|
+
hoverOpen={true}
|
|
189
|
+
>
|
|
190
|
+
<div onMouseEnter={handleMouseEnter} onMouseLeave={handleMouseLeave}>
|
|
191
|
+
{subMenuElement}
|
|
192
|
+
</div>
|
|
193
|
+
</AnchorPositioner>
|
|
194
|
+
)}
|
|
195
|
+
</div>
|
|
196
|
+
);
|
|
197
|
+
};
|