import { useCallback , useEffect , useRef , useState } from "react" ; export function usePositionObserver ( target , active ) { const [ position , setPosition ] = useState < ClientRect > ( ) ; const onAnimationFrameHandler = useCallback ( ( ) => { const newPosition = target ?. getBoundingClientRect ( ) ; if ( shouldUpdatePosition ( newPosition , position ) ) { setPosition ( newPosition ) ; } } , [ position , target ] ) ; useAnimationFrameEffect ( active ? onAnimationFrameHandler : undefined ) ; return position ; } function useAnimationFrameEffect ( callback ? ) { const requestId = useRef < number | undefined > ( ) ; const onAnimationFrame = useCallback ( ( ) => { callback ! ( ) ; requestId . current = window . requestAnimationFrame ( onAnimationFrame ) ; } , [ callback ] ) ; useEffect ( ( ) => { if ( ! callback ) { return ; } requestId . current = window . requestAnimationFrame ( onAnimationFrame ) ; return ( ) => { window . cancelAnimationFrame ( requestId . current ! ) ; } ; } , [ callback , onAnimationFrame ] ) ; } function shouldUpdatePosition ( a ? , b ? ) { return ( ! a || ! b || a . height !== b . height || a . width !== b . width || a . bottom !== b . bottom || a . top !== b . top || a . left !== b . left || a . right !== b . right ) ; }