|
1 | 1 | import MoreVertIcon from "@mui/icons-material/MoreVert"; |
2 | 2 | import { Divider, IconButton, ListItemIcon, ListItemText, Menu, MenuItem } from "@mui/material"; |
3 | 3 | import { styled } from "@mui/material/styles"; |
4 | | -import React from "react"; |
| 4 | +import { useState } from "react"; |
| 5 | + |
5 | 6 | const StyledListItemText = styled(ListItemText)(({ theme }) => ({ |
6 | 7 | color: theme.palette.text.primary, |
7 | 8 | })); |
8 | 9 |
|
9 | 10 | export default function BugItemMenu({ item, menuItems }) { |
10 | | - const [anchorEl, setAnchorEl] = React.useState(null); |
11 | | - const open = Boolean(anchorEl); |
| 11 | + const [anchorEl, setAnchorEl] = useState(null); |
| 12 | + const isOpen = Boolean(anchorEl); |
12 | 13 |
|
13 | | - const handleOpenMenuClick = (event) => { |
14 | | - setAnchorEl(event.currentTarget); |
| 14 | + // helper to stop event propagation and closing the menu |
| 15 | + const stopAndClose = (event) => { |
15 | 16 | event.stopPropagation(); |
16 | 17 | event.preventDefault(); |
17 | | - }; |
18 | | - |
19 | | - const handleClose = (event) => { |
20 | 18 | setAnchorEl(null); |
21 | | - event.stopPropagation(); |
22 | | - event.preventDefault(); |
23 | 19 | }; |
24 | 20 |
|
25 | | - const handleMenuItemClicked = (event, menuItem) => { |
26 | | - setAnchorEl(null); |
| 21 | + const handleOpen = (event) => { |
27 | 22 | event.stopPropagation(); |
28 | 23 | event.preventDefault(); |
29 | | - if (menuItem.disabled !== true && typeof menuItem.onClick === "function") { |
30 | | - menuItem.onClick(event, item); |
31 | | - } |
| 24 | + setAnchorEl(event.currentTarget); |
32 | 25 | }; |
33 | 26 |
|
34 | | - const parseDisabled = (disabledValue) => { |
35 | | - if (disabledValue === undefined) { |
36 | | - return false; |
37 | | - } |
| 27 | + const handleItemClick = (event, menuItem) => { |
| 28 | + const isDisabled = resolveValue(menuItem.disabled, item); |
38 | 29 |
|
39 | | - if (typeof disabledValue === "function") { |
40 | | - return disabledValue(item); |
41 | | - } |
| 30 | + stopAndClose(event); |
42 | 31 |
|
43 | | - return disabledValue; |
| 32 | + if (!isDisabled && typeof menuItem.onClick === "function") { |
| 33 | + menuItem.onClick(event, item); |
| 34 | + } |
44 | 35 | }; |
45 | 36 |
|
46 | | - const getIcon = (icon) => { |
47 | | - if (typeof icon === "function") { |
48 | | - return icon(item); |
49 | | - } |
50 | | - return icon; |
| 37 | + // generic helper to handle both static values and function-based props |
| 38 | + const resolveValue = (value, context) => { |
| 39 | + return typeof value === "function" ? value(context) : value; |
51 | 40 | }; |
52 | 41 |
|
53 | 42 | return ( |
54 | 43 | <div> |
55 | | - <IconButton |
56 | | - component="span" |
57 | | - sx={{ |
58 | | - padding: "4px", |
59 | | - }} |
60 | | - aria-label="menu" |
61 | | - aria-controls="long-menu" |
62 | | - aria-haspopup="true" |
63 | | - onClick={handleOpenMenuClick} |
64 | | - > |
| 44 | + <IconButton size="small" sx={{ padding: "4px" }} onClick={handleOpen}> |
65 | 45 | <MoreVertIcon /> |
66 | 46 | </IconButton> |
67 | | - <Menu anchorEl={anchorEl} open={open} onClose={handleClose}> |
68 | | - {menuItems |
69 | | - .filter((menuItem) => menuItem !== null) |
70 | | - .map((menuItem, index) => { |
71 | | - if (menuItem.title === "-") { |
72 | | - return <Divider key={index} />; |
73 | | - } else { |
74 | | - return ( |
75 | | - <MenuItem |
76 | | - onClick={(event) => handleMenuItemClicked(event, menuItem)} |
77 | | - key={index} |
78 | | - disabled={parseDisabled(menuItem.disabled)} |
79 | | - > |
80 | | - <ListItemIcon disabled={parseDisabled(menuItem.disabled)}> |
81 | | - {getIcon(menuItem.icon)} |
82 | | - </ListItemIcon> |
83 | | - <StyledListItemText primary={menuItem.title} /> |
84 | | - </MenuItem> |
85 | | - ); |
86 | | - } |
87 | | - })} |
| 47 | + |
| 48 | + <Menu anchorEl={anchorEl} open={isOpen} onClose={stopAndClose}> |
| 49 | + {menuItems.filter(Boolean).map((menuItem, index) => { |
| 50 | + // render divider for shorthand title |
| 51 | + if (menuItem.title === "-") { |
| 52 | + return <Divider key={`divider-${index}`} />; |
| 53 | + } |
| 54 | + |
| 55 | + const isDisabled = resolveValue(menuItem.disabled, item); |
| 56 | + const icon = resolveValue(menuItem.icon, item); |
| 57 | + |
| 58 | + return ( |
| 59 | + <MenuItem |
| 60 | + key={`menu-item-${index}`} |
| 61 | + onClick={(e) => handleItemClick(e, menuItem)} |
| 62 | + disabled={isDisabled} |
| 63 | + > |
| 64 | + {icon && <ListItemIcon>{icon}</ListItemIcon>} |
| 65 | + <StyledListItemText primary={menuItem.title} /> |
| 66 | + </MenuItem> |
| 67 | + ); |
| 68 | + })} |
88 | 69 | </Menu> |
89 | 70 | </div> |
90 | 71 | ); |
|
0 commit comments