UNPKG

mui-nav-menu

Version:

Navigation menu component based on material ui

176 lines (175 loc) 6.66 kB
"use strict"; 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 react_1 = tslib_1.__importStar(require("react")); const MenuContext_1 = require("./contexts/MenuContext"); const useDidMountEffect_1 = require("./hooks/useDidMountEffect"); const useMenuNodes_1 = require("./hooks/useMenuNodes"); const MenuRoot_1 = tslib_1.__importDefault(require("./MenuRoot")); const utils_1 = require("./utils"); const NavMenu = ({ items: itemsProp, mode = "inline", inlineIndent = { base: 12, step: 12, }, openIds: openIdsProp, onOpenChange: onOpenChangeProp, onItemClick, defaultOpenIds, accordion, defaultSelectedIds, children, rootClassName, collapsed, popperClassName, disableSelection, checkSelectedFn, selectedIds: selectedIdsProp, onSelectedChange: onSelectedChangeProp, placement, defaultCollapseIcon, defaultExpandIcon, defaultPopupRootIcon, defaultPopupSubIcon, TransitionComponent = material_1.Grow, disableCloseOnSelect, trigger = "hover", arrow = true, enterDelay = 100, leaveDelay = 100, elevation = 2, linkComponent, prefixCls = "NavMenu", }) => { const restoredOpenIds = (0, react_1.useRef)(); const isClosedRef = (0, react_1.useRef)(true); const [openIds = [], setOpenIds] = (0, material_1.useControlled)({ name: "openIds", controlled: openIdsProp, default: defaultOpenIds, }); const openIdsRef = (0, react_1.useRef)([]); const { processItem, getChildrenIds, getNode, clearNodes, getDescendantIds, } = (0, useMenuNodes_1.useMenuNodes)(); const mergedMode = (0, react_1.useMemo)(() => { return collapsed && mode == "inline" ? "vertical" : mode; }, [mode, collapsed]); const handleOpenIds = (newOpenIds) => { openIdsRef.current = []; onOpenChangeProp && onOpenChangeProp(newOpenIds); setOpenIds(newOpenIds); }; const closeAll = () => { isClosedRef.current = true; handleOpenIds([]); }; const onInternalOpenChange = (0, material_1.useEventCallback)((id, open, idPaths) => { if (mergedMode == "inline" && accordion) { if (open) { handleOpenIds(idPaths); } else { handleOpenIds(openIdsRef.current.filter((openId) => openId != id)); } } else { let newOpenIds = openIdsRef.current.filter((openId) => openId != id); if (open) { if (idPaths.length > 1 && isClosedRef.current) { //Prevents direct ejection from second level if everything is closed return; } if (mergedMode == "inline") { newOpenIds.push(id); } else { newOpenIds = [...idPaths]; } isClosedRef.current = false; } else { //When closing, all child nodes need to be closed if (mergedMode != "inline") { const descendantIds = getDescendantIds(id); newOpenIds = newOpenIds.filter((id) => !descendantIds.includes(id)); } } handleOpenIds(newOpenIds); } }); const [focusedNodeId, setFocusedNodeId] = (0, react_1.useState)(); const [selectedIds = [], setSelectedIds] = (0, material_1.useControlled)({ name: "selectedIds", controlled: selectedIdsProp, default: defaultSelectedIds, }); const onSelectedChange = (newSelectedIds, closePopup) => { if (!disableSelection) { onSelectedChangeProp && onSelectedChangeProp(newSelectedIds); setSelectedIds(newSelectedIds); closePopup && setFocusedNodeId(null); } if (mergedMode != "inline" && closePopup && !disableCloseOnSelect) { closeAll(); } }; const contextValue = (0, react_1.useMemo)(() => { return { mode: mergedMode, inlineIndent, openIds, onInternalOpenChange, defaultOpenIds, popperClassName, collapsed, selectedIds, onSelectedChange, checkSelectedFn, TransitionComponent, onItemClick, getChildrenIds, getNode, focusedNodeId, setFocusedNodeId, elevation, arrow, placement, defaultCollapseIcon, defaultExpandIcon, defaultPopupRootIcon, defaultPopupSubIcon, prefixCls, trigger, linkComponent, enterDelay, leaveDelay, }; }, [ mergedMode, inlineIndent, openIds, defaultOpenIds, popperClassName, collapsed, selectedIds, onSelectedChange, checkSelectedFn, TransitionComponent, onItemClick, focusedNodeId, elevation, arrow, placement, defaultCollapseIcon, defaultExpandIcon, defaultPopupRootIcon, defaultPopupSubIcon, prefixCls, trigger, linkComponent, enterDelay, leaveDelay, ]); const itemNodes = (0, react_1.useMemo)(() => { return itemsProp ? (0, utils_1.parseItemsToNodes)(itemsProp) : null; }, [itemsProp]); (0, useDidMountEffect_1.useDidMountEffect)(() => { if (collapsed) { //store openids restoredOpenIds.current = [...openIdsRef.current]; handleOpenIds([]); } else { if (restoredOpenIds.current) { handleOpenIds(restoredOpenIds.current); restoredOpenIds.current = null; } } }, [collapsed]); const items = (0, react_1.useMemo)(() => { return children || itemNodes; }, [children, itemNodes]); (0, react_1.useEffect)(() => { clearNodes(); react_1.default.Children.forEach(items, (child, index) => { processItem(child, null, index); }); }, [items]); (0, react_1.useEffect)(() => { openIdsRef.current = openIds; isClosedRef.current = openIds.length == 0; }, [openIds]); return ((0, jsx_runtime_1.jsx)(MenuContext_1.MenuContext.Provider, { value: contextValue, children: (0, jsx_runtime_1.jsx)(MenuRoot_1.default, { className: rootClassName, children: items }) })); }; exports.default = NavMenu;