mui-nav-menu
Version:
Navigation menu component based on material ui
214 lines (213 loc) • 9.67 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
const tslib_1 = require("tslib");
const jsx_runtime_1 = require("react/jsx-runtime");
const material_1 = require("@mui/material");
const classnames_1 = tslib_1.__importDefault(require("classnames"));
const react_1 = require("react");
const react_dom_1 = require("react-dom");
const mui_1 = require("tss-react/mui");
const Arrow_1 = tslib_1.__importDefault(require("./Arrow"));
const MenuContext_1 = require("./contexts/MenuContext");
const PathContext_1 = tslib_1.__importStar(require("./contexts/PathContext"));
const ListMenuItem_1 = tslib_1.__importDefault(require("./ListMenuItem"));
const utils_1 = require("./utils");
const useStyle = (0, mui_1.makeStyles)()((theme) => ({
popper: {
"& .MuiListItemButton-root": {
minWidth: 200,
},
"&.NestedLevel-isRoot": {
"& .MuiPaper-root": {
marginLeft: 0,
},
'&[data-popper-placement*="right"]': {
"& .PopperArrow": {
left: -5,
},
"& .MuiPaper-root": {
marginLeft: 10,
},
},
'&[data-popper-placement*="left"]': {
"& .PopperArrow": {
right: -5,
},
"& .MuiPaper-root": {
marginRight: 10,
},
},
'&[data-popper-placement*="top"]': {
"& .PopperArrow": {
bottom: -5,
},
"& .MuiPaper-root": {
marginBottom: 10,
},
},
'&[data-popper-placement*="bottom"]': {
"& .PopperArrow": {
top: -5,
},
"& .MuiPaper-root": {
marginTop: 10,
},
},
},
},
paper: {
transformOrigin: "top left",
position: "relative",
zIndex: 1,
marginLeft: 10,
"& .PopperContent": {
background: theme.palette.background.paper,
overflowY: "auto",
maxHeight: 500,
padding: 5,
borderRadius: 10,
},
},
isSubMenuActive: {
background: (0, material_1.alpha)("#000000", 0.05),
},
}));
const SubMenu = (props) => {
const { openIds = [], selectedIds, checkSelectedFn, mode, collapsed, inlineIndent, onInternalOpenChange, onSelectedChange, popperClassName, TransitionComponent, onItemClick, focusedNodeId, elevation, arrow, defaultCollapseIcon, defaultExpandIcon, defaultPopupRootIcon, defaultPopupSubIcon, placement: placementProp, prefixCls, trigger, enterDelay, leaveDelay, } = (0, MenuContext_1.useMenuContext)();
const { classes } = useStyle();
const { id, children, ...rest } = props;
const connectedIdPath = (0, PathContext_1.useConnectedPath)(id);
// const { transitioning, transitionHandlers } = useTransitionState();
const isInlineMode = mode == "inline";
const [arrowRef, setArrowRef] = (0, react_1.useState)(null);
const subIsOpen = (0, react_1.useMemo)(() => {
return openIds.includes(id);
}, [openIds]);
const delayTimerRef = (0, react_1.useRef)();
const isSubMenuActive = subIsOpen && mode != "inline";
const isSelected = (0, react_1.useMemo)(() => {
if (checkSelectedFn) {
return checkSelectedFn(props);
}
return selectedIds ? selectedIds.includes(id) : false;
}, [selectedIds, checkSelectedFn]);
const [menuItemElement, setMenuItemElement] = (0, react_1.useState)(null);
const nestedLevel = (0, react_1.useMemo)(() => {
return connectedIdPath.length;
}, [connectedIdPath]);
const isRoot = nestedLevel == 1;
const setPopupVisible = (0, react_1.useCallback)((visible) => {
clearDelayTimer();
onInternalOpenChange &&
onInternalOpenChange(id, visible, connectedIdPath);
}, [connectedIdPath, onInternalOpenChange, openIds]);
const delaySetPopupVisible = (0, react_1.useCallback)((value, delayTime) => {
clearDelayTimer();
if (delayTime) {
delayTimerRef.current = setTimeout(() => {
setPopupVisible(value);
clearDelayTimer();
}, delayTime);
}
else {
setPopupVisible(value);
}
}, [openIds]);
const toggleInlineSubVisible = (0, react_1.useCallback)(() => {
onInternalOpenChange &&
onInternalOpenChange(id, !subIsOpen, connectedIdPath);
}, [openIds, id]);
const handleMouseEnter = (evt) => {
if (isRoot && trigger == "click") {
return;
}
delaySetPopupVisible(true, enterDelay);
};
const handleMouseLeave = (evt) => {
if (trigger == "click") {
return;
}
if (children) {
delaySetPopupVisible(false, leaveDelay);
}
};
const clearDelayTimer = () => {
if (delayTimerRef.current) {
clearTimeout(delayTimerRef.current);
delayTimerRef.current = null;
}
};
const handleItemClick = (0, material_1.useEventCallback)((event) => {
if (event.type !== "click") {
return;
}
if (!children) {
(0, react_dom_1.unstable_batchedUpdates)(() => {
onSelectedChange(connectedIdPath, true);
});
}
else {
if (mode == "inline") {
toggleInlineSubVisible();
}
else if (trigger == "click" && isRoot) {
setPopupVisible(!subIsOpen);
}
}
onItemClick && onItemClick(id, connectedIdPath, event);
});
const handleClickAway = () => {
setPopupVisible(false);
};
const placement = (0, react_1.useMemo)(() => {
if (placementProp && isRoot) {
return placementProp;
}
if (mode == "horizontal" && isRoot) {
return "bottom-start";
}
return "right-start";
}, [mode, isRoot, placementProp]);
const modifiers = (0, react_1.useMemo)(() => {
return [
{
name: "flip",
enabled: true,
},
{
name: "preventOverflow",
enabled: true,
options: {
boundariesElement: "viewport",
},
},
{
name: "arrow",
enabled: isRoot && arrow,
options: {
element: arrowRef,
},
},
];
}, [arrowRef, isRoot, arrow]);
const setMenuItemElementRef = (ele) => {
if (mode !== "inline") {
setTimeout(() => {
setMenuItemElement(ele);
}, 200);
}
};
return ((0, jsx_runtime_1.jsxs)("div", { className: (0, classnames_1.default)(prefixCls + "SubListItem-root", prefixCls + "ListItem-root"), ...(!isInlineMode && {
style: {
pointerEvents: rest.disabled ? "none" : undefined,
},
onMouseEnter: handleMouseEnter,
onMouseLeave: handleMouseLeave,
}), children: [(0, jsx_runtime_1.jsx)(ListMenuItem_1.default, { id: id, hasChildren: !!children, ref: setMenuItemElementRef, onClick: handleItemClick, inlineIndent: inlineIndent, subIsOpen: subIsOpen, isSelected: isSelected, collapsed: collapsed, mode: mode, isFocused: focusedNodeId == id, connectedIdPath: connectedIdPath, expandIcon: defaultExpandIcon, collapseIcon: defaultCollapseIcon, popupRootIcon: defaultPopupRootIcon, popupSubIcon: defaultPopupSubIcon, className: (0, classnames_1.default)({
isSubMenuActive: isSubMenuActive,
[classes.isSubMenuActive]: isSubMenuActive,
}), ...rest }), children && isInlineMode && ((0, jsx_runtime_1.jsx)(material_1.Collapse, { in: subIsOpen, timeout: "auto", unmountOnExit: true, children: (0, jsx_runtime_1.jsx)(material_1.List, { className: prefixCls + "SubList-root", component: "div", disablePadding: true, children: (0, jsx_runtime_1.jsx)(PathContext_1.default.Provider, { value: connectedIdPath, children: children }) }) })), children && !isInlineMode && ((0, jsx_runtime_1.jsx)(material_1.Popper, { className: (0, classnames_1.default)(classes.popper, popperClassName, "NestedLevel-" + nestedLevel, {
"NestedLevel-isRoot": nestedLevel == 1,
}), transition: true, anchorEl: menuItemElement, placement: placement, open: subIsOpen && !!menuItemElement, modifiers: modifiers, children: ({ TransitionProps }) => ((0, jsx_runtime_1.jsx)(utils_1.ConditionalWrapper, { condition: isRoot && trigger == "click", wrapper: (child) => ((0, jsx_runtime_1.jsx)(material_1.ClickAwayListener, { onClickAway: handleClickAway, children: (0, jsx_runtime_1.jsx)("div", { children: child }) })), children: (0, jsx_runtime_1.jsx)(TransitionComponent, { ...TransitionProps, children: (0, jsx_runtime_1.jsxs)(material_1.Paper, { elevation: elevation, className: classes.paper, children: [(0, jsx_runtime_1.jsx)("div", { className: "PopperContent", children: (0, jsx_runtime_1.jsx)(material_1.List, { component: "div", disablePadding: true, children: (0, jsx_runtime_1.jsx)(PathContext_1.default.Provider, { value: connectedIdPath, children: children }) }) }), isRoot && arrow && ((0, jsx_runtime_1.jsx)(Arrow_1.default, { elevation: elevation, ref: setArrowRef }))] }) }) })) }))] }));
};
exports.default = SubMenu;