packageDocumentation module import * as React from "react" ; import { ResizeObserver } from "./ResizeObserverPolyfill" ; import { useRefEffect } from "./useRefEffect" ; import { useRefs } from "./useRefs" ; internal export function useResizeObserver < T extends Element > ( onResize ? ) { const [ bounds , setBounds ] = React . useState ( { width : 0 , height : 0 } ) ; const resizeObserver = React . useRef < ResizeObserver | null > ( null ) ; const rafRef = React . useRef ( 0 ) ; const isMountedRef = React . useRef ( false ) ; const owningWindowRef = React . useRef < any > ( null ) ; const resizeObserverCleanup = ( ) => { if ( rafRef . current ) owningWindowRef . current . cancelAnimationFrame ( rafRef . current ) ; resizeObserver . current ?. disconnect ( ) ; resizeObserver . current = null ; } ; React . useEffect ( ( ) => { isMountedRef . current = true ; return ( ) => { isMountedRef . current = false ; if ( rafRef . current ) owningWindowRef . current . cancelAnimationFrame ( rafRef . current ) ; owningWindowRef . current ?. removeEventListener ( "beforeunload" , resizeObserverCleanup ) ; } ; } , [ ] ) ; const processResize = React . useCallback ( ( target ) => { const newBounds = target . getBoundingClientRect ( ) ; if ( isMountedRef . current && ( bounds . width !== newBounds . width || bounds . height !== newBounds . height ) ) { setBounds ( newBounds ) ; onResize && onResize ( newBounds . width , newBounds . height ) ; } } , [ onResize , bounds . height , bounds . width ] ) ; const handleResize = React . useCallback ( ( entries ) => { if ( ! isMountedRef . current || ! Array . isArray ( entries ) || 0 === entries . length ) { return ; } const target = entries [ 0 ] . target as HTMLElement ; owningWindowRef . current && owningWindowRef . current . removeEventListener ( "beforeunload" , resizeObserverCleanup ) ; owningWindowRef . current = target . ownerDocument . defaultView ; if ( owningWindowRef . current ) { owningWindowRef . current . addEventListener ( "beforeunload" , resizeObserverCleanup ) ; rafRef . current = owningWindowRef . current . requestAnimationFrame ( ( ) => processResize ( target ) ) ; } } , [ processResize ] ) ; const observerRef = useRefEffect ( ( instance ) => { resizeObserver . current = new ResizeObserver ( handleResize ) ; if ( instance ) { resizeObserver . current . observe ( instance ) ; const newBounds = instance . getBoundingClientRect ( ) ; onResize && onResize ( newBounds . width , newBounds . height ) ; setBounds ( newBounds ) ; } return ( ) => { instance && ( resizeObserver . current ?. unobserve ( instance ) ) ; resizeObserver . current = null ; } ; } , [ handleResize , onResize ] ) ; const handleRef = React . useCallback ( ( instance ) => { const newBounds = instance && instance . getBoundingClientRect ( ) ; if ( newBounds && ( bounds . width !== newBounds . width || bounds . height !== newBounds . height ) ) { setBounds ( newBounds ) ; onResize && onResize ( newBounds . width , newBounds . height ) ; } } , [ bounds . height , bounds . width , onResize ] ) ; const ref = useRefs ( handleRef , observerRef ) ; return ref ; } internal export function useLayoutResizeObserver ( inElement , onResize ? ) { const inBoundingRect = inElement ?. getBoundingClientRect ( ) ; const [ bounds , setBounds ] = React . useState < { width ? : number ; height ? : number ; } > ( { width : inBoundingRect ?. width , height : inBoundingRect ?. height } ) ; const [ watchedElement , setWatchedElement ] = React . useState ( inElement ) ; const resizeObserver = React . useRef < ResizeObserver | null > ( null ) ; const rafRef = React . useRef ( 0 ) ; const isMountedRef = React . useRef ( false ) ; const owningWindowRef = React . useRef < any > ( null ) ; const resizeObserverCleanup = ( ) => { if ( rafRef . current ) owningWindowRef . current . cancelAnimationFrame ( rafRef . current ) ; resizeObserver . current ?. disconnect ( ) ; resizeObserver . current = null ; } ; React . useEffect ( ( ) => { isMountedRef . current = true ; setWatchedElement ( inElement ) ; if ( inElement ) { const newBounds = inElement . getBoundingClientRect ( ) ; onResize && onResize ( newBounds . width , newBounds . height ) ; setBounds ( newBounds ) ; } return ( ) => { isMountedRef . current = false ; ( rafRef . current && owningWindowRef . current ) && owningWindowRef . current . cancelAnimationFrame ( rafRef . current ) ; owningWindowRef . current && owningWindowRef . current . removeEventListener ( "beforeunload" , resizeObserverCleanup ) ; } ; } , [ onResize , inElement ] ) ; const processResize = React . useCallback ( ( target ) => { const newBounds = target . getBoundingClientRect ( ) ; if ( isMountedRef . current && ( bounds . width !== newBounds . width || bounds . height !== newBounds . height ) ) { onResize && onResize ( newBounds . width , newBounds . height ) ; setBounds ( newBounds ) ; } } , [ bounds . height , bounds . width , onResize ] ) ; const handleResize = React . useCallback ( ( entries ) => { if ( ! isMountedRef . current || ! Array . isArray ( entries ) || 0 === entries . length ) { return ; } const target = entries [ 0 ] . target as HTMLElement ; if ( owningWindowRef . current ) owningWindowRef . current . removeEventListener ( "beforeunload" , resizeObserverCleanup ) ; owningWindowRef . current = target . ownerDocument . defaultView ; if ( owningWindowRef . current ) { owningWindowRef . current . addEventListener ( "beforeunload" , resizeObserverCleanup ) ; rafRef . current = owningWindowRef . current . requestAnimationFrame ( ( ) => processResize ( target ) ) ; } } , [ processResize ] ) ; React . useLayoutEffect ( ( ) => { if ( ! watchedElement ) { return ; } resizeObserver . current = new ResizeObserver ( handleResize ) ; resizeObserver . current . observe ( watchedElement ) ; return ( ) => { resizeObserver . current ?. disconnect ( ) ; resizeObserver . current = null ; } ; } , [ handleResize , watchedElement ] ) ; return [ bounds . width , bounds . height ] ; } public export interface RenderPropsArgs { width ? : number ; height ? : number ; } public export function ElementResizeObserver ( { watchedElement , render } ) { const [ width , height ] = useLayoutResizeObserver ( watchedElement ) ; return render ( { width , height } ) ; } public export function ResizableContainerObserver ( { onResize , children } ) { const containerRef = React . useRef < HTMLDivElement > ( null ) ; const [ containerElement , setContainerElement ] = React . useState < HTMLElement | null > ( null ) ; const isMountedRef = React . useRef ( false ) ; const hasChildren = React . Children . count ( children ) !== 0 ; React . useEffect ( ( ) => { if ( ! isMountedRef . current && containerRef . current ) { isMountedRef . current = true ; const hasParent = ! ! containerRef . current . parentElement ; setContainerElement ( hasChildren && hasParent ? containerRef . current : containerRef . current . parentElement ) ; } } , [ hasChildren ] ) ; const processResize = React . useCallback ( ( width ? , height ? ) => { onResize ( width ?? 0 , height ?? 0 ) ; } , [ onResize ] ) ; useLayoutResizeObserver ( containerElement , processResize ) ; const style = hasChildren ? { width : "100%" , height : "100%" } : { display : "none" } ; return ( < div ref = { containerRef } className = "uicore-resizable-container" style = { style } > { hasChildren && children } < /div>); }