orcs-design-system
Version:
TeamForm's Design System, aka: ORCS
99 lines (94 loc) • 4.22 kB
JavaScript
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;