UNPKG

@ui5/webcomponents-react

Version:

React Wrapper for UI5 Web Components and additional components

86 lines (83 loc) 2.89 kB
import { useCallback, useEffect, useRef, useState } from 'react'; export const useObserveHeights = (pageRef, topHeaderRef, headerContentRef, [headerCollapsed, setHeaderCollapsed], { noHeader, fixedHeader = false, scrollTimeout = { current: 0 }, preserveHeaderStateOnScroll }) => { const [topHeaderHeight, setTopHeaderHeight] = useState(0); const [headerContentHeight, setHeaderContentHeight] = useState(0); const [isIntersecting, setIsIntersecting] = useState(true); const prevScrollTop = useRef(0); const onScroll = useCallback( // ToDo: Check how to properly memoize this callback so it supports React Compiler e => { const scrollDown = prevScrollTop.current <= e.target.scrollTop; prevScrollTop.current = e.target.scrollTop; if (scrollTimeout.current >= performance.now()) { return; } if (scrollDown && e.target.scrollTop >= headerContentHeight && !headerCollapsed) { setIsIntersecting(false); setHeaderCollapsed(true); } else if (!scrollDown && e.target.scrollTop <= topHeaderHeight + Math.max(0, headerContentHeight - topHeaderHeight) && headerCollapsed) { setIsIntersecting(true); setHeaderCollapsed(false); } }, [headerContentHeight, topHeaderHeight, headerCollapsed]); useEffect(() => { if (headerContentRef.current && headerCollapsed !== undefined) { setHeaderContentHeight(headerContentRef.current.getBoundingClientRect().height); } }, [headerCollapsed]); useEffect(() => { const page = pageRef.current; if (!fixedHeader && !preserveHeaderStateOnScroll) { page.addEventListener('scroll', onScroll); } return () => { page.removeEventListener('scroll', onScroll); }; }, [onScroll, fixedHeader, preserveHeaderStateOnScroll]); // top header useEffect(() => { const headerContentResizeObserver = new ResizeObserver(([entry]) => { const { blockSize } = entry.borderBoxSize[0]; setTopHeaderHeight(blockSize); }); if (topHeaderRef?.current) { headerContentResizeObserver.observe(topHeaderRef.current); } return () => { headerContentResizeObserver.disconnect(); }; }, []); // header content useEffect(() => { const headerContentResizeObserver = new ResizeObserver(([entry]) => { if (isIntersecting || fixedHeader) { const { blockSize } = entry.borderBoxSize[0]; setHeaderContentHeight(blockSize); } }); if (headerContentRef?.current) { headerContentResizeObserver.observe(headerContentRef.current); } return () => { headerContentResizeObserver.disconnect(); }; }, [isIntersecting, fixedHeader]); const totalHeaderHeight = noHeader ? 0 : topHeaderHeight + headerContentHeight; return { topHeaderHeight, headerContentHeight, totalHeaderHeight, headerCollapsed }; };