mui-nav-menu
Version:
Navigation menu component based on material ui
150 lines (149 loc) • 5.69 kB
JavaScript
import { createElement as _createElement } from "react";
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
import { ChevronRight, ExpandLess, ExpandMore } from "@mui/icons-material";
import { ListItemButton, ListItemIcon, ListItemText, Tooltip, } from "@mui/material";
import classNames from "classnames";
import { forwardRef, memo, useMemo } from "react";
import { makeStyles } from "tss-react/mui";
import { useMenuContext } from "./contexts/MenuContext";
const useStyle = makeStyles()((theme) => ({
root: {
whiteSpace: "normal",
wordBreak: "break-all",
"&.Mui-selected": {
"&.isNested:not(.isMini)": {
color: theme.palette.primary.main,
fontWeight: "bold",
"&:not(:hover)": {
background: "none",
},
},
},
"&.isMini": {
"& .MuiListItemIcon-root": {
marginRight: 0,
},
},
},
noWrap: {
whiteSpace: "nowrap",
overflow: "hidden",
textOverflow: "ellipsis",
},
label: {
transition: "transform 300ms ease 0s, opacity 300ms ease 0s",
opacity: 1,
transform: "translate3d(0rem, 0, 0)",
},
icon: {
transition: "transform 300ms ease 0s, opacity 300ms ease 0s",
opacity: 1,
},
labelMini: {
opacity: 0,
overflow: "hidden",
transform: "translate3d(-1.5625rem, 0, 0)",
},
iconMini: {
opacity: 0,
},
tooltip: {
"& .MuiTooltip-tooltip": {
fontSize: 14,
"&.MuiTooltip-tooltipPlacementRight": {
margin: "0px 25px !important",
},
},
},
headerMini: {
textAlign: "center",
padding: 0,
},
focused: {
outline: "3px solid " + theme.palette.primary.main,
borderRadius: 4,
},
}));
const ListMenuItem = forwardRef((props, ref) => {
const { classes } = useStyle();
const { id, label, subIsOpen, onClick, inlineIndent, isSelected, collapsed, connectedIdPath, mode, disabled, hasChildren, link, Content, icon, linkComponent: linkComponentProp, className, isFocused, onMouseEnter, onMouseLeave, renderContent: renderContentProp, collapseIcon = _jsx(ExpandLess, {}), expandIcon = _jsx(ExpandMore, {}), popupRootIcon = (_jsx(ChevronRight, { style: { transform: "rotate(90deg)" } })), popupSubIcon = _jsx(ChevronRight, {}), } = props;
const { linkComponent } = useMenuContext();
const nestedLevel = useMemo(() => {
return connectedIdPath.length;
}, [connectedIdPath]);
const hasLink = link && !hasChildren;
const showLabel = !collapsed || nestedLevel > 1;
const linkProps = useMemo(() => {
if (typeof link == "object") {
return {
component: linkComponentProp ?? linkComponent,
href: link.url,
target: link.target ?? "_parent",
};
}
return {
component: linkComponentProp ?? linkComponent,
to: link,
};
}, [link]);
const inlineIndentPadding = useMemo(() => {
if (mode !== "inline") {
return undefined;
}
return nestedLevel > 1
? inlineIndent.step * (nestedLevel - 2) + inlineIndent.base
: undefined;
}, [nestedLevel, mode, inlineIndent]);
const renderArrow = () => {
if (!hasChildren) {
return null;
}
if (collapsed && nestedLevel == 1) {
return null;
}
if (mode == "inline") {
return subIsOpen ? collapseIcon : expandIcon;
}
if (nestedLevel == 1 && mode == "horizontal") {
return popupRootIcon;
}
return popupSubIcon;
};
const shouldUseTooltip = useMemo(() => {
return collapsed && nestedLevel == 1 && !hasChildren;
}, [collapsed, nestedLevel, hasChildren]);
const textClasses = classNames(classes.label, {
"Label-mini": !showLabel,
[classes.labelMini]: !showLabel,
});
const renderContent = () => {
if (Content) {
return (_jsx(Content, { ...{
nodeId: id,
isSelected,
itemProps: { textClasses, label },
} }));
}
if (renderContentProp) {
return renderContentProp({
nodeId: id,
isSelected,
itemProps: { textClasses, label },
});
}
return (_jsxs(_Fragment, { children: [icon && _jsx(ListItemIcon, { children: icon }), _jsx(ListItemText, { className: textClasses, primary: label })] }));
};
const listItemNode = (_createElement(ListItemButton, { disableRipple: true, ...(hasLink && linkProps), ref: ref, key: id, disableTouchRipple: true, tabIndex: -1, disabled: disabled, onMouseEnter: onMouseEnter, onMouseLeave: onMouseLeave, className: classNames(className, classes.root, classes.noWrap, {
isRoot: nestedLevel == 1,
isNested: hasChildren,
[classes.focused]: isFocused,
isFocused: isFocused,
isMini: collapsed && nestedLevel == 1,
}), selected: isSelected, style: {
paddingLeft: inlineIndentPadding,
}, onClick: onClick },
renderContent(),
hasChildren ? renderArrow() : null));
return (_jsx(Tooltip, { disableHoverListener: !shouldUseTooltip, classes: { popper: classes.tooltip }, title: label, arrow: true, placement: "right", children: listItemNode }));
});
export default memo(ListMenuItem);