diff --git a/package.json b/package.json
index 952e63de..a9dd9179 100644
--- a/package.json
+++ b/package.json
@@ -39,6 +39,7 @@
},
"devDependencies": {
"@emanprague/eslint-config": "^1.0.2",
+ "@testing-library/react": "^12.1.1",
"@types/jest": "^24.9.1",
"@types/prettier": "^2.0.1",
"@types/rimraf": "^3.0.0",
@@ -57,6 +58,7 @@
},
"peerDependencies": {
"mobx": "^4.15.4",
- "react": "^16.13.0"
+ "react": "^16.13.0",
+ "react-dom": "^16.13.0"
}
}
diff --git a/packages/views/__tests__/errorBoundary.test.tsx b/packages/views/__tests__/errorBoundary.test.tsx
new file mode 100644
index 00000000..5903ae2f
--- /dev/null
+++ b/packages/views/__tests__/errorBoundary.test.tsx
@@ -0,0 +1,183 @@
+/**
+ * @jest-environment jsdom
+ */
+import * as React from "react";
+import { fireEvent, render, screen } from "@testing-library/react";
+import { bound } from "@frui.ts/helpers";
+import ErrorBoundary, { ErrorBoundaryProps } from "../src/errorBoundary";
+
+function SimulateError({ title }: { title: string }): JSX.Element {
+ throw new Error(title);
+}
+
+function Test(): JSX.Element {
+ return ;
+}
+
+class TestApp extends React.Component {
+ state = {
+ error: false,
+ };
+
+ @bound
+ protected setError(error: boolean) {
+ this.setState({ error });
+ }
+
+ render() {
+ return (
+ {
+ this.setError(false);
+ if (this.props.onReset) {
+ this.props.onReset(...args);
+ }
+ }}>
+ {this.state.error ? : this.props.children}
+ {
+ this.setError(true);
+ }}>
+ Raise error
+
+
+ );
+ }
+}
+
+describe("ErrorBoundary", () => {
+ it("renders children correctly when there is no error", () => {
+ const { container } = render(
+ Error Component}>
+ children
+
+ );
+
+ expect(container.innerHTML).toBe("children ");
+ });
+
+ it("renders 'Something went wrong :-(' if not given `fallback` prop", () => {
+ const renderResult = render(
+
+
+
+ );
+
+ expect(renderResult.container.innerHTML).toBe("Something went wrong :-(
");
+ });
+
+ it("renders a fallback string when error occur", () => {
+ const renderResult = render(
+
+
+
+ );
+
+ expect(renderResult.container.innerHTML).toBe("Error occur");
+ });
+
+ it("renders a fallback component on error", () => {
+ const { container } = render(
+ Error Component}>
+
+
+ );
+ expect(container.innerHTML).toBe("Error Component ");
+ });
+
+ it("renders a fallback component when error occur", async () => {
+ const { container } = render(
+ You have hit an error
}>
+ children
+
+ );
+
+ expect(container.innerHTML).toContain("children ");
+
+ const btn = screen.getByTestId("raiseErrorBtn");
+ fireEvent.click(btn);
+
+ expect(container.innerHTML).not.toContain("children ");
+ expect(container.innerHTML).toBe("You have hit an error
");
+ });
+
+ it("renders fallback as function", async () => {
+ let errorString = "";
+ let componentStackString = "";
+ const { container } = render(
+ {
+ errorString = error.toString();
+ componentStackString = errorInfo?.componentStack || "";
+ return Fallback here
;
+ }}>
+ children
+
+ );
+
+ expect(container.innerHTML).toContain("children ");
+
+ const btn = screen.getByTestId("raiseErrorBtn");
+ fireEvent.click(btn);
+
+ expect(container.innerHTML).not.toContain("children ");
+ expect(container.innerHTML).toBe("Fallback here
");
+ expect(errorString).toBe("Error: errorMessage");
+ /*
+ in SimulateError
+ in Test
+ in ErrorBoundary
+ in TestApp
+ */
+ expect(componentStackString).toMatch(
+ /\s*(in SimulateError)([a-z]|[A-Z]|\(|\)| )*\s*(in Test)([a-z]|[A-Z]|\(|\)| )*\s*(in ErrorBoundary)([a-z]|[A-Z]|\(|\)| )*\s*(in TestApp)([a-z]|[A-Z]|\(|\)| )*/g
+ );
+ });
+
+ it("renders children component after reset from error", async () => {
+ const { container } = render(
+ {
+ return (
+
+ Reset error
+
+ );
+ }}>
+ children
+
+ );
+
+ expect(container.innerHTML).toContain("children ");
+
+ const btn = screen.getByTestId("raiseErrorBtn");
+ fireEvent.click(btn);
+
+ expect(container.innerHTML).not.toContain("children ");
+ expect(container.innerHTML).toContain('Reset error ');
+
+ const resetErrorBtn = screen.getByTestId("resetErrorBtn");
+ fireEvent.click(resetErrorBtn);
+
+ expect(container.innerHTML).toContain("children ");
+ });
+
+ it("calls `componentDidCatch() when an error occurs`", () => {
+ const mockOnError = jest.fn();
+ render(
+ You have hit an error} onError={mockOnError}>
+ children
+
+ );
+
+ expect(mockOnError).toHaveBeenCalledTimes(0);
+
+ const btn = screen.getByTestId("raiseErrorBtn");
+ fireEvent.click(btn);
+
+ expect(mockOnError).toHaveBeenCalledTimes(1);
+ expect(mockOnError).toHaveBeenCalledWith(expect.any(Error), expect.any(Object));
+ });
+});
diff --git a/packages/views/src/errorBoundary.tsx b/packages/views/src/errorBoundary.tsx
new file mode 100644
index 00000000..f46644db
--- /dev/null
+++ b/packages/views/src/errorBoundary.tsx
@@ -0,0 +1,62 @@
+import * as React from "react";
+
+export type FallbackRender = (errorData: {
+ error: Error;
+ errorInfo: React.ErrorInfo | null;
+ resetError(): void;
+}) => React.ReactNode;
+
+export interface ErrorBoundaryProps {
+ onError?: (error: Error, errorInfo: React.ErrorInfo) => void;
+ /** Called if resetError() is called from the fallback render props function */
+ onReset?(error: Error | null, errorInfo: React.ErrorInfo | null): void;
+ fallback?: React.ReactNode | FallbackRender;
+}
+
+interface ErrorBoundaryState {
+ error: Error | null;
+ errorInfo: React.ErrorInfo | null;
+}
+
+const INITIAL_STATE = Object.freeze({
+ errorInfo: null,
+ error: null,
+});
+
+export default class ErrorBoundary extends React.PureComponent {
+ state: ErrorBoundaryState = INITIAL_STATE;
+
+ public readonly resetErrorBoundary = () => {
+ const { onReset } = this.props;
+
+ if (onReset) {
+ const { error, errorInfo } = this.state;
+ onReset(error, errorInfo);
+ }
+
+ this.setState(INITIAL_STATE);
+ };
+
+ componentDidCatch(error: Error, errorInfo: React.ErrorInfo) {
+ this.props.onError?.(error, errorInfo);
+
+ this.setState({ error, errorInfo });
+ }
+
+ render() {
+ if (this.state.error) {
+ const { error, errorInfo } = this.state;
+ const { fallback } = this.props;
+ const element =
+ typeof fallback === "function" ? fallback({ error, errorInfo, resetError: this.resetErrorBoundary }) : fallback;
+
+ if (element !== undefined) {
+ return element;
+ }
+
+ return Something went wrong :-(
;
+ }
+
+ return {this.props.children} ;
+ }
+}
diff --git a/packages/views/src/view.tsx b/packages/views/src/view.tsx
index 846878cd..882a8a0b 100644
--- a/packages/views/src/view.tsx
+++ b/packages/views/src/view.tsx
@@ -1,81 +1,49 @@
-import { isActivatable, isDeactivatable } from "@frui.ts/screens";
import * as React from "react";
+import ErrorBoundary, { ErrorBoundaryProps } from "./errorBoundary";
+import useScreenLifecycle from "./useScreenLifecycle";
import { getView, tryGetView } from "./viewLocator";
interface ViewProps {
vm: any;
context?: string;
useLifecycle?: boolean;
- fallbackMode?: "message" | "children";
- onError?: (error: Error, errorInfo: React.ErrorInfo) => void;
}
-interface ViewState {
- hasError: boolean;
-}
-
-export default class View extends React.PureComponent {
- static defaultProps: Partial = {
- fallbackMode: "children",
- };
-
- static getDerivedStateFromError(error: any) {
- return { hasError: true };
- }
+const PureView: React.FunctionComponent = props => {
+ const { vm, children, context, useLifecycle } = props;
- componentDidCatch(error: Error, errorInfo: React.ErrorInfo) {
- this.props.onError?.(error, errorInfo);
+ if (!vm) {
+ return {children} ;
}
- componentDidMount() {
- this.tryActivateViewModel();
- }
+ const FoundView = children === undefined ? getView(vm.constructor, context) : tryGetView(vm.constructor, context);
- componentDidUpdate(prevProps: ViewProps) {
- if (prevProps.vm !== this.props.vm) {
- this.tryActivateViewModel();
- }
+ if (!FoundView) {
+ return {children} ;
}
- componentWillUnmount() {
- if (this.props.useLifecycle) {
- const { vm } = this.props;
- if (vm && isDeactivatable(vm)) {
- vm.deactivate(true);
- }
- }
+ if (!!useLifecycle) {
+ useScreenLifecycle(vm);
}
- render() {
- if (this.state?.hasError) {
- return Something went wrong :-(
;
- }
+ return ;
+};
- const { vm, context, fallbackMode, children } = this.props;
+PureView.displayName = "View";
- if (!vm) {
- return {children} ;
- }
+const ViewWithErrorBoundary: React.FunctionComponent = props => {
+ const { onError, onReset, fallback, ...rest } = props;
- const FoundView = fallbackMode ? tryGetView(vm.constructor, context) : getView(vm.constructor, context);
+ return (
+
+
+
+ );
+};
- if (!FoundView) {
- return fallbackMode === "message" ? (
- Could not find a view for {vm.constructor.name}
- ) : (
- {children}
- );
- }
+ViewWithErrorBoundary.displayName = "View.ErrorBoundary";
- return ;
- }
+const View = PureView as React.FunctionComponent & { ErrorBoundary: typeof ViewWithErrorBoundary };
+View.ErrorBoundary = ViewWithErrorBoundary;
- protected tryActivateViewModel() {
- if (this.props.useLifecycle) {
- const { vm } = this.props;
- if (vm && isActivatable(vm)) {
- vm.activate();
- }
- }
- }
-}
+export default View;
diff --git a/yarn.lock b/yarn.lock
index f5dbb7e9..62684eb7 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -9,6 +9,13 @@
dependencies:
"@babel/highlight" "^7.8.3"
+"@babel/code-frame@^7.10.4":
+ version "7.14.5"
+ resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.14.5.tgz#23b08d740e83f49c5e59945fbf1b43e80bbf4edb"
+ integrity sha512-9pzDqyc6OLDaqe+zbACgFkb6fKMNG6CObKpnYXChRsvYGyEdc7CA2BaqeOM+vOtCS5ndmJicPJhKAwYRI6UfFw==
+ dependencies:
+ "@babel/highlight" "^7.14.5"
+
"@babel/core@^7.1.0":
version "7.8.7"
resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.8.7.tgz#b69017d221ccdeb203145ae9da269d72cf102f3b"
@@ -68,6 +75,11 @@
dependencies:
"@babel/types" "^7.8.3"
+"@babel/helper-validator-identifier@^7.14.5":
+ version "7.15.7"
+ resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.15.7.tgz#220df993bfe904a4a6b02ab4f3385a5ebf6e2389"
+ integrity sha512-K4JvCtQqad9OY2+yTU8w+E82ywk/fe+ELNlt1G8z3bVGlZfn/hOcQQsUhGhW/N+tb3fxK800wLtKOE/aM0m72w==
+
"@babel/helper-validator-identifier@^7.9.0":
version "7.9.0"
resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.9.0.tgz#ad53562a7fc29b3b9a91bbf7d10397fd146346ed"
@@ -82,6 +94,15 @@
"@babel/traverse" "^7.8.4"
"@babel/types" "^7.8.3"
+"@babel/highlight@^7.14.5":
+ version "7.14.5"
+ resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.14.5.tgz#6861a52f03966405001f6aa534a01a24d99e8cd9"
+ integrity sha512-qf9u2WFWVV0MppaL877j2dBtQIDgmidgjGk5VIMw3OadXvYaXn66U1BFlH2t4+t3i+8PhedppRv+i40ABzd+gg==
+ dependencies:
+ "@babel/helper-validator-identifier" "^7.14.5"
+ chalk "^2.0.0"
+ js-tokens "^4.0.0"
+
"@babel/highlight@^7.8.3":
version "7.8.3"
resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.8.3.tgz#28f173d04223eaaa59bc1d439a3836e6d1265797"
@@ -103,6 +124,14 @@
dependencies:
"@babel/helper-plugin-utils" "^7.8.0"
+"@babel/runtime-corejs3@^7.10.2":
+ version "7.15.4"
+ resolved "https://registry.yarnpkg.com/@babel/runtime-corejs3/-/runtime-corejs3-7.15.4.tgz#403139af262b9a6e8f9ba04a6fdcebf8de692bf1"
+ integrity sha512-lWcAqKeB624/twtTc3w6w/2o9RqJPaNBhPGK6DKLSiwuVWC7WFkypWyNg+CpZoyJH0jVzv1uMtXZ/5/lQOLtCg==
+ dependencies:
+ core-js-pure "^3.16.0"
+ regenerator-runtime "^0.13.4"
+
"@babel/runtime-corejs3@^7.8.3":
version "7.9.2"
resolved "https://registry.yarnpkg.com/@babel/runtime-corejs3/-/runtime-corejs3-7.9.2.tgz#26fe4aa77e9f1ecef9b776559bbb8e84d34284b7"
@@ -111,6 +140,13 @@
core-js-pure "^3.0.0"
regenerator-runtime "^0.13.4"
+"@babel/runtime@^7.10.2", "@babel/runtime@^7.12.5":
+ version "7.15.4"
+ resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.15.4.tgz#fd17d16bfdf878e6dd02d19753a39fa8a8d9c84a"
+ integrity sha512-99catp6bHCaxr4sJ/DbTGgHS4+Rs2RVd2g7iOap6SLGPDknRK9ztKNsE/Fg6QhSeh1FGE5f6gHGQmvvn3I3xhw==
+ dependencies:
+ regenerator-runtime "^0.13.4"
+
"@babel/template@^7.4.0", "@babel/template@^7.8.3", "@babel/template@^7.8.6":
version "7.8.6"
resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.8.6.tgz#86b22af15f828dfb086474f964dcc3e39c43ce2b"
@@ -388,6 +424,17 @@
"@types/istanbul-reports" "^1.1.1"
"@types/yargs" "^13.0.0"
+"@jest/types@^27.2.4":
+ version "27.2.4"
+ resolved "https://registry.yarnpkg.com/@jest/types/-/types-27.2.4.tgz#2430042a66e00dc5b140c3636f4474d464c21ee8"
+ integrity sha512-IDO2ezTxeMvQAHxzG/ZvEyA47q0aVfzT95rGFl7bZs/Go0aIucvfDbS2rmnoEdXxlLQhcolmoG/wvL/uKx4tKA==
+ dependencies:
+ "@types/istanbul-lib-coverage" "^2.0.0"
+ "@types/istanbul-reports" "^3.0.0"
+ "@types/node" "*"
+ "@types/yargs" "^16.0.0"
+ chalk "^4.0.0"
+
"@lerna/add@3.21.0":
version "3.21.0"
resolved "https://registry.yarnpkg.com/@lerna/add/-/add-3.21.0.tgz#27007bde71cc7b0a2969ab3c2f0ae41578b4577b"
@@ -1179,6 +1226,33 @@
dependencies:
"@types/node" ">= 8"
+"@testing-library/dom@^8.0.0":
+ version "8.7.1"
+ resolved "https://registry.yarnpkg.com/@testing-library/dom/-/dom-8.7.1.tgz#c17b1e90e682c7945b2d88ce2f078e522c775ce3"
+ integrity sha512-nMqxP8qPHgYAiIPMVb6zko5DInPJ/LdILgrkWB5HBJhBCIU5avso8pU9IafnXVGLRq+LDtbvo0LuVbjEo27BgQ==
+ dependencies:
+ "@babel/code-frame" "^7.10.4"
+ "@babel/runtime" "^7.12.5"
+ "@types/aria-query" "^4.2.0"
+ aria-query "^4.2.2"
+ chalk "^4.1.0"
+ dom-accessibility-api "^0.5.6"
+ lz-string "^1.4.4"
+ pretty-format "^27.0.2"
+
+"@testing-library/react@^12.1.1":
+ version "12.1.1"
+ resolved "https://registry.yarnpkg.com/@testing-library/react/-/react-12.1.1.tgz#e693943aa48d0190099acdc3928a751d73bcf7d5"
+ integrity sha512-JDyWbvMuedEpP6SPL4Cvbhk59TVxQ3pwuR6ZfJHdRsHuxDd/ziSMA3nVM3fViaSbsQhuQFE/mvFrPrvQbL5kRQ==
+ dependencies:
+ "@babel/runtime" "^7.12.5"
+ "@testing-library/dom" "^8.0.0"
+
+"@types/aria-query@^4.2.0":
+ version "4.2.2"
+ resolved "https://registry.yarnpkg.com/@types/aria-query/-/aria-query-4.2.2.tgz#ed4e0ad92306a704f9fb132a0cfcf77486dbe2bc"
+ integrity sha512-HnYpAE1Y6kRyKM/XkEuiRQhTHvkzMBurTHnpFLYLBGPIylZNPs9jJcuOOYWxPLJCSEtmZT0Y8rHDokKN7rRTig==
+
"@types/babel__core@^7.1.0":
version "7.1.6"
resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.1.6.tgz#16ff42a5ae203c9af1c6e190ed1f30f83207b610"
@@ -1256,6 +1330,13 @@
"@types/istanbul-lib-coverage" "*"
"@types/istanbul-lib-report" "*"
+"@types/istanbul-reports@^3.0.0":
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz#9153fe98bba2bd565a63add9436d6f0d7f8468ff"
+ integrity sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==
+ dependencies:
+ "@types/istanbul-lib-report" "*"
+
"@types/jest@^24.9.1":
version "24.9.1"
resolved "https://registry.yarnpkg.com/@types/jest/-/jest-24.9.1.tgz#02baf9573c78f1b9974a5f36778b366aa77bd534"
@@ -1308,6 +1389,13 @@
dependencies:
"@types/yargs-parser" "*"
+"@types/yargs@^16.0.0":
+ version "16.0.4"
+ resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-16.0.4.tgz#26aad98dd2c2a38e421086ea9ad42b9e51642977"
+ integrity sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==
+ dependencies:
+ "@types/yargs-parser" "*"
+
"@typescript-eslint/eslint-plugin-tslint@^2.18.0":
version "2.34.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin-tslint/-/eslint-plugin-tslint-2.34.0.tgz#0a2cea8e9a0726ae5a42cecd94095b41b749a8e7"
@@ -1482,6 +1570,11 @@ ansi-regex@^5.0.0:
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.0.tgz#388539f55179bf39339c81af30a654d69f87cb75"
integrity sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==
+ansi-regex@^5.0.1:
+ version "5.0.1"
+ resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304"
+ integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==
+
ansi-styles@^3.2.0, ansi-styles@^3.2.1:
version "3.2.1"
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d"
@@ -1497,6 +1590,11 @@ ansi-styles@^4.1.0:
"@types/color-name" "^1.1.1"
color-convert "^2.0.1"
+ansi-styles@^5.0.0:
+ version "5.2.0"
+ resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-5.2.0.tgz#07449690ad45777d1924ac2abb2fc8895dba836b"
+ integrity sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==
+
any-promise@^1.0.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/any-promise/-/any-promise-1.3.0.tgz#abc6afeedcea52e809cdc0376aed3ce39635d17f"
@@ -1540,6 +1638,14 @@ argparse@^1.0.7:
dependencies:
sprintf-js "~1.0.2"
+aria-query@^4.2.2:
+ version "4.2.2"
+ resolved "https://registry.yarnpkg.com/aria-query/-/aria-query-4.2.2.tgz#0d2ca6c9aceb56b8977e9fed6aed7e15bbd2f83b"
+ integrity sha512-o/HelwhuKpTj/frsOsbNLNgnNGVIFsVP/SW2BSF14gVl7kAfMOJ6/8wUAUvG1R1NHKrfG+2sHZTu0yauT1qBrA==
+ dependencies:
+ "@babel/runtime" "^7.10.2"
+ "@babel/runtime-corejs3" "^7.10.2"
+
arr-diff@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520"
@@ -1949,6 +2055,14 @@ chalk@^3.0.0:
ansi-styles "^4.1.0"
supports-color "^7.1.0"
+chalk@^4.0.0, chalk@^4.1.0:
+ version "4.1.2"
+ resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01"
+ integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==
+ dependencies:
+ ansi-styles "^4.1.0"
+ supports-color "^7.1.0"
+
chardet@^0.7.0:
version "0.7.0"
resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e"
@@ -2241,6 +2355,11 @@ core-js-pure@^3.0.0:
resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.6.4.tgz#4bf1ba866e25814f149d4e9aaa08c36173506e3a"
integrity sha512-epIhRLkXdgv32xIUFaaAry2wdxZYBi6bgM7cB136dzzXXa+dFyRLTZeLUJxnd8ShrmyVXBub63n2NHo2JAt8Cw==
+core-js-pure@^3.16.0:
+ version "3.18.1"
+ resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.18.1.tgz#097d34d24484be45cea700a448d1e74622646c80"
+ integrity sha512-kmW/k8MaSuqpvA1xm2l3TVlBuvW+XBkcaOroFUpO3D4lsTGQWBTb/tBDCf/PNkkPLrwgrkQRIYNPB0CeqGJWGQ==
+
core-util-is@1.0.2, core-util-is@~1.0.0:
version "1.0.2"
resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
@@ -2488,6 +2607,11 @@ doctrine@^3.0.0:
dependencies:
esutils "^2.0.2"
+dom-accessibility-api@^0.5.6:
+ version "0.5.7"
+ resolved "https://registry.yarnpkg.com/dom-accessibility-api/-/dom-accessibility-api-0.5.7.tgz#8c2aa6325968f2933160a0b7dbb380893ddf3e7d"
+ integrity sha512-ml3lJIq9YjUfM9TUnEPvEYWFSwivwIGBPKpewX7tii7fwCazA8yCioGdqQcNsItPpfFvSJ3VIdMQPj60LJhcQA==
+
domexception@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/domexception/-/domexception-1.0.1.tgz#937442644ca6a31261ef36e3ec677fe805582c90"
@@ -4665,6 +4789,11 @@ lunr@^2.3.8:
resolved "https://registry.yarnpkg.com/lunr/-/lunr-2.3.8.tgz#a8b89c31f30b5a044b97d2d28e2da191b6ba2072"
integrity sha512-oxMeX/Y35PNFuZoHp+jUj5OSEmLCaIH4KTFJh7a93cHBoFmpw2IoPs22VIz7vyO2YUnx2Tn9dzIwO2P/4quIRg==
+lz-string@^1.4.4:
+ version "1.4.4"
+ resolved "https://registry.yarnpkg.com/lz-string/-/lz-string-1.4.4.tgz#c0d8eaf36059f705796e1e344811cf4c498d3a26"
+ integrity sha1-wNjq82BZ9wV5bh40SBHPTEmNOiY=
+
macos-release@^2.2.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/macos-release/-/macos-release-2.3.0.tgz#eb1930b036c0800adebccd5f17bc4c12de8bb71f"
@@ -5615,6 +5744,16 @@ pretty-format@^24.9.0:
ansi-styles "^3.2.0"
react-is "^16.8.4"
+pretty-format@^27.0.2:
+ version "27.2.4"
+ resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-27.2.4.tgz#08ea39c5eab41b082852d7093059a091f6ddc748"
+ integrity sha512-NUjw22WJHldzxyps2YjLZkUj6q1HvjqFezkB9Y2cklN8NtVZN/kZEXGZdFw4uny3oENzV5EEMESrkI0YDUH8vg==
+ dependencies:
+ "@jest/types" "^27.2.4"
+ ansi-regex "^5.0.1"
+ ansi-styles "^5.0.0"
+ react-is "^17.0.1"
+
pretty-hrtime@^1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz#b7e3ea42435a4c9b2759d99e0f201eb195802ee1"
@@ -5739,6 +5878,11 @@ react-is@^16.8.1, react-is@^16.8.4:
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4"
integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==
+react-is@^17.0.1:
+ version "17.0.2"
+ resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.2.tgz#e691d4a8e9c789365655539ab372762b0efb54f0"
+ integrity sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==
+
read-cmd-shim@^1.0.1:
version "1.0.5"
resolved "https://registry.yarnpkg.com/read-cmd-shim/-/read-cmd-shim-1.0.5.tgz#87e43eba50098ba5a32d0ceb583ab8e43b961c16"