diff --git a/extensions/cornerstone/src/index.js b/extensions/cornerstone/src/index.js
index 0d30d2232..431948332 100644
--- a/extensions/cornerstone/src/index.js
+++ b/extensions/cornerstone/src/index.js
@@ -39,7 +39,9 @@ export default {
const onNewImageHandler = jumpData => {
commandsManager.runCommand('jumpToImage', jumpData);
};
- return ;
+ return (
+
+ );
};
return ExtendedOHIFCornerstoneViewport;
diff --git a/extensions/dicom-microscopy/src/DicomMicroscopyViewport.js b/extensions/dicom-microscopy/src/DicomMicroscopyViewport.js
index acbfbca48..2290895dc 100644
--- a/extensions/dicom-microscopy/src/DicomMicroscopyViewport.js
+++ b/extensions/dicom-microscopy/src/DicomMicroscopyViewport.js
@@ -92,8 +92,8 @@ class DicomMicroscopyViewport extends Component {
{this.state.error ? (
{JSON.stringify(this.state.error)}
) : (
-
- )}
+
+ )}
);
}
diff --git a/extensions/dicom-rt/src/components/RTPanel/RTPanel.js b/extensions/dicom-rt/src/components/RTPanel/RTPanel.js
index e6399bb02..80eb785d2 100644
--- a/extensions/dicom-rt/src/components/RTPanel/RTPanel.js
+++ b/extensions/dicom-rt/src/components/RTPanel/RTPanel.js
@@ -31,7 +31,18 @@ const refreshViewport = () => {
* @param {number} props.isOpen - isOpen
* @returns component
*/
-const RTPanel = ({ studies, viewports, activeIndex, isOpen, onContourItemClick }) => {
+const RTPanel = ({
+ studies,
+ viewports,
+ activeIndex,
+ isOpen,
+ onContourItemClick,
+ activeContexts = [],
+ contexts = {}
+}) => {
+ const isVTK = () => activeContexts.includes(contexts.VTK);
+ const isCornerstone = () => activeContexts.includes(contexts.CORNERSTONE);
+
const [selectedContour, setSelectedContour] = useState();
const DEFAULT_SET_INDEX = 0;
const DEFAULT_STATE = {
@@ -119,33 +130,35 @@ const RTPanel = ({ studies, viewports, activeIndex, isOpen, onContourItemClick }
onClick={() => {
setSelectedContour(isSameContour ? null : ROINumber);
- const enabledElements = cornerstone.getEnabledElements();
- const element = enabledElements[activeIndex].element;
- const toolState = cornerstoneTools.getToolState(element, 'stack');
+ if (isCornerstone()) {
+ const enabledElements = cornerstone.getEnabledElements();
+ const element = enabledElements[activeIndex].element;
+ const toolState = cornerstoneTools.getToolState(element, 'stack');
- if (!toolState) {
- return;
+ if (!toolState) {
+ return;
+ }
+
+ const imageIds = toolState.data[0].imageIds;
+
+ const module = cornerstoneTools.getModule('rtstruct');
+ const imageId = module.getters.imageIdOfCenterFrameOfROIContour(
+ state.selectedSet.SeriesInstanceUID,
+ ROINumber,
+ imageIds
+ );
+
+ const frameIndex = imageIds.indexOf(imageId);
+ const SOPInstanceUID = cornerstone.metaData.get('SOPInstanceUID', imageId);
+ const StudyInstanceUID = cornerstone.metaData.get('StudyInstanceUID', imageId);
+
+ onContourItemClick({
+ StudyInstanceUID,
+ SOPInstanceUID,
+ frameIndex,
+ activeViewportIndex: activeIndex
+ });
}
-
- const imageIds = toolState.data[0].imageIds;
-
- const module = cornerstoneTools.getModule('rtstruct');
- const imageId = module.getters.imageIdOfCenterFrameOfROIContour(
- state.selectedSet.SeriesInstanceUID,
- ROINumber,
- imageIds
- );
-
- const frameIndex = imageIds.indexOf(imageId);
- const SOPInstanceUID = cornerstone.metaData.get('SOPInstanceUID', imageId);
- const StudyInstanceUID = cornerstone.metaData.get('StudyInstanceUID', imageId);
-
- onContourItemClick({
- StudyInstanceUID,
- SOPInstanceUID,
- frameIndex,
- activeViewportIndex: activeIndex
- });
}}
label={`${ROIName} ${interpretedType}`}
index={ROINumber}
diff --git a/extensions/dicom-rt/src/index.js b/extensions/dicom-rt/src/index.js
index e73bf1069..fae258a11 100644
--- a/extensions/dicom-rt/src/index.js
+++ b/extensions/dicom-rt/src/index.js
@@ -20,14 +20,21 @@ export default {
preRegistration({ servicesManager, configuration = {} }) {
init({ servicesManager, configuration });
},
- getPanelModule({ commandsManager }) {
+ getPanelModule({ commandsManager, api }) {
const ExtendedRTPanel = props => {
+ const { activeContexts } = api.hooks.useAppContext();
+
const contourItemClickHandler = contourData => {
commandsManager.runCommand('jumpToImage', contourData);
};
return (
-
+
);
};
diff --git a/extensions/dicom-segmentation/src/components/SegmentationPanel/SegmentationPanel.js b/extensions/dicom-segmentation/src/components/SegmentationPanel/SegmentationPanel.js
index 084f7a0c9..2af848454 100644
--- a/extensions/dicom-segmentation/src/components/SegmentationPanel/SegmentationPanel.js
+++ b/extensions/dicom-segmentation/src/components/SegmentationPanel/SegmentationPanel.js
@@ -49,8 +49,8 @@ const SegmentationPanel = ({
onConfigurationChange,
onDisplaySetLoadFailure,
onSelectedSegmentationChange,
- activeContexts,
- contexts,
+ activeContexts = [],
+ contexts = {},
}) => {
const isVTK = () => activeContexts.includes(contexts.VTK);
const isCornerstone = () => activeContexts.includes(contexts.CORNERSTONE);
diff --git a/extensions/dicom-segmentation/src/index.js b/extensions/dicom-segmentation/src/index.js
index 0eb6ef545..a01184b66 100644
--- a/extensions/dicom-segmentation/src/index.js
+++ b/extensions/dicom-segmentation/src/index.js
@@ -46,7 +46,7 @@ export default {
const onSegmentVisibilityChangeHandler = (segmentNumber, visible) => {
commandsManager.runCommand('setSegmentConfiguration', {
segmentNumber,
- visible
+ visible,
});
};
@@ -55,7 +55,7 @@ export default {
globalOpacity: configuration.fillAlpha,
outlineThickness: configuration.outlineWidth,
renderOutline: configuration.renderOutline,
- visible: configuration.renderFill
+ visible: configuration.renderFill,
});
};
diff --git a/extensions/vtk/src/index.js b/extensions/vtk/src/index.js
index f66061b43..4b0dee69e 100644
--- a/extensions/vtk/src/index.js
+++ b/extensions/vtk/src/index.js
@@ -1,3 +1,4 @@
+import React from 'react';
import asyncComponent from './asyncComponent.js';
import commandsModule from './commandsModule.js';
import toolbarModule from './toolbarModule.js';
@@ -16,7 +17,8 @@ const vtkExtension = {
id: 'vtk',
getViewportModule({ commandsManager }) {
- return withCommandsManager(OHIFVTKViewport, commandsManager);
+ const ExtendedVTKViewport = props => ;
+ return withCommandsManager(ExtendedVTKViewport, commandsManager);
},
getToolbarModule() {
return toolbarModule;
diff --git a/platform/ui/package.json b/platform/ui/package.json
index ea67c6537..97a2732aa 100644
--- a/platform/ui/package.json
+++ b/platform/ui/package.json
@@ -53,6 +53,7 @@
"react-dnd-html5-backend": "^9.4.0",
"react-dnd-touch-backend": "^9.4.0",
"react-draggable": "^4.1.0",
+ "react-error-boundary": "^2.2.1",
"react-i18next": "^10.11.0",
"react-modal": "^3.11.1",
"react-with-direction": "1.3.0"
diff --git a/platform/ui/src/components/errorBoundary/ErrorBoundary.js b/platform/ui/src/components/errorBoundary/ErrorBoundary.js
new file mode 100644
index 000000000..d2acec560
--- /dev/null
+++ b/platform/ui/src/components/errorBoundary/ErrorBoundary.js
@@ -0,0 +1,51 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { ErrorBoundary } from 'react-error-boundary';
+import './ErrorFallback.css';
+
+const ErrorFallback = ({ error, componentStack, resetErrorBoundary }) => {
+ return (
+
+
Something went wrong.
+
{error.message}
+
{componentStack}
+
+ );
+};
+
+const OHIFErrorBoundary = ({
+ context = 'OHIF',
+ onReset = () => {},
+ onError = () => {},
+ fallbackComponent,
+ children,
+}) => {
+ const onErrorHandler = (error, componentStack) => {
+ console.error(`${context} Error Boundary`, error, componentStack);
+ onError(error, componentStack);
+ };
+
+ const onResetHandler = () => {
+ onReset();
+ };
+
+ return (
+
+ {children}
+
+ );
+};
+
+OHIFErrorBoundary.propTypes = {
+ context: PropTypes.string,
+ onReset: PropTypes.func,
+ onError: PropTypes.func,
+ children: PropTypes.node.isRequired,
+ fallbackComponent: PropTypes.element,
+};
+
+export default OHIFErrorBoundary;
diff --git a/platform/ui/src/components/errorBoundary/ErrorFallback.css b/platform/ui/src/components/errorBoundary/ErrorFallback.css
new file mode 100644
index 000000000..c000e83c8
--- /dev/null
+++ b/platform/ui/src/components/errorBoundary/ErrorFallback.css
@@ -0,0 +1,4 @@
+.ErrorFallback {
+ padding: 10px;
+ color: var(--active-color);
+}
diff --git a/platform/ui/src/components/errorBoundary/index.js b/platform/ui/src/components/errorBoundary/index.js
new file mode 100644
index 000000000..e5d6dda21
--- /dev/null
+++ b/platform/ui/src/components/errorBoundary/index.js
@@ -0,0 +1 @@
+export { default as ErrorBoundary } from './ErrorBoundary';
diff --git a/platform/ui/src/components/index.js b/platform/ui/src/components/index.js
index 3624e4115..c3853be93 100644
--- a/platform/ui/src/components/index.js
+++ b/platform/ui/src/components/index.js
@@ -7,7 +7,6 @@ import { AboutContent } from './content/aboutContent/AboutContent';
import { TabComponents, TabFooter } from './tabComponents';
import { HotkeyField } from './customForm';
import { LanguageSwitcher } from './languageSwitcher';
-
import { Checkbox } from './checkbox';
import { CineDialog } from './cineDialog';
import { ViewportDownloadForm } from './content/viewportDownloadForm';
@@ -25,8 +24,10 @@ import {
} from './studyList';
import { ToolbarSection } from './toolbarSection';
import { Tooltip } from './tooltip';
+import { ErrorBoundary } from './errorBoundary';
export {
+ ErrorBoundary,
ContextMenu,
Checkbox,
CineDialog,
diff --git a/platform/ui/src/index.js b/platform/ui/src/index.js
index 451ac244e..36237ac06 100644
--- a/platform/ui/src/index.js
+++ b/platform/ui/src/index.js
@@ -29,6 +29,7 @@ import {
Tooltip,
AboutContent,
OHIFModal,
+ ErrorBoundary
} from './components';
import { useDebounce, useMedia } from './hooks';
@@ -123,6 +124,7 @@ export {
DialogProvider,
withDialog,
useDialog,
+ ErrorBoundary,
// Hooks
useDebounce,
useMedia,
diff --git a/platform/viewer/cypress/integration/pwa/OHIFExtensionMicroscopy.spec.js b/platform/viewer/cypress/integration/pwa/OHIFExtensionMicroscopy.spec.js
index 5e0ac5386..c650e86f9 100644
--- a/platform/viewer/cypress/integration/pwa/OHIFExtensionMicroscopy.spec.js
+++ b/platform/viewer/cypress/integration/pwa/OHIFExtensionMicroscopy.spec.js
@@ -1,7 +1,7 @@
describe('OHIF Microscopy Extension', () => {
before(() => {
cy.openStudyModality('SM');
- cy.expectMinimumThumbnails(6);
+ cy.expectMinimumThumbnails(2);
});
it('checks if series thumbnails are being displayed', () => {
diff --git a/platform/viewer/src/App.js b/platform/viewer/src/App.js
index 47d869c9d..07e62c283 100644
--- a/platform/viewer/src/App.js
+++ b/platform/viewer/src/App.js
@@ -13,6 +13,7 @@ import {
ModalProvider,
DialogProvider,
OHIFModal,
+ ErrorBoundary
} from '@ohif/ui';
import {
@@ -167,53 +168,57 @@ class App extends Component {
if (this._userManager) {
return (
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
);
}
return (
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
);
}
diff --git a/platform/viewer/src/OHIFStandaloneViewer.js b/platform/viewer/src/OHIFStandaloneViewer.js
index baad5d759..fd5d875e5 100644
--- a/platform/viewer/src/OHIFStandaloneViewer.js
+++ b/platform/viewer/src/OHIFStandaloneViewer.js
@@ -5,7 +5,7 @@ import { Route, Switch } from 'react-router-dom';
import { NProgress } from '@tanem/react-nprogress';
import { CSSTransition } from 'react-transition-group';
import { connect } from 'react-redux';
-import { ViewerbaseDragDropContext } from '@ohif/ui';
+import { ViewerbaseDragDropContext, ErrorBoundary } from '@ohif/ui';
import { SignoutCallbackComponent } from 'redux-oidc';
import asyncComponent from './components/AsyncComponent.js';
import * as RoutesUtil from './routes/routesUtil';
@@ -191,7 +191,9 @@ class OHIFStandaloneViewer extends Component {
{match === null ? (
<>>
) : (
-
+
+
+
)}
)}
diff --git a/platform/viewer/src/components/ErrorBoundaryDialog/ErrorBoundaryDialog.js b/platform/viewer/src/components/ErrorBoundaryDialog/ErrorBoundaryDialog.js
new file mode 100644
index 000000000..24a5807c0
--- /dev/null
+++ b/platform/viewer/src/components/ErrorBoundaryDialog/ErrorBoundaryDialog.js
@@ -0,0 +1,52 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { ErrorBoundary } from '@ohif/ui';
+import { servicesManager } from './../../App';
+
+const { UIModalService } = servicesManager.services;
+
+const ErrorBoundaryDialog = ({ context, children }) => {
+ const handleOnError = (error, componentStack) => {
+ const ErrorDialog = () => (
+
+
+
+ {context}: {error.message}
+
+
+
{componentStack}
+
+ );
+
+ UIModalService.show({
+ content: ErrorDialog,
+ title: `${context}: ${error.message}`,
+ });
+ };
+
+ const fallbackComponent = () => (
+
+
+ Error rendering {context}.
Check the browser console for more
+ details.
+
+
+ );
+
+ return (
+
+ {children}
+
+ );
+};
+
+ErrorBoundaryDialog.propTypes = {
+ context: PropTypes.string.isRequired,
+ children: PropTypes.node.isRequired,
+};
+
+export default ErrorBoundaryDialog;
diff --git a/platform/viewer/src/components/ErrorBoundaryDialog/index.js b/platform/viewer/src/components/ErrorBoundaryDialog/index.js
new file mode 100644
index 000000000..0fe70549f
--- /dev/null
+++ b/platform/viewer/src/components/ErrorBoundaryDialog/index.js
@@ -0,0 +1,3 @@
+import ErrorBoundaryDialog from './ErrorBoundaryDialog';
+
+export default ErrorBoundaryDialog;
diff --git a/platform/viewer/src/components/ViewportGrid/ViewportGrid.js b/platform/viewer/src/components/ViewportGrid/ViewportGrid.js
index e59449956..cb52c06c6 100644
--- a/platform/viewer/src/components/ViewportGrid/ViewportGrid.js
+++ b/platform/viewer/src/components/ViewportGrid/ViewportGrid.js
@@ -12,7 +12,7 @@ import EmptyViewport from './EmptyViewport.js';
const { loadAndCacheDerivedDisplaySets } = utils;
-const ViewportGrid = function (props) {
+const ViewportGrid = function(props) {
const {
activeViewportIndex,
availablePlugins,
@@ -24,7 +24,7 @@ const ViewportGrid = function (props) {
studies,
viewportData,
children,
- isStudyLoaded
+ isStudyLoaded,
} = props;
const rowSize = 100 / numRows;
@@ -54,7 +54,7 @@ const ViewportGrid = function (props) {
});
});
}
- }, [studies, viewportData, isStudyLoaded]);
+ }, [studies, viewportData, isStudyLoaded, snackbar]);
const getViewportPanes = () =>
layout.viewports.map((layout, viewportIndex) => {
diff --git a/platform/viewer/src/components/ViewportGrid/ViewportPane.js b/platform/viewer/src/components/ViewportGrid/ViewportPane.js
index 15a6bcd65..f1995f297 100644
--- a/platform/viewer/src/components/ViewportGrid/ViewportPane.js
+++ b/platform/viewer/src/components/ViewportGrid/ViewportPane.js
@@ -4,7 +4,7 @@ import PropTypes from 'prop-types';
import classNames from 'classnames';
import './ViewportPane.css';
-const ViewportPane = function(props) {
+const ViewportPane = function (props) {
const { children, onDrop, viewportIndex, className: propClassName } = props;
const [{ hovered, highlighted }, drop] = useDrop({
accept: 'thumbnail',
diff --git a/platform/viewer/src/connectedComponents/Viewer.js b/platform/viewer/src/connectedComponents/Viewer.js
index 7bb799df6..632d2909b 100644
--- a/platform/viewer/src/connectedComponents/Viewer.js
+++ b/platform/viewer/src/connectedComponents/Viewer.js
@@ -2,8 +2,7 @@ import React, { Component } from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';
-import { MODULE_TYPES } from '@ohif/core';
-import OHIF, { DICOMSR } from '@ohif/core';
+import OHIF, { MODULE_TYPES, DICOMSR } from '@ohif/core';
import { withDialog } from '@ohif/ui';
import moment from 'moment';
import ConnectedHeader from './ConnectedHeader.js';
@@ -11,6 +10,7 @@ import ToolbarRow from './ToolbarRow.js';
import ConnectedStudyBrowser from './ConnectedStudyBrowser.js';
import ConnectedViewerMain from './ConnectedViewerMain.js';
import SidePanel from './../components/SidePanel.js';
+import ErrorBoundaryDialog from './../components/ErrorBoundaryDialog';
import { extensionManager } from './../App.js';
// Contexts
@@ -26,6 +26,7 @@ class Viewer extends Component {
PropTypes.shape({
StudyInstanceUID: PropTypes.string.isRequired,
StudyDate: PropTypes.string,
+ PatientID: PropTypes.string,
displaySets: PropTypes.arrayOf(
PropTypes.shape({
displaySetInstanceUID: PropTypes.string.isRequired,
@@ -256,42 +257,44 @@ class Viewer extends Component {
{/* TOOLBAR */}
- {
- const sideClicked = side && side[0].toUpperCase() + side.slice(1);
- const openKey = `is${sideClicked}SidePanelOpen`;
- const selectedKey = `selected${sideClicked}SidePanel`;
- const updatedState = Object.assign({}, this.state);
-
- const isOpen = updatedState[openKey];
- const prevSelectedPanel = updatedState[selectedKey];
- // RoundedButtonGroup returns `null` if selected button is clicked
- const isSameSelectedPanel =
- prevSelectedPanel === selectedPanel || selectedPanel === null;
-
- updatedState[selectedKey] = selectedPanel || prevSelectedPanel;
-
- const isClosedOrShouldClose = !isOpen || isSameSelectedPanel;
- if (isClosedOrShouldClose) {
- updatedState[openKey] = !updatedState[openKey];
+
+ {
+ const sideClicked = side && side[0].toUpperCase() + side.slice(1);
+ const openKey = `is${sideClicked}SidePanelOpen`;
+ const selectedKey = `selected${sideClicked}SidePanel`;
+ const updatedState = Object.assign({}, this.state);
- this.setState(updatedState);
- }}
- studies={this.props.studies}
- />
+ const isOpen = updatedState[openKey];
+ const prevSelectedPanel = updatedState[selectedKey];
+ // RoundedButtonGroup returns `null` if selected button is clicked
+ const isSameSelectedPanel =
+ prevSelectedPanel === selectedPanel || selectedPanel === null;
+
+ updatedState[selectedKey] = selectedPanel || prevSelectedPanel;
+
+ const isClosedOrShouldClose = !isOpen || isSameSelectedPanel;
+ if (isClosedOrShouldClose) {
+ updatedState[openKey] = !updatedState[openKey];
+ }
+
+ this.setState(updatedState);
+ }}
+ studies={this.props.studies}
+ />
+
{/**/}
{/**/}
@@ -299,37 +302,46 @@ class Viewer extends Component {
{/* VIEWPORTS + SIDEPANELS */}
{/* LEFT */}
-
- {VisiblePanelLeft ? (
-
- ) : (
+
+
+ {VisiblePanelLeft ? (
+
+ ) : (
)}
-
+
+
{/* MAIN */}
-
+
+
+
{/* RIGHT */}
-
- {VisiblePanelRight && (
-
- )}
-
+
+
+ {VisiblePanelRight && (
+
+ )}
+
+
>
);
@@ -349,7 +361,7 @@ export default withDialog(Viewer);
* @param {Study[]} studies
* @param {DisplaySet[]} studies[].displaySets
*/
-const _mapStudiesToThumbnails = function (studies) {
+const _mapStudiesToThumbnails = function(studies) {
return studies.map(study => {
const { StudyInstanceUID } = study;
diff --git a/yarn.lock b/yarn.lock
index 2e4be842c..f774efc57 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1247,7 +1247,7 @@
pirates "^4.0.0"
source-map-support "^0.5.9"
-"@babel/runtime@7.1.2", "@babel/runtime@7.5.5", "@babel/runtime@7.6.0", "@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.2.0", "@babel/runtime@^7.3.1", "@babel/runtime@^7.4.0", "@babel/runtime@^7.4.2", "@babel/runtime@^7.4.4", "@babel/runtime@^7.4.5", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.0", "@babel/runtime@^7.6.3", "@babel/runtime@^7.7.2", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7":
+"@babel/runtime@7.1.2", "@babel/runtime@7.5.5", "@babel/runtime@7.6.0", "@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.2.0", "@babel/runtime@^7.3.1", "@babel/runtime@^7.4.0", "@babel/runtime@^7.4.2", "@babel/runtime@^7.4.4", "@babel/runtime@^7.4.5", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.0", "@babel/runtime@^7.6.3", "@babel/runtime@^7.7.2", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.6":
version "7.5.5"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.5.5.tgz#74fba56d35efbeca444091c7850ccd494fd2f132"
integrity sha512-28QvEGyQyNkB0/m2B4FU7IEZGK2NUrcMtT6BZEFALTguLk+AUT6ofsHtPk5QyjAdUkpMJ+/Em+quwz4HOt30AQ==
@@ -15796,6 +15796,13 @@ react-dropzone@^10.1.7:
file-selector "^0.1.11"
prop-types "^15.7.2"
+react-error-boundary@^2.2.1:
+ version "2.2.1"
+ resolved "https://registry.yarnpkg.com/react-error-boundary/-/react-error-boundary-2.2.1.tgz#32ed74386a90482060cc2fea948bb7135465c4cb"
+ integrity sha512-8SZMkJRFUb0JuluHKwuUtkh5vvVWBg3O/bJIWgNMhMJv529aG//TmcphR3cSMhCWjz1vFZDb4taJd6pmwP5mEQ==
+ dependencies:
+ "@babel/runtime" "^7.9.6"
+
react-error-overlay@^4.0.1:
version "4.0.1"
resolved "https://registry.yarnpkg.com/react-error-overlay/-/react-error-overlay-4.0.1.tgz#417addb0814a90f3a7082eacba7cee588d00da89"