@unicity/design-system
Version:
A comprehensive React component library built on Material-UI with advanced theming capabilities including neumorphism design support
108 lines • 5.43 kB
JavaScript
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
import React from 'react';
import { Menu as MuiMenu, MenuItem, MenuList, ListItemIcon, ListItemText, Divider, IconButton, Paper, ClickAwayListener, Popper, Grow, Fade, } from '@mui/material';
import { MoreVert } from '@mui/icons-material';
import { styled } from '@mui/material/styles';
const StyledMenu = styled(MuiMenu)(({ theme }) => ({
'& .MuiPaper-root': {
borderRadius: `calc(${theme.shape.borderRadius}px * 1.5)`,
marginTop: theme.spacing(1),
minWidth: 180,
boxShadow: theme.shadows[8],
'& .MuiMenuItem-root': {
padding: theme.spacing(1, 2),
borderRadius: theme.shape.borderRadius,
margin: theme.spacing(0.25, 1),
'&:hover': {
backgroundColor: theme.palette.action.hover,
},
'&.Mui-disabled': {
opacity: 0.5,
},
'& .MuiListItemIcon-root': {
minWidth: 36,
color: theme.palette.text.secondary,
},
'& .MuiListItemText-primary': {
fontSize: theme.typography.body2.fontSize,
},
'& .MuiListItemText-secondary': {
fontSize: theme.typography.caption.fontSize,
},
},
},
}));
const ContextMenuContainer = styled(Paper)(({ theme }) => ({
borderRadius: `calc(${theme.shape.borderRadius}px * 1.5)`,
minWidth: 180,
boxShadow: theme.shadows[8],
backgroundColor: theme.palette.background.paper,
border: `1px solid ${theme.palette.divider}`,
}));
const renderMenuItem = (item, index, onClose, showIconsColumn = false) => {
if (item.divider) {
return _jsx(Divider, { sx: { my: 0.5 } }, `divider-${index}`);
}
const handleClick = () => {
item.onClick?.();
onClose();
};
return (_jsxs(MenuItem, { onClick: handleClick, disabled: item.disabled, sx: {
...(item.color && item.color !== 'default' && {
color: `${item.color}.main`,
'& .MuiListItemIcon-root': {
color: `${item.color}.main`,
},
}),
}, children: [(item.icon || showIconsColumn) && (_jsx(ListItemIcon, { children: item.icon })), _jsx(ListItemText, { primary: item.label, secondary: item.secondary })] }, item.id));
};
export const Menu = ({ items, open, anchorEl, onClose, variant = 'dropdown', animation = 'fade', showIconsColumn = false, maxHeight = 300, ...props }) => {
const TransitionComponent = animation === 'grow' ? Grow : Fade;
if (variant === 'context') {
return (_jsx(Popper, { open: open, anchorEl: anchorEl, placement: "bottom-start", transition: true, disablePortal: true, children: ({ TransitionProps }) => (_jsx(TransitionComponent, { ...TransitionProps, children: _jsx(ContextMenuContainer, { children: _jsx(ClickAwayListener, { onClickAway: onClose, children: _jsx(MenuList, { autoFocusItem: open, sx: { py: 1, maxHeight, overflowY: 'auto' }, children: items.map((item, index) => renderMenuItem(item, index, onClose, showIconsColumn)) }) }) }) })) }));
}
return (_jsx(StyledMenu, { open: open, anchorEl: anchorEl, onClose: onClose, TransitionComponent: TransitionComponent, ...props, PaperProps: {
...props.PaperProps,
sx: {
maxHeight,
overflowY: 'auto',
...props.PaperProps?.sx,
},
}, children: items.map((item, index) => renderMenuItem(item, index, onClose, showIconsColumn)) }));
};
export const ContextMenu = ({ items, children, disabled = false, animation = 'fade', }) => {
const [contextMenu, setContextMenu] = React.useState(null);
const handleContextMenu = (event) => {
if (disabled)
return;
event.preventDefault();
setContextMenu(contextMenu === null
? {
mouseX: event.clientX + 2,
mouseY: event.clientY - 6,
}
: null);
};
const handleClose = () => {
setContextMenu(null);
};
return (_jsxs(_Fragment, { children: [_jsx("div", { onContextMenu: handleContextMenu, style: { cursor: disabled ? 'default' : 'context-menu' }, children: children }), _jsx(Menu, { open: contextMenu !== null, onClose: handleClose, variant: "context", animation: animation, anchorReference: "anchorPosition", anchorPosition: contextMenu !== null
? { top: contextMenu.mouseY, left: contextMenu.mouseX }
: undefined, items: items })] }));
};
export const MenuButton = ({ items, children, variant = 'icon', size = 'medium', disabled = false, buttonProps = {}, }) => {
const [anchorEl, setAnchorEl] = React.useState(null);
const open = Boolean(anchorEl);
const handleClick = (event) => {
setAnchorEl(event.currentTarget);
};
const handleClose = () => {
setAnchorEl(null);
};
if (variant === 'icon') {
return (_jsxs(_Fragment, { children: [_jsx(IconButton, { onClick: handleClick, size: size, disabled: disabled, ...buttonProps, children: children || _jsx(MoreVert, {}) }), _jsx(Menu, { items: items, open: open, anchorEl: anchorEl, onClose: handleClose })] }));
}
// For other variants, you could implement Button component here
return null;
};
//# sourceMappingURL=Menu.js.map