diff --git a/__tests__/src/extend/withSize.test.js b/__tests__/src/extend/withSize.test.js
new file mode 100644
index 0000000000..ece8055b56
--- /dev/null
+++ b/__tests__/src/extend/withSize.test.js
@@ -0,0 +1,50 @@
+import { render, screen } from '@testing-library/react';
+import PropTypes from 'prop-types';
+import { withSize } from '../../../src/extend/withSize';
+
+/** Mock ResizeObserver */
+class ResizeObserver {
+ /** */
+ constructor(callback) {
+ this.callback = callback;
+ }
+
+ /** */
+ observe(element) {
+ // Fake a resize event
+ setTimeout(() => {
+ this.callback([{ contentRect: { height: 300, width: 400 } }]);
+ }, 0);
+ }
+
+ /** */
+ disconnect() { jest.fn(); } // eslint-disable-line
+}
+
+// Replace the global ResizeObserver with the mock
+global.ResizeObserver = ResizeObserver;
+
+/** */
+const TestComponent = ({ size }) => (
+
+ {size.width}
+ {size.height}
+
+);
+
+TestComponent.propTypes = {
+ size: PropTypes.shape({
+ height: PropTypes.number,
+ width: PropTypes.number,
+ }).isRequired,
+};
+
+const WrappedTestComponent = withSize()(TestComponent);
+
+test('it should render with size', async () => {
+ render();
+
+ // Assert that the updated size is reflected
+ expect(await screen.findByText(/400/)).toBeInTheDocument();
+ expect(await screen.findByText(/300/)).toBeInTheDocument();
+});
diff --git a/package.json b/package.json
index cbc145d4ef..aca9e491d0 100644
--- a/package.json
+++ b/package.json
@@ -68,7 +68,6 @@
"react-redux": "^8.0.0 || ^9.0.0",
"react-resize-observer": "^1.1.1",
"react-rnd": "^10.1",
- "react-sizeme": "^2.6.7 || ^3.0.0",
"react-virtualized-auto-sizer": "^1.0.2",
"react-window": "^1.8.5",
"redux": "^5.0.0",
diff --git a/setupJest.js b/setupJest.js
index d5a0664075..af9f272bcf 100644
--- a/setupJest.js
+++ b/setupJest.js
@@ -1,18 +1,22 @@
/* eslint-disable import/no-extraneous-dependencies */
import fetchMock from 'jest-fetch-mock';
-import sizeMe from 'react-sizeme';
import i18next from 'i18next';
import { setupIntersectionMocking } from 'react-intersection-observer/test-utils';
import en from './src/locales/en/translation.json';
jest.setTimeout(10000);
-sizeMe.noPlaceholders = true;
-
const { TextEncoder } = require('util');
global.TextEncoder = TextEncoder;
+// Mock the browser's native ResizeObserver
+global.ResizeObserver = jest.fn().mockImplementation(() => ({
+ disconnect: jest.fn(),
+ observe: jest.fn(),
+ unobserve: jest.fn(),
+}));
+
// Setup Jest to mock fetch
fetchMock.enableMocks();
diff --git a/src/components/CompanionWindow.js b/src/components/CompanionWindow.js
index 8a31ce2fb1..3b0d04e28d 100644
--- a/src/components/CompanionWindow.js
+++ b/src/components/CompanionWindow.js
@@ -1,4 +1,4 @@
-import { Children, cloneElement, Component } from 'react';
+import { Children, cloneElement } from 'react';
import PropTypes from 'prop-types';
import { styled } from '@mui/material/styles';
import CloseIcon from '@mui/icons-material/CloseSharp';
@@ -23,17 +23,17 @@ const StyledCloseButton = styled(MiradorMenuButton, { name: 'CompanionWindow', s
/**
* CompanionWindow
*/
-export class CompanionWindow extends Component {
+export function CompanionWindow(props) {
/** */
- openInNewStyle() {
- const { direction } = this.props;
+ const openInNewStyle = () => {
+ const { direction } = props;
if (direction === 'rtl') return { transform: 'scale(-1, 1)' };
return {};
- }
+ };
/** */
- resizeHandles() {
- const { direction, position } = this.props;
+ const resizeHandles = () => {
+ const { direction, position } = props;
const positions = {
ltr: {
default: 'left',
@@ -69,126 +69,119 @@ export class CompanionWindow extends Component {
}
return base;
- }
+ };
+ const {
+ ariaLabel, classes, paperClassName, onCloseClick, updateCompanionWindow, isDisplayed,
+ position, t, title, children, titleControls, size,
+ defaultSidebarPanelWidth, defaultSidebarPanelHeight, innerRef,
+ } = props;
- /**
- * render
- * @return
- */
- render() {
- const {
- ariaLabel, classes, paperClassName, onCloseClick, updateCompanionWindow, isDisplayed,
- position, t, title, children, titleControls, size,
- defaultSidebarPanelWidth, defaultSidebarPanelHeight, innerRef,
- } = this.props;
+ const isBottom = (position === 'bottom' || position === 'far-bottom');
- const isBottom = (position === 'bottom' || position === 'far-bottom');
-
- const childrenWithAdditionalProps = Children.map(children, (child) => {
- if (!child) return null;
- return cloneElement(
- child,
- {
- parentactions: {
- closeCompanionWindow: onCloseClick,
- },
+ const childrenWithAdditionalProps = Children.map(children, (child) => {
+ if (!child) return null;
+ return cloneElement(
+ child,
+ {
+ parentactions: {
+ closeCompanionWindow: onCloseClick,
},
- );
- });
+ },
+ );
+ });
- return (
-
+
-
-
- {title}
- {
- position === 'left'
- ? updateCompanionWindow
- && (
- { updateCompanionWindow({ position: 'right' }); }}
- >
-
-
- )
- : (
- <>
- {
- updateCompanionWindow && (
- { updateCompanionWindow({ position: position === 'bottom' ? 'right' : 'bottom' }); }}
- >
-
-
- )
- }
-
-
-
- >
- )
- }
- {
- titleControls && (
-
+ {title}
+ {
+ position === 'left'
+ ? updateCompanionWindow
+ && (
+ { updateCompanionWindow({ position: 'right' }); }}
>
- {titleControls}
-
+
+
)
- }
-
-
- {childrenWithAdditionalProps}
-
-
-
- );
- }
+ : (
+ <>
+ {
+ updateCompanionWindow && (
+ { updateCompanionWindow({ position: position === 'bottom' ? 'right' : 'bottom' }); }}
+ >
+
+
+ )
+ }
+
+
+
+ >
+ )
+ }
+ {
+ titleControls && (
+
+ {titleControls}
+
+ )
+ }
+
+
+ {childrenWithAdditionalProps}
+
+
+
+ );
}
CompanionWindow.propTypes = {
@@ -224,7 +217,7 @@ CompanionWindow.defaultProps = {
defaultSidebarPanelWidth: 235,
innerRef: undefined,
isDisplayed: false,
- onCloseClick: () => {},
+ onCloseClick: () => { },
paperClassName: '',
position: null,
size: {},
diff --git a/src/containers/CompanionWindow.js b/src/containers/CompanionWindow.js
index 64a1806440..4747d9c166 100644
--- a/src/containers/CompanionWindow.js
+++ b/src/containers/CompanionWindow.js
@@ -1,7 +1,7 @@
import { compose } from 'redux';
import { connect } from 'react-redux';
import { withTranslation } from 'react-i18next';
-import { withSize } from 'react-sizeme';
+import { withSize } from '../extend/withSize';
import { withPlugins } from '../extend/withPlugins';
import { withRef } from '../extend/withRef';
import * as actions from '../state/actions';
@@ -46,8 +46,8 @@ const mapDispatchToProps = (dispatch, { windowId, id }) => ({
const enhance = compose(
withRef(),
- withTranslation(),
withSize(),
+ withTranslation(),
connect(mapStateToProps, mapDispatchToProps),
withPlugins('CompanionWindow'),
);
diff --git a/src/containers/WindowCanvasNavigationControls.js b/src/containers/WindowCanvasNavigationControls.js
index ca5088f34b..91b62e584c 100644
--- a/src/containers/WindowCanvasNavigationControls.js
+++ b/src/containers/WindowCanvasNavigationControls.js
@@ -1,6 +1,6 @@
import { connect } from 'react-redux';
import { compose } from 'redux';
-import { withSize } from 'react-sizeme';
+import { withSize } from '../extend/withSize';
import { withPlugins } from '../extend/withPlugins';
import { getShowZoomControlsConfig, getWorkspace } from '../state/selectors';
import { WindowCanvasNavigationControls } from '../components/WindowCanvasNavigationControls';
diff --git a/src/extend/withSize.js b/src/extend/withSize.js
new file mode 100644
index 0000000000..14f2d136e9
--- /dev/null
+++ b/src/extend/withSize.js
@@ -0,0 +1,47 @@
+/** This file was written to replace https://github.com/ctrlplusb/react-sizeme
+ * when its dependencies went out of date and is very much inspired by its code.
+ */
+
+import { useEffect, useRef, useState } from 'react';
+
+/** */
+export function withSize() {
+ return function WrapComponent(WrappedComponent) {
+ /** */
+ const SizeAwareComponent = (props) => {
+ const [size, setSize] = useState({ height: undefined, width: undefined });
+ const elementRef = useRef(null);
+ const observerRef = useRef(null);
+
+ useEffect(() => {
+ /** */
+ const handleResize = (entries) => {
+ for (const entry of entries) {
+ const { width, height } = entry.contentRect;
+ setSize({ height, width });
+ }
+ };
+
+ observerRef.current = new ResizeObserver(handleResize);
+
+ if (elementRef.current) {
+ observerRef.current.observe(elementRef.current);
+ }
+
+ return () => {
+ if (observerRef.current) {
+ observerRef.current.disconnect();
+ }
+ };
+ }, []);
+
+ return (
+
+
+
+ );
+ };
+
+ return SizeAwareComponent;
+ };
+}