UNPKG

orcs-design-system

Version:
137 lines (132 loc) 4.81 kB
import { useEffect, useRef, useMemo, useCallback } from "react"; import { findFirstExpandedByDefault } from "../utils/itemUtils"; import { getInitialSize as getInitialSizeUtil } from "../utils/resizeUtils"; import useResponsive from "./useResponsive"; import { useSideNavStateContext } from "../context/SideNavStateProvider"; import { useState } from "react"; /** * Custom hook to manage SideNavV2 state * @param {Array} items - Navigation items * @param {boolean} startExpanded - Whether the sidebar should start expanded * @returns {Object} Object containing all state and handlers */ const useSideNavState = function (items) { let startExpanded = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true; const { expandedItem, setExpandedItem, isExpanded, setIsExpanded, expandedWidth, setExpandedWidth } = useSideNavStateContext(); const { isSmallScreen } = useResponsive(); const expandedRef = useRef(null); const navItemRefs = useRef({}); const wrapperRef = useRef(null); const isExpandedRef = useRef(isExpanded); const [startedExpanded, setStartedExpanded] = useState(null); useEffect(() => { // first render or startExpanded changed? if (startedExpanded === null || startedExpanded !== startExpanded) { setStartedExpanded(startExpanded); if (startExpanded) { setIsExpanded(true); } else { setIsExpanded(false); } } }, [setIsExpanded, startExpanded, startedExpanded]); const firstExpandedItemByDefault = findFirstExpandedByDefault(items); // Initialize expanded item by default useEffect(() => { if (firstExpandedItemByDefault >= 0) { setExpandedItem(firstExpandedItemByDefault); } }, [firstExpandedItemByDefault, setExpandedItem]); // Set initial size when an item is expanded useEffect(() => { if (expandedItem !== null) { const currentItem = items[expandedItem]; const initialSize = getInitialSizeUtil(currentItem, isSmallScreen); setExpandedWidth(initialSize); } }, [expandedItem, items, setExpandedWidth, isSmallScreen]); // Focus on expanded item when it changes useEffect(() => { if (expandedItem !== null && expandedRef.current) { expandedRef.current.focus(); } }, [expandedItem]); // Update isExpandedRef when isExpanded changes useEffect(() => { isExpandedRef.current = isExpanded; }, [isExpanded]); const handleItemClick = useCallback(function (item) { let forceClose = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; const { index: itemIndex, actionType, onClick: onButtonClick } = item; if (actionType === "link" || actionType === "button") { // For link/button items, we need to handle related expanded panels if (actionType === "link") { // Find related expanded panels that should be opened for this route const relatedPanelIndex = items.findIndex(navItem => navItem.actionType === "component" && navItem.pageSpecific === true && navItem.hide !== true); if (relatedPanelIndex >= 0) { // If we're already on this panel, keep it open (don't toggle) if (expandedItem !== relatedPanelIndex) { setExpandedItem(relatedPanelIndex); } } else { // No related panel, close any open panel setExpandedItem(null); } } else { // For button items, just close any open panel setExpandedItem(null); } onButtonClick && onButtonClick(item); } else { // Component items: open the panel and keep it open (no toggle) // Exception: if forceClose is true (from close button), close the panel if (forceClose && expandedItem === itemIndex) { setExpandedItem(null); } else if (expandedItem !== itemIndex) { setExpandedItem(itemIndex); } onButtonClick && onButtonClick(item); } }, [expandedItem, setExpandedItem, items]); const handleBlur = useCallback(item => { handleItemClick(item); }, [handleItemClick]); const handleExpandToggle = useCallback(() => { // Simple toggle behavior const newExpandedState = !isExpanded; setIsExpanded(newExpandedState); }, [isExpanded, setIsExpanded]); const handleWidthChange = useCallback(newWidth => { setExpandedWidth(newWidth); }, [setExpandedWidth]); const isExpandedOnBigScreen = useMemo(() => { const result = isExpanded && !isSmallScreen; return result; }, [isExpanded, isSmallScreen]); return { expandedItem, isExpanded: isExpandedOnBigScreen, expandedWidth, expandedRef, navItemRefs, wrapperRef, handleItemClick, handleBlur, handleWidthChange, handleExpandToggle }; }; export default useSideNavState;