diff --git a/CHANGELOG.md b/CHANGELOG.md
index 1bdc06cbb0cf..16f419383503 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -3,6 +3,7 @@
## Unreleased
- "You miss 100 percent of the chances you don't take. — Wayne Gretzky" — Michael Scott
+- [react] feat: Add @sentry/react package (#2631)
## 5.16.0
diff --git a/package.json b/package.json
index 762e7ab7f25f..69935f2abd94 100644
--- a/package.json
+++ b/package.json
@@ -26,7 +26,7 @@
"packages/integrations",
"packages/minimal",
"packages/node",
- "packages/opentracing",
+ "packages/react",
"packages/types",
"packages/typescript",
"packages/utils"
diff --git a/packages/react/.npmignore b/packages/react/.npmignore
new file mode 100644
index 000000000000..14e80551ae7c
--- /dev/null
+++ b/packages/react/.npmignore
@@ -0,0 +1,4 @@
+*
+!/dist/**/*
+!/esm/**/*
+*.tsbuildinfo
diff --git a/packages/react/LICENSE b/packages/react/LICENSE
new file mode 100644
index 000000000000..8b42db873c95
--- /dev/null
+++ b/packages/react/LICENSE
@@ -0,0 +1,29 @@
+BSD 3-Clause License
+
+Copyright (c) 2019, Sentry
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+* Neither the name of the copyright holder nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/packages/react/README.md b/packages/react/README.md
new file mode 100644
index 000000000000..8df1272d44af
--- /dev/null
+++ b/packages/react/README.md
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+# Official Sentry SDK for ReactJS
+
+## Links
+
+- [Official SDK Docs](https://docs.sentry.io/quickstart/)
+- [TypeDoc](http://getsentry.github.io/sentry-javascript/)
diff --git a/packages/react/package.json b/packages/react/package.json
new file mode 100644
index 000000000000..2b3dc11c4a57
--- /dev/null
+++ b/packages/react/package.json
@@ -0,0 +1,88 @@
+{
+ "name": "@sentry/react",
+ "version": "5.16.0",
+ "description": "Offical Sentry SDK for React.js",
+ "repository": "git://github.com/getsentry/sentry-javascript.git",
+ "homepage": "https://github.com/getsentry/sentry-javascript/tree/master/packages/react",
+ "author": "Sentry",
+ "license": "BSD-3-Clause",
+ "engines": {
+ "node": ">=6"
+ },
+ "main": "dist/index.js",
+ "module": "esm/index.js",
+ "types": "dist/index.d.ts",
+ "publishConfig": {
+ "access": "public"
+ },
+ "dependencies": {
+ "@sentry/browser": "5.16.0",
+ "@sentry/types": "5.16.0",
+ "@sentry/utils": "5.16.0",
+ "hoist-non-react-statics": "^3.3.2",
+ "tslib": "^1.9.3"
+ },
+ "peerDependencies": {
+ "react": "^16.0.0",
+ "react-dom": "^16.0.0"
+ },
+ "devDependencies": {
+ "@types/hoist-non-react-statics": "^3.3.1",
+ "@types/react": "^16.9.35",
+ "@types/react-test-renderer": "^16.9.2",
+ "jest": "^24.7.1",
+ "npm-run-all": "^4.1.2",
+ "prettier": "^1.17.0",
+ "prettier-check": "^2.0.0",
+ "react": "^16.0.0",
+ "react-dom": "^16.0.0",
+ "react-test-renderer": "^16.13.1",
+ "rimraf": "^2.6.3",
+ "tslint": "^5.16.0",
+ "tslint-react": "^5.0.0",
+ "typescript": "^3.5.1"
+ },
+ "scripts": {
+ "build": "run-p build:es5 build:esm",
+ "build:es5": "tsc -p tsconfig.build.json",
+ "build:esm": "tsc -p tsconfig.esm.json",
+ "build:watch": "run-p build:watch:es5 build:watch:esm",
+ "build:watch:es5": "tsc -p tsconfig.build.json -w --preserveWatchOutput",
+ "build:watch:esm": "tsc -p tsconfig.esm.json -w --preserveWatchOutput",
+ "clean": "rimraf dist coverage build esm",
+ "link:yarn": "yarn link",
+ "lint": "run-s lint:prettier lint:tslint",
+ "lint:prettier": "prettier-check \"{src,test}/**/*.{ts,tsx}\"",
+ "lint:tslint": "tslint -t stylish -p .",
+ "lint:tslint:json": "tslint --format json -p . | tee lint-results.json",
+ "fix": "run-s fix:tslint fix:prettier",
+ "fix:prettier": "prettier --write \"{src,test}/**/*.{ts,tsx}\"",
+ "fix:tslint": "tslint --fix -t stylish -p .",
+ "test": "jest",
+ "test:watch": "jest --watch"
+ },
+ "jest": {
+ "collectCoverage": true,
+ "transform": {
+ "^.+\\.ts$": "ts-jest",
+ "^.+\\.tsx$": "ts-jest"
+ },
+ "moduleFileExtensions": [
+ "js",
+ "ts",
+ "tsx"
+ ],
+ "testEnvironment": "jsdom",
+ "testMatch": [
+ "**/*.test.ts",
+ "**/*.test.tsx"
+ ],
+ "globals": {
+ "ts-jest": {
+ "tsConfig": "./tsconfig.json",
+ "diagnostics": false
+ }
+ }
+ },
+ "sideEffects": false
+}
diff --git a/packages/react/src/index.ts b/packages/react/src/index.ts
new file mode 100644
index 000000000000..93fa1c640dcc
--- /dev/null
+++ b/packages/react/src/index.ts
@@ -0,0 +1,3 @@
+export * from '@sentry/browser';
+
+export { Profiler, withProfiler } from './profiler';
diff --git a/packages/react/src/profiler.tsx b/packages/react/src/profiler.tsx
new file mode 100644
index 000000000000..16373639c18a
--- /dev/null
+++ b/packages/react/src/profiler.tsx
@@ -0,0 +1,119 @@
+import { getCurrentHub } from '@sentry/browser';
+import { Integration, IntegrationClass } from '@sentry/types';
+import { logger } from '@sentry/utils';
+import * as hoistNonReactStatic from 'hoist-non-react-statics';
+import * as React from 'react';
+
+export const UNKNOWN_COMPONENT = 'unknown';
+
+const TRACING_GETTER = ({
+ id: 'Tracing',
+} as any) as IntegrationClass;
+
+/**
+ *
+ * Based on implementation from Preact:
+ * https:github.com/preactjs/preact/blob/9a422017fec6dab287c77c3aef63c7b2fef0c7e1/hooks/src/index.js#L301-L313
+ *
+ * Schedule a callback to be invoked after the browser has a chance to paint a new frame.
+ * Do this by combining requestAnimationFrame (rAF) + setTimeout to invoke a callback after
+ * the next browser frame.
+ *
+ * Also, schedule a timeout in parallel to the the rAF to ensure the callback is invoked
+ * even if RAF doesn't fire (for example if the browser tab is not visible)
+ *
+ * This is what we use to tell if a component activity has finished
+ *
+ */
+function afterNextFrame(callback: Function): void {
+ let timeout: number | undefined;
+ let raf: number;
+
+ const done = () => {
+ window.clearTimeout(timeout);
+ window.cancelAnimationFrame(raf);
+ window.setTimeout(callback);
+ };
+
+ raf = window.requestAnimationFrame(done);
+ timeout = window.setTimeout(done, 100);
+}
+
+const getInitActivity = (componentDisplayName: string): number | null => {
+ const tracingIntegration = getCurrentHub().getIntegration(TRACING_GETTER);
+
+ if (tracingIntegration !== null) {
+ // tslint:disable-next-line:no-unsafe-any
+ const activity = (tracingIntegration as any).constructor.pushActivity(componentDisplayName, {
+ description: `<${componentDisplayName}>`,
+ op: 'react',
+ });
+
+ // tslint:disable-next-line: no-unsafe-any
+ return activity;
+ }
+
+ logger.warn(
+ `Unable to profile component ${componentDisplayName} due to invalid Tracing Integration. Please make sure to setup the Tracing integration.`,
+ );
+ return null;
+};
+
+interface ProfilerProps {
+ componentDisplayName?: string;
+}
+
+class Profiler extends React.Component {
+ public activity: number | null;
+ public constructor(props: ProfilerProps) {
+ super(props);
+
+ const { componentDisplayName = UNKNOWN_COMPONENT } = this.props;
+
+ this.activity = getInitActivity(componentDisplayName);
+ }
+
+ public componentDidMount(): void {
+ afterNextFrame(this.finishProfile);
+ }
+
+ public componentWillUnmount(): void {
+ afterNextFrame(this.finishProfile);
+ }
+
+ public finishProfile = () => {
+ if (!this.activity) {
+ return;
+ }
+
+ const tracingIntegration = getCurrentHub().getIntegration(TRACING_GETTER);
+ if (tracingIntegration !== null) {
+ // tslint:disable-next-line:no-unsafe-any
+ (tracingIntegration as any).constructor.popActivity(this.activity);
+ this.activity = null;
+ }
+ };
+
+ public render(): React.ReactNode {
+ return this.props.children;
+ }
+}
+
+function withProfiler(WrappedComponent: React.ComponentType
): React.FC
{
+ const componentDisplayName = WrappedComponent.displayName || WrappedComponent.name || UNKNOWN_COMPONENT;
+
+ const Wrapped: React.FC
= (props: P) => (
+
+
+
+ );
+
+ Wrapped.displayName = `profiler(${componentDisplayName})`;
+
+ // Copy over static methods from Wrapped component to Profiler HOC
+ // See: https://reactjs.org/docs/higher-order-components.html#static-methods-must-be-copied-over
+ hoistNonReactStatic(Wrapped, WrappedComponent);
+ return Wrapped;
+}
+
+export { withProfiler, Profiler };
diff --git a/packages/react/test/profiler.test.tsx b/packages/react/test/profiler.test.tsx
new file mode 100644
index 000000000000..fa208211010c
--- /dev/null
+++ b/packages/react/test/profiler.test.tsx
@@ -0,0 +1,70 @@
+import * as React from 'react';
+import { create } from 'react-test-renderer';
+
+import { UNKNOWN_COMPONENT, withProfiler } from '../src/profiler';
+
+const mockPushActivity = jest.fn().mockReturnValue(1);
+const mockPopActivity = jest.fn();
+
+jest.mock('@sentry/browser', () => ({
+ getCurrentHub: () => ({
+ getIntegration: (_: string) => {
+ class MockIntegration {
+ public constructor(name: string) {
+ this.name = name;
+ }
+ public name: string;
+ public setupOnce: () => void = jest.fn();
+ public static pushActivity: () => void = mockPushActivity;
+ public static popActivity: () => void = mockPopActivity;
+ }
+
+ return new MockIntegration('test');
+ },
+ }),
+}));
+
+describe('withProfiler', () => {
+ it('sets displayName properly', () => {
+ const TestComponent = () =>
Hello World
;
+
+ const ProfiledComponent = withProfiler(TestComponent);
+ expect(ProfiledComponent.displayName).toBe('profiler(TestComponent)');
+ });
+
+ describe('Tracing Integration', () => {
+ beforeEach(() => {
+ jest.useFakeTimers();
+ mockPushActivity.mockClear();
+ mockPopActivity.mockClear();
+ });
+
+ it('is called with popActivity() when unmounted', () => {
+ const ProfiledComponent = withProfiler(() => Hello World
);
+
+ expect(mockPopActivity).toHaveBeenCalledTimes(0);
+
+ const profiler = create();
+ profiler.unmount();
+
+ jest.runAllTimers();
+
+ expect(mockPopActivity).toHaveBeenCalledTimes(1);
+ expect(mockPopActivity).toHaveBeenLastCalledWith(1);
+ });
+
+ describe('pushActivity()', () => {
+ it('is called when mounted', () => {
+ const ProfiledComponent = withProfiler(() => Testing
);
+
+ expect(mockPushActivity).toHaveBeenCalledTimes(0);
+ create();
+ expect(mockPushActivity).toHaveBeenCalledTimes(1);
+ expect(mockPushActivity).toHaveBeenLastCalledWith(UNKNOWN_COMPONENT, {
+ description: `<${UNKNOWN_COMPONENT}>`,
+ op: 'react',
+ });
+ });
+ });
+ });
+});
diff --git a/packages/react/tsconfig.build.json b/packages/react/tsconfig.build.json
new file mode 100644
index 000000000000..b1470d524cab
--- /dev/null
+++ b/packages/react/tsconfig.build.json
@@ -0,0 +1,9 @@
+{
+ "extends": "../../tsconfig.json",
+ "compilerOptions": {
+ "baseUrl": ".",
+ "outDir": "dist",
+ "jsx": "react"
+ },
+ "include": ["src/**/*"]
+}
diff --git a/packages/react/tsconfig.esm.json b/packages/react/tsconfig.esm.json
new file mode 100644
index 000000000000..1ed43d018cc7
--- /dev/null
+++ b/packages/react/tsconfig.esm.json
@@ -0,0 +1,9 @@
+{
+ "extends": "../../tsconfig.esm.json",
+ "compilerOptions": {
+ "baseUrl": ".",
+ "outDir": "esm",
+ "jsx": "react"
+ },
+ "include": ["src/**/*"]
+}
diff --git a/packages/react/tsconfig.json b/packages/react/tsconfig.json
new file mode 100644
index 000000000000..d627bc66b496
--- /dev/null
+++ b/packages/react/tsconfig.json
@@ -0,0 +1,9 @@
+{
+ "extends": "./tsconfig.build.json",
+ "include": ["src/**/*.ts", "test/**/*.ts", "src/**/*.tsx", "test/**/*.tsx"],
+ "exclude": ["dist"],
+ "compilerOptions": {
+ "rootDir": ".",
+ "types": ["jest"]
+ }
+}
diff --git a/packages/react/tslint.json b/packages/react/tslint.json
new file mode 100644
index 000000000000..1c16df5658e5
--- /dev/null
+++ b/packages/react/tslint.json
@@ -0,0 +1,11 @@
+{
+ "extends": ["@sentry/typescript/tslint", "tslint-react"],
+ "rules": {
+ "no-implicit-dependencies": [
+ true,
+ "dev"
+ ],
+ "variable-name": false,
+ "completed-docs": false
+ }
+}
diff --git a/typedoc.js b/typedoc.js
index b7ba773c464b..178b68e58212 100644
--- a/typedoc.js
+++ b/typedoc.js
@@ -9,7 +9,6 @@ module.exports = {
'**/dist/**/*',
'**/esm/**/*',
'**/build/**/*',
- '**/packages/opentracing/**/*',
'**/packages/typescript/**/*',
'**/dangerfile.ts',
],
diff --git a/yarn.lock b/yarn.lock
index 65a51f8eef12..abf8e70b088b 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1295,6 +1295,14 @@
resolved "https://registry.yarnpkg.com/@types/highlight.js/-/highlight.js-9.12.3.tgz#b672cfaac25cbbc634a0fd92c515f66faa18dbca"
integrity sha512-pGF/zvYOACZ/gLGWdQH8zSwteQS1epp68yRcVLJMgUck/MjEn/FBYmPub9pXT8C1e4a8YZfHo1CKyV8q1vKUnQ==
+"@types/hoist-non-react-statics@^3.3.1":
+ version "3.3.1"
+ resolved "https://registry.yarnpkg.com/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz#1124aafe5118cb591977aeb1ceaaed1070eb039f"
+ integrity sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA==
+ dependencies:
+ "@types/react" "*"
+ hoist-non-react-statics "^3.3.0"
+
"@types/istanbul-lib-coverage@^2.0.0":
version "2.0.0"
resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.0.tgz#1eb8c033e98cf4e1a4cedcaf8bcafe8cb7591e85"
@@ -1359,11 +1367,31 @@
resolved "https://registry.yarnpkg.com/@types/node/-/node-11.13.7.tgz#85dbb71c510442d00c0631f99dae957ce44fd104"
integrity sha512-suFHr6hcA9mp8vFrZTgrmqW2ZU3mbWsryQtQlY/QvwTISCw7nw/j+bCQPPohqmskhmqa5wLNuMHTTsc+xf1MQg==
+"@types/prop-types@*":
+ version "15.7.3"
+ resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.3.tgz#2ab0d5da2e5815f94b0b9d4b95d1e5f243ab2ca7"
+ integrity sha512-KfRL3PuHmqQLOG+2tGpRO26Ctg+Cq1E01D2DMriKEATHgWLfeNDmq9e29Q9WIky0dQ3NPkd1mzYH8Lm936Z9qw==
+
"@types/range-parser@*":
version "1.2.3"
resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.3.tgz#7ee330ba7caafb98090bece86a5ee44115904c2c"
integrity sha512-ewFXqrQHlFsgc09MK5jP5iR7vumV/BYayNC6PgJO2LPe8vrnNFyjQjSppfEngITi0qvfKtzFvgKymGheFM9UOA==
+"@types/react-test-renderer@^16.9.2":
+ version "16.9.2"
+ resolved "https://registry.yarnpkg.com/@types/react-test-renderer/-/react-test-renderer-16.9.2.tgz#e1c408831e8183e5ad748fdece02214a7c2ab6c5"
+ integrity sha512-4eJr1JFLIAlWhzDkBCkhrOIWOvOxcCAfQh+jiKg7l/nNZcCIL2MHl2dZhogIFKyHzedVWHaVP1Yydq/Ruu4agw==
+ dependencies:
+ "@types/react" "*"
+
+"@types/react@*", "@types/react@^16.9.35":
+ version "16.9.35"
+ resolved "https://registry.yarnpkg.com/@types/react/-/react-16.9.35.tgz#a0830d172e8aadd9bd41709ba2281a3124bbd368"
+ integrity sha512-q0n0SsWcGc8nDqH2GJfWQWUOmZSJhXV64CjVN5SvcNti3TdEaA3AH0D8DwNmMdzjMAC/78tB8nAZIlV8yTz+zQ==
+ dependencies:
+ "@types/prop-types" "*"
+ csstype "^2.2.0"
+
"@types/request@^2.48.1":
version "2.48.1"
resolved "https://registry.yarnpkg.com/@types/request/-/request-2.48.1.tgz#e402d691aa6670fbbff1957b15f1270230ab42fa"
@@ -3754,6 +3782,11 @@ cssstyle@^1.0.0, cssstyle@^1.1.1:
dependencies:
cssom "0.3.x"
+csstype@^2.2.0:
+ version "2.6.10"
+ resolved "https://registry.yarnpkg.com/csstype/-/csstype-2.6.10.tgz#e63af50e66d7c266edb6b32909cfd0aabe03928b"
+ integrity sha512-D34BqZU4cIlMCY93rZHbrq9pjTAQJ3U8S8rfBqjwHxkGPThWFjzZDQpgMJY0QViLxth6ZKYiwFBo14RdN44U/w==
+
currently-unhandled@^0.4.1:
version "0.4.1"
resolved "https://registry.yarnpkg.com/currently-unhandled/-/currently-unhandled-0.4.1.tgz#988df33feab191ef799a61369dd76c17adf957ea"
@@ -5454,6 +5487,13 @@ hmac-drbg@^1.0.0:
minimalistic-assert "^1.0.0"
minimalistic-crypto-utils "^1.0.1"
+hoist-non-react-statics@^3.3.0, hoist-non-react-statics@^3.3.2:
+ version "3.3.2"
+ resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45"
+ integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==
+ dependencies:
+ react-is "^16.7.0"
+
home-or-tmp@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/home-or-tmp/-/home-or-tmp-2.0.0.tgz#e36c3f2d2cae7d746a857e38d18d5f32a7882db8"
@@ -7280,7 +7320,7 @@ longest@^1.0.1:
resolved "https://registry.yarnpkg.com/longest/-/longest-1.0.1.tgz#30a0b2da38f73770e8294a0d22e6625ed77d0097"
integrity sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=
-loose-envify@^1.0.0:
+loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf"
integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==
@@ -8180,7 +8220,7 @@ oauth-sign@~0.9.0:
resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455"
integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==
-object-assign@^4.0.1, object-assign@^4.1.0:
+object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1:
version "4.1.1"
resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=
@@ -8895,6 +8935,15 @@ promzard@^0.3.0:
dependencies:
read "1"
+prop-types@^15.6.2:
+ version "15.7.2"
+ resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5"
+ integrity sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==
+ dependencies:
+ loose-envify "^1.4.0"
+ object-assign "^4.1.1"
+ react-is "^16.8.1"
+
proto-list@~1.2.1:
version "1.2.4"
resolved "https://registry.yarnpkg.com/proto-list/-/proto-list-1.2.4.tgz#212d5bfe1318306a420f6402b8e26ff39647a849"
@@ -9081,11 +9130,45 @@ rc@^1.0.1, rc@^1.1.6, rc@^1.2.7:
minimist "^1.2.0"
strip-json-comments "~2.0.1"
+react-dom@^16.0.0:
+ version "16.13.1"
+ resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.13.1.tgz#c1bd37331a0486c078ee54c4740720993b2e0e7f"
+ integrity sha512-81PIMmVLnCNLO/fFOQxdQkvEq/+Hfpv24XNJfpyZhTRfO0QcmQIF/PgCa1zCOj2w1hrn12MFLyaJ/G0+Mxtfag==
+ dependencies:
+ loose-envify "^1.1.0"
+ object-assign "^4.1.1"
+ prop-types "^15.6.2"
+ scheduler "^0.19.1"
+
+react-is@^16.7.0, react-is@^16.8.1, react-is@^16.8.6:
+ version "16.13.1"
+ resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4"
+ integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==
+
react-is@^16.8.4:
version "16.8.4"
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.8.4.tgz#90f336a68c3a29a096a3d648ab80e87ec61482a2"
integrity sha512-PVadd+WaUDOAciICm/J1waJaSvgq+4rHE/K70j0PFqKhkTBsPv/82UGQJNXAngz1fOQLLxI6z1sEDmJDQhCTAA==
+react-test-renderer@^16.13.1:
+ version "16.13.1"
+ resolved "https://registry.yarnpkg.com/react-test-renderer/-/react-test-renderer-16.13.1.tgz#de25ea358d9012606de51e012d9742e7f0deabc1"
+ integrity sha512-Sn2VRyOK2YJJldOqoh8Tn/lWQ+ZiKhyZTPtaO0Q6yNj+QDbmRkVFap6pZPy3YQk8DScRDfyqm/KxKYP9gCMRiQ==
+ dependencies:
+ object-assign "^4.1.1"
+ prop-types "^15.6.2"
+ react-is "^16.8.6"
+ scheduler "^0.19.1"
+
+react@^16.0.0:
+ version "16.13.1"
+ resolved "https://registry.yarnpkg.com/react/-/react-16.13.1.tgz#2e818822f1a9743122c063d6410d85c1e3afe48e"
+ integrity sha512-YMZQQq32xHLX0bz5Mnibv1/LHb3Sqzngu7xstSM+vrkE5Kzr9xE0yMByK5kMoTK30YVJE61WfbxIFFvfeDKT1w==
+ dependencies:
+ loose-envify "^1.1.0"
+ object-assign "^4.1.1"
+ prop-types "^15.6.2"
+
read-cmd-shim@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/read-cmd-shim/-/read-cmd-shim-1.0.1.tgz#2d5d157786a37c055d22077c32c53f8329e91c7b"
@@ -9688,6 +9771,14 @@ saxes@^3.1.9:
dependencies:
xmlchars "^1.3.1"
+scheduler@^0.19.1:
+ version "0.19.1"
+ resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.19.1.tgz#4f3e2ed2c1a7d65681f4c854fa8c5a1ccb40f196"
+ integrity sha512-n/zwRWRYSUj0/3g/otKDRPMh6qv2SYMWNq85IEa8iZyAv8od9zDYpGSnpBEjNgcMNq6Scbu5KfIPxNF72R/2EA==
+ dependencies:
+ loose-envify "^1.1.0"
+ object-assign "^4.1.1"
+
schema-utils@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-1.0.0.tgz#0b79a93204d7b600d4b2850d1f66c2a34951c770"
@@ -10778,6 +10869,13 @@ tslint-consistent-codestyle@^1.15.1:
tslib "^1.7.1"
tsutils "^2.29.0"
+tslint-react@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/tslint-react/-/tslint-react-5.0.0.tgz#d0ae644e8163bdd3e134012e9353094904e8dd44"
+ integrity sha512-/IbcSmoBPlFic8kQaRfQ4knTY4mivwo5LVzvozvX6Dyu2ynEnrh1dIcR2ujjyp/IodXqY/H5GbxFxSMo/Kf2Hg==
+ dependencies:
+ tsutils "^3.17.1"
+
tslint@^5.16.0:
version "5.16.0"
resolved "https://registry.yarnpkg.com/tslint/-/tslint-5.16.0.tgz#ae61f9c5a98d295b9a4f4553b1b1e831c1984d67"
@@ -10803,6 +10901,13 @@ tsutils@^2.29.0:
dependencies:
tslib "^1.8.1"
+tsutils@^3.17.1:
+ version "3.17.1"
+ resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.17.1.tgz#ed719917f11ca0dee586272b2ac49e015a2dd759"
+ integrity sha512-kzeQ5B8H3w60nFY2g8cJIuH7JDpsALXySGtwGJ0p2LSjLgay3NdIpqq5SoOBe46bKDW2iq25irHCr8wjomUS2g==
+ dependencies:
+ tslib "^1.8.1"
+
tsutils@^3.5.0:
version "3.8.0"
resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.8.0.tgz#7a3dbadc88e465596440622b65c04edc8e187ae5"
@@ -10909,6 +11014,11 @@ typescript@^3.4.5:
resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.4.5.tgz#2d2618d10bb566572b8d7aad5180d84257d70a99"
integrity sha512-YycBxUb49UUhdNMU5aJ7z5Ej2XGmaIBL0x34vZ82fn3hGvD+bgrMrVDpatgz2f7YxUMJxMkbWxJZeAvDxVe7Vw==
+typescript@^3.5.1:
+ version "3.9.3"
+ resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.9.3.tgz#d3ac8883a97c26139e42df5e93eeece33d610b8a"
+ integrity sha512-D/wqnB2xzNFIcoBG9FG8cXRDjiqSTbG2wd8DMZeQyJlP1vfTkIxH4GKveWaEBYySKIg+USu+E+EDIR47SqnaMQ==
+
uglify-js@^2.6:
version "2.8.29"
resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-2.8.29.tgz#29c5733148057bb4e1f75df35b7a9cb72e6a59dd"