UNPKG

@hitachivantara/uikit-react-core

Version:
196 lines (195 loc) 7.32 kB
import { useControlled } from "../../hooks/useControlled.js"; import { uniqueId } from "../../utils/helpers.js"; import { getParentItemById } from "../NavigationSlider/utils.js"; import { VerticalNavigationContext } from "../VerticalNavigationContext.js"; import { NavigationPopupContainer } from "../NavigationPopup/NavigationPopupContainer.js"; import { HvVerticalNavigationSlider } from "../NavigationSlider/NavigationSlider.js"; import { HvVerticalNavigationTreeView } from "../TreeView/TreeView.js"; import { HvVerticalNavigationTreeViewItem } from "../TreeView/TreeViewItem.js"; import { useClasses } from "./Navigation.styles.js"; import { useDefaultProps } from "@hitachivantara/uikit-react-utils"; import { useCallback, useContext, useEffect, useMemo, useState } from "react"; import { jsx, jsxs } from "react/jsx-runtime"; //#region src/VerticalNavigation/Navigation/Navigation.tsx var createListHierarchy = (items, classes, mouseEnterHandler, disableTooltip = false) => items.map((item) => { const { id: itemId, label: itemLabel, icon, data: children, selectable, disabled, href, target } = item; const itemMouseEnterHandler = (event) => { mouseEnterHandler?.(event, item); }; return /* @__PURE__ */ jsx(HvVerticalNavigationTreeViewItem, { className: classes?.listItem, href, target, nodeId: itemId, label: itemLabel, icon, payload: item, selectable, disabled, onMouseEnter: itemMouseEnterHandler, disableTooltip, children: children ? createListHierarchy(children, classes, mouseEnterHandler, disableTooltip) : void 0 }, itemId); }); var getAllParents = (items) => { const parents = items.filter((item) => item.data != null && item.data.length > 0); const childParents = parents.flatMap((item) => getAllParents(item.data)); return [...parents, ...childParents]; }; function pathToElement(data, targetId) { const path = []; if (data != null && data.length > 0) for (let i = 0; i !== data.length; ++i) { const item = data[i]; if (item.id === targetId) { path.push(item.id); break; } const subPaths = pathToElement(item.data, targetId); if (subPaths.length > 0) { path.push(item.id); path.push(...subPaths); break; } } return path; } var HvVerticalNavigationTree = (props) => { const { id, className, classes: classesProp, data, mode = "navigation", collapsible = false, expanded: expandedProp, defaultExpanded, onToggle, selected: selectedProp, defaultSelected, onChange, sliderForwardButtonAriaLabel = "Navigate to submenu", ...others } = useDefaultProps("HvVerticalNavigationTree", props); const { classes, cx } = useClasses(classesProp); const [selected, setSelected] = useControlled(selectedProp, defaultSelected); const [expanded, setExpanded] = useControlled(expandedProp, () => { if (defaultExpanded === true) return getAllParents(data).map((item) => item.id); if (defaultExpanded === false) return []; if (defaultExpanded == null) { if (selected != null) return pathToElement(data, selected).slice(0, -1); return []; } return defaultExpanded; }); const { isOpen, useIcons, slider, parentItem, setParentItem, withParentData, navigateToChildHandler, setParentData, setParentSelected } = useContext(VerticalNavigationContext); const [navigationPopup, setNavigationPopup] = useState(null); const handleChange = useCallback((event, selectedId, selectedItem) => { if (useIcons && !isOpen && selectedItem.data) { const currentEventTarget = event.currentTarget; setNavigationPopup((prevState) => { return prevState?.anchorEl === currentEventTarget ? null : { uniqueKey: uniqueId(), anchorEl: currentEventTarget, fixedMode: true, data: selectedItem.data }; }); event.stopPropagation(); } else { setSelected(selectedId); setExpanded((prevState) => { if (!isOpen) return [...prevState, ...pathToElement(data, selectedId)]; return [...prevState]; }); setNavigationPopup(null); onChange?.(event, selectedItem); } }, [ onChange, setSelected, setExpanded, isOpen, useIcons, data ]); const treeViewItemMouseEnterHandler = useCallback((event, item) => { const isCollapsed = useIcons && !isOpen; if (isCollapsed && item.data && !navigationPopup?.fixedMode) { const currentEventTarget = event.currentTarget; setNavigationPopup?.({ uniqueKey: uniqueId(), anchorEl: currentEventTarget, fixedMode: false, data: item.data }); } else if (isCollapsed && !item.data && !navigationPopup?.fixedMode) setNavigationPopup(null); }, [ isOpen, useIcons, navigationPopup ]); const handleToggle = useCallback((event, newExpanded) => { setExpanded(newExpanded); onToggle?.(event, newExpanded); }, [onToggle, setExpanded]); const children = useMemo(() => data && createListHierarchy(data, classes, treeViewItemMouseEnterHandler, navigationPopup?.fixedMode), [ classes, data, navigationPopup, treeViewItemMouseEnterHandler ]); useEffect(() => { if (!isOpen) setNavigationPopup?.(null); }, [isOpen]); useEffect(() => { if (setParentSelected) setParentSelected(selected); }, [ selected, setSelected, setParentSelected ]); useEffect(() => { if (setParentData) setParentData(data); }, [data, setParentData]); useEffect(() => { if (withParentData && selected && setParentItem && getParentItemById(withParentData, selected)) setParentItem(getParentItemById(withParentData, selected)); }, [ withParentData, selected, setParentItem ]); const navigateToTargetHandler = (event, selectedItem) => handleChange(event, selectedItem.id, selectedItem); const handleNavigationPopupClose = () => setNavigationPopup(null); const handleStyledNavMouseLeave = () => { if (useIcons && !isOpen && !navigationPopup?.fixedMode) setNavigationPopup(null); }; const handleNavigationPopupMouseLeave = () => { if (!navigationPopup?.fixedMode) handleNavigationPopupClose(); }; const handleNavigationPopupChange = (event, selectedItem) => { handleChange(event, selectedItem.id, selectedItem); }; return /* @__PURE__ */ jsx("nav", { id, className: cx(classes.root, { [classes.collapsed]: !isOpen && !useIcons }, className), onMouseLeave: handleStyledNavMouseLeave, ...others, children: slider ? /* @__PURE__ */ jsx(HvVerticalNavigationSlider, { data: parentItem.data || withParentData, selected, onNavigateToTarget: navigateToTargetHandler, onNavigateToChild: navigateToChildHandler, forwardButtonAriaLabel: sliderForwardButtonAriaLabel }) : /* @__PURE__ */ jsxs(HvVerticalNavigationTreeView, { className: classes.list, selectable: true, mode, collapsible, selected, onChange: handleChange, expanded, onToggle: handleToggle, children: [useIcons && !isOpen && navigationPopup && /* @__PURE__ */ jsx(NavigationPopupContainer, { anchorEl: navigationPopup.anchorEl, onClose: handleNavigationPopupClose, className: classes.navigationPopup, children: /* @__PURE__ */ jsx(HvVerticalNavigationTree, { className: classes.popup, collapsible: true, defaultExpanded: true, selected, data: navigationPopup.data, onChange: handleNavigationPopupChange, onMouseLeave: handleNavigationPopupMouseLeave }) }, navigationPopup.uniqueKey), children] }) }); }; //#endregion export { HvVerticalNavigationTree };