UNPKG

orcs-design-system

Version:
99 lines (94 loc) 4.22 kB
import { useState, useEffect, useCallback } from "react"; import { calculateDesktopWidth, calculateMobileHeight, applyResizeCursor, removeResizeCursor } from "../utils/resizeUtils"; /** * Custom hook to handle resize functionality for expanded panels * * Provides resize functionality for both desktop (horizontal) and mobile (vertical) * orientations with proper cursor management and event handling. * * @param {React.RefObject} expandedRef - Ref to the expanded panel * @param {boolean} isSmallScreen - Whether we're on a small screen * @param {number} expandedItem - Currently expanded item index * @param {Function} onWidthChange - Callback to update width state * @param {Object} currentItem - Current expanded item * @returns {Object} Object containing resize state and handlers */ const useResize = (expandedRef, isSmallScreen, expandedItem, onWidthChange, currentItem) => { const [isResizing, setIsResizing] = useState(false); const [hasResized, setHasResized] = useState(false); const [resizeStartY, setResizeStartY] = useState(0); const [resizeStartHeight, setResizeStartHeight] = useState(0); const handleResizeStart = useCallback(e => { e.preventDefault(); setIsResizing(true); setHasResized(false); // Reset resize flag applyResizeCursor(isSmallScreen); if (isSmallScreen && expandedRef.current) { setResizeStartY(e.clientY); setResizeStartHeight(expandedRef.current.offsetHeight); } }, [isSmallScreen, expandedRef]); const handleResizeMove = useCallback(e => { if (!isResizing || !expandedRef.current) { return; } // Mark that we've actually resized setHasResized(true); if (isSmallScreen) { // Vertical resizing for small screens const newHeight = calculateMobileHeight(e.clientY, resizeStartY, resizeStartHeight, currentItem); if (newHeight && !isNaN(newHeight)) { expandedRef.current.style.height = "".concat(newHeight, "px"); } } else { var _expandedRef$current; // Horizontal resizing for large screens // Find the SideNavItems element from the SideNavWrapper root const expandedPanel = (_expandedRef$current = expandedRef.current) === null || _expandedRef$current === void 0 ? void 0 : _expandedRef$current.parentElement; // Box const sideNavWrapper = expandedPanel === null || expandedPanel === void 0 ? void 0 : expandedPanel.parentElement; // SideNavWrapper const sideNavItems = sideNavWrapper === null || sideNavWrapper === void 0 ? void 0 : sideNavWrapper.querySelector('[data-testid="side-nav-items"]'); if (!sideNavItems) { console.warn("SideNavItems element not found for resize calculation"); return; } const newWidth = calculateDesktopWidth(e.clientX, sideNavItems, currentItem); // Update the width state through the callback if (onWidthChange && newWidth && !isNaN(newWidth)) { onWidthChange(newWidth); } } }, [isResizing, expandedRef, isSmallScreen, resizeStartY, resizeStartHeight, onWidthChange, currentItem]); const handleResizeEnd = useCallback(() => { setIsResizing(false); removeResizeCursor(); }, []); // Add global event listeners for resize useEffect(() => { if (isResizing) { const handleMouseMove = e => { handleResizeMove(e); }; document.addEventListener("mousemove", handleMouseMove); document.addEventListener("mouseup", handleResizeEnd); return () => { document.removeEventListener("mousemove", handleMouseMove); document.removeEventListener("mouseup", handleResizeEnd); }; } }, [isResizing, expandedItem, isSmallScreen, resizeStartY, resizeStartHeight, onWidthChange, handleResizeMove, handleResizeEnd]); // Clear inline height style when switching from mobile to desktop useEffect(() => { if (!isSmallScreen && expandedRef.current) { // Clear any inline height style to allow CSS height: inherit to take effect expandedRef.current.style.height = ""; } }, [isSmallScreen, expandedRef]); return { isResizing, hasResized, handleResizeStart, handleResizeMove, handleResizeEnd }; }; export default useResize;