import { createMergedRef } from '@fluentui/react' ; import { CSSProperties , HTMLAttributes , PropsWithChildren , useCallback , useMemo , useRef } from 'react' ; import { forwardRef } from './with-display-name' ; export interface Size { width : number ; height : number ; } export interface ResizeObserverProps extends HTMLAttributes < HTMLDivElement > , PropsWithChildren < { } > { onResize : ( size : Size ) => void ; } export function useCallbackRef < TArgs extends any [ ] , R > ( callback ) { const ref = useRef < ( ... args : TArgs ) => R > ( callback ) ; ref . current = callback ; const wrapper = useCallback ( ( ... args ) => { return ref . current . apply ( undefined , args ) ; } , [ ] ) ; return wrapper ; } const iframeStyle = { position : 'absolute' , top : 0 , left : 0 , width : '100%' , height : '100%' , visibility : 'hidden' , } ; export const ResizeObserver = forwardRef < HTMLDivElement > ( 'ResizeObserver' ) ( ( { onResize , style , children , ... rest } , ref ) : JSX . Element | null => { const containerRef = useRef < HTMLDivElement | null > ( null ) ; const mergedRef = createMergedRef < HTMLDivElement | null > ( ) ( ref , containerRef ) ; const handleResize = useCallbackRef ( ( ) => { const { width , height } = containerRef . current ! . getBoundingClientRect ( ) ; onResize ( { width , height } ) ; } ) ; const handleIframeRef = useCallback ( ( element ) => { if ( element ) { element . contentWindow ! . addEventListener ( 'resize' , handleResize ) ; } } , [ ] ) ; const containerStyle = useMemo ( ( ) => { if ( ! style ) { return { position : 'relative' } ; } if ( ! style . position ) { return { ... style , position : 'relative' } ; } return style ; } , [ style ] ) ; return ( < div ref = { mergedRef } style = { containerStyle } { ... rest } > < iframe ref = { handleIframeRef } style = { iframeStyle } / > { children } < /div>); } ) ;