1- import { useRef , useCallback , useEffect , useMemo } from 'react' ;
1+ import { FunctionComponent , MouseEvent as ReactMouseEvent , ReactNode , useRef , useCallback , useEffect } from 'react' ;
22import { action } from 'mobx' ;
33// https://github.com/mobxjs/mobx-react#observer-batching
44import 'mobx-react/batchingForReactDom' ;
55import { observer } from 'mobx-react' ;
6- import ReactMeasure , { ContentRect } from 'react-measure ' ;
6+ import { debounce , getResizeObserver } from '@patternfly/ react-core ' ;
77import { css } from '@patternfly/react-styles' ;
88import styles from '../css/topology-components' ;
99import { State } from '../types' ;
@@ -16,72 +16,70 @@ interface VisualizationSurfaceProps {
1616 /** State to be passed to the controller */
1717 state ?: State ;
1818 /** Additional content rendered inside the surface */
19- children ?: React . ReactNode ;
19+ children ?: ReactNode ;
2020}
2121
22- const stopEvent = ( e : React . MouseEvent ) : void => {
22+ const stopEvent = ( e : ReactMouseEvent ) : void => {
2323 e . preventDefault ( ) ;
2424 e . stopPropagation ( ) ;
2525} ;
2626
27- const VisualizationSurface : React . FunctionComponent < VisualizationSurfaceProps > = ( {
28- state
29- } : VisualizationSurfaceProps ) => {
27+ const VisualizationSurface : FunctionComponent < VisualizationSurfaceProps > = ( { state } : VisualizationSurfaceProps ) => {
3028 const controller = useVisualizationController ( ) ;
31- const timerId = useRef < NodeJS . Timeout > ( null ) ;
29+ const unObserver = useRef < ( ) => void > ( null ) ;
3230
33- const debounceMeasure = useCallback ( ( func : ( contentRect : ContentRect ) => void , delay ?: number ) => {
34- return ( contentRect : ContentRect ) => {
35- if ( ! timerId . current ) {
36- func ( contentRect ) ;
31+ const measureRef = useCallback (
32+ ( ref : HTMLDivElement ) => {
33+ // Remove any previous observer
34+ if ( unObserver . current ) {
35+ unObserver . current ( ) ;
3736 }
38- clearTimeout ( timerId . current ) ;
3937
40- timerId . current = setTimeout ( ( ) => func ( contentRect ) , delay ) ;
38+ if ( ! ref ) {
39+ return ;
40+ }
41+
42+ const handleResize = action ( ( ) =>
43+ controller . getGraph ( ) . setDimensions ( new Dimensions ( ref . clientWidth , ref . clientHeight ) )
44+ ) ;
45+
46+ // Set size on initialization
47+ handleResize ( ) ;
48+
49+ const debounceResize = debounce ( handleResize , 100 ) ;
50+
51+ // Update graph size on resize events
52+ unObserver . current = getResizeObserver ( ref , debounceResize ) ;
53+ } ,
54+ [ controller ]
55+ ) ;
56+
57+ useEffect ( ( ) => {
58+ return ( ) => {
59+ if ( unObserver . current ) {
60+ unObserver . current ( ) ;
61+ }
4162 } ;
4263 } , [ ] ) ;
4364
4465 useEffect ( ( ) => {
4566 state && controller . setState ( state ) ;
4667 } , [ controller , state ] ) ;
4768
48- const onMeasure = useMemo (
49- ( ) =>
50- debounceMeasure (
51- action ( ( contentRect : ContentRect ) => {
52- controller . getGraph ( ) . setDimensions ( new Dimensions ( contentRect . client . width , contentRect . client . height ) ) ;
53- } ) ,
54- 100
55- ) ,
56- [ controller , debounceMeasure ]
57- ) ;
58-
59- // dispose of onMeasure
60- useEffect ( ( ) => ( ) => clearTimeout ( timerId . current ) , [ onMeasure ] ) ;
61-
6269 if ( ! controller . hasGraph ( ) ) {
6370 return null ;
6471 }
6572
6673 const graph = controller . getGraph ( ) ;
6774
68- // TODO: We need to replace react-measure as it doesn't support React 19. The following
69- // casting helps to get topology to build with React 19 versions
70- const Wrapper = ReactMeasure as any ;
71-
7275 return (
73- < Wrapper client onResize = { onMeasure } >
74- { ( { measureRef } : { measureRef : React . LegacyRef < any > } ) => (
75- < div data-test-id = "topology" className = { css ( styles . topologyVisualizationSurface ) } ref = { measureRef } >
76- { /* render an outer div because react-measure doesn't seem to fire events properly on svg resize */ }
77- < svg className = { css ( styles . topologyVisualizationSurfaceSvg ) } onContextMenu = { stopEvent } >
78- < SVGDefsProvider >
79- < ElementWrapper element = { graph } />
80- </ SVGDefsProvider >
81- </ svg >
82- </ div >
83- ) }
84- </ Wrapper >
76+ < div data-test-id = "topology" className = { css ( styles . topologyVisualizationSurface ) } ref = { measureRef } >
77+ < svg className = { css ( styles . topologyVisualizationSurfaceSvg ) } onContextMenu = { stopEvent } >
78+ < SVGDefsProvider >
79+ < ElementWrapper element = { graph } />
80+ </ SVGDefsProvider >
81+ </ svg >
82+ </ div >
8583 ) ;
8684} ;
8785
0 commit comments