diff --git a/packages/module/package.json b/packages/module/package.json index 4ec214f9..02399211 100644 --- a/packages/module/package.json +++ b/packages/module/package.json @@ -38,14 +38,12 @@ "@patternfly/react-styles": "^6.0.0", "@types/d3": "^7.4.0", "@types/d3-force": "^1.2.1", - "@types/react-measure": "^2.0.6", "d3": "^7.8.0", "@dagrejs/dagre": "1.1.2", "mobx": "^6.9.0", "mobx-react": "^7.6.0", "point-in-svg-path": "^1.0.1", "popper.js": "^1.16.1", - "react-measure": "^2.3.0", "tslib": "^2.0.0", "webcola": "3.4.0" }, diff --git a/packages/module/src/components/VisualizationSurface.tsx b/packages/module/src/components/VisualizationSurface.tsx index a5da9294..22ee595d 100644 --- a/packages/module/src/components/VisualizationSurface.tsx +++ b/packages/module/src/components/VisualizationSurface.tsx @@ -1,9 +1,9 @@ -import { useRef, useCallback, useEffect, useMemo } from 'react'; +import { FunctionComponent, MouseEvent as ReactMouseEvent, ReactNode, useRef, useCallback, useEffect } from 'react'; import { action } from 'mobx'; // https://github.com/mobxjs/mobx-react#observer-batching import 'mobx-react/batchingForReactDom'; import { observer } from 'mobx-react'; -import ReactMeasure, { ContentRect } from 'react-measure'; +import { debounce, getResizeObserver } from '@patternfly/react-core'; import { css } from '@patternfly/react-styles'; import styles from '../css/topology-components'; import { State } from '../types'; @@ -16,28 +16,49 @@ interface VisualizationSurfaceProps { /** State to be passed to the controller */ state?: State; /** Additional content rendered inside the surface */ - children?: React.ReactNode; + children?: ReactNode; } -const stopEvent = (e: React.MouseEvent): void => { +const stopEvent = (e: ReactMouseEvent): void => { e.preventDefault(); e.stopPropagation(); }; -const VisualizationSurface: React.FunctionComponent = ({ - state -}: VisualizationSurfaceProps) => { +const VisualizationSurface: FunctionComponent = ({ state }: VisualizationSurfaceProps) => { const controller = useVisualizationController(); - const timerId = useRef(null); + const unObserver = useRef<() => void>(null); - const debounceMeasure = useCallback((func: (contentRect: ContentRect) => void, delay?: number) => { - return (contentRect: ContentRect) => { - if (!timerId.current) { - func(contentRect); + const measureRef = useCallback( + (ref: HTMLDivElement) => { + // Remove any previous observer + if (unObserver.current) { + unObserver.current(); } - clearTimeout(timerId.current); - timerId.current = setTimeout(() => func(contentRect), delay); + if (!ref) { + return; + } + + const handleResize = action(() => + controller.getGraph().setDimensions(new Dimensions(ref.clientWidth, ref.clientHeight)) + ); + + // Set size on initialization + handleResize(); + + const debounceResize = debounce(handleResize, 100); + + // Update graph size on resize events + unObserver.current = getResizeObserver(ref, debounceResize); + }, + [controller] + ); + + useEffect(() => { + return () => { + if (unObserver.current) { + unObserver.current(); + } }; }, []); @@ -45,43 +66,20 @@ const VisualizationSurface: React.FunctionComponent = state && controller.setState(state); }, [controller, state]); - const onMeasure = useMemo( - () => - debounceMeasure( - action((contentRect: ContentRect) => { - controller.getGraph().setDimensions(new Dimensions(contentRect.client.width, contentRect.client.height)); - }), - 100 - ), - [controller, debounceMeasure] - ); - - // dispose of onMeasure - useEffect(() => () => clearTimeout(timerId.current), [onMeasure]); - if (!controller.hasGraph()) { return null; } const graph = controller.getGraph(); - // TODO: We need to replace react-measure as it doesn't support React 19. The following - // casting helps to get topology to build with React 19 versions - const Wrapper = ReactMeasure as any; - return ( - - {({ measureRef }: { measureRef: React.LegacyRef }) => ( -
- {/* render an outer div because react-measure doesn't seem to fire events properly on svg resize */} - - - - - -
- )} -
+
+ + + + + +
); }; diff --git a/yarn.lock b/yarn.lock index 523d3175..4be7028c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1979,7 +1979,7 @@ resolved "https://registry.yarnpkg.com/@babel/regjsgen/-/regjsgen-0.8.0.tgz#f0ba69b075e1f05fb2825b7fad991e7adbb18310" integrity sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA== -"@babel/runtime@^7.1.2", "@babel/runtime@^7.12.13", "@babel/runtime@^7.2.0": +"@babel/runtime@^7.1.2", "@babel/runtime@^7.12.13": version "7.20.13" resolved "https://registry.npmjs.org/@babel/runtime/-/runtime-7.20.13.tgz" integrity sha512-gt3PKXs0DBoL9xCvOIIZ2NEqAGZqHjAnmVbfQtB620V0uReIQutpel14KcneZuer7UioY8ALKZ7iocavvzTNFA== @@ -3403,13 +3403,6 @@ dependencies: "@types/react" "*" -"@types/react-measure@^2.0.6": - version "2.0.8" - resolved "https://registry.npmjs.org/@types/react-measure/-/react-measure-2.0.8.tgz" - integrity sha512-Pu4/hQ/1AKVN6efoawtcM+l376WYOI8e1fiM6ir4pdLkHilDCkJLjUGvAm0mWKJ0GE6hzu55yCrcJ/xNyEdFwA== - dependencies: - "@types/react" "*" - "@types/react-router-dom@^5.3.3": version "5.3.3" resolved "https://registry.yarnpkg.com/@types/react-router-dom/-/react-router-dom-5.3.3.tgz#e9d6b4a66fcdbd651a5f106c2656a30088cc1e83" @@ -8007,11 +8000,6 @@ get-intrinsic@^1.2.4: has-symbols "^1.0.3" hasown "^2.0.0" -get-node-dimensions@^1.2.1: - version "1.2.1" - resolved "https://registry.npmjs.org/get-node-dimensions/-/get-node-dimensions-1.2.1.tgz" - integrity sha512-2MSPMu7S1iOTL+BOa6K1S62hB2zUAYNF/lV0gSVlOaacd087lc6nR1H1r0e3B1CerTo+RceOmi1iJW+vp21xcQ== - get-package-type@^0.1.0: version "0.1.0" resolved "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz" @@ -12384,16 +12372,6 @@ react-lifecycles-compat@^3.0.4: resolved "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz" integrity sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA== -react-measure@^2.3.0: - version "2.5.2" - resolved "https://registry.npmjs.org/react-measure/-/react-measure-2.5.2.tgz" - integrity sha512-M+rpbTLWJ3FD6FXvYV6YEGvQ5tMayQ3fGrZhRPHrE9bVlBYfDCLuDcgNttYfk8IqfOI03jz6cbpqMRTUclQnaA== - dependencies: - "@babel/runtime" "^7.2.0" - get-node-dimensions "^1.2.1" - prop-types "^15.6.2" - resize-observer-polyfill "^1.5.0" - react-monaco-editor@^0.51.0: version "0.51.0" resolved "https://registry.yarnpkg.com/react-monaco-editor/-/react-monaco-editor-0.51.0.tgz#68d6afc912f7fcb7782e57b39889a5fd75fc0ceb" @@ -12859,11 +12837,6 @@ requires-port@^1.0.0: resolved "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz" integrity sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ== -resize-observer-polyfill@^1.5.0: - version "1.5.1" - resolved "https://registry.npmjs.org/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz" - integrity sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg== - resolve-cwd@^3.0.0: version "3.0.0" resolved "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz"