Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 | 2833x 2833x 2833x 3446x 3446x 3446x 3446x 3446x 3446x 3446x 3446x 3446x 3415x 3218x 197x 2833x 1820x 8x 1812x 1812x 1634x 1812x 1812x 1812x 1734x 1734x 1734x 1734x 2833x 2833x | import { useEffect, useState, useCallback, useMemo } from 'react';
import { useViewportRef } from './';
interface ViewportSize {
width: number;
height: number;
offsetLeft: number;
offsetTop: number;
clientRect: DOMRect | null;
isVisible: boolean;
}
/**
* Hook that provides viewport size dimensions and monitors for changes
* @param viewportId - The ID of the viewport to monitor
* @returns ViewportSize object containing width, height, and visibility info
*/
function useViewportSize(viewportId: string): ViewportSize {
const viewportElementRef = useViewportRef(viewportId);
const [size, setSize] = useState<ViewportSize>({
width: 0,
height: 0,
offsetLeft: 0,
offsetTop: 0,
clientRect: null,
isVisible: false,
});
// Update viewport dimensions
const updateViewportSize = useCallback(() => {
Iif (!viewportElementRef?.current) {
return;
}
const element = viewportElementRef.current;
const clientRect = element.getBoundingClientRect();
const newWidth = clientRect.width;
const newHeight = clientRect.height;
const newOffsetLeft = element.offsetLeft;
const newOffsetTop = element.offsetTop;
const newIsVisible = newWidth > 0 && newHeight > 0;
setSize(prevSize => {
if (
prevSize.width === newWidth &&
prevSize.height === newHeight &&
prevSize.offsetLeft === newOffsetLeft &&
prevSize.offsetTop === newOffsetTop &&
prevSize.isVisible === newIsVisible
) {
return prevSize;
}
return {
width: newWidth,
height: newHeight,
offsetLeft: newOffsetLeft,
offsetTop: newOffsetTop,
clientRect,
isVisible: newIsVisible,
};
});
}, [viewportElementRef]);
useEffect(() => {
if (!viewportId || !viewportElementRef?.current) {
return;
}
updateViewportSize();
const resizeObserver = new ResizeObserver(() => {
updateViewportSize();
});
resizeObserver.observe(viewportElementRef.current);
window.addEventListener('resize', updateViewportSize);
return () => {
window.removeEventListener('resize', updateViewportSize);
if (viewportElementRef.current) {
resizeObserver.unobserve(viewportElementRef.current);
}
resizeObserver.disconnect();
};
}, [viewportId, viewportElementRef, updateViewportSize]);
const memoizedSize = useMemo(() => size, [size]);
return memoizedSize;
}
export default useViewportSize;
export { useViewportSize };
|