Index: node_modules/.bin/loose-envify
===================================================================
--- node_modules/.bin/loose-envify	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
+++ node_modules/.bin/loose-envify	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
@@ -0,0 +1,1 @@
+../loose-envify/cli.js
Index: node_modules/.package-lock.json
===================================================================
--- node_modules/.package-lock.json	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
+++ node_modules/.package-lock.json	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
@@ -0,0 +1,73 @@
+{
+  "name": "Phonelux",
+  "lockfileVersion": 2,
+  "requires": true,
+  "packages": {
+    "node_modules/js-tokens": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
+      "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
+      "peer": true
+    },
+    "node_modules/loose-envify": {
+      "version": "1.4.0",
+      "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
+      "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
+      "peer": true,
+      "dependencies": {
+        "js-tokens": "^3.0.0 || ^4.0.0"
+      },
+      "bin": {
+        "loose-envify": "cli.js"
+      }
+    },
+    "node_modules/object-assign": {
+      "version": "4.1.1",
+      "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
+      "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
+      "peer": true,
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/prop-types": {
+      "version": "15.8.1",
+      "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
+      "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
+      "peer": true,
+      "dependencies": {
+        "loose-envify": "^1.4.0",
+        "object-assign": "^4.1.1",
+        "react-is": "^16.13.1"
+      }
+    },
+    "node_modules/react": {
+      "version": "16.14.0",
+      "resolved": "https://registry.npmjs.org/react/-/react-16.14.0.tgz",
+      "integrity": "sha512-0X2CImDkJGApiAlcf0ODKIneSwBPhqJawOa5wCtKbu7ZECrmS26NvtSILynQ66cgkT/RJ4LidJOc3bUESwmU8g==",
+      "peer": true,
+      "dependencies": {
+        "loose-envify": "^1.1.0",
+        "object-assign": "^4.1.1",
+        "prop-types": "^15.6.2"
+      },
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/react-facebook-login": {
+      "version": "4.1.1",
+      "resolved": "https://registry.npmjs.org/react-facebook-login/-/react-facebook-login-4.1.1.tgz",
+      "integrity": "sha512-COnHEHlYGTKipz4963safFAK9PaNTcCiXfPXMS/yxo8El+/AJL5ye8kMJf23lKSSGGPgqFQuInskIHVqGqTvSw==",
+      "peerDependencies": {
+        "react": "^16.0.0"
+      }
+    },
+    "node_modules/react-is": {
+      "version": "16.13.1",
+      "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
+      "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
+      "peer": true
+    }
+  }
+}
Index: node_modules/js-tokens/CHANGELOG.md
===================================================================
--- node_modules/js-tokens/CHANGELOG.md	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
+++ node_modules/js-tokens/CHANGELOG.md	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
@@ -0,0 +1,151 @@
+### Version 4.0.0 (2018-01-28) ###
+
+- Added: Support for ES2018. The only change needed was recognizing the `s`
+  regex flag.
+- Changed: _All_ tokens returned by the `matchToToken` function now have a
+  `closed` property. It is set to `undefined` for the tokens where “closed”
+  doesn’t make sense. This means that all tokens objects have the same shape,
+  which might improve performance.
+
+These are the breaking changes:
+
+- `'/a/s'.match(jsTokens)` no longer returns `['/', 'a', '/', 's']`, but
+  `['/a/s']`. (There are of course other variations of this.)
+- Code that rely on some token objects not having the `closed` property could
+  now behave differently.
+
+
+### Version 3.0.2 (2017-06-28) ###
+
+- No code changes. Just updates to the readme.
+
+
+### Version 3.0.1 (2017-01-30) ###
+
+- Fixed: ES2015 unicode escapes with more than 6 hex digits are now matched
+  correctly.
+
+
+### Version 3.0.0 (2017-01-11) ###
+
+This release contains one breaking change, that should [improve performance in
+V8][v8-perf]:
+
+> So how can you, as a JavaScript developer, ensure that your RegExps are fast?
+> If you are not interested in hooking into RegExp internals, make sure that
+> neither the RegExp instance, nor its prototype is modified in order to get the
+> best performance:
+>
+> ```js
+> var re = /./g;
+> re.exec('');  // Fast path.
+> re.new_property = 'slow';
+> ```
+
+This module used to export a single regex, with `.matchToToken` bolted
+on, just like in the above example. This release changes the exports of
+the module to avoid this issue.
+
+Before:
+
+```js
+import jsTokens from "js-tokens"
+// or:
+var jsTokens = require("js-tokens")
+var matchToToken = jsTokens.matchToToken
+```
+
+After:
+
+```js
+import jsTokens, {matchToToken} from "js-tokens"
+// or:
+var jsTokens = require("js-tokens").default
+var matchToToken = require("js-tokens").matchToToken
+```
+
+[v8-perf]: http://v8project.blogspot.se/2017/01/speeding-up-v8-regular-expressions.html
+
+
+### Version 2.0.0 (2016-06-19) ###
+
+- Added: Support for ES2016. In other words, support for the `**` exponentiation
+  operator.
+
+These are the breaking changes:
+
+- `'**'.match(jsTokens)` no longer returns `['*', '*']`, but `['**']`.
+- `'**='.match(jsTokens)` no longer returns `['*', '*=']`, but `['**=']`.
+
+
+### Version 1.0.3 (2016-03-27) ###
+
+- Improved: Made the regex ever so slightly smaller.
+- Updated: The readme.
+
+
+### Version 1.0.2 (2015-10-18) ###
+
+- Improved: Limited npm package contents for a smaller download. Thanks to
+  @zertosh!
+
+
+### Version 1.0.1 (2015-06-20) ###
+
+- Fixed: Declared an undeclared variable.
+
+
+### Version 1.0.0 (2015-02-26) ###
+
+- Changed: Merged the 'operator' and 'punctuation' types into 'punctuator'. That
+  type is now equivalent to the Punctuator token in the ECMAScript
+  specification. (Backwards-incompatible change.)
+- Fixed: A `-` followed by a number is now correctly matched as a punctuator
+  followed by a number. It used to be matched as just a number, but there is no
+  such thing as negative number literals. (Possibly backwards-incompatible
+  change.)
+
+
+### Version 0.4.1 (2015-02-21) ###
+
+- Added: Support for the regex `u` flag.
+
+
+### Version 0.4.0 (2015-02-21) ###
+
+- Improved: `jsTokens.matchToToken` performance.
+- Added: Support for octal and binary number literals.
+- Added: Support for template strings.
+
+
+### Version 0.3.1 (2015-01-06) ###
+
+- Fixed: Support for unicode spaces. They used to be allowed in names (which is
+  very confusing), and some unicode newlines were wrongly allowed in strings and
+  regexes.
+
+
+### Version 0.3.0 (2014-12-19) ###
+
+- Changed: The `jsTokens.names` array has been replaced with the
+  `jsTokens.matchToToken` function. The capturing groups of `jsTokens` are no
+  longer part of the public API; instead use said function. See this [gist] for
+  an example. (Backwards-incompatible change.)
+- Changed: The empty string is now considered an “invalid” token, instead an
+  “empty” token (its own group). (Backwards-incompatible change.)
+- Removed: component support. (Backwards-incompatible change.)
+
+[gist]: https://gist.github.com/lydell/be49dbf80c382c473004
+
+
+### Version 0.2.0 (2014-06-19) ###
+
+- Changed: Match ES6 function arrows (`=>`) as an operator, instead of its own
+  category (“functionArrow”), for simplicity. (Backwards-incompatible change.)
+- Added: ES6 splats (`...`) are now matched as an operator (instead of three
+  punctuations). (Backwards-incompatible change.)
+
+
+### Version 0.1.0 (2014-03-08) ###
+
+- Initial release.
Index: node_modules/js-tokens/LICENSE
===================================================================
--- node_modules/js-tokens/LICENSE	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
+++ node_modules/js-tokens/LICENSE	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2014, 2015, 2016, 2017, 2018 Simon Lydell
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
Index: node_modules/js-tokens/README.md
===================================================================
--- node_modules/js-tokens/README.md	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
+++ node_modules/js-tokens/README.md	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
@@ -0,0 +1,240 @@
+Overview [![Build Status](https://travis-ci.org/lydell/js-tokens.svg?branch=master)](https://travis-ci.org/lydell/js-tokens)
+========
+
+A regex that tokenizes JavaScript.
+
+```js
+var jsTokens = require("js-tokens").default
+
+var jsString = "var foo=opts.foo;\n..."
+
+jsString.match(jsTokens)
+// ["var", " ", "foo", "=", "opts", ".", "foo", ";", "\n", ...]
+```
+
+
+Installation
+============
+
+`npm install js-tokens`
+
+```js
+import jsTokens from "js-tokens"
+// or:
+var jsTokens = require("js-tokens").default
+```
+
+
+Usage
+=====
+
+### `jsTokens` ###
+
+A regex with the `g` flag that matches JavaScript tokens.
+
+The regex _always_ matches, even invalid JavaScript and the empty string.
+
+The next match is always directly after the previous.
+
+### `var token = matchToToken(match)` ###
+
+```js
+import {matchToToken} from "js-tokens"
+// or:
+var matchToToken = require("js-tokens").matchToToken
+```
+
+Takes a `match` returned by `jsTokens.exec(string)`, and returns a `{type:
+String, value: String}` object. The following types are available:
+
+- string
+- comment
+- regex
+- number
+- name
+- punctuator
+- whitespace
+- invalid
+
+Multi-line comments and strings also have a `closed` property indicating if the
+token was closed or not (see below).
+
+Comments and strings both come in several flavors. To distinguish them, check if
+the token starts with `//`, `/*`, `'`, `"` or `` ` ``.
+
+Names are ECMAScript IdentifierNames, that is, including both identifiers and
+keywords. You may use [is-keyword-js] to tell them apart.
+
+Whitespace includes both line terminators and other whitespace.
+
+[is-keyword-js]: https://github.com/crissdev/is-keyword-js
+
+
+ECMAScript support
+==================
+
+The intention is to always support the latest ECMAScript version whose feature
+set has been finalized.
+
+If adding support for a newer version requires changes, a new version with a
+major verion bump will be released.
+
+Currently, ECMAScript 2018 is supported.
+
+
+Invalid code handling
+=====================
+
+Unterminated strings are still matched as strings. JavaScript strings cannot
+contain (unescaped) newlines, so unterminated strings simply end at the end of
+the line. Unterminated template strings can contain unescaped newlines, though,
+so they go on to the end of input.
+
+Unterminated multi-line comments are also still matched as comments. They
+simply go on to the end of the input.
+
+Unterminated regex literals are likely matched as division and whatever is
+inside the regex.
+
+Invalid ASCII characters have their own capturing group.
+
+Invalid non-ASCII characters are treated as names, to simplify the matching of
+names (except unicode spaces which are treated as whitespace). Note: See also
+the [ES2018](#es2018) section.
+
+Regex literals may contain invalid regex syntax. They are still matched as
+regex literals. They may also contain repeated regex flags, to keep the regex
+simple.
+
+Strings may contain invalid escape sequences.
+
+
+Limitations
+===========
+
+Tokenizing JavaScript using regexes—in fact, _one single regex_—won’t be
+perfect. But that’s not the point either.
+
+You may compare jsTokens with [esprima] by using `esprima-compare.js`.
+See `npm run esprima-compare`!
+
+[esprima]: http://esprima.org/
+
+### Template string interpolation ###
+
+Template strings are matched as single tokens, from the starting `` ` `` to the
+ending `` ` ``, including interpolations (whose tokens are not matched
+individually).
+
+Matching template string interpolations requires recursive balancing of `{` and
+`}`—something that JavaScript regexes cannot do. Only one level of nesting is
+supported.
+
+### Division and regex literals collision ###
+
+Consider this example:
+
+```js
+var g = 9.82
+var number = bar / 2/g
+
+var regex = / 2/g
+```
+
+A human can easily understand that in the `number` line we’re dealing with
+division, and in the `regex` line we’re dealing with a regex literal. How come?
+Because humans can look at the whole code to put the `/` characters in context.
+A JavaScript regex cannot. It only sees forwards. (Well, ES2018 regexes can also
+look backwards. See the [ES2018](#es2018) section).
+
+When the `jsTokens` regex scans throught the above, it will see the following
+at the end of both the `number` and `regex` rows:
+
+```js
+/ 2/g
+```
+
+It is then impossible to know if that is a regex literal, or part of an
+expression dealing with division.
+
+Here is a similar case:
+
+```js
+foo /= 2/g
+foo(/= 2/g)
+```
+
+The first line divides the `foo` variable with `2/g`. The second line calls the
+`foo` function with the regex literal `/= 2/g`. Again, since `jsTokens` only
+sees forwards, it cannot tell the two cases apart.
+
+There are some cases where we _can_ tell division and regex literals apart,
+though.
+
+First off, we have the simple cases where there’s only one slash in the line:
+
+```js
+var foo = 2/g
+foo /= 2
+```
+
+Regex literals cannot contain newlines, so the above cases are correctly
+identified as division. Things are only problematic when there are more than
+one non-comment slash in a single line.
+
+Secondly, not every character is a valid regex flag.
+
+```js
+var number = bar / 2/e
+```
+
+The above example is also correctly identified as division, because `e` is not a
+valid regex flag. I initially wanted to future-proof by allowing `[a-zA-Z]*`
+(any letter) as flags, but it is not worth it since it increases the amount of
+ambigous cases. So only the standard `g`, `m`, `i`, `y` and `u` flags are
+allowed. This means that the above example will be identified as division as
+long as you don’t rename the `e` variable to some permutation of `gmiyus` 1 to 6
+characters long.
+
+Lastly, we can look _forward_ for information.
+
+- If the token following what looks like a regex literal is not valid after a
+  regex literal, but is valid in a division expression, then the regex literal
+  is treated as division instead. For example, a flagless regex cannot be
+  followed by a string, number or name, but all of those three can be the
+  denominator of a division.
+- Generally, if what looks like a regex literal is followed by an operator, the
+  regex literal is treated as division instead. This is because regexes are
+  seldomly used with operators (such as `+`, `*`, `&&` and `==`), but division
+  could likely be part of such an expression.
+
+Please consult the regex source and the test cases for precise information on
+when regex or division is matched (should you need to know). In short, you
+could sum it up as:
+
+If the end of a statement looks like a regex literal (even if it isn’t), it
+will be treated as one. Otherwise it should work as expected (if you write sane
+code).
+
+### ES2018 ###
+
+ES2018 added some nice regex improvements to the language.
+
+- [Unicode property escapes] should allow telling names and invalid non-ASCII
+  characters apart without blowing up the regex size.
+- [Lookbehind assertions] should allow matching telling division and regex
+  literals apart in more cases.
+- [Named capture groups] might simplify some things.
+
+These things would be nice to do, but are not critical. They probably have to
+wait until the oldest maintained Node.js LTS release supports those features.
+
+[Unicode property escapes]: http://2ality.com/2017/07/regexp-unicode-property-escapes.html
+[Lookbehind assertions]: http://2ality.com/2017/05/regexp-lookbehind-assertions.html
+[Named capture groups]: http://2ality.com/2017/05/regexp-named-capture-groups.html
+
+
+License
+=======
+
+[MIT](LICENSE).
Index: node_modules/js-tokens/index.js
===================================================================
--- node_modules/js-tokens/index.js	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
+++ node_modules/js-tokens/index.js	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
@@ -0,0 +1,23 @@
+// Copyright 2014, 2015, 2016, 2017, 2018 Simon Lydell
+// License: MIT. (See LICENSE.)
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+})
+
+// This regex comes from regex.coffee, and is inserted here by generate-index.js
+// (run `npm run build`).
+exports.default = /((['"])(?:(?!\2|\\).|\\(?:\r\n|[\s\S]))*(\2)?|`(?:[^`\\$]|\\[\s\S]|\$(?!\{)|\$\{(?:[^{}]|\{[^}]*\}?)*\}?)*(`)?)|(\/\/.*)|(\/\*(?:[^*]|\*(?!\/))*(\*\/)?)|(\/(?!\*)(?:\[(?:(?![\]\\]).|\\.)*\]|(?![\/\]\\]).|\\.)+\/(?:(?!\s*(?:\b|[\u0080-\uFFFF$\\'"~({]|[+\-!](?!=)|\.?\d))|[gmiyus]{1,6}\b(?![\u0080-\uFFFF$\\]|\s*(?:[+\-*%&|^<>!=?({]|\/(?![\/*])))))|(0[xX][\da-fA-F]+|0[oO][0-7]+|0[bB][01]+|(?:\d*\.\d+|\d+\.?)(?:[eE][+-]?\d+)?)|((?!\d)(?:(?!\s)[$\w\u0080-\uFFFF]|\\u[\da-fA-F]{4}|\\u\{[\da-fA-F]+\})+)|(--|\+\+|&&|\|\||=>|\.{3}|(?:[+\-\/%&|^]|\*{1,2}|<{1,2}|>{1,3}|!=?|={1,2})=?|[?~.,:;[\](){}])|(\s+)|(^$|[\s\S])/g
+
+exports.matchToToken = function(match) {
+  var token = {type: "invalid", value: match[0], closed: undefined}
+       if (match[ 1]) token.type = "string" , token.closed = !!(match[3] || match[4])
+  else if (match[ 5]) token.type = "comment"
+  else if (match[ 6]) token.type = "comment", token.closed = !!match[7]
+  else if (match[ 8]) token.type = "regex"
+  else if (match[ 9]) token.type = "number"
+  else if (match[10]) token.type = "name"
+  else if (match[11]) token.type = "punctuator"
+  else if (match[12]) token.type = "whitespace"
+  return token
+}
Index: node_modules/js-tokens/package.json
===================================================================
--- node_modules/js-tokens/package.json	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
+++ node_modules/js-tokens/package.json	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
@@ -0,0 +1,30 @@
+{
+  "name": "js-tokens",
+  "version": "4.0.0",
+  "author": "Simon Lydell",
+  "license": "MIT",
+  "description": "A regex that tokenizes JavaScript.",
+  "keywords": [
+    "JavaScript",
+    "js",
+    "token",
+    "tokenize",
+    "regex"
+  ],
+  "files": [
+    "index.js"
+  ],
+  "repository": "lydell/js-tokens",
+  "scripts": {
+    "test": "mocha --ui tdd",
+    "esprima-compare": "node esprima-compare ./index.js everything.js/es5.js",
+    "build": "node generate-index.js",
+    "dev": "npm run build && npm test"
+  },
+  "devDependencies": {
+    "coffeescript": "2.1.1",
+    "esprima": "4.0.0",
+    "everything.js": "1.0.3",
+    "mocha": "5.0.0"
+  }
+}
Index: node_modules/loose-envify/LICENSE
===================================================================
--- node_modules/loose-envify/LICENSE	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
+++ node_modules/loose-envify/LICENSE	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2015 Andres Suarez <zertosh@gmail.com>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
Index: node_modules/loose-envify/README.md
===================================================================
--- node_modules/loose-envify/README.md	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
+++ node_modules/loose-envify/README.md	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
@@ -0,0 +1,45 @@
+# loose-envify
+
+[![Build Status](https://travis-ci.org/zertosh/loose-envify.svg?branch=master)](https://travis-ci.org/zertosh/loose-envify)
+
+Fast (and loose) selective `process.env` replacer using [js-tokens](https://github.com/lydell/js-tokens) instead of an AST. Works just like [envify](https://github.com/hughsk/envify) but much faster.
+
+## Gotchas
+
+* Doesn't handle broken syntax.
+* Doesn't look inside embedded expressions in template strings.
+  - **this won't work:**
+  ```js
+  console.log(`the current env is ${process.env.NODE_ENV}`);
+  ```
+* Doesn't replace oddly-spaced or oddly-commented expressions.
+  - **this won't work:**
+  ```js
+  console.log(process./*won't*/env./*work*/NODE_ENV);
+  ```
+
+## Usage/Options
+
+loose-envify has the exact same interface as [envify](https://github.com/hughsk/envify), including the CLI.
+
+## Benchmark
+
+```
+envify:
+
+  $ for i in {1..5}; do node bench/bench.js 'envify'; done
+  708ms
+  727ms
+  791ms
+  719ms
+  720ms
+
+loose-envify:
+
+  $ for i in {1..5}; do node bench/bench.js '../'; done
+  51ms
+  52ms
+  52ms
+  52ms
+  52ms
+```
Index: node_modules/loose-envify/cli.js
===================================================================
--- node_modules/loose-envify/cli.js	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
+++ node_modules/loose-envify/cli.js	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
@@ -0,0 +1,16 @@
+#!/usr/bin/env node
+'use strict';
+
+var looseEnvify = require('./');
+var fs = require('fs');
+
+if (process.argv[2]) {
+  fs.createReadStream(process.argv[2], {encoding: 'utf8'})
+    .pipe(looseEnvify(process.argv[2]))
+    .pipe(process.stdout);
+} else {
+  process.stdin.resume()
+  process.stdin
+    .pipe(looseEnvify(__filename))
+    .pipe(process.stdout);
+}
Index: node_modules/loose-envify/custom.js
===================================================================
--- node_modules/loose-envify/custom.js	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
+++ node_modules/loose-envify/custom.js	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
@@ -0,0 +1,4 @@
+// envify compatibility
+'use strict';
+
+module.exports = require('./loose-envify');
Index: node_modules/loose-envify/index.js
===================================================================
--- node_modules/loose-envify/index.js	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
+++ node_modules/loose-envify/index.js	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
@@ -0,0 +1,3 @@
+'use strict';
+
+module.exports = require('./loose-envify')(process.env);
Index: node_modules/loose-envify/loose-envify.js
===================================================================
--- node_modules/loose-envify/loose-envify.js	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
+++ node_modules/loose-envify/loose-envify.js	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
@@ -0,0 +1,36 @@
+'use strict';
+
+var stream = require('stream');
+var util = require('util');
+var replace = require('./replace');
+
+var jsonExtRe = /\.json$/;
+
+module.exports = function(rootEnv) {
+  rootEnv = rootEnv || process.env;
+  return function (file, trOpts) {
+    if (jsonExtRe.test(file)) {
+      return stream.PassThrough();
+    }
+    var envs = trOpts ? [rootEnv, trOpts] : [rootEnv];
+    return new LooseEnvify(envs);
+  };
+};
+
+function LooseEnvify(envs) {
+  stream.Transform.call(this);
+  this._data = '';
+  this._envs = envs;
+}
+util.inherits(LooseEnvify, stream.Transform);
+
+LooseEnvify.prototype._transform = function(buf, enc, cb) {
+  this._data += buf;
+  cb();
+};
+
+LooseEnvify.prototype._flush = function(cb) {
+  var replaced = replace(this._data, this._envs);
+  this.push(replaced);
+  cb();
+};
Index: node_modules/loose-envify/package.json
===================================================================
--- node_modules/loose-envify/package.json	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
+++ node_modules/loose-envify/package.json	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
@@ -0,0 +1,36 @@
+{
+  "name": "loose-envify",
+  "version": "1.4.0",
+  "description": "Fast (and loose) selective `process.env` replacer using js-tokens instead of an AST",
+  "keywords": [
+    "environment",
+    "variables",
+    "browserify",
+    "browserify-transform",
+    "transform",
+    "source",
+    "configuration"
+  ],
+  "homepage": "https://github.com/zertosh/loose-envify",
+  "license": "MIT",
+  "author": "Andres Suarez <zertosh@gmail.com>",
+  "main": "index.js",
+  "bin": {
+    "loose-envify": "cli.js"
+  },
+  "repository": {
+    "type": "git",
+    "url": "git://github.com/zertosh/loose-envify.git"
+  },
+  "scripts": {
+    "test": "tap test/*.js"
+  },
+  "dependencies": {
+    "js-tokens": "^3.0.0 || ^4.0.0"
+  },
+  "devDependencies": {
+    "browserify": "^13.1.1",
+    "envify": "^3.4.0",
+    "tap": "^8.0.0"
+  }
+}
Index: node_modules/loose-envify/replace.js
===================================================================
--- node_modules/loose-envify/replace.js	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
+++ node_modules/loose-envify/replace.js	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
@@ -0,0 +1,65 @@
+'use strict';
+
+var jsTokens = require('js-tokens').default;
+
+var processEnvRe = /\bprocess\.env\.[_$a-zA-Z][$\w]+\b/;
+var spaceOrCommentRe = /^(?:\s|\/[/*])/;
+
+function replace(src, envs) {
+  if (!processEnvRe.test(src)) {
+    return src;
+  }
+
+  var out = [];
+  var purge = envs.some(function(env) {
+    return env._ && env._.indexOf('purge') !== -1;
+  });
+
+  jsTokens.lastIndex = 0
+  var parts = src.match(jsTokens);
+
+  for (var i = 0; i < parts.length; i++) {
+    if (parts[i    ] === 'process' &&
+        parts[i + 1] === '.' &&
+        parts[i + 2] === 'env' &&
+        parts[i + 3] === '.') {
+      var prevCodeToken = getAdjacentCodeToken(-1, parts, i);
+      var nextCodeToken = getAdjacentCodeToken(1, parts, i + 4);
+      var replacement = getReplacementString(envs, parts[i + 4], purge);
+      if (prevCodeToken !== '.' &&
+          nextCodeToken !== '.' &&
+          nextCodeToken !== '=' &&
+          typeof replacement === 'string') {
+        out.push(replacement);
+        i += 4;
+        continue;
+      }
+    }
+    out.push(parts[i]);
+  }
+
+  return out.join('');
+}
+
+function getAdjacentCodeToken(dir, parts, i) {
+  while (true) {
+    var part = parts[i += dir];
+    if (!spaceOrCommentRe.test(part)) {
+      return part;
+    }
+  }
+}
+
+function getReplacementString(envs, name, purge) {
+  for (var j = 0; j < envs.length; j++) {
+    var env = envs[j];
+    if (typeof env[name] !== 'undefined') {
+      return JSON.stringify(env[name]);
+    }
+  }
+  if (purge) {
+    return 'undefined';
+  }
+}
+
+module.exports = replace;
Index: node_modules/object-assign/index.js
===================================================================
--- node_modules/object-assign/index.js	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
+++ node_modules/object-assign/index.js	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
@@ -0,0 +1,90 @@
+/*
+object-assign
+(c) Sindre Sorhus
+@license MIT
+*/
+
+'use strict';
+/* eslint-disable no-unused-vars */
+var getOwnPropertySymbols = Object.getOwnPropertySymbols;
+var hasOwnProperty = Object.prototype.hasOwnProperty;
+var propIsEnumerable = Object.prototype.propertyIsEnumerable;
+
+function toObject(val) {
+	if (val === null || val === undefined) {
+		throw new TypeError('Object.assign cannot be called with null or undefined');
+	}
+
+	return Object(val);
+}
+
+function shouldUseNative() {
+	try {
+		if (!Object.assign) {
+			return false;
+		}
+
+		// Detect buggy property enumeration order in older V8 versions.
+
+		// https://bugs.chromium.org/p/v8/issues/detail?id=4118
+		var test1 = new String('abc');  // eslint-disable-line no-new-wrappers
+		test1[5] = 'de';
+		if (Object.getOwnPropertyNames(test1)[0] === '5') {
+			return false;
+		}
+
+		// https://bugs.chromium.org/p/v8/issues/detail?id=3056
+		var test2 = {};
+		for (var i = 0; i < 10; i++) {
+			test2['_' + String.fromCharCode(i)] = i;
+		}
+		var order2 = Object.getOwnPropertyNames(test2).map(function (n) {
+			return test2[n];
+		});
+		if (order2.join('') !== '0123456789') {
+			return false;
+		}
+
+		// https://bugs.chromium.org/p/v8/issues/detail?id=3056
+		var test3 = {};
+		'abcdefghijklmnopqrst'.split('').forEach(function (letter) {
+			test3[letter] = letter;
+		});
+		if (Object.keys(Object.assign({}, test3)).join('') !==
+				'abcdefghijklmnopqrst') {
+			return false;
+		}
+
+		return true;
+	} catch (err) {
+		// We don't expect any of the above to throw, but better to be safe.
+		return false;
+	}
+}
+
+module.exports = shouldUseNative() ? Object.assign : function (target, source) {
+	var from;
+	var to = toObject(target);
+	var symbols;
+
+	for (var s = 1; s < arguments.length; s++) {
+		from = Object(arguments[s]);
+
+		for (var key in from) {
+			if (hasOwnProperty.call(from, key)) {
+				to[key] = from[key];
+			}
+		}
+
+		if (getOwnPropertySymbols) {
+			symbols = getOwnPropertySymbols(from);
+			for (var i = 0; i < symbols.length; i++) {
+				if (propIsEnumerable.call(from, symbols[i])) {
+					to[symbols[i]] = from[symbols[i]];
+				}
+			}
+		}
+	}
+
+	return to;
+};
Index: node_modules/object-assign/license
===================================================================
--- node_modules/object-assign/license	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
+++ node_modules/object-assign/license	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
Index: node_modules/object-assign/package.json
===================================================================
--- node_modules/object-assign/package.json	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
+++ node_modules/object-assign/package.json	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
@@ -0,0 +1,42 @@
+{
+  "name": "object-assign",
+  "version": "4.1.1",
+  "description": "ES2015 `Object.assign()` ponyfill",
+  "license": "MIT",
+  "repository": "sindresorhus/object-assign",
+  "author": {
+    "name": "Sindre Sorhus",
+    "email": "sindresorhus@gmail.com",
+    "url": "sindresorhus.com"
+  },
+  "engines": {
+    "node": ">=0.10.0"
+  },
+  "scripts": {
+    "test": "xo && ava",
+    "bench": "matcha bench.js"
+  },
+  "files": [
+    "index.js"
+  ],
+  "keywords": [
+    "object",
+    "assign",
+    "extend",
+    "properties",
+    "es2015",
+    "ecmascript",
+    "harmony",
+    "ponyfill",
+    "prollyfill",
+    "polyfill",
+    "shim",
+    "browser"
+  ],
+  "devDependencies": {
+    "ava": "^0.16.0",
+    "lodash": "^4.16.4",
+    "matcha": "^0.7.0",
+    "xo": "^0.16.0"
+  }
+}
Index: node_modules/object-assign/readme.md
===================================================================
--- node_modules/object-assign/readme.md	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
+++ node_modules/object-assign/readme.md	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
@@ -0,0 +1,61 @@
+# object-assign [![Build Status](https://travis-ci.org/sindresorhus/object-assign.svg?branch=master)](https://travis-ci.org/sindresorhus/object-assign)
+
+> ES2015 [`Object.assign()`](http://www.2ality.com/2014/01/object-assign.html) [ponyfill](https://ponyfill.com)
+
+
+## Use the built-in
+
+Node.js 4 and up, as well as every evergreen browser (Chrome, Edge, Firefox, Opera, Safari),
+support `Object.assign()` :tada:. If you target only those environments, then by all
+means, use `Object.assign()` instead of this package.
+
+
+## Install
+
+```
+$ npm install --save object-assign
+```
+
+
+## Usage
+
+```js
+const objectAssign = require('object-assign');
+
+objectAssign({foo: 0}, {bar: 1});
+//=> {foo: 0, bar: 1}
+
+// multiple sources
+objectAssign({foo: 0}, {bar: 1}, {baz: 2});
+//=> {foo: 0, bar: 1, baz: 2}
+
+// overwrites equal keys
+objectAssign({foo: 0}, {foo: 1}, {foo: 2});
+//=> {foo: 2}
+
+// ignores null and undefined sources
+objectAssign({foo: 0}, null, {bar: 1}, undefined);
+//=> {foo: 0, bar: 1}
+```
+
+
+## API
+
+### objectAssign(target, [source, ...])
+
+Assigns enumerable own properties of `source` objects to the `target` object and returns the `target` object. Additional `source` objects will overwrite previous ones.
+
+
+## Resources
+
+- [ES2015 spec - Object.assign](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-object.assign)
+
+
+## Related
+
+- [deep-assign](https://github.com/sindresorhus/deep-assign) - Recursive `Object.assign()`
+
+
+## License
+
+MIT © [Sindre Sorhus](https://sindresorhus.com)
Index: node_modules/prop-types/LICENSE
===================================================================
--- node_modules/prop-types/LICENSE	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
+++ node_modules/prop-types/LICENSE	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2013-present, Facebook, Inc.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
Index: node_modules/prop-types/README.md
===================================================================
--- node_modules/prop-types/README.md	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
+++ node_modules/prop-types/README.md	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
@@ -0,0 +1,302 @@
+# prop-types [![Build Status](https://travis-ci.com/facebook/prop-types.svg?branch=main)](https://travis-ci.org/facebook/prop-types)
+
+Runtime type checking for React props and similar objects.
+
+You can use prop-types to document the intended types of properties passed to
+components. React (and potentially other libraries—see the `checkPropTypes()`
+reference below) will check props passed to your components against those
+definitions, and warn in development if they don’t match.
+
+## Installation
+
+```shell
+npm install --save prop-types
+```
+
+## Importing
+
+```js
+import PropTypes from 'prop-types'; // ES6
+var PropTypes = require('prop-types'); // ES5 with npm
+```
+
+### CDN
+
+If you prefer to exclude `prop-types` from your application and use it
+globally via `window.PropTypes`, the `prop-types` package provides
+single-file distributions, which are hosted on the following CDNs:
+
+* [**unpkg**](https://unpkg.com/prop-types/)
+```html
+<!-- development version -->
+<script src="https://unpkg.com/prop-types@15.6/prop-types.js"></script>
+
+<!-- production version -->
+<script src="https://unpkg.com/prop-types@15.6/prop-types.min.js"></script>
+```
+
+* [**cdnjs**](https://cdnjs.com/libraries/prop-types)
+```html
+<!-- development version -->
+<script src="https://cdnjs.cloudflare.com/ajax/libs/prop-types/15.6.0/prop-types.js"></script>
+
+<!-- production version -->
+<script src="https://cdnjs.cloudflare.com/ajax/libs/prop-types/15.6.0/prop-types.min.js"></script>
+```
+
+To load a specific version of `prop-types` replace `15.6.0` with the version number.
+
+## Usage
+
+PropTypes was originally exposed as part of the React core module, and is
+commonly used with React components.
+Here is an example of using PropTypes with a React component, which also
+documents the different validators provided:
+
+```js
+import React from 'react';
+import PropTypes from 'prop-types';
+
+class MyComponent extends React.Component {
+  render() {
+    // ... do things with the props
+  }
+}
+
+MyComponent.propTypes = {
+  // You can declare that a prop is a specific JS primitive. By default, these
+  // are all optional.
+  optionalArray: PropTypes.array,
+  optionalBigInt: PropTypes.bigint,
+  optionalBool: PropTypes.bool,
+  optionalFunc: PropTypes.func,
+  optionalNumber: PropTypes.number,
+  optionalObject: PropTypes.object,
+  optionalString: PropTypes.string,
+  optionalSymbol: PropTypes.symbol,
+
+  // Anything that can be rendered: numbers, strings, elements or an array
+  // (or fragment) containing these types.
+  // see https://reactjs.org/docs/rendering-elements.html for more info
+  optionalNode: PropTypes.node,
+
+  // A React element (ie. <MyComponent />).
+  optionalElement: PropTypes.element,
+
+  // A React element type (eg. MyComponent).
+  // a function, string, or "element-like" object (eg. React.Fragment, Suspense, etc.)
+  // see https://github.com/facebook/react/blob/HEAD/packages/shared/isValidElementType.js
+  optionalElementType: PropTypes.elementType,
+
+  // You can also declare that a prop is an instance of a class. This uses
+  // JS's instanceof operator.
+  optionalMessage: PropTypes.instanceOf(Message),
+
+  // You can ensure that your prop is limited to specific values by treating
+  // it as an enum.
+  optionalEnum: PropTypes.oneOf(['News', 'Photos']),
+
+  // An object that could be one of many types
+  optionalUnion: PropTypes.oneOfType([
+    PropTypes.string,
+    PropTypes.number,
+    PropTypes.instanceOf(Message)
+  ]),
+
+  // An array of a certain type
+  optionalArrayOf: PropTypes.arrayOf(PropTypes.number),
+
+  // An object with property values of a certain type
+  optionalObjectOf: PropTypes.objectOf(PropTypes.number),
+
+  // You can chain any of the above with `isRequired` to make sure a warning
+  // is shown if the prop isn't provided.
+
+  // An object taking on a particular shape
+  optionalObjectWithShape: PropTypes.shape({
+    optionalProperty: PropTypes.string,
+    requiredProperty: PropTypes.number.isRequired
+  }),
+
+  // An object with warnings on extra properties
+  optionalObjectWithStrictShape: PropTypes.exact({
+    optionalProperty: PropTypes.string,
+    requiredProperty: PropTypes.number.isRequired
+  }),
+
+  requiredFunc: PropTypes.func.isRequired,
+
+  // A value of any data type
+  requiredAny: PropTypes.any.isRequired,
+
+  // You can also specify a custom validator. It should return an Error
+  // object if the validation fails. Don't `console.warn` or throw, as this
+  // won't work inside `oneOfType`.
+  customProp: function(props, propName, componentName) {
+    if (!/matchme/.test(props[propName])) {
+      return new Error(
+        'Invalid prop `' + propName + '` supplied to' +
+        ' `' + componentName + '`. Validation failed.'
+      );
+    }
+  },
+
+  // You can also supply a custom validator to `arrayOf` and `objectOf`.
+  // It should return an Error object if the validation fails. The validator
+  // will be called for each key in the array or object. The first two
+  // arguments of the validator are the array or object itself, and the
+  // current item's key.
+  customArrayProp: PropTypes.arrayOf(function(propValue, key, componentName, location, propFullName) {
+    if (!/matchme/.test(propValue[key])) {
+      return new Error(
+        'Invalid prop `' + propFullName + '` supplied to' +
+        ' `' + componentName + '`. Validation failed.'
+      );
+    }
+  })
+};
+```
+
+Refer to the [React documentation](https://facebook.github.io/react/docs/typechecking-with-proptypes.html) for more information.
+
+## Migrating from React.PropTypes
+
+Check out [Migrating from React.PropTypes](https://facebook.github.io/react/blog/2017/04/07/react-v15.5.0.html#migrating-from-react.proptypes) for details on how to migrate to `prop-types` from `React.PropTypes`.
+
+Note that this blog posts **mentions a codemod script that performs the conversion automatically**.
+
+There are also important notes below.
+
+## How to Depend on This Package?
+
+For apps, we recommend putting it in `dependencies` with a caret range.
+For example:
+
+```js
+  "dependencies": {
+    "prop-types": "^15.5.7"
+  }
+```
+
+For libraries, we *also* recommend leaving it in `dependencies`:
+
+```js
+  "dependencies": {
+    "prop-types": "^15.5.7"
+  },
+  "peerDependencies": {
+    "react": "^15.5.0"
+  }
+```
+
+**Note:** there are known issues in versions before 15.5.7 so we recommend using it as the minimal version.
+
+Make sure that the version range uses a caret (`^`) and thus is broad enough for npm to efficiently deduplicate packages.
+
+For UMD bundles of your components, make sure you **don’t** include `PropTypes` in the build. Usually this is done by marking it as an external (the specifics depend on your bundler), just like you do with React.
+
+## Compatibility
+
+### React 0.14
+
+This package is compatible with **React 0.14.9**. Compared to 0.14.8 (which was released in March of 2016), there are no other changes in 0.14.9, so it should be a painless upgrade.
+
+```shell
+# ATTENTION: Only run this if you still use React 0.14!
+npm install --save react@^0.14.9 react-dom@^0.14.9
+```
+
+### React 15+
+
+This package is compatible with **React 15.3.0** and higher.
+
+```
+npm install --save react@^15.3.0 react-dom@^15.3.0
+```
+
+### What happens on other React versions?
+
+It outputs warnings with the message below even though the developer doesn’t do anything wrong. Unfortunately there is no solution for this other than updating React to either 15.3.0 or higher, or 0.14.9 if you’re using React 0.14.
+
+## Difference from `React.PropTypes`: Don’t Call Validator Functions
+
+First of all, **which version of React are you using**? You might be seeing this message because a component library has updated to use `prop-types` package, but your version of React is incompatible with it. See the [above section](#compatibility) for more details.
+
+Are you using either React 0.14.9 or a version higher than React 15.3.0? Read on.
+
+When you migrate components to use the standalone `prop-types`, **all validator functions will start throwing an error if you call them directly**. This makes sure that nobody relies on them in production code, and it is safe to strip their implementations to optimize the bundle size.
+
+Code like this is still fine:
+
+```js
+MyComponent.propTypes = {
+  myProp: PropTypes.bool
+};
+```
+
+However, code like this will not work with the `prop-types` package:
+
+```js
+// Will not work with `prop-types` package!
+var errorOrNull = PropTypes.bool(42, 'myProp', 'MyComponent', 'prop');
+```
+
+It will throw an error:
+
+```
+Calling PropTypes validators directly is not supported by the `prop-types` package.
+Use PropTypes.checkPropTypes() to call them.
+```
+
+(If you see **a warning** rather than an error with this message, please check the [above section about compatibility](#compatibility).)
+
+This is new behavior, and you will only encounter it when you migrate from `React.PropTypes` to the `prop-types` package. For the vast majority of components, this doesn’t matter, and if you didn’t see [this warning](https://facebook.github.io/react/warnings/dont-call-proptypes.html) in your components, your code is safe to migrate. This is not a breaking change in React because you are only opting into this change for a component by explicitly changing your imports to use `prop-types`. If you temporarily need the old behavior, you can keep using `React.PropTypes` until React 16.
+
+**If you absolutely need to trigger the validation manually**, call `PropTypes.checkPropTypes()`. Unlike the validators themselves, this function is safe to call in production, as it will be replaced by an empty function:
+
+```js
+// Works with standalone PropTypes
+PropTypes.checkPropTypes(MyComponent.propTypes, props, 'prop', 'MyComponent');
+```
+See below for more info.
+
+**If you DO want to use validation in production**, you can choose to use the **development version** by importing/requiring `prop-types/prop-types` instead of `prop-types`.
+
+**You might also see this error** if you’re calling a `PropTypes` validator from your own custom `PropTypes` validator. In this case, the fix is to make sure that you are passing *all* of the arguments to the inner function. There is a more in-depth explanation of how to fix it [on this page](https://facebook.github.io/react/warnings/dont-call-proptypes.html#fixing-the-false-positive-in-third-party-proptypes). Alternatively, you can temporarily keep using `React.PropTypes` until React 16, as it would still only warn in this case.
+
+If you use a bundler like Browserify or Webpack, don’t forget to [follow these instructions](https://reactjs.org/docs/optimizing-performance.html#use-the-production-build) to correctly bundle your application in development or production mode. Otherwise you’ll ship unnecessary code to your users.
+
+## PropTypes.checkPropTypes
+
+React will automatically check the propTypes you set on the component, but if
+you are using PropTypes without React then you may want to manually call
+`PropTypes.checkPropTypes`, like so:
+
+```js
+const myPropTypes = {
+  name: PropTypes.string,
+  age: PropTypes.number,
+  // ... define your prop validations
+};
+
+const props = {
+  name: 'hello', // is valid
+  age: 'world', // not valid
+};
+
+// Let's say your component is called 'MyComponent'
+
+// Works with standalone PropTypes
+PropTypes.checkPropTypes(myPropTypes, props, 'prop', 'MyComponent');
+// This will warn as follows:
+// Warning: Failed prop type: Invalid prop `age` of type `string` supplied to
+// `MyComponent`, expected `number`.
+```
+
+## PropTypes.resetWarningCache()
+
+`PropTypes.checkPropTypes(...)` only `console.error`s a given message once. To reset the error warning cache in tests, call `PropTypes.resetWarningCache()`
+
+### License
+
+prop-types is [MIT licensed](./LICENSE).
Index: node_modules/prop-types/checkPropTypes.js
===================================================================
--- node_modules/prop-types/checkPropTypes.js	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
+++ node_modules/prop-types/checkPropTypes.js	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
@@ -0,0 +1,103 @@
+/**
+ * Copyright (c) 2013-present, Facebook, Inc.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+'use strict';
+
+var printWarning = function() {};
+
+if (process.env.NODE_ENV !== 'production') {
+  var ReactPropTypesSecret = require('./lib/ReactPropTypesSecret');
+  var loggedTypeFailures = {};
+  var has = require('./lib/has');
+
+  printWarning = function(text) {
+    var message = 'Warning: ' + text;
+    if (typeof console !== 'undefined') {
+      console.error(message);
+    }
+    try {
+      // --- Welcome to debugging React ---
+      // This error was thrown as a convenience so that you can use this stack
+      // to find the callsite that caused this warning to fire.
+      throw new Error(message);
+    } catch (x) { /**/ }
+  };
+}
+
+/**
+ * Assert that the values match with the type specs.
+ * Error messages are memorized and will only be shown once.
+ *
+ * @param {object} typeSpecs Map of name to a ReactPropType
+ * @param {object} values Runtime values that need to be type-checked
+ * @param {string} location e.g. "prop", "context", "child context"
+ * @param {string} componentName Name of the component for error messages.
+ * @param {?Function} getStack Returns the component stack.
+ * @private
+ */
+function checkPropTypes(typeSpecs, values, location, componentName, getStack) {
+  if (process.env.NODE_ENV !== 'production') {
+    for (var typeSpecName in typeSpecs) {
+      if (has(typeSpecs, typeSpecName)) {
+        var error;
+        // Prop type validation may throw. In case they do, we don't want to
+        // fail the render phase where it didn't fail before. So we log it.
+        // After these have been cleaned up, we'll let them throw.
+        try {
+          // This is intentionally an invariant that gets caught. It's the same
+          // behavior as without this statement except with a better message.
+          if (typeof typeSpecs[typeSpecName] !== 'function') {
+            var err = Error(
+              (componentName || 'React class') + ': ' + location + ' type `' + typeSpecName + '` is invalid; ' +
+              'it must be a function, usually from the `prop-types` package, but received `' + typeof typeSpecs[typeSpecName] + '`.' +
+              'This often happens because of typos such as `PropTypes.function` instead of `PropTypes.func`.'
+            );
+            err.name = 'Invariant Violation';
+            throw err;
+          }
+          error = typeSpecs[typeSpecName](values, typeSpecName, componentName, location, null, ReactPropTypesSecret);
+        } catch (ex) {
+          error = ex;
+        }
+        if (error && !(error instanceof Error)) {
+          printWarning(
+            (componentName || 'React class') + ': type specification of ' +
+            location + ' `' + typeSpecName + '` is invalid; the type checker ' +
+            'function must return `null` or an `Error` but returned a ' + typeof error + '. ' +
+            'You may have forgotten to pass an argument to the type checker ' +
+            'creator (arrayOf, instanceOf, objectOf, oneOf, oneOfType, and ' +
+            'shape all require an argument).'
+          );
+        }
+        if (error instanceof Error && !(error.message in loggedTypeFailures)) {
+          // Only monitor this failure once because there tends to be a lot of the
+          // same error.
+          loggedTypeFailures[error.message] = true;
+
+          var stack = getStack ? getStack() : '';
+
+          printWarning(
+            'Failed ' + location + ' type: ' + error.message + (stack != null ? stack : '')
+          );
+        }
+      }
+    }
+  }
+}
+
+/**
+ * Resets warning cache when testing.
+ *
+ * @private
+ */
+checkPropTypes.resetWarningCache = function() {
+  if (process.env.NODE_ENV !== 'production') {
+    loggedTypeFailures = {};
+  }
+}
+
+module.exports = checkPropTypes;
Index: node_modules/prop-types/factory.js
===================================================================
--- node_modules/prop-types/factory.js	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
+++ node_modules/prop-types/factory.js	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
@@ -0,0 +1,19 @@
+/**
+ * Copyright (c) 2013-present, Facebook, Inc.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+'use strict';
+
+// React 15.5 references this module, and assumes PropTypes are still callable in production.
+// Therefore we re-export development-only version with all the PropTypes checks here.
+// However if one is migrating to the `prop-types` npm library, they will go through the
+// `index.js` entry point, and it will branch depending on the environment.
+var factory = require('./factoryWithTypeCheckers');
+module.exports = function(isValidElement) {
+  // It is still allowed in 15.5.
+  var throwOnDirectAccess = false;
+  return factory(isValidElement, throwOnDirectAccess);
+};
Index: node_modules/prop-types/factoryWithThrowingShims.js
===================================================================
--- node_modules/prop-types/factoryWithThrowingShims.js	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
+++ node_modules/prop-types/factoryWithThrowingShims.js	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
@@ -0,0 +1,65 @@
+/**
+ * Copyright (c) 2013-present, Facebook, Inc.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+'use strict';
+
+var ReactPropTypesSecret = require('./lib/ReactPropTypesSecret');
+
+function emptyFunction() {}
+function emptyFunctionWithReset() {}
+emptyFunctionWithReset.resetWarningCache = emptyFunction;
+
+module.exports = function() {
+  function shim(props, propName, componentName, location, propFullName, secret) {
+    if (secret === ReactPropTypesSecret) {
+      // It is still safe when called from React.
+      return;
+    }
+    var err = new Error(
+      'Calling PropTypes validators directly is not supported by the `prop-types` package. ' +
+      'Use PropTypes.checkPropTypes() to call them. ' +
+      'Read more at http://fb.me/use-check-prop-types'
+    );
+    err.name = 'Invariant Violation';
+    throw err;
+  };
+  shim.isRequired = shim;
+  function getShim() {
+    return shim;
+  };
+  // Important!
+  // Keep this list in sync with production version in `./factoryWithTypeCheckers.js`.
+  var ReactPropTypes = {
+    array: shim,
+    bigint: shim,
+    bool: shim,
+    func: shim,
+    number: shim,
+    object: shim,
+    string: shim,
+    symbol: shim,
+
+    any: shim,
+    arrayOf: getShim,
+    element: shim,
+    elementType: shim,
+    instanceOf: getShim,
+    node: shim,
+    objectOf: getShim,
+    oneOf: getShim,
+    oneOfType: getShim,
+    shape: getShim,
+    exact: getShim,
+
+    checkPropTypes: emptyFunctionWithReset,
+    resetWarningCache: emptyFunction
+  };
+
+  ReactPropTypes.PropTypes = ReactPropTypes;
+
+  return ReactPropTypes;
+};
Index: node_modules/prop-types/factoryWithTypeCheckers.js
===================================================================
--- node_modules/prop-types/factoryWithTypeCheckers.js	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
+++ node_modules/prop-types/factoryWithTypeCheckers.js	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
@@ -0,0 +1,610 @@
+/**
+ * Copyright (c) 2013-present, Facebook, Inc.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+'use strict';
+
+var ReactIs = require('react-is');
+var assign = require('object-assign');
+
+var ReactPropTypesSecret = require('./lib/ReactPropTypesSecret');
+var has = require('./lib/has');
+var checkPropTypes = require('./checkPropTypes');
+
+var printWarning = function() {};
+
+if (process.env.NODE_ENV !== 'production') {
+  printWarning = function(text) {
+    var message = 'Warning: ' + text;
+    if (typeof console !== 'undefined') {
+      console.error(message);
+    }
+    try {
+      // --- Welcome to debugging React ---
+      // This error was thrown as a convenience so that you can use this stack
+      // to find the callsite that caused this warning to fire.
+      throw new Error(message);
+    } catch (x) {}
+  };
+}
+
+function emptyFunctionThatReturnsNull() {
+  return null;
+}
+
+module.exports = function(isValidElement, throwOnDirectAccess) {
+  /* global Symbol */
+  var ITERATOR_SYMBOL = typeof Symbol === 'function' && Symbol.iterator;
+  var FAUX_ITERATOR_SYMBOL = '@@iterator'; // Before Symbol spec.
+
+  /**
+   * Returns the iterator method function contained on the iterable object.
+   *
+   * Be sure to invoke the function with the iterable as context:
+   *
+   *     var iteratorFn = getIteratorFn(myIterable);
+   *     if (iteratorFn) {
+   *       var iterator = iteratorFn.call(myIterable);
+   *       ...
+   *     }
+   *
+   * @param {?object} maybeIterable
+   * @return {?function}
+   */
+  function getIteratorFn(maybeIterable) {
+    var iteratorFn = maybeIterable && (ITERATOR_SYMBOL && maybeIterable[ITERATOR_SYMBOL] || maybeIterable[FAUX_ITERATOR_SYMBOL]);
+    if (typeof iteratorFn === 'function') {
+      return iteratorFn;
+    }
+  }
+
+  /**
+   * Collection of methods that allow declaration and validation of props that are
+   * supplied to React components. Example usage:
+   *
+   *   var Props = require('ReactPropTypes');
+   *   var MyArticle = React.createClass({
+   *     propTypes: {
+   *       // An optional string prop named "description".
+   *       description: Props.string,
+   *
+   *       // A required enum prop named "category".
+   *       category: Props.oneOf(['News','Photos']).isRequired,
+   *
+   *       // A prop named "dialog" that requires an instance of Dialog.
+   *       dialog: Props.instanceOf(Dialog).isRequired
+   *     },
+   *     render: function() { ... }
+   *   });
+   *
+   * A more formal specification of how these methods are used:
+   *
+   *   type := array|bool|func|object|number|string|oneOf([...])|instanceOf(...)
+   *   decl := ReactPropTypes.{type}(.isRequired)?
+   *
+   * Each and every declaration produces a function with the same signature. This
+   * allows the creation of custom validation functions. For example:
+   *
+   *  var MyLink = React.createClass({
+   *    propTypes: {
+   *      // An optional string or URI prop named "href".
+   *      href: function(props, propName, componentName) {
+   *        var propValue = props[propName];
+   *        if (propValue != null && typeof propValue !== 'string' &&
+   *            !(propValue instanceof URI)) {
+   *          return new Error(
+   *            'Expected a string or an URI for ' + propName + ' in ' +
+   *            componentName
+   *          );
+   *        }
+   *      }
+   *    },
+   *    render: function() {...}
+   *  });
+   *
+   * @internal
+   */
+
+  var ANONYMOUS = '<<anonymous>>';
+
+  // Important!
+  // Keep this list in sync with production version in `./factoryWithThrowingShims.js`.
+  var ReactPropTypes = {
+    array: createPrimitiveTypeChecker('array'),
+    bigint: createPrimitiveTypeChecker('bigint'),
+    bool: createPrimitiveTypeChecker('boolean'),
+    func: createPrimitiveTypeChecker('function'),
+    number: createPrimitiveTypeChecker('number'),
+    object: createPrimitiveTypeChecker('object'),
+    string: createPrimitiveTypeChecker('string'),
+    symbol: createPrimitiveTypeChecker('symbol'),
+
+    any: createAnyTypeChecker(),
+    arrayOf: createArrayOfTypeChecker,
+    element: createElementTypeChecker(),
+    elementType: createElementTypeTypeChecker(),
+    instanceOf: createInstanceTypeChecker,
+    node: createNodeChecker(),
+    objectOf: createObjectOfTypeChecker,
+    oneOf: createEnumTypeChecker,
+    oneOfType: createUnionTypeChecker,
+    shape: createShapeTypeChecker,
+    exact: createStrictShapeTypeChecker,
+  };
+
+  /**
+   * inlined Object.is polyfill to avoid requiring consumers ship their own
+   * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is
+   */
+  /*eslint-disable no-self-compare*/
+  function is(x, y) {
+    // SameValue algorithm
+    if (x === y) {
+      // Steps 1-5, 7-10
+      // Steps 6.b-6.e: +0 != -0
+      return x !== 0 || 1 / x === 1 / y;
+    } else {
+      // Step 6.a: NaN == NaN
+      return x !== x && y !== y;
+    }
+  }
+  /*eslint-enable no-self-compare*/
+
+  /**
+   * We use an Error-like object for backward compatibility as people may call
+   * PropTypes directly and inspect their output. However, we don't use real
+   * Errors anymore. We don't inspect their stack anyway, and creating them
+   * is prohibitively expensive if they are created too often, such as what
+   * happens in oneOfType() for any type before the one that matched.
+   */
+  function PropTypeError(message, data) {
+    this.message = message;
+    this.data = data && typeof data === 'object' ? data: {};
+    this.stack = '';
+  }
+  // Make `instanceof Error` still work for returned errors.
+  PropTypeError.prototype = Error.prototype;
+
+  function createChainableTypeChecker(validate) {
+    if (process.env.NODE_ENV !== 'production') {
+      var manualPropTypeCallCache = {};
+      var manualPropTypeWarningCount = 0;
+    }
+    function checkType(isRequired, props, propName, componentName, location, propFullName, secret) {
+      componentName = componentName || ANONYMOUS;
+      propFullName = propFullName || propName;
+
+      if (secret !== ReactPropTypesSecret) {
+        if (throwOnDirectAccess) {
+          // New behavior only for users of `prop-types` package
+          var err = new Error(
+            'Calling PropTypes validators directly is not supported by the `prop-types` package. ' +
+            'Use `PropTypes.checkPropTypes()` to call them. ' +
+            'Read more at http://fb.me/use-check-prop-types'
+          );
+          err.name = 'Invariant Violation';
+          throw err;
+        } else if (process.env.NODE_ENV !== 'production' && typeof console !== 'undefined') {
+          // Old behavior for people using React.PropTypes
+          var cacheKey = componentName + ':' + propName;
+          if (
+            !manualPropTypeCallCache[cacheKey] &&
+            // Avoid spamming the console because they are often not actionable except for lib authors
+            manualPropTypeWarningCount < 3
+          ) {
+            printWarning(
+              'You are manually calling a React.PropTypes validation ' +
+              'function for the `' + propFullName + '` prop on `' + componentName + '`. This is deprecated ' +
+              'and will throw in the standalone `prop-types` package. ' +
+              'You may be seeing this warning due to a third-party PropTypes ' +
+              'library. See https://fb.me/react-warning-dont-call-proptypes ' + 'for details.'
+            );
+            manualPropTypeCallCache[cacheKey] = true;
+            manualPropTypeWarningCount++;
+          }
+        }
+      }
+      if (props[propName] == null) {
+        if (isRequired) {
+          if (props[propName] === null) {
+            return new PropTypeError('The ' + location + ' `' + propFullName + '` is marked as required ' + ('in `' + componentName + '`, but its value is `null`.'));
+          }
+          return new PropTypeError('The ' + location + ' `' + propFullName + '` is marked as required in ' + ('`' + componentName + '`, but its value is `undefined`.'));
+        }
+        return null;
+      } else {
+        return validate(props, propName, componentName, location, propFullName);
+      }
+    }
+
+    var chainedCheckType = checkType.bind(null, false);
+    chainedCheckType.isRequired = checkType.bind(null, true);
+
+    return chainedCheckType;
+  }
+
+  function createPrimitiveTypeChecker(expectedType) {
+    function validate(props, propName, componentName, location, propFullName, secret) {
+      var propValue = props[propName];
+      var propType = getPropType(propValue);
+      if (propType !== expectedType) {
+        // `propValue` being instance of, say, date/regexp, pass the 'object'
+        // check, but we can offer a more precise error message here rather than
+        // 'of type `object`'.
+        var preciseType = getPreciseType(propValue);
+
+        return new PropTypeError(
+          'Invalid ' + location + ' `' + propFullName + '` of type ' + ('`' + preciseType + '` supplied to `' + componentName + '`, expected ') + ('`' + expectedType + '`.'),
+          {expectedType: expectedType}
+        );
+      }
+      return null;
+    }
+    return createChainableTypeChecker(validate);
+  }
+
+  function createAnyTypeChecker() {
+    return createChainableTypeChecker(emptyFunctionThatReturnsNull);
+  }
+
+  function createArrayOfTypeChecker(typeChecker) {
+    function validate(props, propName, componentName, location, propFullName) {
+      if (typeof typeChecker !== 'function') {
+        return new PropTypeError('Property `' + propFullName + '` of component `' + componentName + '` has invalid PropType notation inside arrayOf.');
+      }
+      var propValue = props[propName];
+      if (!Array.isArray(propValue)) {
+        var propType = getPropType(propValue);
+        return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` of type ' + ('`' + propType + '` supplied to `' + componentName + '`, expected an array.'));
+      }
+      for (var i = 0; i < propValue.length; i++) {
+        var error = typeChecker(propValue, i, componentName, location, propFullName + '[' + i + ']', ReactPropTypesSecret);
+        if (error instanceof Error) {
+          return error;
+        }
+      }
+      return null;
+    }
+    return createChainableTypeChecker(validate);
+  }
+
+  function createElementTypeChecker() {
+    function validate(props, propName, componentName, location, propFullName) {
+      var propValue = props[propName];
+      if (!isValidElement(propValue)) {
+        var propType = getPropType(propValue);
+        return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` of type ' + ('`' + propType + '` supplied to `' + componentName + '`, expected a single ReactElement.'));
+      }
+      return null;
+    }
+    return createChainableTypeChecker(validate);
+  }
+
+  function createElementTypeTypeChecker() {
+    function validate(props, propName, componentName, location, propFullName) {
+      var propValue = props[propName];
+      if (!ReactIs.isValidElementType(propValue)) {
+        var propType = getPropType(propValue);
+        return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` of type ' + ('`' + propType + '` supplied to `' + componentName + '`, expected a single ReactElement type.'));
+      }
+      return null;
+    }
+    return createChainableTypeChecker(validate);
+  }
+
+  function createInstanceTypeChecker(expectedClass) {
+    function validate(props, propName, componentName, location, propFullName) {
+      if (!(props[propName] instanceof expectedClass)) {
+        var expectedClassName = expectedClass.name || ANONYMOUS;
+        var actualClassName = getClassName(props[propName]);
+        return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` of type ' + ('`' + actualClassName + '` supplied to `' + componentName + '`, expected ') + ('instance of `' + expectedClassName + '`.'));
+      }
+      return null;
+    }
+    return createChainableTypeChecker(validate);
+  }
+
+  function createEnumTypeChecker(expectedValues) {
+    if (!Array.isArray(expectedValues)) {
+      if (process.env.NODE_ENV !== 'production') {
+        if (arguments.length > 1) {
+          printWarning(
+            'Invalid arguments supplied to oneOf, expected an array, got ' + arguments.length + ' arguments. ' +
+            'A common mistake is to write oneOf(x, y, z) instead of oneOf([x, y, z]).'
+          );
+        } else {
+          printWarning('Invalid argument supplied to oneOf, expected an array.');
+        }
+      }
+      return emptyFunctionThatReturnsNull;
+    }
+
+    function validate(props, propName, componentName, location, propFullName) {
+      var propValue = props[propName];
+      for (var i = 0; i < expectedValues.length; i++) {
+        if (is(propValue, expectedValues[i])) {
+          return null;
+        }
+      }
+
+      var valuesString = JSON.stringify(expectedValues, function replacer(key, value) {
+        var type = getPreciseType(value);
+        if (type === 'symbol') {
+          return String(value);
+        }
+        return value;
+      });
+      return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` of value `' + String(propValue) + '` ' + ('supplied to `' + componentName + '`, expected one of ' + valuesString + '.'));
+    }
+    return createChainableTypeChecker(validate);
+  }
+
+  function createObjectOfTypeChecker(typeChecker) {
+    function validate(props, propName, componentName, location, propFullName) {
+      if (typeof typeChecker !== 'function') {
+        return new PropTypeError('Property `' + propFullName + '` of component `' + componentName + '` has invalid PropType notation inside objectOf.');
+      }
+      var propValue = props[propName];
+      var propType = getPropType(propValue);
+      if (propType !== 'object') {
+        return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` of type ' + ('`' + propType + '` supplied to `' + componentName + '`, expected an object.'));
+      }
+      for (var key in propValue) {
+        if (has(propValue, key)) {
+          var error = typeChecker(propValue, key, componentName, location, propFullName + '.' + key, ReactPropTypesSecret);
+          if (error instanceof Error) {
+            return error;
+          }
+        }
+      }
+      return null;
+    }
+    return createChainableTypeChecker(validate);
+  }
+
+  function createUnionTypeChecker(arrayOfTypeCheckers) {
+    if (!Array.isArray(arrayOfTypeCheckers)) {
+      process.env.NODE_ENV !== 'production' ? printWarning('Invalid argument supplied to oneOfType, expected an instance of array.') : void 0;
+      return emptyFunctionThatReturnsNull;
+    }
+
+    for (var i = 0; i < arrayOfTypeCheckers.length; i++) {
+      var checker = arrayOfTypeCheckers[i];
+      if (typeof checker !== 'function') {
+        printWarning(
+          'Invalid argument supplied to oneOfType. Expected an array of check functions, but ' +
+          'received ' + getPostfixForTypeWarning(checker) + ' at index ' + i + '.'
+        );
+        return emptyFunctionThatReturnsNull;
+      }
+    }
+
+    function validate(props, propName, componentName, location, propFullName) {
+      var expectedTypes = [];
+      for (var i = 0; i < arrayOfTypeCheckers.length; i++) {
+        var checker = arrayOfTypeCheckers[i];
+        var checkerResult = checker(props, propName, componentName, location, propFullName, ReactPropTypesSecret);
+        if (checkerResult == null) {
+          return null;
+        }
+        if (checkerResult.data && has(checkerResult.data, 'expectedType')) {
+          expectedTypes.push(checkerResult.data.expectedType);
+        }
+      }
+      var expectedTypesMessage = (expectedTypes.length > 0) ? ', expected one of type [' + expectedTypes.join(', ') + ']': '';
+      return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` supplied to ' + ('`' + componentName + '`' + expectedTypesMessage + '.'));
+    }
+    return createChainableTypeChecker(validate);
+  }
+
+  function createNodeChecker() {
+    function validate(props, propName, componentName, location, propFullName) {
+      if (!isNode(props[propName])) {
+        return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` supplied to ' + ('`' + componentName + '`, expected a ReactNode.'));
+      }
+      return null;
+    }
+    return createChainableTypeChecker(validate);
+  }
+
+  function invalidValidatorError(componentName, location, propFullName, key, type) {
+    return new PropTypeError(
+      (componentName || 'React class') + ': ' + location + ' type `' + propFullName + '.' + key + '` is invalid; ' +
+      'it must be a function, usually from the `prop-types` package, but received `' + type + '`.'
+    );
+  }
+
+  function createShapeTypeChecker(shapeTypes) {
+    function validate(props, propName, componentName, location, propFullName) {
+      var propValue = props[propName];
+      var propType = getPropType(propValue);
+      if (propType !== 'object') {
+        return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` of type `' + propType + '` ' + ('supplied to `' + componentName + '`, expected `object`.'));
+      }
+      for (var key in shapeTypes) {
+        var checker = shapeTypes[key];
+        if (typeof checker !== 'function') {
+          return invalidValidatorError(componentName, location, propFullName, key, getPreciseType(checker));
+        }
+        var error = checker(propValue, key, componentName, location, propFullName + '.' + key, ReactPropTypesSecret);
+        if (error) {
+          return error;
+        }
+      }
+      return null;
+    }
+    return createChainableTypeChecker(validate);
+  }
+
+  function createStrictShapeTypeChecker(shapeTypes) {
+    function validate(props, propName, componentName, location, propFullName) {
+      var propValue = props[propName];
+      var propType = getPropType(propValue);
+      if (propType !== 'object') {
+        return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` of type `' + propType + '` ' + ('supplied to `' + componentName + '`, expected `object`.'));
+      }
+      // We need to check all keys in case some are required but missing from props.
+      var allKeys = assign({}, props[propName], shapeTypes);
+      for (var key in allKeys) {
+        var checker = shapeTypes[key];
+        if (has(shapeTypes, key) && typeof checker !== 'function') {
+          return invalidValidatorError(componentName, location, propFullName, key, getPreciseType(checker));
+        }
+        if (!checker) {
+          return new PropTypeError(
+            'Invalid ' + location + ' `' + propFullName + '` key `' + key + '` supplied to `' + componentName + '`.' +
+            '\nBad object: ' + JSON.stringify(props[propName], null, '  ') +
+            '\nValid keys: ' + JSON.stringify(Object.keys(shapeTypes), null, '  ')
+          );
+        }
+        var error = checker(propValue, key, componentName, location, propFullName + '.' + key, ReactPropTypesSecret);
+        if (error) {
+          return error;
+        }
+      }
+      return null;
+    }
+
+    return createChainableTypeChecker(validate);
+  }
+
+  function isNode(propValue) {
+    switch (typeof propValue) {
+      case 'number':
+      case 'string':
+      case 'undefined':
+        return true;
+      case 'boolean':
+        return !propValue;
+      case 'object':
+        if (Array.isArray(propValue)) {
+          return propValue.every(isNode);
+        }
+        if (propValue === null || isValidElement(propValue)) {
+          return true;
+        }
+
+        var iteratorFn = getIteratorFn(propValue);
+        if (iteratorFn) {
+          var iterator = iteratorFn.call(propValue);
+          var step;
+          if (iteratorFn !== propValue.entries) {
+            while (!(step = iterator.next()).done) {
+              if (!isNode(step.value)) {
+                return false;
+              }
+            }
+          } else {
+            // Iterator will provide entry [k,v] tuples rather than values.
+            while (!(step = iterator.next()).done) {
+              var entry = step.value;
+              if (entry) {
+                if (!isNode(entry[1])) {
+                  return false;
+                }
+              }
+            }
+          }
+        } else {
+          return false;
+        }
+
+        return true;
+      default:
+        return false;
+    }
+  }
+
+  function isSymbol(propType, propValue) {
+    // Native Symbol.
+    if (propType === 'symbol') {
+      return true;
+    }
+
+    // falsy value can't be a Symbol
+    if (!propValue) {
+      return false;
+    }
+
+    // 19.4.3.5 Symbol.prototype[@@toStringTag] === 'Symbol'
+    if (propValue['@@toStringTag'] === 'Symbol') {
+      return true;
+    }
+
+    // Fallback for non-spec compliant Symbols which are polyfilled.
+    if (typeof Symbol === 'function' && propValue instanceof Symbol) {
+      return true;
+    }
+
+    return false;
+  }
+
+  // Equivalent of `typeof` but with special handling for array and regexp.
+  function getPropType(propValue) {
+    var propType = typeof propValue;
+    if (Array.isArray(propValue)) {
+      return 'array';
+    }
+    if (propValue instanceof RegExp) {
+      // Old webkits (at least until Android 4.0) return 'function' rather than
+      // 'object' for typeof a RegExp. We'll normalize this here so that /bla/
+      // passes PropTypes.object.
+      return 'object';
+    }
+    if (isSymbol(propType, propValue)) {
+      return 'symbol';
+    }
+    return propType;
+  }
+
+  // This handles more types than `getPropType`. Only used for error messages.
+  // See `createPrimitiveTypeChecker`.
+  function getPreciseType(propValue) {
+    if (typeof propValue === 'undefined' || propValue === null) {
+      return '' + propValue;
+    }
+    var propType = getPropType(propValue);
+    if (propType === 'object') {
+      if (propValue instanceof Date) {
+        return 'date';
+      } else if (propValue instanceof RegExp) {
+        return 'regexp';
+      }
+    }
+    return propType;
+  }
+
+  // Returns a string that is postfixed to a warning about an invalid type.
+  // For example, "undefined" or "of type array"
+  function getPostfixForTypeWarning(value) {
+    var type = getPreciseType(value);
+    switch (type) {
+      case 'array':
+      case 'object':
+        return 'an ' + type;
+      case 'boolean':
+      case 'date':
+      case 'regexp':
+        return 'a ' + type;
+      default:
+        return type;
+    }
+  }
+
+  // Returns class name of the object, if any.
+  function getClassName(propValue) {
+    if (!propValue.constructor || !propValue.constructor.name) {
+      return ANONYMOUS;
+    }
+    return propValue.constructor.name;
+  }
+
+  ReactPropTypes.checkPropTypes = checkPropTypes;
+  ReactPropTypes.resetWarningCache = checkPropTypes.resetWarningCache;
+  ReactPropTypes.PropTypes = ReactPropTypes;
+
+  return ReactPropTypes;
+};
Index: node_modules/prop-types/index.js
===================================================================
--- node_modules/prop-types/index.js	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
+++ node_modules/prop-types/index.js	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
@@ -0,0 +1,19 @@
+/**
+ * Copyright (c) 2013-present, Facebook, Inc.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+if (process.env.NODE_ENV !== 'production') {
+  var ReactIs = require('react-is');
+
+  // By explicitly using `prop-types` you are opting into new development behavior.
+  // http://fb.me/prop-types-in-prod
+  var throwOnDirectAccess = true;
+  module.exports = require('./factoryWithTypeCheckers')(ReactIs.isElement, throwOnDirectAccess);
+} else {
+  // By explicitly using `prop-types` you are opting into new production behavior.
+  // http://fb.me/prop-types-in-prod
+  module.exports = require('./factoryWithThrowingShims')();
+}
Index: node_modules/prop-types/lib/ReactPropTypesSecret.js
===================================================================
--- node_modules/prop-types/lib/ReactPropTypesSecret.js	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
+++ node_modules/prop-types/lib/ReactPropTypesSecret.js	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
@@ -0,0 +1,12 @@
+/**
+ * Copyright (c) 2013-present, Facebook, Inc.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+'use strict';
+
+var ReactPropTypesSecret = 'SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED';
+
+module.exports = ReactPropTypesSecret;
Index: node_modules/prop-types/lib/has.js
===================================================================
--- node_modules/prop-types/lib/has.js	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
+++ node_modules/prop-types/lib/has.js	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
@@ -0,0 +1,1 @@
+module.exports = Function.call.bind(Object.prototype.hasOwnProperty);
Index: node_modules/prop-types/package.json
===================================================================
--- node_modules/prop-types/package.json	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
+++ node_modules/prop-types/package.json	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
@@ -0,0 +1,60 @@
+{
+  "name": "prop-types",
+  "version": "15.8.1",
+  "description": "Runtime type checking for React props and similar objects.",
+  "sideEffects": false,
+  "main": "index.js",
+  "license": "MIT",
+  "files": [
+    "LICENSE",
+    "README.md",
+    "checkPropTypes.js",
+    "factory.js",
+    "factoryWithThrowingShims.js",
+    "factoryWithTypeCheckers.js",
+    "index.js",
+    "prop-types.js",
+    "prop-types.min.js",
+    "lib"
+  ],
+  "repository": "facebook/prop-types",
+  "keywords": [
+    "react"
+  ],
+  "bugs": {
+    "url": "https://github.com/facebook/prop-types/issues"
+  },
+  "homepage": "https://facebook.github.io/react/",
+  "dependencies": {
+    "loose-envify": "^1.4.0",
+    "object-assign": "^4.1.1",
+    "react-is": "^16.13.1"
+  },
+  "scripts": {
+    "pretest": "npm run lint",
+    "lint": "eslint .",
+    "test": "npm run tests-only",
+    "tests-only": "jest",
+    "umd": "NODE_ENV=development browserify index.js -t loose-envify --standalone PropTypes -o prop-types.js",
+    "umd-min": "NODE_ENV=production browserify index.js -t loose-envify -t uglifyify --standalone PropTypes  -p bundle-collapser/plugin -o | uglifyjs --compress unused,dead_code -o prop-types.min.js",
+    "build": "yarn umd && yarn umd-min",
+    "prepublish": "not-in-publish || yarn build"
+  },
+  "devDependencies": {
+    "babel-jest": "^19.0.0",
+    "babel-preset-react": "^6.24.1",
+    "browserify": "^16.5.0",
+    "bundle-collapser": "^1.4.0",
+    "eslint": "^8.6.0",
+    "in-publish": "^2.0.1",
+    "jest": "^19.0.2",
+    "react": "^15.7.0",
+    "uglifyify": "^5.0.2",
+    "uglifyjs": "^2.4.11"
+  },
+  "browserify": {
+    "transform": [
+      "loose-envify"
+    ]
+  }
+}
Index: node_modules/prop-types/prop-types.js
===================================================================
--- node_modules/prop-types/prop-types.js	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
+++ node_modules/prop-types/prop-types.js	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
@@ -0,0 +1,1315 @@
+(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.PropTypes = f()}})(function(){var define,module,exports;return (function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){
+/**
+ * Copyright (c) 2013-present, Facebook, Inc.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+'use strict';
+
+var printWarning = function() {};
+
+if ("development" !== 'production') {
+  var ReactPropTypesSecret = require('./lib/ReactPropTypesSecret');
+  var loggedTypeFailures = {};
+  var has = require('./lib/has');
+
+  printWarning = function(text) {
+    var message = 'Warning: ' + text;
+    if (typeof console !== 'undefined') {
+      console.error(message);
+    }
+    try {
+      // --- Welcome to debugging React ---
+      // This error was thrown as a convenience so that you can use this stack
+      // to find the callsite that caused this warning to fire.
+      throw new Error(message);
+    } catch (x) { /**/ }
+  };
+}
+
+/**
+ * Assert that the values match with the type specs.
+ * Error messages are memorized and will only be shown once.
+ *
+ * @param {object} typeSpecs Map of name to a ReactPropType
+ * @param {object} values Runtime values that need to be type-checked
+ * @param {string} location e.g. "prop", "context", "child context"
+ * @param {string} componentName Name of the component for error messages.
+ * @param {?Function} getStack Returns the component stack.
+ * @private
+ */
+function checkPropTypes(typeSpecs, values, location, componentName, getStack) {
+  if ("development" !== 'production') {
+    for (var typeSpecName in typeSpecs) {
+      if (has(typeSpecs, typeSpecName)) {
+        var error;
+        // Prop type validation may throw. In case they do, we don't want to
+        // fail the render phase where it didn't fail before. So we log it.
+        // After these have been cleaned up, we'll let them throw.
+        try {
+          // This is intentionally an invariant that gets caught. It's the same
+          // behavior as without this statement except with a better message.
+          if (typeof typeSpecs[typeSpecName] !== 'function') {
+            var err = Error(
+              (componentName || 'React class') + ': ' + location + ' type `' + typeSpecName + '` is invalid; ' +
+              'it must be a function, usually from the `prop-types` package, but received `' + typeof typeSpecs[typeSpecName] + '`.' +
+              'This often happens because of typos such as `PropTypes.function` instead of `PropTypes.func`.'
+            );
+            err.name = 'Invariant Violation';
+            throw err;
+          }
+          error = typeSpecs[typeSpecName](values, typeSpecName, componentName, location, null, ReactPropTypesSecret);
+        } catch (ex) {
+          error = ex;
+        }
+        if (error && !(error instanceof Error)) {
+          printWarning(
+            (componentName || 'React class') + ': type specification of ' +
+            location + ' `' + typeSpecName + '` is invalid; the type checker ' +
+            'function must return `null` or an `Error` but returned a ' + typeof error + '. ' +
+            'You may have forgotten to pass an argument to the type checker ' +
+            'creator (arrayOf, instanceOf, objectOf, oneOf, oneOfType, and ' +
+            'shape all require an argument).'
+          );
+        }
+        if (error instanceof Error && !(error.message in loggedTypeFailures)) {
+          // Only monitor this failure once because there tends to be a lot of the
+          // same error.
+          loggedTypeFailures[error.message] = true;
+
+          var stack = getStack ? getStack() : '';
+
+          printWarning(
+            'Failed ' + location + ' type: ' + error.message + (stack != null ? stack : '')
+          );
+        }
+      }
+    }
+  }
+}
+
+/**
+ * Resets warning cache when testing.
+ *
+ * @private
+ */
+checkPropTypes.resetWarningCache = function() {
+  if ("development" !== 'production') {
+    loggedTypeFailures = {};
+  }
+}
+
+module.exports = checkPropTypes;
+
+},{"./lib/ReactPropTypesSecret":5,"./lib/has":6}],2:[function(require,module,exports){
+/**
+ * Copyright (c) 2013-present, Facebook, Inc.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+'use strict';
+
+var ReactPropTypesSecret = require('./lib/ReactPropTypesSecret');
+
+function emptyFunction() {}
+function emptyFunctionWithReset() {}
+emptyFunctionWithReset.resetWarningCache = emptyFunction;
+
+module.exports = function() {
+  function shim(props, propName, componentName, location, propFullName, secret) {
+    if (secret === ReactPropTypesSecret) {
+      // It is still safe when called from React.
+      return;
+    }
+    var err = new Error(
+      'Calling PropTypes validators directly is not supported by the `prop-types` package. ' +
+      'Use PropTypes.checkPropTypes() to call them. ' +
+      'Read more at http://fb.me/use-check-prop-types'
+    );
+    err.name = 'Invariant Violation';
+    throw err;
+  };
+  shim.isRequired = shim;
+  function getShim() {
+    return shim;
+  };
+  // Important!
+  // Keep this list in sync with production version in `./factoryWithTypeCheckers.js`.
+  var ReactPropTypes = {
+    array: shim,
+    bigint: shim,
+    bool: shim,
+    func: shim,
+    number: shim,
+    object: shim,
+    string: shim,
+    symbol: shim,
+
+    any: shim,
+    arrayOf: getShim,
+    element: shim,
+    elementType: shim,
+    instanceOf: getShim,
+    node: shim,
+    objectOf: getShim,
+    oneOf: getShim,
+    oneOfType: getShim,
+    shape: getShim,
+    exact: getShim,
+
+    checkPropTypes: emptyFunctionWithReset,
+    resetWarningCache: emptyFunction
+  };
+
+  ReactPropTypes.PropTypes = ReactPropTypes;
+
+  return ReactPropTypes;
+};
+
+},{"./lib/ReactPropTypesSecret":5}],3:[function(require,module,exports){
+/**
+ * Copyright (c) 2013-present, Facebook, Inc.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+'use strict';
+
+var ReactIs = require('react-is');
+var assign = require('object-assign');
+
+var ReactPropTypesSecret = require('./lib/ReactPropTypesSecret');
+var has = require('./lib/has');
+var checkPropTypes = require('./checkPropTypes');
+
+var printWarning = function() {};
+
+if ("development" !== 'production') {
+  printWarning = function(text) {
+    var message = 'Warning: ' + text;
+    if (typeof console !== 'undefined') {
+      console.error(message);
+    }
+    try {
+      // --- Welcome to debugging React ---
+      // This error was thrown as a convenience so that you can use this stack
+      // to find the callsite that caused this warning to fire.
+      throw new Error(message);
+    } catch (x) {}
+  };
+}
+
+function emptyFunctionThatReturnsNull() {
+  return null;
+}
+
+module.exports = function(isValidElement, throwOnDirectAccess) {
+  /* global Symbol */
+  var ITERATOR_SYMBOL = typeof Symbol === 'function' && Symbol.iterator;
+  var FAUX_ITERATOR_SYMBOL = '@@iterator'; // Before Symbol spec.
+
+  /**
+   * Returns the iterator method function contained on the iterable object.
+   *
+   * Be sure to invoke the function with the iterable as context:
+   *
+   *     var iteratorFn = getIteratorFn(myIterable);
+   *     if (iteratorFn) {
+   *       var iterator = iteratorFn.call(myIterable);
+   *       ...
+   *     }
+   *
+   * @param {?object} maybeIterable
+   * @return {?function}
+   */
+  function getIteratorFn(maybeIterable) {
+    var iteratorFn = maybeIterable && (ITERATOR_SYMBOL && maybeIterable[ITERATOR_SYMBOL] || maybeIterable[FAUX_ITERATOR_SYMBOL]);
+    if (typeof iteratorFn === 'function') {
+      return iteratorFn;
+    }
+  }
+
+  /**
+   * Collection of methods that allow declaration and validation of props that are
+   * supplied to React components. Example usage:
+   *
+   *   var Props = require('ReactPropTypes');
+   *   var MyArticle = React.createClass({
+   *     propTypes: {
+   *       // An optional string prop named "description".
+   *       description: Props.string,
+   *
+   *       // A required enum prop named "category".
+   *       category: Props.oneOf(['News','Photos']).isRequired,
+   *
+   *       // A prop named "dialog" that requires an instance of Dialog.
+   *       dialog: Props.instanceOf(Dialog).isRequired
+   *     },
+   *     render: function() { ... }
+   *   });
+   *
+   * A more formal specification of how these methods are used:
+   *
+   *   type := array|bool|func|object|number|string|oneOf([...])|instanceOf(...)
+   *   decl := ReactPropTypes.{type}(.isRequired)?
+   *
+   * Each and every declaration produces a function with the same signature. This
+   * allows the creation of custom validation functions. For example:
+   *
+   *  var MyLink = React.createClass({
+   *    propTypes: {
+   *      // An optional string or URI prop named "href".
+   *      href: function(props, propName, componentName) {
+   *        var propValue = props[propName];
+   *        if (propValue != null && typeof propValue !== 'string' &&
+   *            !(propValue instanceof URI)) {
+   *          return new Error(
+   *            'Expected a string or an URI for ' + propName + ' in ' +
+   *            componentName
+   *          );
+   *        }
+   *      }
+   *    },
+   *    render: function() {...}
+   *  });
+   *
+   * @internal
+   */
+
+  var ANONYMOUS = '<<anonymous>>';
+
+  // Important!
+  // Keep this list in sync with production version in `./factoryWithThrowingShims.js`.
+  var ReactPropTypes = {
+    array: createPrimitiveTypeChecker('array'),
+    bigint: createPrimitiveTypeChecker('bigint'),
+    bool: createPrimitiveTypeChecker('boolean'),
+    func: createPrimitiveTypeChecker('function'),
+    number: createPrimitiveTypeChecker('number'),
+    object: createPrimitiveTypeChecker('object'),
+    string: createPrimitiveTypeChecker('string'),
+    symbol: createPrimitiveTypeChecker('symbol'),
+
+    any: createAnyTypeChecker(),
+    arrayOf: createArrayOfTypeChecker,
+    element: createElementTypeChecker(),
+    elementType: createElementTypeTypeChecker(),
+    instanceOf: createInstanceTypeChecker,
+    node: createNodeChecker(),
+    objectOf: createObjectOfTypeChecker,
+    oneOf: createEnumTypeChecker,
+    oneOfType: createUnionTypeChecker,
+    shape: createShapeTypeChecker,
+    exact: createStrictShapeTypeChecker,
+  };
+
+  /**
+   * inlined Object.is polyfill to avoid requiring consumers ship their own
+   * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is
+   */
+  /*eslint-disable no-self-compare*/
+  function is(x, y) {
+    // SameValue algorithm
+    if (x === y) {
+      // Steps 1-5, 7-10
+      // Steps 6.b-6.e: +0 != -0
+      return x !== 0 || 1 / x === 1 / y;
+    } else {
+      // Step 6.a: NaN == NaN
+      return x !== x && y !== y;
+    }
+  }
+  /*eslint-enable no-self-compare*/
+
+  /**
+   * We use an Error-like object for backward compatibility as people may call
+   * PropTypes directly and inspect their output. However, we don't use real
+   * Errors anymore. We don't inspect their stack anyway, and creating them
+   * is prohibitively expensive if they are created too often, such as what
+   * happens in oneOfType() for any type before the one that matched.
+   */
+  function PropTypeError(message, data) {
+    this.message = message;
+    this.data = data && typeof data === 'object' ? data: {};
+    this.stack = '';
+  }
+  // Make `instanceof Error` still work for returned errors.
+  PropTypeError.prototype = Error.prototype;
+
+  function createChainableTypeChecker(validate) {
+    if ("development" !== 'production') {
+      var manualPropTypeCallCache = {};
+      var manualPropTypeWarningCount = 0;
+    }
+    function checkType(isRequired, props, propName, componentName, location, propFullName, secret) {
+      componentName = componentName || ANONYMOUS;
+      propFullName = propFullName || propName;
+
+      if (secret !== ReactPropTypesSecret) {
+        if (throwOnDirectAccess) {
+          // New behavior only for users of `prop-types` package
+          var err = new Error(
+            'Calling PropTypes validators directly is not supported by the `prop-types` package. ' +
+            'Use `PropTypes.checkPropTypes()` to call them. ' +
+            'Read more at http://fb.me/use-check-prop-types'
+          );
+          err.name = 'Invariant Violation';
+          throw err;
+        } else if ("development" !== 'production' && typeof console !== 'undefined') {
+          // Old behavior for people using React.PropTypes
+          var cacheKey = componentName + ':' + propName;
+          if (
+            !manualPropTypeCallCache[cacheKey] &&
+            // Avoid spamming the console because they are often not actionable except for lib authors
+            manualPropTypeWarningCount < 3
+          ) {
+            printWarning(
+              'You are manually calling a React.PropTypes validation ' +
+              'function for the `' + propFullName + '` prop on `' + componentName + '`. This is deprecated ' +
+              'and will throw in the standalone `prop-types` package. ' +
+              'You may be seeing this warning due to a third-party PropTypes ' +
+              'library. See https://fb.me/react-warning-dont-call-proptypes ' + 'for details.'
+            );
+            manualPropTypeCallCache[cacheKey] = true;
+            manualPropTypeWarningCount++;
+          }
+        }
+      }
+      if (props[propName] == null) {
+        if (isRequired) {
+          if (props[propName] === null) {
+            return new PropTypeError('The ' + location + ' `' + propFullName + '` is marked as required ' + ('in `' + componentName + '`, but its value is `null`.'));
+          }
+          return new PropTypeError('The ' + location + ' `' + propFullName + '` is marked as required in ' + ('`' + componentName + '`, but its value is `undefined`.'));
+        }
+        return null;
+      } else {
+        return validate(props, propName, componentName, location, propFullName);
+      }
+    }
+
+    var chainedCheckType = checkType.bind(null, false);
+    chainedCheckType.isRequired = checkType.bind(null, true);
+
+    return chainedCheckType;
+  }
+
+  function createPrimitiveTypeChecker(expectedType) {
+    function validate(props, propName, componentName, location, propFullName, secret) {
+      var propValue = props[propName];
+      var propType = getPropType(propValue);
+      if (propType !== expectedType) {
+        // `propValue` being instance of, say, date/regexp, pass the 'object'
+        // check, but we can offer a more precise error message here rather than
+        // 'of type `object`'.
+        var preciseType = getPreciseType(propValue);
+
+        return new PropTypeError(
+          'Invalid ' + location + ' `' + propFullName + '` of type ' + ('`' + preciseType + '` supplied to `' + componentName + '`, expected ') + ('`' + expectedType + '`.'),
+          {expectedType: expectedType}
+        );
+      }
+      return null;
+    }
+    return createChainableTypeChecker(validate);
+  }
+
+  function createAnyTypeChecker() {
+    return createChainableTypeChecker(emptyFunctionThatReturnsNull);
+  }
+
+  function createArrayOfTypeChecker(typeChecker) {
+    function validate(props, propName, componentName, location, propFullName) {
+      if (typeof typeChecker !== 'function') {
+        return new PropTypeError('Property `' + propFullName + '` of component `' + componentName + '` has invalid PropType notation inside arrayOf.');
+      }
+      var propValue = props[propName];
+      if (!Array.isArray(propValue)) {
+        var propType = getPropType(propValue);
+        return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` of type ' + ('`' + propType + '` supplied to `' + componentName + '`, expected an array.'));
+      }
+      for (var i = 0; i < propValue.length; i++) {
+        var error = typeChecker(propValue, i, componentName, location, propFullName + '[' + i + ']', ReactPropTypesSecret);
+        if (error instanceof Error) {
+          return error;
+        }
+      }
+      return null;
+    }
+    return createChainableTypeChecker(validate);
+  }
+
+  function createElementTypeChecker() {
+    function validate(props, propName, componentName, location, propFullName) {
+      var propValue = props[propName];
+      if (!isValidElement(propValue)) {
+        var propType = getPropType(propValue);
+        return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` of type ' + ('`' + propType + '` supplied to `' + componentName + '`, expected a single ReactElement.'));
+      }
+      return null;
+    }
+    return createChainableTypeChecker(validate);
+  }
+
+  function createElementTypeTypeChecker() {
+    function validate(props, propName, componentName, location, propFullName) {
+      var propValue = props[propName];
+      if (!ReactIs.isValidElementType(propValue)) {
+        var propType = getPropType(propValue);
+        return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` of type ' + ('`' + propType + '` supplied to `' + componentName + '`, expected a single ReactElement type.'));
+      }
+      return null;
+    }
+    return createChainableTypeChecker(validate);
+  }
+
+  function createInstanceTypeChecker(expectedClass) {
+    function validate(props, propName, componentName, location, propFullName) {
+      if (!(props[propName] instanceof expectedClass)) {
+        var expectedClassName = expectedClass.name || ANONYMOUS;
+        var actualClassName = getClassName(props[propName]);
+        return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` of type ' + ('`' + actualClassName + '` supplied to `' + componentName + '`, expected ') + ('instance of `' + expectedClassName + '`.'));
+      }
+      return null;
+    }
+    return createChainableTypeChecker(validate);
+  }
+
+  function createEnumTypeChecker(expectedValues) {
+    if (!Array.isArray(expectedValues)) {
+      if ("development" !== 'production') {
+        if (arguments.length > 1) {
+          printWarning(
+            'Invalid arguments supplied to oneOf, expected an array, got ' + arguments.length + ' arguments. ' +
+            'A common mistake is to write oneOf(x, y, z) instead of oneOf([x, y, z]).'
+          );
+        } else {
+          printWarning('Invalid argument supplied to oneOf, expected an array.');
+        }
+      }
+      return emptyFunctionThatReturnsNull;
+    }
+
+    function validate(props, propName, componentName, location, propFullName) {
+      var propValue = props[propName];
+      for (var i = 0; i < expectedValues.length; i++) {
+        if (is(propValue, expectedValues[i])) {
+          return null;
+        }
+      }
+
+      var valuesString = JSON.stringify(expectedValues, function replacer(key, value) {
+        var type = getPreciseType(value);
+        if (type === 'symbol') {
+          return String(value);
+        }
+        return value;
+      });
+      return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` of value `' + String(propValue) + '` ' + ('supplied to `' + componentName + '`, expected one of ' + valuesString + '.'));
+    }
+    return createChainableTypeChecker(validate);
+  }
+
+  function createObjectOfTypeChecker(typeChecker) {
+    function validate(props, propName, componentName, location, propFullName) {
+      if (typeof typeChecker !== 'function') {
+        return new PropTypeError('Property `' + propFullName + '` of component `' + componentName + '` has invalid PropType notation inside objectOf.');
+      }
+      var propValue = props[propName];
+      var propType = getPropType(propValue);
+      if (propType !== 'object') {
+        return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` of type ' + ('`' + propType + '` supplied to `' + componentName + '`, expected an object.'));
+      }
+      for (var key in propValue) {
+        if (has(propValue, key)) {
+          var error = typeChecker(propValue, key, componentName, location, propFullName + '.' + key, ReactPropTypesSecret);
+          if (error instanceof Error) {
+            return error;
+          }
+        }
+      }
+      return null;
+    }
+    return createChainableTypeChecker(validate);
+  }
+
+  function createUnionTypeChecker(arrayOfTypeCheckers) {
+    if (!Array.isArray(arrayOfTypeCheckers)) {
+      "development" !== 'production' ? printWarning('Invalid argument supplied to oneOfType, expected an instance of array.') : void 0;
+      return emptyFunctionThatReturnsNull;
+    }
+
+    for (var i = 0; i < arrayOfTypeCheckers.length; i++) {
+      var checker = arrayOfTypeCheckers[i];
+      if (typeof checker !== 'function') {
+        printWarning(
+          'Invalid argument supplied to oneOfType. Expected an array of check functions, but ' +
+          'received ' + getPostfixForTypeWarning(checker) + ' at index ' + i + '.'
+        );
+        return emptyFunctionThatReturnsNull;
+      }
+    }
+
+    function validate(props, propName, componentName, location, propFullName) {
+      var expectedTypes = [];
+      for (var i = 0; i < arrayOfTypeCheckers.length; i++) {
+        var checker = arrayOfTypeCheckers[i];
+        var checkerResult = checker(props, propName, componentName, location, propFullName, ReactPropTypesSecret);
+        if (checkerResult == null) {
+          return null;
+        }
+        if (checkerResult.data.hasOwnProperty('expectedType')) {
+          expectedTypes.push(checkerResult.data.expectedType);
+        }
+      }
+      var expectedTypesMessage = (expectedTypes.length > 0) ? ', expected one of type [' + expectedTypes.join(', ') + ']': '';
+      return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` supplied to ' + ('`' + componentName + '`' + expectedTypesMessage + '.'));
+    }
+    return createChainableTypeChecker(validate);
+  }
+
+  function createNodeChecker() {
+    function validate(props, propName, componentName, location, propFullName) {
+      if (!isNode(props[propName])) {
+        return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` supplied to ' + ('`' + componentName + '`, expected a ReactNode.'));
+      }
+      return null;
+    }
+    return createChainableTypeChecker(validate);
+  }
+
+  function invalidValidatorError(componentName, location, propFullName, key, type) {
+    return new PropTypeError(
+      (componentName || 'React class') + ': ' + location + ' type `' + propFullName + '.' + key + '` is invalid; ' +
+      'it must be a function, usually from the `prop-types` package, but received `' + type + '`.'
+    );
+  }
+
+  function createShapeTypeChecker(shapeTypes) {
+    function validate(props, propName, componentName, location, propFullName) {
+      var propValue = props[propName];
+      var propType = getPropType(propValue);
+      if (propType !== 'object') {
+        return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` of type `' + propType + '` ' + ('supplied to `' + componentName + '`, expected `object`.'));
+      }
+      for (var key in shapeTypes) {
+        var checker = shapeTypes[key];
+        if (typeof checker !== 'function') {
+          return invalidValidatorError(componentName, location, propFullName, key, getPreciseType(checker));
+        }
+        var error = checker(propValue, key, componentName, location, propFullName + '.' + key, ReactPropTypesSecret);
+        if (error) {
+          return error;
+        }
+      }
+      return null;
+    }
+    return createChainableTypeChecker(validate);
+  }
+
+  function createStrictShapeTypeChecker(shapeTypes) {
+    function validate(props, propName, componentName, location, propFullName) {
+      var propValue = props[propName];
+      var propType = getPropType(propValue);
+      if (propType !== 'object') {
+        return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` of type `' + propType + '` ' + ('supplied to `' + componentName + '`, expected `object`.'));
+      }
+      // We need to check all keys in case some are required but missing from props.
+      var allKeys = assign({}, props[propName], shapeTypes);
+      for (var key in allKeys) {
+        var checker = shapeTypes[key];
+        if (has(shapeTypes, key) && typeof checker !== 'function') {
+          return invalidValidatorError(componentName, location, propFullName, key, getPreciseType(checker));
+        }
+        if (!checker) {
+          return new PropTypeError(
+            'Invalid ' + location + ' `' + propFullName + '` key `' + key + '` supplied to `' + componentName + '`.' +
+            '\nBad object: ' + JSON.stringify(props[propName], null, '  ') +
+            '\nValid keys: ' + JSON.stringify(Object.keys(shapeTypes), null, '  ')
+          );
+        }
+        var error = checker(propValue, key, componentName, location, propFullName + '.' + key, ReactPropTypesSecret);
+        if (error) {
+          return error;
+        }
+      }
+      return null;
+    }
+
+    return createChainableTypeChecker(validate);
+  }
+
+  function isNode(propValue) {
+    switch (typeof propValue) {
+      case 'number':
+      case 'string':
+      case 'undefined':
+        return true;
+      case 'boolean':
+        return !propValue;
+      case 'object':
+        if (Array.isArray(propValue)) {
+          return propValue.every(isNode);
+        }
+        if (propValue === null || isValidElement(propValue)) {
+          return true;
+        }
+
+        var iteratorFn = getIteratorFn(propValue);
+        if (iteratorFn) {
+          var iterator = iteratorFn.call(propValue);
+          var step;
+          if (iteratorFn !== propValue.entries) {
+            while (!(step = iterator.next()).done) {
+              if (!isNode(step.value)) {
+                return false;
+              }
+            }
+          } else {
+            // Iterator will provide entry [k,v] tuples rather than values.
+            while (!(step = iterator.next()).done) {
+              var entry = step.value;
+              if (entry) {
+                if (!isNode(entry[1])) {
+                  return false;
+                }
+              }
+            }
+          }
+        } else {
+          return false;
+        }
+
+        return true;
+      default:
+        return false;
+    }
+  }
+
+  function isSymbol(propType, propValue) {
+    // Native Symbol.
+    if (propType === 'symbol') {
+      return true;
+    }
+
+    // falsy value can't be a Symbol
+    if (!propValue) {
+      return false;
+    }
+
+    // 19.4.3.5 Symbol.prototype[@@toStringTag] === 'Symbol'
+    if (propValue['@@toStringTag'] === 'Symbol') {
+      return true;
+    }
+
+    // Fallback for non-spec compliant Symbols which are polyfilled.
+    if (typeof Symbol === 'function' && propValue instanceof Symbol) {
+      return true;
+    }
+
+    return false;
+  }
+
+  // Equivalent of `typeof` but with special handling for array and regexp.
+  function getPropType(propValue) {
+    var propType = typeof propValue;
+    if (Array.isArray(propValue)) {
+      return 'array';
+    }
+    if (propValue instanceof RegExp) {
+      // Old webkits (at least until Android 4.0) return 'function' rather than
+      // 'object' for typeof a RegExp. We'll normalize this here so that /bla/
+      // passes PropTypes.object.
+      return 'object';
+    }
+    if (isSymbol(propType, propValue)) {
+      return 'symbol';
+    }
+    return propType;
+  }
+
+  // This handles more types than `getPropType`. Only used for error messages.
+  // See `createPrimitiveTypeChecker`.
+  function getPreciseType(propValue) {
+    if (typeof propValue === 'undefined' || propValue === null) {
+      return '' + propValue;
+    }
+    var propType = getPropType(propValue);
+    if (propType === 'object') {
+      if (propValue instanceof Date) {
+        return 'date';
+      } else if (propValue instanceof RegExp) {
+        return 'regexp';
+      }
+    }
+    return propType;
+  }
+
+  // Returns a string that is postfixed to a warning about an invalid type.
+  // For example, "undefined" or "of type array"
+  function getPostfixForTypeWarning(value) {
+    var type = getPreciseType(value);
+    switch (type) {
+      case 'array':
+      case 'object':
+        return 'an ' + type;
+      case 'boolean':
+      case 'date':
+      case 'regexp':
+        return 'a ' + type;
+      default:
+        return type;
+    }
+  }
+
+  // Returns class name of the object, if any.
+  function getClassName(propValue) {
+    if (!propValue.constructor || !propValue.constructor.name) {
+      return ANONYMOUS;
+    }
+    return propValue.constructor.name;
+  }
+
+  ReactPropTypes.checkPropTypes = checkPropTypes;
+  ReactPropTypes.resetWarningCache = checkPropTypes.resetWarningCache;
+  ReactPropTypes.PropTypes = ReactPropTypes;
+
+  return ReactPropTypes;
+};
+
+},{"./checkPropTypes":1,"./lib/ReactPropTypesSecret":5,"./lib/has":6,"object-assign":7,"react-is":11}],4:[function(require,module,exports){
+/**
+ * Copyright (c) 2013-present, Facebook, Inc.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+if ("development" !== 'production') {
+  var ReactIs = require('react-is');
+
+  // By explicitly using `prop-types` you are opting into new development behavior.
+  // http://fb.me/prop-types-in-prod
+  var throwOnDirectAccess = true;
+  module.exports = require('./factoryWithTypeCheckers')(ReactIs.isElement, throwOnDirectAccess);
+} else {
+  // By explicitly using `prop-types` you are opting into new production behavior.
+  // http://fb.me/prop-types-in-prod
+  module.exports = require('./factoryWithThrowingShims')();
+}
+
+},{"./factoryWithThrowingShims":2,"./factoryWithTypeCheckers":3,"react-is":11}],5:[function(require,module,exports){
+/**
+ * Copyright (c) 2013-present, Facebook, Inc.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+'use strict';
+
+var ReactPropTypesSecret = 'SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED';
+
+module.exports = ReactPropTypesSecret;
+
+},{}],6:[function(require,module,exports){
+module.exports = Function.call.bind(Object.prototype.hasOwnProperty);
+
+},{}],7:[function(require,module,exports){
+/*
+object-assign
+(c) Sindre Sorhus
+@license MIT
+*/
+
+'use strict';
+/* eslint-disable no-unused-vars */
+var getOwnPropertySymbols = Object.getOwnPropertySymbols;
+var hasOwnProperty = Object.prototype.hasOwnProperty;
+var propIsEnumerable = Object.prototype.propertyIsEnumerable;
+
+function toObject(val) {
+	if (val === null || val === undefined) {
+		throw new TypeError('Object.assign cannot be called with null or undefined');
+	}
+
+	return Object(val);
+}
+
+function shouldUseNative() {
+	try {
+		if (!Object.assign) {
+			return false;
+		}
+
+		// Detect buggy property enumeration order in older V8 versions.
+
+		// https://bugs.chromium.org/p/v8/issues/detail?id=4118
+		var test1 = new String('abc');  // eslint-disable-line no-new-wrappers
+		test1[5] = 'de';
+		if (Object.getOwnPropertyNames(test1)[0] === '5') {
+			return false;
+		}
+
+		// https://bugs.chromium.org/p/v8/issues/detail?id=3056
+		var test2 = {};
+		for (var i = 0; i < 10; i++) {
+			test2['_' + String.fromCharCode(i)] = i;
+		}
+		var order2 = Object.getOwnPropertyNames(test2).map(function (n) {
+			return test2[n];
+		});
+		if (order2.join('') !== '0123456789') {
+			return false;
+		}
+
+		// https://bugs.chromium.org/p/v8/issues/detail?id=3056
+		var test3 = {};
+		'abcdefghijklmnopqrst'.split('').forEach(function (letter) {
+			test3[letter] = letter;
+		});
+		if (Object.keys(Object.assign({}, test3)).join('') !==
+				'abcdefghijklmnopqrst') {
+			return false;
+		}
+
+		return true;
+	} catch (err) {
+		// We don't expect any of the above to throw, but better to be safe.
+		return false;
+	}
+}
+
+module.exports = shouldUseNative() ? Object.assign : function (target, source) {
+	var from;
+	var to = toObject(target);
+	var symbols;
+
+	for (var s = 1; s < arguments.length; s++) {
+		from = Object(arguments[s]);
+
+		for (var key in from) {
+			if (hasOwnProperty.call(from, key)) {
+				to[key] = from[key];
+			}
+		}
+
+		if (getOwnPropertySymbols) {
+			symbols = getOwnPropertySymbols(from);
+			for (var i = 0; i < symbols.length; i++) {
+				if (propIsEnumerable.call(from, symbols[i])) {
+					to[symbols[i]] = from[symbols[i]];
+				}
+			}
+		}
+	}
+
+	return to;
+};
+
+},{}],8:[function(require,module,exports){
+// shim for using process in browser
+var process = module.exports = {};
+
+// cached from whatever global is present so that test runners that stub it
+// don't break things.  But we need to wrap it in a try catch in case it is
+// wrapped in strict mode code which doesn't define any globals.  It's inside a
+// function because try/catches deoptimize in certain engines.
+
+var cachedSetTimeout;
+var cachedClearTimeout;
+
+function defaultSetTimout() {
+    throw new Error('setTimeout has not been defined');
+}
+function defaultClearTimeout () {
+    throw new Error('clearTimeout has not been defined');
+}
+(function () {
+    try {
+        if (typeof setTimeout === 'function') {
+            cachedSetTimeout = setTimeout;
+        } else {
+            cachedSetTimeout = defaultSetTimout;
+        }
+    } catch (e) {
+        cachedSetTimeout = defaultSetTimout;
+    }
+    try {
+        if (typeof clearTimeout === 'function') {
+            cachedClearTimeout = clearTimeout;
+        } else {
+            cachedClearTimeout = defaultClearTimeout;
+        }
+    } catch (e) {
+        cachedClearTimeout = defaultClearTimeout;
+    }
+} ())
+function runTimeout(fun) {
+    if (cachedSetTimeout === setTimeout) {
+        //normal enviroments in sane situations
+        return setTimeout(fun, 0);
+    }
+    // if setTimeout wasn't available but was latter defined
+    if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) {
+        cachedSetTimeout = setTimeout;
+        return setTimeout(fun, 0);
+    }
+    try {
+        // when when somebody has screwed with setTimeout but no I.E. maddness
+        return cachedSetTimeout(fun, 0);
+    } catch(e){
+        try {
+            // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally
+            return cachedSetTimeout.call(null, fun, 0);
+        } catch(e){
+            // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error
+            return cachedSetTimeout.call(this, fun, 0);
+        }
+    }
+
+
+}
+function runClearTimeout(marker) {
+    if (cachedClearTimeout === clearTimeout) {
+        //normal enviroments in sane situations
+        return clearTimeout(marker);
+    }
+    // if clearTimeout wasn't available but was latter defined
+    if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) {
+        cachedClearTimeout = clearTimeout;
+        return clearTimeout(marker);
+    }
+    try {
+        // when when somebody has screwed with setTimeout but no I.E. maddness
+        return cachedClearTimeout(marker);
+    } catch (e){
+        try {
+            // When we are in I.E. but the script has been evaled so I.E. doesn't  trust the global object when called normally
+            return cachedClearTimeout.call(null, marker);
+        } catch (e){
+            // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error.
+            // Some versions of I.E. have different rules for clearTimeout vs setTimeout
+            return cachedClearTimeout.call(this, marker);
+        }
+    }
+
+
+
+}
+var queue = [];
+var draining = false;
+var currentQueue;
+var queueIndex = -1;
+
+function cleanUpNextTick() {
+    if (!draining || !currentQueue) {
+        return;
+    }
+    draining = false;
+    if (currentQueue.length) {
+        queue = currentQueue.concat(queue);
+    } else {
+        queueIndex = -1;
+    }
+    if (queue.length) {
+        drainQueue();
+    }
+}
+
+function drainQueue() {
+    if (draining) {
+        return;
+    }
+    var timeout = runTimeout(cleanUpNextTick);
+    draining = true;
+
+    var len = queue.length;
+    while(len) {
+        currentQueue = queue;
+        queue = [];
+        while (++queueIndex < len) {
+            if (currentQueue) {
+                currentQueue[queueIndex].run();
+            }
+        }
+        queueIndex = -1;
+        len = queue.length;
+    }
+    currentQueue = null;
+    draining = false;
+    runClearTimeout(timeout);
+}
+
+process.nextTick = function (fun) {
+    var args = new Array(arguments.length - 1);
+    if (arguments.length > 1) {
+        for (var i = 1; i < arguments.length; i++) {
+            args[i - 1] = arguments[i];
+        }
+    }
+    queue.push(new Item(fun, args));
+    if (queue.length === 1 && !draining) {
+        runTimeout(drainQueue);
+    }
+};
+
+// v8 likes predictible objects
+function Item(fun, array) {
+    this.fun = fun;
+    this.array = array;
+}
+Item.prototype.run = function () {
+    this.fun.apply(null, this.array);
+};
+process.title = 'browser';
+process.browser = true;
+process.env = {};
+process.argv = [];
+process.version = ''; // empty string to avoid regexp issues
+process.versions = {};
+
+function noop() {}
+
+process.on = noop;
+process.addListener = noop;
+process.once = noop;
+process.off = noop;
+process.removeListener = noop;
+process.removeAllListeners = noop;
+process.emit = noop;
+process.prependListener = noop;
+process.prependOnceListener = noop;
+
+process.listeners = function (name) { return [] }
+
+process.binding = function (name) {
+    throw new Error('process.binding is not supported');
+};
+
+process.cwd = function () { return '/' };
+process.chdir = function (dir) {
+    throw new Error('process.chdir is not supported');
+};
+process.umask = function() { return 0; };
+
+},{}],9:[function(require,module,exports){
+(function (process){(function (){
+/** @license React v16.13.1
+ * react-is.development.js
+ *
+ * Copyright (c) Facebook, Inc. and its affiliates.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+'use strict';
+
+
+
+if (process.env.NODE_ENV !== "production") {
+  (function() {
+'use strict';
+
+// The Symbol used to tag the ReactElement-like types. If there is no native Symbol
+// nor polyfill, then a plain number is used for performance.
+var hasSymbol = typeof Symbol === 'function' && Symbol.for;
+var REACT_ELEMENT_TYPE = hasSymbol ? Symbol.for('react.element') : 0xeac7;
+var REACT_PORTAL_TYPE = hasSymbol ? Symbol.for('react.portal') : 0xeaca;
+var REACT_FRAGMENT_TYPE = hasSymbol ? Symbol.for('react.fragment') : 0xeacb;
+var REACT_STRICT_MODE_TYPE = hasSymbol ? Symbol.for('react.strict_mode') : 0xeacc;
+var REACT_PROFILER_TYPE = hasSymbol ? Symbol.for('react.profiler') : 0xead2;
+var REACT_PROVIDER_TYPE = hasSymbol ? Symbol.for('react.provider') : 0xeacd;
+var REACT_CONTEXT_TYPE = hasSymbol ? Symbol.for('react.context') : 0xeace; // TODO: We don't use AsyncMode or ConcurrentMode anymore. They were temporary
+// (unstable) APIs that have been removed. Can we remove the symbols?
+
+var REACT_ASYNC_MODE_TYPE = hasSymbol ? Symbol.for('react.async_mode') : 0xeacf;
+var REACT_CONCURRENT_MODE_TYPE = hasSymbol ? Symbol.for('react.concurrent_mode') : 0xeacf;
+var REACT_FORWARD_REF_TYPE = hasSymbol ? Symbol.for('react.forward_ref') : 0xead0;
+var REACT_SUSPENSE_TYPE = hasSymbol ? Symbol.for('react.suspense') : 0xead1;
+var REACT_SUSPENSE_LIST_TYPE = hasSymbol ? Symbol.for('react.suspense_list') : 0xead8;
+var REACT_MEMO_TYPE = hasSymbol ? Symbol.for('react.memo') : 0xead3;
+var REACT_LAZY_TYPE = hasSymbol ? Symbol.for('react.lazy') : 0xead4;
+var REACT_BLOCK_TYPE = hasSymbol ? Symbol.for('react.block') : 0xead9;
+var REACT_FUNDAMENTAL_TYPE = hasSymbol ? Symbol.for('react.fundamental') : 0xead5;
+var REACT_RESPONDER_TYPE = hasSymbol ? Symbol.for('react.responder') : 0xead6;
+var REACT_SCOPE_TYPE = hasSymbol ? Symbol.for('react.scope') : 0xead7;
+
+function isValidElementType(type) {
+  return typeof type === 'string' || typeof type === 'function' || // Note: its typeof might be other than 'symbol' or 'number' if it's a polyfill.
+  type === REACT_FRAGMENT_TYPE || type === REACT_CONCURRENT_MODE_TYPE || type === REACT_PROFILER_TYPE || type === REACT_STRICT_MODE_TYPE || type === REACT_SUSPENSE_TYPE || type === REACT_SUSPENSE_LIST_TYPE || typeof type === 'object' && type !== null && (type.$$typeof === REACT_LAZY_TYPE || type.$$typeof === REACT_MEMO_TYPE || type.$$typeof === REACT_PROVIDER_TYPE || type.$$typeof === REACT_CONTEXT_TYPE || type.$$typeof === REACT_FORWARD_REF_TYPE || type.$$typeof === REACT_FUNDAMENTAL_TYPE || type.$$typeof === REACT_RESPONDER_TYPE || type.$$typeof === REACT_SCOPE_TYPE || type.$$typeof === REACT_BLOCK_TYPE);
+}
+
+function typeOf(object) {
+  if (typeof object === 'object' && object !== null) {
+    var $$typeof = object.$$typeof;
+
+    switch ($$typeof) {
+      case REACT_ELEMENT_TYPE:
+        var type = object.type;
+
+        switch (type) {
+          case REACT_ASYNC_MODE_TYPE:
+          case REACT_CONCURRENT_MODE_TYPE:
+          case REACT_FRAGMENT_TYPE:
+          case REACT_PROFILER_TYPE:
+          case REACT_STRICT_MODE_TYPE:
+          case REACT_SUSPENSE_TYPE:
+            return type;
+
+          default:
+            var $$typeofType = type && type.$$typeof;
+
+            switch ($$typeofType) {
+              case REACT_CONTEXT_TYPE:
+              case REACT_FORWARD_REF_TYPE:
+              case REACT_LAZY_TYPE:
+              case REACT_MEMO_TYPE:
+              case REACT_PROVIDER_TYPE:
+                return $$typeofType;
+
+              default:
+                return $$typeof;
+            }
+
+        }
+
+      case REACT_PORTAL_TYPE:
+        return $$typeof;
+    }
+  }
+
+  return undefined;
+} // AsyncMode is deprecated along with isAsyncMode
+
+var AsyncMode = REACT_ASYNC_MODE_TYPE;
+var ConcurrentMode = REACT_CONCURRENT_MODE_TYPE;
+var ContextConsumer = REACT_CONTEXT_TYPE;
+var ContextProvider = REACT_PROVIDER_TYPE;
+var Element = REACT_ELEMENT_TYPE;
+var ForwardRef = REACT_FORWARD_REF_TYPE;
+var Fragment = REACT_FRAGMENT_TYPE;
+var Lazy = REACT_LAZY_TYPE;
+var Memo = REACT_MEMO_TYPE;
+var Portal = REACT_PORTAL_TYPE;
+var Profiler = REACT_PROFILER_TYPE;
+var StrictMode = REACT_STRICT_MODE_TYPE;
+var Suspense = REACT_SUSPENSE_TYPE;
+var hasWarnedAboutDeprecatedIsAsyncMode = false; // AsyncMode should be deprecated
+
+function isAsyncMode(object) {
+  {
+    if (!hasWarnedAboutDeprecatedIsAsyncMode) {
+      hasWarnedAboutDeprecatedIsAsyncMode = true; // Using console['warn'] to evade Babel and ESLint
+
+      console['warn']('The ReactIs.isAsyncMode() alias has been deprecated, ' + 'and will be removed in React 17+. Update your code to use ' + 'ReactIs.isConcurrentMode() instead. It has the exact same API.');
+    }
+  }
+
+  return isConcurrentMode(object) || typeOf(object) === REACT_ASYNC_MODE_TYPE;
+}
+function isConcurrentMode(object) {
+  return typeOf(object) === REACT_CONCURRENT_MODE_TYPE;
+}
+function isContextConsumer(object) {
+  return typeOf(object) === REACT_CONTEXT_TYPE;
+}
+function isContextProvider(object) {
+  return typeOf(object) === REACT_PROVIDER_TYPE;
+}
+function isElement(object) {
+  return typeof object === 'object' && object !== null && object.$$typeof === REACT_ELEMENT_TYPE;
+}
+function isForwardRef(object) {
+  return typeOf(object) === REACT_FORWARD_REF_TYPE;
+}
+function isFragment(object) {
+  return typeOf(object) === REACT_FRAGMENT_TYPE;
+}
+function isLazy(object) {
+  return typeOf(object) === REACT_LAZY_TYPE;
+}
+function isMemo(object) {
+  return typeOf(object) === REACT_MEMO_TYPE;
+}
+function isPortal(object) {
+  return typeOf(object) === REACT_PORTAL_TYPE;
+}
+function isProfiler(object) {
+  return typeOf(object) === REACT_PROFILER_TYPE;
+}
+function isStrictMode(object) {
+  return typeOf(object) === REACT_STRICT_MODE_TYPE;
+}
+function isSuspense(object) {
+  return typeOf(object) === REACT_SUSPENSE_TYPE;
+}
+
+exports.AsyncMode = AsyncMode;
+exports.ConcurrentMode = ConcurrentMode;
+exports.ContextConsumer = ContextConsumer;
+exports.ContextProvider = ContextProvider;
+exports.Element = Element;
+exports.ForwardRef = ForwardRef;
+exports.Fragment = Fragment;
+exports.Lazy = Lazy;
+exports.Memo = Memo;
+exports.Portal = Portal;
+exports.Profiler = Profiler;
+exports.StrictMode = StrictMode;
+exports.Suspense = Suspense;
+exports.isAsyncMode = isAsyncMode;
+exports.isConcurrentMode = isConcurrentMode;
+exports.isContextConsumer = isContextConsumer;
+exports.isContextProvider = isContextProvider;
+exports.isElement = isElement;
+exports.isForwardRef = isForwardRef;
+exports.isFragment = isFragment;
+exports.isLazy = isLazy;
+exports.isMemo = isMemo;
+exports.isPortal = isPortal;
+exports.isProfiler = isProfiler;
+exports.isStrictMode = isStrictMode;
+exports.isSuspense = isSuspense;
+exports.isValidElementType = isValidElementType;
+exports.typeOf = typeOf;
+  })();
+}
+
+}).call(this)}).call(this,require('_process'))
+},{"_process":8}],10:[function(require,module,exports){
+/** @license React v16.13.1
+ * react-is.production.min.js
+ *
+ * Copyright (c) Facebook, Inc. and its affiliates.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+'use strict';var b="function"===typeof Symbol&&Symbol.for,c=b?Symbol.for("react.element"):60103,d=b?Symbol.for("react.portal"):60106,e=b?Symbol.for("react.fragment"):60107,f=b?Symbol.for("react.strict_mode"):60108,g=b?Symbol.for("react.profiler"):60114,h=b?Symbol.for("react.provider"):60109,k=b?Symbol.for("react.context"):60110,l=b?Symbol.for("react.async_mode"):60111,m=b?Symbol.for("react.concurrent_mode"):60111,n=b?Symbol.for("react.forward_ref"):60112,p=b?Symbol.for("react.suspense"):60113,q=b?
+Symbol.for("react.suspense_list"):60120,r=b?Symbol.for("react.memo"):60115,t=b?Symbol.for("react.lazy"):60116,v=b?Symbol.for("react.block"):60121,w=b?Symbol.for("react.fundamental"):60117,x=b?Symbol.for("react.responder"):60118,y=b?Symbol.for("react.scope"):60119;
+function z(a){if("object"===typeof a&&null!==a){var u=a.$$typeof;switch(u){case c:switch(a=a.type,a){case l:case m:case e:case g:case f:case p:return a;default:switch(a=a&&a.$$typeof,a){case k:case n:case t:case r:case h:return a;default:return u}}case d:return u}}}function A(a){return z(a)===m}exports.AsyncMode=l;exports.ConcurrentMode=m;exports.ContextConsumer=k;exports.ContextProvider=h;exports.Element=c;exports.ForwardRef=n;exports.Fragment=e;exports.Lazy=t;exports.Memo=r;exports.Portal=d;
+exports.Profiler=g;exports.StrictMode=f;exports.Suspense=p;exports.isAsyncMode=function(a){return A(a)||z(a)===l};exports.isConcurrentMode=A;exports.isContextConsumer=function(a){return z(a)===k};exports.isContextProvider=function(a){return z(a)===h};exports.isElement=function(a){return"object"===typeof a&&null!==a&&a.$$typeof===c};exports.isForwardRef=function(a){return z(a)===n};exports.isFragment=function(a){return z(a)===e};exports.isLazy=function(a){return z(a)===t};
+exports.isMemo=function(a){return z(a)===r};exports.isPortal=function(a){return z(a)===d};exports.isProfiler=function(a){return z(a)===g};exports.isStrictMode=function(a){return z(a)===f};exports.isSuspense=function(a){return z(a)===p};
+exports.isValidElementType=function(a){return"string"===typeof a||"function"===typeof a||a===e||a===m||a===g||a===f||a===p||a===q||"object"===typeof a&&null!==a&&(a.$$typeof===t||a.$$typeof===r||a.$$typeof===h||a.$$typeof===k||a.$$typeof===n||a.$$typeof===w||a.$$typeof===x||a.$$typeof===y||a.$$typeof===v)};exports.typeOf=z;
+
+},{}],11:[function(require,module,exports){
+(function (process){(function (){
+'use strict';
+
+if (process.env.NODE_ENV === 'production') {
+  module.exports = require('./cjs/react-is.production.min.js');
+} else {
+  module.exports = require('./cjs/react-is.development.js');
+}
+
+}).call(this)}).call(this,require('_process'))
+},{"./cjs/react-is.development.js":9,"./cjs/react-is.production.min.js":10,"_process":8}]},{},[4])(4)
+});
Index: node_modules/prop-types/prop-types.min.js
===================================================================
--- node_modules/prop-types/prop-types.min.js	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
+++ node_modules/prop-types/prop-types.min.js	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
@@ -0,0 +1,1 @@
+!function(f){"object"==typeof exports&&"undefined"!=typeof module?module.exports=f():"function"==typeof define&&define.amd?define([],f):("undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this).PropTypes=f()}(function(){return function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var p="function"==typeof require&&require;if(!f&&p)return p(i,!0);if(u)return u(i,!0);throw(p=new Error("Cannot find module '"+i+"'")).code="MODULE_NOT_FOUND",p}p=n[i]={exports:{}},e[i][0].call(p.exports,function(r){return o(e[i][1][r]||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}({1:[function(require,module,exports){"use strict";var ReactPropTypesSecret=require(3);function emptyFunction(){}function emptyFunctionWithReset(){}emptyFunctionWithReset.resetWarningCache=emptyFunction,module.exports=function(){function e(e,t,n,r,o,c){if(c!==ReactPropTypesSecret){c=new Error("Calling PropTypes validators directly is not supported by the `prop-types` package. Use PropTypes.checkPropTypes() to call them. Read more at http://fb.me/use-check-prop-types");throw c.name="Invariant Violation",c}}function t(){return e}var n={array:e.isRequired=e,bigint:e,bool:e,func:e,number:e,object:e,string:e,symbol:e,any:e,arrayOf:t,element:e,elementType:e,instanceOf:t,node:e,objectOf:t,oneOf:t,oneOfType:t,shape:t,exact:t,checkPropTypes:emptyFunctionWithReset,resetWarningCache:emptyFunction};return n.PropTypes=n}},{3:3}],2:[function(require,module,exports){module.exports=require(1)()},{1:1}],3:[function(require,module,exports){"use strict";module.exports="SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED"},{}]},{},[2])(2)});
Index: node_modules/react-facebook-login/.editorconfig
===================================================================
--- node_modules/react-facebook-login/.editorconfig	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
+++ node_modules/react-facebook-login/.editorconfig	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
@@ -0,0 +1,21 @@
+# EditorConfig helps developers define and maintain consistent
+# coding styles between different editors and IDEs
+# editorconfig.org
+
+root = true
+
+[*]
+indent_style = space
+indent_size = 2
+
+end_of_line = lf
+charset = utf-8
+trim_trailing_whitespace = true
+insert_final_newline = true
+
+[*.md]
+trim_trailing_whitespace = false
+
+[*.{json,yml}]
+indent_style = space
+indent_size = 2
Index: node_modules/react-facebook-login/.eslintrc
===================================================================
--- node_modules/react-facebook-login/.eslintrc	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
+++ node_modules/react-facebook-login/.eslintrc	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
@@ -0,0 +1,20 @@
+{
+  "env": {
+    "browser": true,
+    "node": true
+  },
+  "extends": [
+    "eslint:recommended",
+    "airbnb"
+  ],
+  "parser": "babel-eslint",
+  "plugins": [
+    "react"
+  ],
+  "globals": {
+    "FB": false
+  },
+  "rules": {
+    "react/no-multi-comp": 0
+  }
+}
Index: node_modules/react-facebook-login/.travis.yml
===================================================================
--- node_modules/react-facebook-login/.travis.yml	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
+++ node_modules/react-facebook-login/.travis.yml	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
@@ -0,0 +1,5 @@
+language: node_js
+node_js:
+  - "5"
+script:
+  - npm test
Index: node_modules/react-facebook-login/README.md
===================================================================
--- node_modules/react-facebook-login/README.md	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
+++ node_modules/react-facebook-login/README.md	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
@@ -0,0 +1,209 @@
+# React Facebook Login - [![Build Status](https://travis-ci.org/keppelen/react-facebook-login.svg?branch=master)](https://travis-ci.org/keppelen/react-facebook-login)
+
+> A Component React for Facebook Login
+
+## Getting Started
+
+- `yarn add react-facebook-login` or `npm install react-facebook-login`
+- Your application will also need `react-dom` and `react` installed.
+
+## Development
+
+```shell
+git clone https://github.com/keppelen/react-facebook-login.git && cd react-facebook-login
+npm install react react-dom react-facebook-login --save --force
+npm start
+```
+- navigate to [localhost:8080](http://localhost:8080)
+
+## How to use
+
+### Basic button with styling
+
+```js
+import React from 'react';
+import ReactDOM from 'react-dom';
+import FacebookLogin from 'react-facebook-login';
+
+const responseFacebook = (response) => {
+  console.log(response);
+}
+
+ReactDOM.render(
+  <FacebookLogin
+    appId="1088597931155576"
+    autoLoad={true}
+    fields="name,email,picture"
+    onClick={componentClicked}
+    callback={responseFacebook} />,
+  document.getElementById('demo')
+);
+```
+
+### Facebook button without styling
+
+If you're providing all your own custom styling, you can use the render prop build. This build doesn't include any CSS or additional code needed to customise the look of the button, and instead leaves that entirely up to you. You can see an example of this in `demo/index.js`.
+
+To make sure you import the right version, you will need to update your import line:
+
+```js
+import FacebookLogin from 'react-facebook-login/dist/facebook-login-render-props'
+```
+
+```
+<FacebookLogin
+  appId="1088597931155576"
+  autoLoad
+  callback={responseFacebook}
+  render={renderProps => (
+    <button onClick={renderProps.onClick}>This is my custom FB button</button>
+  )}
+/>
+```
+
+The `render` function will be passed the following properties for you to use:
+
+- `onClick`
+- `isDisabled`
+- `isProcessing`
+- `isSdkLoaded`
+
+
+### Custom CSS Class and Icon
+
+By default fontawesome is included, If you don't want to use default fontawesome icons, you can send an element in icon attribute
+
+Fontawesome example:
+```js
+
+import React from 'react';
+import ReactDOM from 'react-dom';
+import FacebookLogin from 'react-facebook-login';
+
+const responseFacebook = (response) => {
+  console.log(response);
+}
+
+ReactDOM.render(
+  <FacebookLogin
+    appId="1088597931155576"
+    autoLoad={true}
+    fields="name,email,picture"
+    callback={responseFacebook}
+    cssClass="my-facebook-button-class"
+    icon="fa-facebook"
+  />,
+  document.getElementById('demo')
+);
+```
+
+Custom element example:
+```js
+
+import React from 'react';
+import ReactDOM from 'react-dom';
+import FacebookLogin from 'react-facebook-login';
+import TiSocialFacebookCircular from 'react-icons/lib/ti/social-facebook-circular';
+
+const responseFacebook = (response) => {
+  console.log(response);
+}
+
+ReactDOM.render(
+  <FacebookLogin
+    appId="1088597931155576"
+    autoLoad={true}
+    fields="name,email,picture"
+    callback={responseFacebook}
+    cssClass="my-facebook-button-class"
+    icon={<TiSocialFacebookCircular />}
+  />,
+  document.getElementById('demo')
+);
+```
+
+### Custom permission
+By default the component, request only 'public_profile' permission, you can change if you send 'scope', that is a string comma separated attribute.
+
+see https://developers.facebook.com/docs/facebook-login/permissions for permissions list
+
+```js
+  import React from 'react';
+  import FacebookLogin from 'react-facebook-login';
+
+  class MyComponent extends React.Component {
+    responseFacebook(response) {
+      console.log(response);
+    }
+
+    render() {
+      return (
+        <FacebookLogin
+          appId="1088597931155576"
+          autoLoad={true}
+          fields="name,email,picture"
+          scope="public_profile,user_friends,user_actions.books"
+          callback={this.responseFacebook}
+        />
+      )
+    }
+  }
+
+  export default MyComponent;
+```
+
+### Server
+```js
+'use strict';
+
+import React from 'react';
+import FacebookLogin from 'react-facebook-login';
+
+class MyComponent extends React.Component {
+  responseFacebook(response) {
+    console.log(response)
+  }
+
+  render() {
+    return (
+      <FacebookLogin
+        appId="1088597931155576"
+        autoLoad={true}
+        fields="name,email,picture"
+        callback={this.responseFacebook}
+      />
+    )
+  }
+}
+
+export default MyComponent;
+```
+
+
+## Parameters
+
+|    params    |     value           |                default value                        |
+|:------------:|:-------------------:|:---------------------------------------------------:|
+|     appId    |     string          |                Required                             |
+|     size     |     string          |              small - medium - metro                 |
+|     scope    |     string          |      public_profile, email, user_birthday           |
+|     fields   |     string          |              name,email,picture                     |
+|   callback   |     function        |             resultFacebookLogin                     |
+| returnScopes |     boolean         |                  false                              |
+|   autoLoad   |     boolean         |                  false                              |
+|     xfbml    |     boolean         |                  false                              |
+|    cookie    |     boolean         |                  false                              |
+|   textButton |     string          |           Login with Facebook                       |
+|   cssClass   |     string          | kep-login-facebook kep-login-facebook-[button-size] |
+| redirectUri  |     string          |               window.location.href (mobile-only)    |
+|   version    |     string          |                  2.3                                |
+|   icon       |     string|element  |                  none                               |
+|   language   |     string          |                  en_US                              |
+|   onClick    |     function        |                  Initial click on the component     |
+|   isMobile   |     boolean         |                  detected via userAgent             |
+|   isDisabled |     boolean         |                  undefined                          |
+|     tag      |     string          |                  HTML Element, Ex: 'a', 'button'             |
+|   onFailure  |     function        | optional function to separatere the failed init     |
+|   state  |     string        | optional string to maintain state between the request and callback. This parameter should be used for preventing Cross-site Request Forgery and will be passed back to you, unchanged, in your redirect URI     |
+| authType | string | optional string to change authentication type |
+| responseType | string | optional string to change response type. Default value is 'code' |
Index: node_modules/react-facebook-login/dist/facebook-login-render-props.js
===================================================================
--- node_modules/react-facebook-login/dist/facebook-login-render-props.js	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
+++ node_modules/react-facebook-login/dist/facebook-login-render-props.js	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
@@ -0,0 +1,1 @@
+!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t(require("react")):"function"==typeof define&&define.amd?define(["react"],t):"object"==typeof exports?exports.FacebookLogin=t(require("react")):e.FacebookLogin=t(e.react)}(this,function(e){return function(e){function t(n){if(o[n])return o[n].exports;var r=o[n]={exports:{},id:n,loaded:!1};return e[n].call(r.exports,r,r.exports,t),r.loaded=!0,r.exports}var o={};return t.m=e,t.c=o,t.p="",t(0)}([function(e,t,o){e.exports=o(4)},function(e,t,o){e.exports=o(6)()},function(t,o){t.exports=e},function(e,t){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t["default"]=function(e,t){return decodeURIComponent(e.replace(new RegExp("^(?:.*[&\\?]"+encodeURIComponent(t).replace(/[\.\+\*]/g,"\\$&")+"(?:\\=([^&]*))?)?.*$","i"),"$1"))}},function(e,t,o){"use strict";function n(e){return e&&e.__esModule?e:{"default":e}}function r(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function i(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}function s(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}Object.defineProperty(t,"__esModule",{value:!0});var a=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var o=arguments[t];for(var n in o)Object.prototype.hasOwnProperty.call(o,n)&&(e[n]=o[n])}return e},c=function(){function e(e,t){for(var o=0;o<t.length;o++){var n=t[o];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(e,n.key,n)}}return function(t,o,n){return o&&e(t.prototype,o),n&&e(t,n),t}}(),u=o(2),d=n(u),l=o(1),p=n(l),f=o(5),b=n(f),y=o(3),h=n(y),g=function(){var e=!1;try{e=!!(window.navigator&&window.navigator.standalone||navigator.userAgent.match("CriOS")||navigator.userAgent.match(/mobile/i))}catch(t){}return e},k=function(e){function t(){var e,o,n,s;r(this,t);for(var c=arguments.length,u=Array(c),d=0;d<c;d++)u[d]=arguments[d];return o=n=i(this,(e=t.__proto__||Object.getPrototypeOf(t)).call.apply(e,[this].concat(u))),n.state={isSdkLoaded:!1,isProcessing:!1},n.responseApi=function(e){window.FB.api("/me",{locale:n.props.language,fields:n.props.fields},function(t){a(t,e),n.props.callback(t)})},n.checkLoginState=function(e){n.setStateIfMounted({isProcessing:!1}),e.authResponse?n.responseApi(e.authResponse):n.props.onFailure?n.props.onFailure({status:e.status}):n.props.callback({status:e.status})},n.checkLoginAfterRefresh=function(e){"connected"===e.status?n.checkLoginState(e):window.FB.login(function(e){return n.checkLoginState(e)},!0)},n.click=function(e){if(n.state.isSdkLoaded&&!n.state.isProcessing&&!n.props.isDisabled){n.setState({isProcessing:!0});var t=n.props,o=t.scope,r=t.appId,i=t.onClick,s=t.returnScopes,a=t.responseType,c=t.redirectUri,u=t.disableMobileRedirect,d=t.authType,l=t.state;if("function"!=typeof i||(i(e),!e.defaultPrevented)){var p={client_id:r,redirect_uri:c,state:l,return_scopes:s,scope:o,response_type:a,auth_type:d};if(n.props.isMobile&&!u)window.location.href="https://www.facebook.com/dialog/oauth"+(0,b["default"])(p);else{if(!window.FB)return void(n.props.onFailure&&n.props.onFailure({status:"facebookNotLoaded"}));window.FB.login(n.checkLoginState,{scope:o,return_scopes:s,auth_type:p.auth_type})}}}},s=o,i(n,s)}return s(t,e),c(t,[{key:"componentDidMount",value:function(){if(this._isMounted=!0,document.getElementById("facebook-jssdk"))return void this.sdkLoaded();this.setFbAsyncInit(),this.loadSdkAsynchronously();var e=document.getElementById("fb-root");e||(e=document.createElement("div"),e.id="fb-root",document.body.appendChild(e))}},{key:"componentWillReceiveProps",value:function(e){this.state.isSdkLoaded&&e.autoLoad&&!this.props.autoLoad&&window.FB.getLoginStatus(this.checkLoginAfterRefresh)}},{key:"componentWillUnmount",value:function(){this._isMounted=!1}},{key:"setStateIfMounted",value:function(e){this._isMounted&&this.setState(e)}},{key:"setFbAsyncInit",value:function(){var e=this,t=this.props,o=t.appId,n=t.xfbml,r=t.cookie,i=t.version,s=t.autoLoad;window.fbAsyncInit=function(){window.FB.init({version:"v"+i,appId:o,xfbml:n,cookie:r}),e.setStateIfMounted({isSdkLoaded:!0}),(s||e.isRedirectedFromFb())&&window.FB.getLoginStatus(e.checkLoginAfterRefresh)}}},{key:"isRedirectedFromFb",value:function(){var e=window.location.search;return(0,h["default"])(e,"code")||(0,h["default"])(e,"granted_scopes")}},{key:"sdkLoaded",value:function(){this.setState({isSdkLoaded:!0})}},{key:"loadSdkAsynchronously",value:function(){var e=this.props.language;!function(t,o,n){var r=t.getElementsByTagName(o)[0],i=r,s=r;t.getElementById(n)||(s=t.createElement(o),s.id=n,s.src="https://connect.facebook.net/"+e+"/sdk.js",i.parentNode.insertBefore(s,i))}(document,"script","facebook-jssdk")}},{key:"render",value:function o(){var o=this.props.render;if(!o)throw new Error("ReactFacebookLogin requires a render prop to render");var e={onClick:this.click,isDisabled:!!this.props.isDisabled,isProcessing:this.state.isProcessing,isSdkLoaded:this.state.isSdkLoaded};return this.props.render(e)}}]),t}(d["default"].Component);k.propTypes={isDisabled:p["default"].bool,callback:p["default"].func.isRequired,appId:p["default"].string.isRequired,xfbml:p["default"].bool,cookie:p["default"].bool,authType:p["default"].string,scope:p["default"].string,state:p["default"].string,responseType:p["default"].string,returnScopes:p["default"].bool,redirectUri:p["default"].string,autoLoad:p["default"].bool,disableMobileRedirect:p["default"].bool,isMobile:p["default"].bool,fields:p["default"].string,version:p["default"].string,language:p["default"].string,onClick:p["default"].func,onFailure:p["default"].func,render:p["default"].func.isRequired},k.defaultProps={redirectUri:"undefined"!=typeof window?window.location.href:"/",scope:"public_profile,email",returnScopes:!1,xfbml:!1,cookie:!1,authType:"",fields:"name",version:"2.3",language:"en_US",disableMobileRedirect:!1,isMobile:g(),onFailure:null,state:"facebookdirect",responseType:"code"},t["default"]=k},function(e,t){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t["default"]=function(e){return"?"+Object.keys(e).map(function(t){return t+"="+encodeURIComponent(e[t])}).join("&")}},function(e,t,o){"use strict";function n(){}var r=o(7);e.exports=function(){function e(e,t,o,n,i,s){if(s!==r){var a=new Error("Calling PropTypes validators directly is not supported by the `prop-types` package. Use PropTypes.checkPropTypes() to call them. Read more at http://fb.me/use-check-prop-types");throw a.name="Invariant Violation",a}}function t(){return e}e.isRequired=e;var o={array:e,bool:e,func:e,number:e,object:e,string:e,symbol:e,any:e,arrayOf:t,element:e,instanceOf:t,node:e,objectOf:t,oneOf:t,oneOfType:t,shape:t,exact:t};return o.checkPropTypes=n,o.PropTypes=o,o}},function(e,t){"use strict";var o="SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED";e.exports=o}])});
Index: node_modules/react-facebook-login/dist/facebook-login-with-button.js
===================================================================
--- node_modules/react-facebook-login/dist/facebook-login-with-button.js	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
+++ node_modules/react-facebook-login/dist/facebook-login-with-button.js	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
@@ -0,0 +1,1 @@
+!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t(require("react")):"function"==typeof define&&define.amd?define(["react"],t):"object"==typeof exports?exports.FacebookLogin=t(require("react")):e.FacebookLogin=t(e.react)}(this,function(e){return function(e){function t(n){if(o[n])return o[n].exports;var r=o[n]={exports:{},id:n,loaded:!1};return e[n].call(r.exports,r,r.exports,t),r.loaded=!0,r.exports}var o={};return t.m=e,t.c=o,t.p="",t(0)}([function(e,t,o){e.exports=o(8)},function(e,t,o){e.exports=o(6)()},function(t,o){t.exports=e},function(e,t){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t["default"]=function(e,t){return decodeURIComponent(e.replace(new RegExp("^(?:.*[&\\?]"+encodeURIComponent(t).replace(/[\.\+\*]/g,"\\$&")+"(?:\\=([^&]*))?)?.*$","i"),"$1"))}},function(e,t,o){"use strict";function n(e){return e&&e.__esModule?e:{"default":e}}function r(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function i(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}function a(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}Object.defineProperty(t,"__esModule",{value:!0});var s=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var o=arguments[t];for(var n in o)Object.prototype.hasOwnProperty.call(o,n)&&(e[n]=o[n])}return e},c=function(){function e(e,t){for(var o=0;o<t.length;o++){var n=t[o];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(e,n.key,n)}}return function(t,o,n){return o&&e(t.prototype,o),n&&e(t,n),t}}(),u=o(2),l=n(u),f=o(1),p=n(f),d=o(5),b=n(d),y=o(3),h=n(y),g=function(){var e=!1;try{e=!!(window.navigator&&window.navigator.standalone||navigator.userAgent.match("CriOS")||navigator.userAgent.match(/mobile/i))}catch(t){}return e},m=function(e){function t(){var e,o,n,a;r(this,t);for(var c=arguments.length,u=Array(c),l=0;l<c;l++)u[l]=arguments[l];return o=n=i(this,(e=t.__proto__||Object.getPrototypeOf(t)).call.apply(e,[this].concat(u))),n.state={isSdkLoaded:!1,isProcessing:!1},n.responseApi=function(e){window.FB.api("/me",{locale:n.props.language,fields:n.props.fields},function(t){s(t,e),n.props.callback(t)})},n.checkLoginState=function(e){n.setStateIfMounted({isProcessing:!1}),e.authResponse?n.responseApi(e.authResponse):n.props.onFailure?n.props.onFailure({status:e.status}):n.props.callback({status:e.status})},n.checkLoginAfterRefresh=function(e){"connected"===e.status?n.checkLoginState(e):window.FB.login(function(e){return n.checkLoginState(e)},!0)},n.click=function(e){if(n.state.isSdkLoaded&&!n.state.isProcessing&&!n.props.isDisabled){n.setState({isProcessing:!0});var t=n.props,o=t.scope,r=t.appId,i=t.onClick,a=t.returnScopes,s=t.responseType,c=t.redirectUri,u=t.disableMobileRedirect,l=t.authType,f=t.state;if("function"!=typeof i||(i(e),!e.defaultPrevented)){var p={client_id:r,redirect_uri:c,state:f,return_scopes:a,scope:o,response_type:s,auth_type:l};if(n.props.isMobile&&!u)window.location.href="https://www.facebook.com/dialog/oauth"+(0,b["default"])(p);else{if(!window.FB)return void(n.props.onFailure&&n.props.onFailure({status:"facebookNotLoaded"}));window.FB.login(n.checkLoginState,{scope:o,return_scopes:a,auth_type:p.auth_type})}}}},a=o,i(n,a)}return a(t,e),c(t,[{key:"componentDidMount",value:function(){if(this._isMounted=!0,document.getElementById("facebook-jssdk"))return void this.sdkLoaded();this.setFbAsyncInit(),this.loadSdkAsynchronously();var e=document.getElementById("fb-root");e||(e=document.createElement("div"),e.id="fb-root",document.body.appendChild(e))}},{key:"componentWillReceiveProps",value:function(e){this.state.isSdkLoaded&&e.autoLoad&&!this.props.autoLoad&&window.FB.getLoginStatus(this.checkLoginAfterRefresh)}},{key:"componentWillUnmount",value:function(){this._isMounted=!1}},{key:"setStateIfMounted",value:function(e){this._isMounted&&this.setState(e)}},{key:"setFbAsyncInit",value:function(){var e=this,t=this.props,o=t.appId,n=t.xfbml,r=t.cookie,i=t.version,a=t.autoLoad;window.fbAsyncInit=function(){window.FB.init({version:"v"+i,appId:o,xfbml:n,cookie:r}),e.setStateIfMounted({isSdkLoaded:!0}),(a||e.isRedirectedFromFb())&&window.FB.getLoginStatus(e.checkLoginAfterRefresh)}}},{key:"isRedirectedFromFb",value:function(){var e=window.location.search;return(0,h["default"])(e,"code")||(0,h["default"])(e,"granted_scopes")}},{key:"sdkLoaded",value:function(){this.setState({isSdkLoaded:!0})}},{key:"loadSdkAsynchronously",value:function(){var e=this.props.language;!function(t,o,n){var r=t.getElementsByTagName(o)[0],i=r,a=r;t.getElementById(n)||(a=t.createElement(o),a.id=n,a.src="https://connect.facebook.net/"+e+"/sdk.js",i.parentNode.insertBefore(a,i))}(document,"script","facebook-jssdk")}},{key:"render",value:function o(){var o=this.props.render;if(!o)throw new Error("ReactFacebookLogin requires a render prop to render");var e={onClick:this.click,isDisabled:!!this.props.isDisabled,isProcessing:this.state.isProcessing,isSdkLoaded:this.state.isSdkLoaded};return this.props.render(e)}}]),t}(l["default"].Component);m.propTypes={isDisabled:p["default"].bool,callback:p["default"].func.isRequired,appId:p["default"].string.isRequired,xfbml:p["default"].bool,cookie:p["default"].bool,authType:p["default"].string,scope:p["default"].string,state:p["default"].string,responseType:p["default"].string,returnScopes:p["default"].bool,redirectUri:p["default"].string,autoLoad:p["default"].bool,disableMobileRedirect:p["default"].bool,isMobile:p["default"].bool,fields:p["default"].string,version:p["default"].string,language:p["default"].string,onClick:p["default"].func,onFailure:p["default"].func,render:p["default"].func.isRequired},m.defaultProps={redirectUri:"undefined"!=typeof window?window.location.href:"/",scope:"public_profile,email",returnScopes:!1,xfbml:!1,cookie:!1,authType:"",fields:"name",version:"2.3",language:"en_US",disableMobileRedirect:!1,isMobile:g(),onFailure:null,state:"facebookdirect",responseType:"code"},t["default"]=m},function(e,t){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t["default"]=function(e){return"?"+Object.keys(e).map(function(t){return t+"="+encodeURIComponent(e[t])}).join("&")}},function(e,t,o){"use strict";function n(){}var r=o(7);e.exports=function(){function e(e,t,o,n,i,a){if(a!==r){var s=new Error("Calling PropTypes validators directly is not supported by the `prop-types` package. Use PropTypes.checkPropTypes() to call them. Read more at http://fb.me/use-check-prop-types");throw s.name="Invariant Violation",s}}function t(){return e}e.isRequired=e;var o={array:e,bool:e,func:e,number:e,object:e,string:e,symbol:e,any:e,arrayOf:t,element:e,instanceOf:t,node:e,objectOf:t,oneOf:t,oneOfType:t,shape:t,exact:t};return o.checkPropTypes=n,o.PropTypes=o,o}},function(e,t){"use strict";var o="SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED";e.exports=o},function(e,t,o){"use strict";function n(e){return e&&e.__esModule?e:{"default":e}}function r(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function i(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}function a(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}Object.defineProperty(t,"__esModule",{value:!0});var s=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var o=arguments[t];for(var n in o)Object.prototype.hasOwnProperty.call(o,n)&&(e[n]=o[n])}return e},c=function(){function e(e,t){for(var o=0;o<t.length;o++){var n=t[o];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(e,n.key,n)}}return function(t,o,n){return o&&e(t.prototype,o),n&&e(t,n),t}}(),u=o(2),l=n(u),f=o(1),p=n(f),d=o(9),b=n(d),y=o(4),h=n(y),g=function(e){return["button","input","select","textarea","optgroup","option","fieldset"].indexOf((e+"").toLowerCase())>=0},m=function(e){function t(){return r(this,t),i(this,(t.__proto__||Object.getPrototypeOf(t)).apply(this,arguments))}return a(t,e),c(t,[{key:"style",value:function(){var e=this.constructor.defaultProps.cssClass;return this.props.cssClass===e&&l["default"].createElement("style",{dangerouslySetInnerHTML:{__html:b["default"]}})}},{key:"containerStyle",value:function(e){var t=e.isProcessing,o=e.isSdkLoaded,n=e.isDisabled,r={transition:"opacity 0.5s"};return(t||!o||n)&&(r.opacity=.6),s(r,this.props.containerStyle)}},{key:"renderOwnButton",value:function(e){var t=this.props,o=t.cssClass,n=t.size,r=t.icon,i=t.textButton,a=t.typeButton,c=t.buttonStyle,u=e.onClick,f=e.isDisabled,p="string"==typeof r,d={};return f&&g(this.props.tag)&&(d.disabled=!0),l["default"].createElement("span",{style:this.containerStyle(e)},p&&l["default"].createElement("link",{rel:"stylesheet",href:"https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css"}),l["default"].createElement(this.props.tag,s({type:a,className:o+" "+n,style:c,onClick:u},d),r&&p&&l["default"].createElement("i",{className:"fa "+r}),r&&!p&&r,i),this.style())}},{key:"render",value:function(){var e=this;return l["default"].createElement(h["default"],s({},this.props,{render:function(t){return e.renderOwnButton(t)}}))}}]),t}(l["default"].Component);m.propTypes={textButton:p["default"].string,typeButton:p["default"].string,size:p["default"].string,cssClass:p["default"].string,icon:p["default"].any,containerStyle:p["default"].object,buttonStyle:p["default"].object,tag:p["default"].oneOfType([p["default"].node,p["default"].func])},m.defaultProps={textButton:"Login with Facebook",typeButton:"button",size:"metro",fields:"name",cssClass:"kep-login-facebook",tag:"button"},t["default"]=m},function(e,t,o){t=e.exports=o(10)(),t.push([e.id,".kep-login-facebook{font-family:Helvetica,sans-serif;font-weight:700;-webkit-font-smoothing:antialiased;color:#fff;cursor:pointer;display:inline-block;font-size:calc(.27548vw + 12.71074px);text-decoration:none;text-transform:uppercase;transition:background-color .3s,border-color .3s;background-color:#4c69ba;border:calc(.06887vw + .67769px) solid #4c69ba;padding:calc(.34435vw + 13.38843px) calc(.34435vw + 18.38843px)}.kep-login-facebook.small{padding:calc(.34435vw + 3.38843px) calc(.34435vw + 8.38843px)}.kep-login-facebook.medium{padding:calc(.34435vw + 8.38843px) calc(.34435vw + 13.38843px)}.kep-login-facebook.metro{border-radius:0}.kep-login-facebook .fa{margin-right:calc(.34435vw + 3.38843px)}",""]),t.locals={"kep-login-facebook":"kep-login-facebook",small:"small",medium:"medium",metro:"metro",fa:"fa"}},function(e,t){e.exports=function(){var e=[];return e.toString=function(){for(var e=[],t=0;t<this.length;t++){var o=this[t];o[2]?e.push("@media "+o[2]+"{"+o[1]+"}"):e.push(o[1])}return e.join("")},e.i=function(t,o){"string"==typeof t&&(t=[[null,t,""]]);for(var n={},r=0;r<this.length;r++){var i=this[r][0];"number"==typeof i&&(n[i]=!0)}for(r=0;r<t.length;r++){var a=t[r];"number"==typeof a[0]&&n[a[0]]||(o&&!a[2]?a[2]=o:o&&(a[2]="("+a[2]+") and ("+o+")"),e.push(a))}},e}}])});
Index: node_modules/react-facebook-login/dist/facebook-login.js
===================================================================
--- node_modules/react-facebook-login/dist/facebook-login.js	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
+++ node_modules/react-facebook-login/dist/facebook-login.js	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
@@ -0,0 +1,1 @@
+!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t(require("react")):"function"==typeof define&&define.amd?define(["react"],t):"object"==typeof exports?exports.FacebookLogin=t(require("react")):e.FacebookLogin=t(e.react)}(this,function(e){return function(e){function t(n){if(o[n])return o[n].exports;var r=o[n]={exports:{},id:n,loaded:!1};return e[n].call(r.exports,r,r.exports,t),r.loaded=!0,r.exports}var o={};return t.m=e,t.c=o,t.p="",t(0)}([function(e,t,o){e.exports=o(5)},function(e,t,o){"use strict";function n(e){return e&&e.__esModule?e:{"default":e}}function r(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function i(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}function a(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}Object.defineProperty(t,"__esModule",{value:!0});var s=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var o=arguments[t];for(var n in o)Object.prototype.hasOwnProperty.call(o,n)&&(e[n]=o[n])}return e},u=function(){function e(e,t){for(var o=0;o<t.length;o++){var n=t[o];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(e,n.key,n)}}return function(t,o,n){return o&&e(t.prototype,o),n&&e(t,n),t}}(),c=o(3),l=n(c),f=o(2),d=n(f),p=o(6),b=n(p),h=function(){var e=!1;try{e=!!(window.navigator&&window.navigator.standalone||navigator.userAgent.match("CriOS")||navigator.userAgent.match(/mobile/i))}catch(t){}return e},g=function(e){function t(){var e,o,n,a;r(this,t);for(var u=arguments.length,c=Array(u),l=0;l<u;l++)c[l]=arguments[l];return o=n=i(this,(e=t.__proto__||Object.getPrototypeOf(t)).call.apply(e,[this].concat(c))),n.state={isSdkLoaded:!1,isProcessing:!1},n.responseApi=function(e){window.FB.api("/me",{locale:n.props.language,fields:n.props.fields},function(t){s(t,e),n.props.callback(t)})},n.checkLoginState=function(e){n.setStateIfMounted({isProcessing:!1}),e.authResponse?n.responseApi(e.authResponse):n.props.onFailure?n.props.onFailure({status:e.status}):n.props.callback({status:e.status})},n.checkLoginAfterRefresh=function(e){"connected"===e.status?n.checkLoginState(e):window.FB.login(function(e){return n.checkLoginState(e)},!0)},n.click=function(e){if(n.state.isSdkLoaded&&!n.state.isProcessing&&!n.props.isDisabled){n.setState({isProcessing:!0});var t=n.props,o=t.scope,r=t.appId,i=t.onClick,a=t.reAuthenticate,s=t.returnScopes,u=t.redirectUri,c=t.disableMobileRedirect;if("function"!=typeof i||(i(e),!e.defaultPrevented)){var l={client_id:r,redirect_uri:u,state:"facebookdirect",return_scopes:s,scope:o};a&&(l.auth_type="reauthenticate"),n.props.isMobile&&!c?window.location.href="//www.facebook.com/dialog/oauth"+(0,b["default"])(l):window.FB.login(n.checkLoginState,{scope:o,return_scopes:s,auth_type:l.auth_type})}}},a=o,i(n,a)}return a(t,e),u(t,[{key:"componentDidMount",value:function(){if(this._isMounted=!0,document.getElementById("facebook-jssdk"))return void this.sdkLoaded();this.setFbAsyncInit(),this.loadSdkAsynchronously();var e=document.getElementById("fb-root");e||(e=document.createElement("div"),e.id="fb-root",document.body.appendChild(e))}},{key:"componentWillReceiveProps",value:function(e){this.state.isSdkLoaded&&e.autoLoad&&!this.props.autoLoad&&window.FB.getLoginStatus(this.checkLoginAfterRefresh)}},{key:"componentWillUnmount",value:function(){this._isMounted=!1}},{key:"setStateIfMounted",value:function(e){this._isMounted&&this.setState(e)}},{key:"setFbAsyncInit",value:function(){var e=this,t=this.props,o=t.appId,n=t.xfbml,r=t.cookie,i=t.version,a=t.autoLoad;window.fbAsyncInit=function(){window.FB.init({version:"v"+i,appId:o,xfbml:n,cookie:r}),e.setStateIfMounted({isSdkLoaded:!0}),(a||window.location.search.includes("facebookdirect"))&&window.FB.getLoginStatus(e.checkLoginAfterRefresh)}}},{key:"sdkLoaded",value:function(){this.setState({isSdkLoaded:!0})}},{key:"loadSdkAsynchronously",value:function(){var e=this.props.language;!function(t,o,n){var r=t.getElementsByTagName(o)[0],i=r,a=r;t.getElementById(n)||(a=t.createElement(o),a.id=n,a.src="https://connect.facebook.net/"+e+"/sdk.js",i.parentNode.insertBefore(a,i))}(document,"script","facebook-jssdk")}},{key:"render",value:function o(){var o=this.props.render;if(o){var e={onClick:this.click,isDisabled:!!this.props.isDisabled,isProcessing:this.state.isProcessing,isSdkLoaded:this.state.isSdkLoaded};return this.props.render(e)}throw new Error("ReactFacebookLogin requires a render prop to render")}}]),t}(l["default"].Component);g.propTypes={isDisabled:d["default"].bool,callback:d["default"].func.isRequired,appId:d["default"].string.isRequired,xfbml:d["default"].bool,cookie:d["default"].bool,reAuthenticate:d["default"].bool,scope:d["default"].string,returnScopes:d["default"].bool,redirectUri:d["default"].string,autoLoad:d["default"].bool,disableMobileRedirect:d["default"].bool,isMobile:d["default"].bool,fields:d["default"].string,version:d["default"].string,language:d["default"].string,onClick:d["default"].func,onFailure:d["default"].func,render:d["default"].func.isRequired},g.defaultProps={redirectUri:"undefined"!=typeof window?window.location.href:"/",scope:"public_profile,email",returnScopes:!1,xfbml:!1,cookie:!1,reAuthenticate:!1,fields:"name",version:"2.3",language:"en_US",disableMobileRedirect:!1,isMobile:h(),onFailure:null},t["default"]=g},function(e,t,o){e.exports=o(11)()},function(t,o){t.exports=e},function(e,t,o){"use strict";function n(e){return e&&e.__esModule?e:{"default":e}}function r(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function i(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}function a(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}Object.defineProperty(t,"__esModule",{value:!0});var s=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var o=arguments[t];for(var n in o)Object.prototype.hasOwnProperty.call(o,n)&&(e[n]=o[n])}return e},u=function(){function e(e,t){for(var o=0;o<t.length;o++){var n=t[o];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(e,n.key,n)}}return function(t,o,n){return o&&e(t.prototype,o),n&&e(t,n),t}}(),c=o(3),l=n(c),f=o(2),d=n(f),p=o(7),b=n(p),h=o(1),g=n(h),y=function(){var e=!1;try{e=!!(window.navigator&&window.navigator.standalone||navigator.userAgent.match("CriOS")||navigator.userAgent.match(/mobile/i))}catch(t){}return e},v=function(e){return["button","input","select","textarea","optgroup","option","fieldset"].indexOf((e+"").toLowerCase())>=0},m=function(e){function t(){return r(this,t),i(this,(t.__proto__||Object.getPrototypeOf(t)).apply(this,arguments))}return a(t,e),u(t,[{key:"style",value:function(){var e=this.constructor.defaultProps.cssClass;return this.props.cssClass===e&&l["default"].createElement("style",{dangerouslySetInnerHTML:{__html:b["default"]}})}},{key:"containerStyle",value:function(e){var t=e.isProcessing,o=e.isSdkLoaded,n=e.isDisabled,r={transition:"opacity 0.5s"};return(t||!o||n)&&(r.opacity=.6),s(r,this.props.containerStyle)}},{key:"renderOwnButton",value:function(e){var t=this.props,o=t.cssClass,n=t.size,r=t.icon,i=t.textButton,a=t.typeButton,u=t.buttonStyle,c=e.onClick,f=e.isDisabled,d="string"==typeof r,p={};return f&&v(this.props.tag)&&(p.disabled=!0),l["default"].createElement("span",{style:this.containerStyle(e)},d&&l["default"].createElement("link",{rel:"stylesheet",href:"//maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css"}),l["default"].createElement(this.props.tag,s({type:a,className:o+" "+n,style:u,onClick:c},p),r&&d&&l["default"].createElement("i",{className:"fa "+r}),r&&!d&&r,i),this.style())}},{key:"render",value:function(){var e=this;return l["default"].createElement(g["default"],s({},this.props,{render:function(t){return e.renderOwnButton(t)}}))}}]),t}(l["default"].Component);m.propTypes={isDisabled:d["default"].bool,callback:d["default"].func.isRequired,appId:d["default"].string.isRequired,xfbml:d["default"].bool,cookie:d["default"].bool,reAuthenticate:d["default"].bool,scope:d["default"].string,returnScopes:d["default"].bool,redirectUri:d["default"].string,textButton:d["default"].string,typeButton:d["default"].string,autoLoad:d["default"].bool,disableMobileRedirect:d["default"].bool,isMobile:d["default"].bool,size:d["default"].string,fields:d["default"].string,cssClass:d["default"].string,version:d["default"].string,icon:d["default"].any,language:d["default"].string,onClick:d["default"].func,containerStyle:d["default"].object,buttonStyle:d["default"].object,children:d["default"].node,tag:d["default"].oneOfType([d["default"].node,d["default"].func]),onFailure:d["default"].func},m.defaultProps={textButton:"Login with Facebook",typeButton:"button",redirectUri:"undefined"!=typeof window?window.location.href:"/",scope:"public_profile,email",returnScopes:!1,xfbml:!1,cookie:!1,reAuthenticate:!1,size:"metro",fields:"name",cssClass:"kep-login-facebook",version:"2.3",language:"en_US",disableMobileRedirect:!1,isMobile:y(),tag:"button",onFailure:null},t["default"]=m},function(e,t,o){"use strict";function n(e){return e&&e.__esModule?e:{"default":e}}Object.defineProperty(t,"__esModule",{value:!0}),t.ReactLoginWithButton=t["default"]=void 0;var r=o(4);Object.defineProperty(t,"ReactLoginWithButton",{enumerable:!0,get:function(){return n(r)["default"]}});var i=o(1),a=n(i);t["default"]=a["default"]},function(e,t){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t["default"]=function(e){return"?"+Object.keys(e).map(function(t){return t+"="+encodeURIComponent(e[t])}).join("&")}},function(e,t,o){t=e.exports=o(8)(),t.push([e.id,".kep-login-facebook{font-family:Helvetica,sans-serif;font-weight:700;-webkit-font-smoothing:antialiased;color:#fff;cursor:pointer;display:inline-block;font-size:calc(.27548vw + 12.71074px);text-decoration:none;text-transform:uppercase;transition:background-color .3s,border-color .3s;background-color:#4c69ba;border:calc(.06887vw + .67769px) solid #4c69ba;padding:calc(.34435vw + 13.38843px) calc(.34435vw + 18.38843px)}.kep-login-facebook.small{padding:calc(.34435vw + 3.38843px) calc(.34435vw + 8.38843px)}.kep-login-facebook.medium{padding:calc(.34435vw + 8.38843px) calc(.34435vw + 13.38843px)}.kep-login-facebook.metro{border-radius:0}.kep-login-facebook .fa{margin-right:calc(.34435vw + 3.38843px)}",""]),t.locals={"kep-login-facebook":"kep-login-facebook",small:"small",medium:"medium",metro:"metro",fa:"fa"}},function(e,t){e.exports=function(){var e=[];return e.toString=function(){for(var e=[],t=0;t<this.length;t++){var o=this[t];o[2]?e.push("@media "+o[2]+"{"+o[1]+"}"):e.push(o[1])}return e.join("")},e.i=function(t,o){"string"==typeof t&&(t=[[null,t,""]]);for(var n={},r=0;r<this.length;r++){var i=this[r][0];"number"==typeof i&&(n[i]=!0)}for(r=0;r<t.length;r++){var a=t[r];"number"==typeof a[0]&&n[a[0]]||(o&&!a[2]?a[2]=o:o&&(a[2]="("+a[2]+") and ("+o+")"),e.push(a))}},e}},function(e,t){"use strict";function o(e){return function(){return e}}var n=function(){};n.thatReturns=o,n.thatReturnsFalse=o(!1),n.thatReturnsTrue=o(!0),n.thatReturnsNull=o(null),n.thatReturnsThis=function(){return this},n.thatReturnsArgument=function(e){return e},e.exports=n},function(e,t,o){"use strict";function n(e,t,o,n,i,a,s,u){if(r(t),!e){var c;if(void 0===t)c=new Error("Minified exception occurred; use the non-minified dev environment for the full error message and additional helpful warnings.");else{var l=[o,n,i,a,s,u],f=0;c=new Error(t.replace(/%s/g,function(){return l[f++]})),c.name="Invariant Violation"}throw c.framesToPop=1,c}}var r=function(e){};e.exports=n},function(e,t,o){"use strict";var n=o(9),r=o(10),i=o(12);e.exports=function(){function e(e,t,o,n,a,s){s!==i&&r(!1,"Calling PropTypes validators directly is not supported by the `prop-types` package. Use PropTypes.checkPropTypes() to call them. Read more at http://fb.me/use-check-prop-types")}function t(){return e}e.isRequired=e;var o={array:e,bool:e,func:e,number:e,object:e,string:e,symbol:e,any:e,arrayOf:t,element:e,instanceOf:t,node:e,objectOf:t,oneOf:t,oneOfType:t,shape:t,exact:t};return o.checkPropTypes=n,o.PropTypes=o,o}},function(e,t){"use strict";var o="SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED";e.exports=o}])});
Index: node_modules/react-facebook-login/dist/facebook.js
===================================================================
--- node_modules/react-facebook-login/dist/facebook.js	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
+++ node_modules/react-facebook-login/dist/facebook.js	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
@@ -0,0 +1,313 @@
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+
+var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
+
+var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
+
+var _react = require('react');
+
+var _react2 = _interopRequireDefault(_react);
+
+var _propTypes = require('prop-types');
+
+var _propTypes2 = _interopRequireDefault(_propTypes);
+
+var _facebook = require('../styles/facebook.scss');
+
+var _facebook2 = _interopRequireDefault(_facebook);
+
+var _objectToParams = require('./objectToParams');
+
+var _objectToParams2 = _interopRequireDefault(_objectToParams);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
+
+function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
+
+var getIsMobile = function getIsMobile() {
+  var isMobile = false;
+
+  try {
+    isMobile = !!(window.navigator && window.navigator.standalone || navigator.userAgent.match('CriOS') || navigator.userAgent.match(/mobile/i));
+  } catch (ex) {
+    // continue regardless of error
+  }
+
+  return isMobile;
+};
+
+// https://www.w3.org/TR/html5/disabled-elements.html#disabled-elements
+var _shouldAddDisabledProp = function _shouldAddDisabledProp(tag) {
+  return ['button', 'input', 'select', 'textarea', 'optgroup', 'option', 'fieldset'].indexOf((tag + '').toLowerCase()) >= 0;
+};
+
+var FacebookLogin = function (_React$Component) {
+  _inherits(FacebookLogin, _React$Component);
+
+  function FacebookLogin() {
+    var _ref;
+
+    var _temp, _this, _ret;
+
+    _classCallCheck(this, FacebookLogin);
+
+    for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
+      args[_key] = arguments[_key];
+    }
+
+    return _ret = (_temp = (_this = _possibleConstructorReturn(this, (_ref = FacebookLogin.__proto__ || Object.getPrototypeOf(FacebookLogin)).call.apply(_ref, [this].concat(args))), _this), _this.state = {
+      isSdkLoaded: false,
+      isProcessing: false
+    }, _this.responseApi = function (authResponse) {
+      window.FB.api('/me', { locale: _this.props.language, fields: _this.props.fields }, function (me) {
+        _extends(me, authResponse);
+        _this.props.callback(me);
+      });
+    }, _this.checkLoginState = function (response) {
+      _this.setStateIfMounted({ isProcessing: false });
+      if (response.authResponse) {
+        _this.responseApi(response.authResponse);
+      } else {
+        if (_this.props.callback) {
+          _this.props.callback({ status: response.status });
+        }
+      }
+    }, _this.checkLoginAfterRefresh = function (response) {
+      if (response.status === 'connected') {
+        _this.checkLoginState(response);
+      } else {
+        window.FB.login(function (loginResponse) {
+          return _this.checkLoginState(loginResponse);
+        }, true);
+      }
+    }, _this.click = function (e) {
+      if (!_this.state.isSdkLoaded || _this.state.isProcessing || _this.props.isDisabled) {
+        return;
+      }
+      _this.setState({ isProcessing: true });
+      var _this$props = _this.props,
+          scope = _this$props.scope,
+          appId = _this$props.appId,
+          onClick = _this$props.onClick,
+          reAuthenticate = _this$props.reAuthenticate,
+          redirectUri = _this$props.redirectUri,
+          disableMobileRedirect = _this$props.disableMobileRedirect;
+
+
+      if (typeof onClick === 'function') {
+        onClick(e);
+        if (e.defaultPrevented) {
+          return;
+        }
+      }
+
+      var params = {
+        client_id: appId,
+        redirect_uri: redirectUri,
+        state: 'facebookdirect',
+        scope: scope
+      };
+
+      if (reAuthenticate) {
+        params.auth_type = 'reauthenticate';
+      }
+
+      if (_this.props.isMobile && !disableMobileRedirect) {
+        window.location.href = '//www.facebook.com/dialog/oauth?' + (0, _objectToParams2.default)(params);
+      } else {
+        window.FB.login(_this.checkLoginState, { scope: scope, auth_type: params.auth_type });
+      }
+    }, _temp), _possibleConstructorReturn(_this, _ret);
+  }
+
+  _createClass(FacebookLogin, [{
+    key: 'componentDidMount',
+    value: function componentDidMount() {
+      this._isMounted = true;
+      if (document.getElementById('facebook-jssdk')) {
+        this.sdkLoaded();
+        return;
+      }
+      this.setFbAsyncInit();
+      this.loadSdkAsynchronously();
+      var fbRoot = document.getElementById('fb-root');
+      if (!fbRoot) {
+        fbRoot = document.createElement('div');
+        fbRoot.id = 'fb-root';
+        document.body.appendChild(fbRoot);
+      }
+    }
+  }, {
+    key: 'componentWillUnmount',
+    value: function componentWillUnmount() {
+      this._isMounted = false;
+    }
+  }, {
+    key: 'setStateIfMounted',
+    value: function setStateIfMounted(state) {
+      if (this._isMounted) {
+        this.setState(state);
+      }
+    }
+  }, {
+    key: 'setFbAsyncInit',
+    value: function setFbAsyncInit() {
+      var _this2 = this;
+
+      var _props = this.props,
+          appId = _props.appId,
+          xfbml = _props.xfbml,
+          cookie = _props.cookie,
+          version = _props.version,
+          autoLoad = _props.autoLoad;
+
+      window.fbAsyncInit = function () {
+        window.FB.init({
+          version: 'v' + version,
+          appId: appId,
+          xfbml: xfbml,
+          cookie: cookie
+        });
+        _this2.setStateIfMounted({ isSdkLoaded: true });
+        if (autoLoad || window.location.search.includes('facebookdirect')) {
+          window.FB.getLoginStatus(_this2.checkLoginAfterRefresh);
+        }
+      };
+    }
+  }, {
+    key: 'sdkLoaded',
+    value: function sdkLoaded() {
+      this.setState({ isSdkLoaded: true });
+    }
+  }, {
+    key: 'loadSdkAsynchronously',
+    value: function loadSdkAsynchronously() {
+      var language = this.props.language;
+
+      (function (d, s, id) {
+        var element = d.getElementsByTagName(s)[0];
+        var fjs = element;
+        var js = element;
+        if (d.getElementById(id)) {
+          return;
+        }
+        js = d.createElement(s);js.id = id;
+        js.src = '//connect.facebook.net/' + language + '/all.js';
+        fjs.parentNode.insertBefore(js, fjs);
+      })(document, 'script', 'facebook-jssdk');
+    }
+  }, {
+    key: 'style',
+    value: function style() {
+      var defaultCSS = this.constructor.defaultProps.cssClass;
+      if (this.props.cssClass === defaultCSS) {
+        return _react2.default.createElement('style', { dangerouslySetInnerHTML: { __html: _facebook2.default } });
+      }
+      return false;
+    }
+
+    // [AdGo] 20.11.2016 - coult not get container class to work
+
+  }, {
+    key: 'containerStyle',
+    value: function containerStyle() {
+      var style = { transition: 'opacity 0.5s' };
+      if (this.state.isProcessing || !this.state.isSdkLoaded || this.props.isDisabled) {
+        style.opacity = 0.6;
+      }
+      return _extends(style, this.props.containerStyle);
+    }
+  }, {
+    key: 'render',
+    value: function render() {
+      var _props2 = this.props,
+          cssClass = _props2.cssClass,
+          size = _props2.size,
+          icon = _props2.icon,
+          textButton = _props2.textButton,
+          typeButton = _props2.typeButton,
+          buttonStyle = _props2.buttonStyle;
+
+      var isIconString = typeof icon === 'string';
+      var optionalProps = {};
+      if (this.props.isDisabled && _shouldAddDisabledProp(this.props.tag)) {
+        optionalProps.disabled = true;
+      }
+      return _react2.default.createElement(
+        'span',
+        { style: this.containerStyle() },
+        isIconString && _react2.default.createElement('link', {
+          rel: 'stylesheet',
+          href: '//maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css'
+        }),
+        _react2.default.createElement(
+          this.props.tag,
+          _extends({
+            type: typeButton,
+            className: cssClass + ' ' + size,
+            style: buttonStyle,
+            onClick: this.click
+          }, optionalProps),
+          icon && isIconString && _react2.default.createElement('i', { className: 'fa ' + icon }),
+          icon && !isIconString && icon,
+          textButton
+        ),
+        this.style()
+      );
+    }
+  }]);
+
+  return FacebookLogin;
+}(_react2.default.Component);
+
+FacebookLogin.propTypes = {
+  isDisabled: _propTypes2.default.bool,
+  callback: _propTypes2.default.func.isRequired,
+  appId: _propTypes2.default.string.isRequired,
+  xfbml: _propTypes2.default.bool,
+  cookie: _propTypes2.default.bool,
+  reAuthenticate: _propTypes2.default.bool,
+  scope: _propTypes2.default.string,
+  redirectUri: _propTypes2.default.string,
+  textButton: _propTypes2.default.string,
+  typeButton: _propTypes2.default.string,
+  autoLoad: _propTypes2.default.bool,
+  disableMobileRedirect: _propTypes2.default.bool,
+  isMobile: _propTypes2.default.bool,
+  size: _propTypes2.default.string,
+  fields: _propTypes2.default.string,
+  cssClass: _propTypes2.default.string,
+  version: _propTypes2.default.string,
+  icon: _propTypes2.default.any,
+  language: _propTypes2.default.string,
+  onClick: _propTypes2.default.func,
+  containerStyle: _propTypes2.default.object,
+  buttonStyle: _propTypes2.default.object,
+  tag: _propTypes2.default.oneOfType([_propTypes2.default.node, _propTypes2.default.func])
+};
+FacebookLogin.defaultProps = {
+  textButton: 'Login with Facebook',
+  typeButton: 'button',
+  redirectUri: typeof window !== 'undefined' ? window.location.href : '/',
+  scope: 'public_profile,email',
+  xfbml: false,
+  cookie: false,
+  reAuthenticate: false,
+  size: 'metro',
+  fields: 'name',
+  cssClass: 'kep-login-facebook',
+  version: '2.3',
+  language: 'en_US',
+  disableMobileRedirect: false,
+  isMobile: getIsMobile(),
+  tag: 'button'
+};
+exports.default = FacebookLogin;
Index: node_modules/react-facebook-login/dist/index.js
===================================================================
--- node_modules/react-facebook-login/dist/index.js	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
+++ node_modules/react-facebook-login/dist/index.js	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
@@ -0,0 +1,14 @@
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.default = undefined;
+
+var _facebook = require('./facebook');
+
+var _facebook2 = _interopRequireDefault(_facebook);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+exports.default = _facebook2.default;
Index: node_modules/react-facebook-login/dist/objectToParams.js
===================================================================
--- node_modules/react-facebook-login/dist/objectToParams.js	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
+++ node_modules/react-facebook-login/dist/objectToParams.js	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
@@ -0,0 +1,22 @@
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+
+/**
+ * Encode object to url parameters
+ *
+ * @param      {Object} paramsObj The object needs to encode as url parameters
+ * @return     {String} Encoded url parameters
+ */
+exports.default = function (paramsObj) {
+  var str = '';
+  for (var key in paramsObj) {
+    if (str !== '') {
+      str += '&';
+    }
+    str += key + '=' + encodeURIComponent(paramsObj[key]);
+  }
+  return str;
+};
Index: node_modules/react-facebook-login/package.json
===================================================================
--- node_modules/react-facebook-login/package.json	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
+++ node_modules/react-facebook-login/package.json	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
@@ -0,0 +1,69 @@
+{
+  "name": "react-facebook-login",
+  "version": "4.1.1",
+  "description": "A Component React for Facebook Login",
+  "main": "dist/facebook-login-with-button.js",
+  "scripts": {
+    "start": "cross-env NODE_ENV=development node_modules/.bin/webpack-dev-server --config webpack.config.js",
+    "bundle": "cross-env NODE_ENV=production node_modules/.bin/webpack -p --config webpack.config.dist.js",
+    "test": "node_modules/.bin/eslint src/**/*.js"
+  },
+  "repository": {
+    "type": "git",
+    "url": "https://github.com/keppelen/react-facebook-login.git"
+  },
+  "keywords": [
+    "react",
+    "reactjs",
+    "react-component",
+    "facebook-login",
+    "react-facebook-login"
+  ],
+  "author": "Giovanni Keppelen <keppelen.as@gmail.com>",
+  "license": "MIT",
+  "bugs": {
+    "url": "https://github.com/keppelen/react-facebook-login/issues"
+  },
+  "homepage": "https://github.com/keppelen/react-facebook-login",
+  "devDependencies": {
+    "autoprefixer": "^6.0.3",
+    "babel": "^6.5.2",
+    "babel-core": "^6.6.5",
+    "babel-eslint": "^4.1.6",
+    "babel-loader": "^6.2.4",
+    "babel-plugin-transform-object-assign": "^6.22.0",
+    "babel-preset-es2015": "^6.1.18",
+    "babel-preset-react": "^6.1.18",
+    "babel-preset-stage-0": "^6.5.0",
+    "cross-env": "^5.0.0",
+    "css-loader": "^0.19.0",
+    "eslint": "^1.10.3",
+    "eslint-config-airbnb": "^2.0.0",
+    "eslint-plugin-react": "^3.11.3",
+    "node-sass": "^3.3.x",
+    "postcss-loader": "^0.6.0",
+    "prop-types": "^15.5.10",
+    "react": "^16.2.0",
+    "react-addons-test-utils": "^15.6.2",
+    "react-css-modules": "^3.5.0",
+    "react-dom": "^16.2.0",
+    "react-router": "^3.0.0",
+    "sass-loader": "^3.0.0",
+    "style-loader": "0.12.x",
+    "webpack": "1.12.x",
+    "webpack-dev-server": "1.12.x"
+  },
+  "peerDependencies": {
+    "react": "^16.0.0"
+  },
+  "babel": {
+    "presets": [
+      "es2015",
+      "react",
+      "stage-0"
+    ],
+    "plugins": [
+      "transform-object-assign"
+    ]
+  }
+}
Index: node_modules/react-facebook-login/yarn.lock
===================================================================
--- node_modules/react-facebook-login/yarn.lock	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
+++ node_modules/react-facebook-login/yarn.lock	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
@@ -0,0 +1,5140 @@
+# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
+# yarn lockfile v1
+
+
+Base64@~0.2.0:
+  version "0.2.1"
+  resolved "https://registry.yarnpkg.com/Base64/-/Base64-0.2.1.tgz#ba3a4230708e186705065e66babdd4c35cf60028"
+
+abbrev@1:
+  version "1.1.1"
+  resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8"
+
+accepts@1.3.3:
+  version "1.3.3"
+  resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.3.tgz#c3ca7434938648c3e0d9c1e328dd68b622c284ca"
+  dependencies:
+    mime-types "~2.1.11"
+    negotiator "0.6.1"
+
+accepts@~1.3.4, accepts@~1.3.5:
+  version "1.3.5"
+  resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.5.tgz#eb777df6011723a3b14e8a72c0805c8e86746bd2"
+  dependencies:
+    mime-types "~2.1.18"
+    negotiator "0.6.1"
+
+acorn-to-esprima@^1.0.5:
+  version "1.0.7"
+  resolved "https://registry.yarnpkg.com/acorn-to-esprima/-/acorn-to-esprima-1.0.7.tgz#9436259760098f9ead9b9da2242fab2f4850281b"
+
+acorn@^5.2.1:
+  version "5.7.2"
+  resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.7.2.tgz#91fa871883485d06708800318404e72bfb26dcc5"
+
+after@0.8.2:
+  version "0.8.2"
+  resolved "https://registry.yarnpkg.com/after/-/after-0.8.2.tgz#fedb394f9f0e02aa9768e702bda23b505fae7e1f"
+
+ajv@^5.3.0:
+  version "5.5.2"
+  resolved "https://registry.yarnpkg.com/ajv/-/ajv-5.5.2.tgz#73b5eeca3fab653e3d3f9422b341ad42205dc965"
+  dependencies:
+    co "^4.6.0"
+    fast-deep-equal "^1.0.0"
+    fast-json-stable-stringify "^2.0.0"
+    json-schema-traverse "^0.3.0"
+
+align-text@^0.1.1, align-text@^0.1.3:
+  version "0.1.4"
+  resolved "https://registry.yarnpkg.com/align-text/-/align-text-0.1.4.tgz#0cd90a561093f35d0a99256c22b7069433fad117"
+  dependencies:
+    kind-of "^3.0.2"
+    longest "^1.0.1"
+    repeat-string "^1.5.2"
+
+alphanum-sort@^1.0.1, alphanum-sort@^1.0.2:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/alphanum-sort/-/alphanum-sort-1.0.2.tgz#97a1119649b211ad33691d9f9f486a8ec9fbe0a3"
+
+alter@~0.2.0:
+  version "0.2.0"
+  resolved "https://registry.yarnpkg.com/alter/-/alter-0.2.0.tgz#c7588808617572034aae62480af26b1d4d1cb3cd"
+  dependencies:
+    stable "~0.1.3"
+
+amdefine@>=0.0.4:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5"
+
+ansi-escapes@^1.1.0:
+  version "1.4.0"
+  resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-1.4.0.tgz#d3a8a83b319aa67793662b13e761c7911422306e"
+
+ansi-regex@^2.0.0:
+  version "2.1.1"
+  resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df"
+
+ansi-regex@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998"
+
+ansi-styles@^2.2.1:
+  version "2.2.1"
+  resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe"
+
+anymatch@^1.3.0:
+  version "1.3.2"
+  resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-1.3.2.tgz#553dcb8f91e3c889845dfdba34c77721b90b9d7a"
+  dependencies:
+    micromatch "^2.1.5"
+    normalize-path "^2.0.0"
+
+aproba@^1.0.3:
+  version "1.2.0"
+  resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a"
+
+are-we-there-yet@~1.1.2:
+  version "1.1.5"
+  resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz#4b35c2944f062a8bfcda66410760350fe9ddfc21"
+  dependencies:
+    delegates "^1.0.0"
+    readable-stream "^2.0.6"
+
+argparse@^1.0.2, argparse@^1.0.7:
+  version "1.0.10"
+  resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911"
+  dependencies:
+    sprintf-js "~1.0.2"
+
+arr-diff@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-2.0.0.tgz#8f3b827f955a8bd669697e4a4256ac3ceae356cf"
+  dependencies:
+    arr-flatten "^1.0.1"
+
+arr-flatten@^1.0.1:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1"
+
+array-find-index@^1.0.1:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/array-find-index/-/array-find-index-1.0.2.tgz#df010aa1287e164bbda6f9723b0a96a1ec4187a1"
+
+array-flatten@1.1.1:
+  version "1.1.1"
+  resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2"
+
+array-union@^1.0.1:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/array-union/-/array-union-1.0.2.tgz#9a34410e4f4e3da23dea375be5be70f24778ec39"
+  dependencies:
+    array-uniq "^1.0.1"
+
+array-uniq@^1.0.1:
+  version "1.0.3"
+  resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6"
+
+array-unique@^0.2.1:
+  version "0.2.1"
+  resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.2.1.tgz#a1d97ccafcbc2625cc70fadceb36a50c58b01a53"
+
+arraybuffer.slice@0.0.6:
+  version "0.0.6"
+  resolved "https://registry.yarnpkg.com/arraybuffer.slice/-/arraybuffer.slice-0.0.6.tgz#f33b2159f0532a3f3107a272c0ccfbd1ad2979ca"
+
+arrify@^1.0.0:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d"
+
+asap@~2.0.3:
+  version "2.0.6"
+  resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46"
+
+asn1@~0.2.3:
+  version "0.2.4"
+  resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.4.tgz#8d2475dfab553bb33e77b54e59e880bb8ce23136"
+  dependencies:
+    safer-buffer "~2.1.0"
+
+assert-plus@1.0.0, assert-plus@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525"
+
+assert@^1.1.1:
+  version "1.4.1"
+  resolved "https://registry.yarnpkg.com/assert/-/assert-1.4.1.tgz#99912d591836b5a6f5b345c0f07eefc08fc65d91"
+  dependencies:
+    util "0.10.3"
+
+ast-traverse@~0.1.1:
+  version "0.1.1"
+  resolved "https://registry.yarnpkg.com/ast-traverse/-/ast-traverse-0.1.1.tgz#69cf2b8386f19dcda1bb1e05d68fe359d8897de6"
+
+ast-types@0.8.12:
+  version "0.8.12"
+  resolved "https://registry.yarnpkg.com/ast-types/-/ast-types-0.8.12.tgz#a0d90e4351bb887716c83fd637ebf818af4adfcc"
+
+ast-types@0.8.15:
+  version "0.8.15"
+  resolved "https://registry.yarnpkg.com/ast-types/-/ast-types-0.8.15.tgz#8eef0827f04dff0ec8857ba925abe3fea6194e52"
+
+ast-types@0.9.6:
+  version "0.9.6"
+  resolved "https://registry.yarnpkg.com/ast-types/-/ast-types-0.9.6.tgz#102c9e9e9005d3e7e3829bf0c4fa24ee862ee9b9"
+
+async-each@^1.0.0:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.1.tgz#19d386a1d9edc6e7c1c85d388aedbcc56d33602d"
+
+async-foreach@^0.1.3:
+  version "0.1.3"
+  resolved "https://registry.yarnpkg.com/async-foreach/-/async-foreach-0.1.3.tgz#36121f845c0578172de419a97dbeb1d16ec34542"
+
+async@^0.9.0:
+  version "0.9.2"
+  resolved "https://registry.yarnpkg.com/async/-/async-0.9.2.tgz#aea74d5e61c1f899613bf64bda66d4c78f2fd17d"
+
+async@^1.3.0, async@^1.4.0:
+  version "1.5.2"
+  resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a"
+
+async@~0.2.6:
+  version "0.2.10"
+  resolved "https://registry.yarnpkg.com/async/-/async-0.2.10.tgz#b6bbe0b0674b9d719708ca38de8c237cb526c3d1"
+
+asynckit@^0.4.0:
+  version "0.4.0"
+  resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79"
+
+autoprefixer@^6.0.3, autoprefixer@^6.3.1:
+  version "6.7.7"
+  resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-6.7.7.tgz#1dbd1c835658e35ce3f9984099db00585c782014"
+  dependencies:
+    browserslist "^1.7.6"
+    caniuse-db "^1.0.30000634"
+    normalize-range "^0.1.2"
+    num2fraction "^1.2.2"
+    postcss "^5.2.16"
+    postcss-value-parser "^3.2.3"
+
+aws-sign2@~0.7.0:
+  version "0.7.0"
+  resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8"
+
+aws4@^1.8.0:
+  version "1.8.0"
+  resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.8.0.tgz#f0e003d9ca9e7f59c7a508945d7b2ef9a04a542f"
+
+babel-code-frame@^6.26.0:
+  version "6.26.0"
+  resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b"
+  dependencies:
+    chalk "^1.1.3"
+    esutils "^2.0.2"
+    js-tokens "^3.0.2"
+
+babel-core@^5.8.33:
+  version "5.8.38"
+  resolved "http://registry.npmjs.org/babel-core/-/babel-core-5.8.38.tgz#1fcaee79d7e61b750b00b8e54f6dfc9d0af86558"
+  dependencies:
+    babel-plugin-constant-folding "^1.0.1"
+    babel-plugin-dead-code-elimination "^1.0.2"
+    babel-plugin-eval "^1.0.1"
+    babel-plugin-inline-environment-variables "^1.0.1"
+    babel-plugin-jscript "^1.0.4"
+    babel-plugin-member-expression-literals "^1.0.1"
+    babel-plugin-property-literals "^1.0.1"
+    babel-plugin-proto-to-assign "^1.0.3"
+    babel-plugin-react-constant-elements "^1.0.3"
+    babel-plugin-react-display-name "^1.0.3"
+    babel-plugin-remove-console "^1.0.1"
+    babel-plugin-remove-debugger "^1.0.1"
+    babel-plugin-runtime "^1.0.7"
+    babel-plugin-undeclared-variables-check "^1.0.2"
+    babel-plugin-undefined-to-void "^1.1.6"
+    babylon "^5.8.38"
+    bluebird "^2.9.33"
+    chalk "^1.0.0"
+    convert-source-map "^1.1.0"
+    core-js "^1.0.0"
+    debug "^2.1.1"
+    detect-indent "^3.0.0"
+    esutils "^2.0.0"
+    fs-readdir-recursive "^0.1.0"
+    globals "^6.4.0"
+    home-or-tmp "^1.0.0"
+    is-integer "^1.0.4"
+    js-tokens "1.0.1"
+    json5 "^0.4.0"
+    lodash "^3.10.0"
+    minimatch "^2.0.3"
+    output-file-sync "^1.1.0"
+    path-exists "^1.0.0"
+    path-is-absolute "^1.0.0"
+    private "^0.1.6"
+    regenerator "0.8.40"
+    regexpu "^1.3.0"
+    repeating "^1.1.2"
+    resolve "^1.1.6"
+    shebang-regex "^1.0.0"
+    slash "^1.0.0"
+    source-map "^0.5.0"
+    source-map-support "^0.2.10"
+    to-fast-properties "^1.0.0"
+    trim-right "^1.0.0"
+    try-resolve "^1.0.0"
+
+babel-core@^6.26.0, babel-core@^6.6.5:
+  version "6.26.3"
+  resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-6.26.3.tgz#b2e2f09e342d0f0c88e2f02e067794125e75c207"
+  dependencies:
+    babel-code-frame "^6.26.0"
+    babel-generator "^6.26.0"
+    babel-helpers "^6.24.1"
+    babel-messages "^6.23.0"
+    babel-register "^6.26.0"
+    babel-runtime "^6.26.0"
+    babel-template "^6.26.0"
+    babel-traverse "^6.26.0"
+    babel-types "^6.26.0"
+    babylon "^6.18.0"
+    convert-source-map "^1.5.1"
+    debug "^2.6.9"
+    json5 "^0.5.1"
+    lodash "^4.17.4"
+    minimatch "^3.0.4"
+    path-is-absolute "^1.0.1"
+    private "^0.1.8"
+    slash "^1.0.0"
+    source-map "^0.5.7"
+
+babel-eslint@^4.1.6:
+  version "4.1.8"
+  resolved "https://registry.yarnpkg.com/babel-eslint/-/babel-eslint-4.1.8.tgz#4f79e7a4f5879ecf03f48cb16f552a355fcc31b2"
+  dependencies:
+    acorn-to-esprima "^1.0.5"
+    babel-core "^5.8.33"
+    lodash.assign "^3.2.0"
+    lodash.pick "^3.1.0"
+
+babel-generator@^6.26.0:
+  version "6.26.1"
+  resolved "https://registry.yarnpkg.com/babel-generator/-/babel-generator-6.26.1.tgz#1844408d3b8f0d35a404ea7ac180f087a601bd90"
+  dependencies:
+    babel-messages "^6.23.0"
+    babel-runtime "^6.26.0"
+    babel-types "^6.26.0"
+    detect-indent "^4.0.0"
+    jsesc "^1.3.0"
+    lodash "^4.17.4"
+    source-map "^0.5.7"
+    trim-right "^1.0.1"
+
+babel-helper-bindify-decorators@^6.24.1:
+  version "6.24.1"
+  resolved "https://registry.yarnpkg.com/babel-helper-bindify-decorators/-/babel-helper-bindify-decorators-6.24.1.tgz#14c19e5f142d7b47f19a52431e52b1ccbc40a330"
+  dependencies:
+    babel-runtime "^6.22.0"
+    babel-traverse "^6.24.1"
+    babel-types "^6.24.1"
+
+babel-helper-builder-binary-assignment-operator-visitor@^6.24.1:
+  version "6.24.1"
+  resolved "https://registry.yarnpkg.com/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.24.1.tgz#cce4517ada356f4220bcae8a02c2b346f9a56664"
+  dependencies:
+    babel-helper-explode-assignable-expression "^6.24.1"
+    babel-runtime "^6.22.0"
+    babel-types "^6.24.1"
+
+babel-helper-builder-react-jsx@^6.24.1:
+  version "6.26.0"
+  resolved "https://registry.yarnpkg.com/babel-helper-builder-react-jsx/-/babel-helper-builder-react-jsx-6.26.0.tgz#39ff8313b75c8b65dceff1f31d383e0ff2a408a0"
+  dependencies:
+    babel-runtime "^6.26.0"
+    babel-types "^6.26.0"
+    esutils "^2.0.2"
+
+babel-helper-call-delegate@^6.24.1:
+  version "6.24.1"
+  resolved "https://registry.yarnpkg.com/babel-helper-call-delegate/-/babel-helper-call-delegate-6.24.1.tgz#ece6aacddc76e41c3461f88bfc575bd0daa2df8d"
+  dependencies:
+    babel-helper-hoist-variables "^6.24.1"
+    babel-runtime "^6.22.0"
+    babel-traverse "^6.24.1"
+    babel-types "^6.24.1"
+
+babel-helper-define-map@^6.24.1:
+  version "6.26.0"
+  resolved "https://registry.yarnpkg.com/babel-helper-define-map/-/babel-helper-define-map-6.26.0.tgz#a5f56dab41a25f97ecb498c7ebaca9819f95be5f"
+  dependencies:
+    babel-helper-function-name "^6.24.1"
+    babel-runtime "^6.26.0"
+    babel-types "^6.26.0"
+    lodash "^4.17.4"
+
+babel-helper-explode-assignable-expression@^6.24.1:
+  version "6.24.1"
+  resolved "https://registry.yarnpkg.com/babel-helper-explode-assignable-expression/-/babel-helper-explode-assignable-expression-6.24.1.tgz#f25b82cf7dc10433c55f70592d5746400ac22caa"
+  dependencies:
+    babel-runtime "^6.22.0"
+    babel-traverse "^6.24.1"
+    babel-types "^6.24.1"
+
+babel-helper-explode-class@^6.24.1:
+  version "6.24.1"
+  resolved "https://registry.yarnpkg.com/babel-helper-explode-class/-/babel-helper-explode-class-6.24.1.tgz#7dc2a3910dee007056e1e31d640ced3d54eaa9eb"
+  dependencies:
+    babel-helper-bindify-decorators "^6.24.1"
+    babel-runtime "^6.22.0"
+    babel-traverse "^6.24.1"
+    babel-types "^6.24.1"
+
+babel-helper-function-name@^6.24.1:
+  version "6.24.1"
+  resolved "https://registry.yarnpkg.com/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz#d3475b8c03ed98242a25b48351ab18399d3580a9"
+  dependencies:
+    babel-helper-get-function-arity "^6.24.1"
+    babel-runtime "^6.22.0"
+    babel-template "^6.24.1"
+    babel-traverse "^6.24.1"
+    babel-types "^6.24.1"
+
+babel-helper-get-function-arity@^6.24.1:
+  version "6.24.1"
+  resolved "https://registry.yarnpkg.com/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz#8f7782aa93407c41d3aa50908f89b031b1b6853d"
+  dependencies:
+    babel-runtime "^6.22.0"
+    babel-types "^6.24.1"
+
+babel-helper-hoist-variables@^6.24.1:
+  version "6.24.1"
+  resolved "https://registry.yarnpkg.com/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.24.1.tgz#1ecb27689c9d25513eadbc9914a73f5408be7a76"
+  dependencies:
+    babel-runtime "^6.22.0"
+    babel-types "^6.24.1"
+
+babel-helper-optimise-call-expression@^6.24.1:
+  version "6.24.1"
+  resolved "https://registry.yarnpkg.com/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz#f7a13427ba9f73f8f4fa993c54a97882d1244257"
+  dependencies:
+    babel-runtime "^6.22.0"
+    babel-types "^6.24.1"
+
+babel-helper-regex@^6.24.1:
+  version "6.26.0"
+  resolved "https://registry.yarnpkg.com/babel-helper-regex/-/babel-helper-regex-6.26.0.tgz#325c59f902f82f24b74faceed0363954f6495e72"
+  dependencies:
+    babel-runtime "^6.26.0"
+    babel-types "^6.26.0"
+    lodash "^4.17.4"
+
+babel-helper-remap-async-to-generator@^6.24.1:
+  version "6.24.1"
+  resolved "https://registry.yarnpkg.com/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.24.1.tgz#5ec581827ad723fecdd381f1c928390676e4551b"
+  dependencies:
+    babel-helper-function-name "^6.24.1"
+    babel-runtime "^6.22.0"
+    babel-template "^6.24.1"
+    babel-traverse "^6.24.1"
+    babel-types "^6.24.1"
+
+babel-helper-replace-supers@^6.24.1:
+  version "6.24.1"
+  resolved "https://registry.yarnpkg.com/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz#bf6dbfe43938d17369a213ca8a8bf74b6a90ab1a"
+  dependencies:
+    babel-helper-optimise-call-expression "^6.24.1"
+    babel-messages "^6.23.0"
+    babel-runtime "^6.22.0"
+    babel-template "^6.24.1"
+    babel-traverse "^6.24.1"
+    babel-types "^6.24.1"
+
+babel-helpers@^6.24.1:
+  version "6.24.1"
+  resolved "https://registry.yarnpkg.com/babel-helpers/-/babel-helpers-6.24.1.tgz#3471de9caec388e5c850e597e58a26ddf37602b2"
+  dependencies:
+    babel-runtime "^6.22.0"
+    babel-template "^6.24.1"
+
+babel-loader@^6.2.4:
+  version "6.4.1"
+  resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-6.4.1.tgz#0b34112d5b0748a8dcdbf51acf6f9bd42d50b8ca"
+  dependencies:
+    find-cache-dir "^0.1.1"
+    loader-utils "^0.2.16"
+    mkdirp "^0.5.1"
+    object-assign "^4.0.1"
+
+babel-messages@^6.23.0:
+  version "6.23.0"
+  resolved "https://registry.yarnpkg.com/babel-messages/-/babel-messages-6.23.0.tgz#f3cdf4703858035b2a2951c6ec5edf6c62f2630e"
+  dependencies:
+    babel-runtime "^6.22.0"
+
+babel-plugin-check-es2015-constants@^6.22.0:
+  version "6.22.0"
+  resolved "https://registry.yarnpkg.com/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz#35157b101426fd2ffd3da3f75c7d1e91835bbf8a"
+  dependencies:
+    babel-runtime "^6.22.0"
+
+babel-plugin-constant-folding@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/babel-plugin-constant-folding/-/babel-plugin-constant-folding-1.0.1.tgz#8361d364c98e449c3692bdba51eff0844290aa8e"
+
+babel-plugin-dead-code-elimination@^1.0.2:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/babel-plugin-dead-code-elimination/-/babel-plugin-dead-code-elimination-1.0.2.tgz#5f7c451274dcd7cccdbfbb3e0b85dd28121f0f65"
+
+babel-plugin-eval@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/babel-plugin-eval/-/babel-plugin-eval-1.0.1.tgz#a2faed25ce6be69ade4bfec263f70169195950da"
+
+babel-plugin-inline-environment-variables@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/babel-plugin-inline-environment-variables/-/babel-plugin-inline-environment-variables-1.0.1.tgz#1f58ce91207ad6a826a8bf645fafe68ff5fe3ffe"
+
+babel-plugin-jscript@^1.0.4:
+  version "1.0.4"
+  resolved "https://registry.yarnpkg.com/babel-plugin-jscript/-/babel-plugin-jscript-1.0.4.tgz#8f342c38276e87a47d5fa0a8bd3d5eb6ccad8fcc"
+
+babel-plugin-member-expression-literals@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/babel-plugin-member-expression-literals/-/babel-plugin-member-expression-literals-1.0.1.tgz#cc5edb0faa8dc927170e74d6d1c02440021624d3"
+
+babel-plugin-property-literals@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/babel-plugin-property-literals/-/babel-plugin-property-literals-1.0.1.tgz#0252301900192980b1c118efea48ce93aab83336"
+
+babel-plugin-proto-to-assign@^1.0.3:
+  version "1.0.4"
+  resolved "https://registry.yarnpkg.com/babel-plugin-proto-to-assign/-/babel-plugin-proto-to-assign-1.0.4.tgz#c49e7afd02f577bc4da05ea2df002250cf7cd123"
+  dependencies:
+    lodash "^3.9.3"
+
+babel-plugin-react-constant-elements@^1.0.3:
+  version "1.0.3"
+  resolved "https://registry.yarnpkg.com/babel-plugin-react-constant-elements/-/babel-plugin-react-constant-elements-1.0.3.tgz#946736e8378429cbc349dcff62f51c143b34e35a"
+
+babel-plugin-react-display-name@^1.0.3:
+  version "1.0.3"
+  resolved "https://registry.yarnpkg.com/babel-plugin-react-display-name/-/babel-plugin-react-display-name-1.0.3.tgz#754fe38926e8424a4e7b15ab6ea6139dee0514fc"
+
+babel-plugin-remove-console@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/babel-plugin-remove-console/-/babel-plugin-remove-console-1.0.1.tgz#d8f24556c3a05005d42aaaafd27787f53ff013a7"
+
+babel-plugin-remove-debugger@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/babel-plugin-remove-debugger/-/babel-plugin-remove-debugger-1.0.1.tgz#fd2ea3cd61a428ad1f3b9c89882ff4293e8c14c7"
+
+babel-plugin-runtime@^1.0.7:
+  version "1.0.7"
+  resolved "https://registry.yarnpkg.com/babel-plugin-runtime/-/babel-plugin-runtime-1.0.7.tgz#bf7c7d966dd56ecd5c17fa1cb253c9acb7e54aaf"
+
+babel-plugin-syntax-async-functions@^6.8.0:
+  version "6.13.0"
+  resolved "http://registry.npmjs.org/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz#cad9cad1191b5ad634bf30ae0872391e0647be95"
+
+babel-plugin-syntax-async-generators@^6.5.0:
+  version "6.13.0"
+  resolved "http://registry.npmjs.org/babel-plugin-syntax-async-generators/-/babel-plugin-syntax-async-generators-6.13.0.tgz#6bc963ebb16eccbae6b92b596eb7f35c342a8b9a"
+
+babel-plugin-syntax-class-constructor-call@^6.18.0:
+  version "6.18.0"
+  resolved "http://registry.npmjs.org/babel-plugin-syntax-class-constructor-call/-/babel-plugin-syntax-class-constructor-call-6.18.0.tgz#9cb9d39fe43c8600bec8146456ddcbd4e1a76416"
+
+babel-plugin-syntax-class-properties@^6.8.0:
+  version "6.13.0"
+  resolved "http://registry.npmjs.org/babel-plugin-syntax-class-properties/-/babel-plugin-syntax-class-properties-6.13.0.tgz#d7eb23b79a317f8543962c505b827c7d6cac27de"
+
+babel-plugin-syntax-decorators@^6.13.0:
+  version "6.13.0"
+  resolved "http://registry.npmjs.org/babel-plugin-syntax-decorators/-/babel-plugin-syntax-decorators-6.13.0.tgz#312563b4dbde3cc806cee3e416cceeaddd11ac0b"
+
+babel-plugin-syntax-do-expressions@^6.8.0:
+  version "6.13.0"
+  resolved "http://registry.npmjs.org/babel-plugin-syntax-do-expressions/-/babel-plugin-syntax-do-expressions-6.13.0.tgz#5747756139aa26d390d09410b03744ba07e4796d"
+
+babel-plugin-syntax-dynamic-import@^6.18.0:
+  version "6.18.0"
+  resolved "http://registry.npmjs.org/babel-plugin-syntax-dynamic-import/-/babel-plugin-syntax-dynamic-import-6.18.0.tgz#8d6a26229c83745a9982a441051572caa179b1da"
+
+babel-plugin-syntax-exponentiation-operator@^6.8.0:
+  version "6.13.0"
+  resolved "http://registry.npmjs.org/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz#9ee7e8337290da95288201a6a57f4170317830de"
+
+babel-plugin-syntax-export-extensions@^6.8.0:
+  version "6.13.0"
+  resolved "http://registry.npmjs.org/babel-plugin-syntax-export-extensions/-/babel-plugin-syntax-export-extensions-6.13.0.tgz#70a1484f0f9089a4e84ad44bac353c95b9b12721"
+
+babel-plugin-syntax-flow@^6.18.0:
+  version "6.18.0"
+  resolved "http://registry.npmjs.org/babel-plugin-syntax-flow/-/babel-plugin-syntax-flow-6.18.0.tgz#4c3ab20a2af26aa20cd25995c398c4eb70310c8d"
+
+babel-plugin-syntax-function-bind@^6.8.0:
+  version "6.13.0"
+  resolved "http://registry.npmjs.org/babel-plugin-syntax-function-bind/-/babel-plugin-syntax-function-bind-6.13.0.tgz#48c495f177bdf31a981e732f55adc0bdd2601f46"
+
+babel-plugin-syntax-jsx@^6.3.13, babel-plugin-syntax-jsx@^6.8.0:
+  version "6.18.0"
+  resolved "http://registry.npmjs.org/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz#0af32a9a6e13ca7a3fd5069e62d7b0f58d0d8946"
+
+babel-plugin-syntax-object-rest-spread@^6.8.0:
+  version "6.13.0"
+  resolved "http://registry.npmjs.org/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz#fd6536f2bce13836ffa3a5458c4903a597bb3bf5"
+
+babel-plugin-syntax-trailing-function-commas@^6.22.0:
+  version "6.22.0"
+  resolved "https://registry.yarnpkg.com/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz#ba0360937f8d06e40180a43fe0d5616fff532cf3"
+
+babel-plugin-transform-async-generator-functions@^6.24.1:
+  version "6.24.1"
+  resolved "https://registry.yarnpkg.com/babel-plugin-transform-async-generator-functions/-/babel-plugin-transform-async-generator-functions-6.24.1.tgz#f058900145fd3e9907a6ddf28da59f215258a5db"
+  dependencies:
+    babel-helper-remap-async-to-generator "^6.24.1"
+    babel-plugin-syntax-async-generators "^6.5.0"
+    babel-runtime "^6.22.0"
+
+babel-plugin-transform-async-to-generator@^6.24.1:
+  version "6.24.1"
+  resolved "https://registry.yarnpkg.com/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.24.1.tgz#6536e378aff6cb1d5517ac0e40eb3e9fc8d08761"
+  dependencies:
+    babel-helper-remap-async-to-generator "^6.24.1"
+    babel-plugin-syntax-async-functions "^6.8.0"
+    babel-runtime "^6.22.0"
+
+babel-plugin-transform-class-constructor-call@^6.24.1:
+  version "6.24.1"
+  resolved "https://registry.yarnpkg.com/babel-plugin-transform-class-constructor-call/-/babel-plugin-transform-class-constructor-call-6.24.1.tgz#80dc285505ac067dcb8d6c65e2f6f11ab7765ef9"
+  dependencies:
+    babel-plugin-syntax-class-constructor-call "^6.18.0"
+    babel-runtime "^6.22.0"
+    babel-template "^6.24.1"
+
+babel-plugin-transform-class-properties@^6.24.1:
+  version "6.24.1"
+  resolved "https://registry.yarnpkg.com/babel-plugin-transform-class-properties/-/babel-plugin-transform-class-properties-6.24.1.tgz#6a79763ea61d33d36f37b611aa9def81a81b46ac"
+  dependencies:
+    babel-helper-function-name "^6.24.1"
+    babel-plugin-syntax-class-properties "^6.8.0"
+    babel-runtime "^6.22.0"
+    babel-template "^6.24.1"
+
+babel-plugin-transform-decorators@^6.24.1:
+  version "6.24.1"
+  resolved "https://registry.yarnpkg.com/babel-plugin-transform-decorators/-/babel-plugin-transform-decorators-6.24.1.tgz#788013d8f8c6b5222bdf7b344390dfd77569e24d"
+  dependencies:
+    babel-helper-explode-class "^6.24.1"
+    babel-plugin-syntax-decorators "^6.13.0"
+    babel-runtime "^6.22.0"
+    babel-template "^6.24.1"
+    babel-types "^6.24.1"
+
+babel-plugin-transform-do-expressions@^6.22.0:
+  version "6.22.0"
+  resolved "https://registry.yarnpkg.com/babel-plugin-transform-do-expressions/-/babel-plugin-transform-do-expressions-6.22.0.tgz#28ccaf92812d949c2cd1281f690c8fdc468ae9bb"
+  dependencies:
+    babel-plugin-syntax-do-expressions "^6.8.0"
+    babel-runtime "^6.22.0"
+
+babel-plugin-transform-es2015-arrow-functions@^6.22.0:
+  version "6.22.0"
+  resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz#452692cb711d5f79dc7f85e440ce41b9f244d221"
+  dependencies:
+    babel-runtime "^6.22.0"
+
+babel-plugin-transform-es2015-block-scoped-functions@^6.22.0:
+  version "6.22.0"
+  resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.22.0.tgz#bbc51b49f964d70cb8d8e0b94e820246ce3a6141"
+  dependencies:
+    babel-runtime "^6.22.0"
+
+babel-plugin-transform-es2015-block-scoping@^6.24.1:
+  version "6.26.0"
+  resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.26.0.tgz#d70f5299c1308d05c12f463813b0a09e73b1895f"
+  dependencies:
+    babel-runtime "^6.26.0"
+    babel-template "^6.26.0"
+    babel-traverse "^6.26.0"
+    babel-types "^6.26.0"
+    lodash "^4.17.4"
+
+babel-plugin-transform-es2015-classes@^6.24.1:
+  version "6.24.1"
+  resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz#5a4c58a50c9c9461e564b4b2a3bfabc97a2584db"
+  dependencies:
+    babel-helper-define-map "^6.24.1"
+    babel-helper-function-name "^6.24.1"
+    babel-helper-optimise-call-expression "^6.24.1"
+    babel-helper-replace-supers "^6.24.1"
+    babel-messages "^6.23.0"
+    babel-runtime "^6.22.0"
+    babel-template "^6.24.1"
+    babel-traverse "^6.24.1"
+    babel-types "^6.24.1"
+
+babel-plugin-transform-es2015-computed-properties@^6.24.1:
+  version "6.24.1"
+  resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz#6fe2a8d16895d5634f4cd999b6d3480a308159b3"
+  dependencies:
+    babel-runtime "^6.22.0"
+    babel-template "^6.24.1"
+
+babel-plugin-transform-es2015-destructuring@^6.22.0:
+  version "6.23.0"
+  resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz#997bb1f1ab967f682d2b0876fe358d60e765c56d"
+  dependencies:
+    babel-runtime "^6.22.0"
+
+babel-plugin-transform-es2015-duplicate-keys@^6.24.1:
+  version "6.24.1"
+  resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.24.1.tgz#73eb3d310ca969e3ef9ec91c53741a6f1576423e"
+  dependencies:
+    babel-runtime "^6.22.0"
+    babel-types "^6.24.1"
+
+babel-plugin-transform-es2015-for-of@^6.22.0:
+  version "6.23.0"
+  resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz#f47c95b2b613df1d3ecc2fdb7573623c75248691"
+  dependencies:
+    babel-runtime "^6.22.0"
+
+babel-plugin-transform-es2015-function-name@^6.24.1:
+  version "6.24.1"
+  resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.24.1.tgz#834c89853bc36b1af0f3a4c5dbaa94fd8eacaa8b"
+  dependencies:
+    babel-helper-function-name "^6.24.1"
+    babel-runtime "^6.22.0"
+    babel-types "^6.24.1"
+
+babel-plugin-transform-es2015-literals@^6.22.0:
+  version "6.22.0"
+  resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.22.0.tgz#4f54a02d6cd66cf915280019a31d31925377ca2e"
+  dependencies:
+    babel-runtime "^6.22.0"
+
+babel-plugin-transform-es2015-modules-amd@^6.24.1:
+  version "6.24.1"
+  resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.1.tgz#3b3e54017239842d6d19c3011c4bd2f00a00d154"
+  dependencies:
+    babel-plugin-transform-es2015-modules-commonjs "^6.24.1"
+    babel-runtime "^6.22.0"
+    babel-template "^6.24.1"
+
+babel-plugin-transform-es2015-modules-commonjs@^6.24.1:
+  version "6.26.2"
+  resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.2.tgz#58a793863a9e7ca870bdc5a881117ffac27db6f3"
+  dependencies:
+    babel-plugin-transform-strict-mode "^6.24.1"
+    babel-runtime "^6.26.0"
+    babel-template "^6.26.0"
+    babel-types "^6.26.0"
+
+babel-plugin-transform-es2015-modules-systemjs@^6.24.1:
+  version "6.24.1"
+  resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.24.1.tgz#ff89a142b9119a906195f5f106ecf305d9407d23"
+  dependencies:
+    babel-helper-hoist-variables "^6.24.1"
+    babel-runtime "^6.22.0"
+    babel-template "^6.24.1"
+
+babel-plugin-transform-es2015-modules-umd@^6.24.1:
+  version "6.24.1"
+  resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.1.tgz#ac997e6285cd18ed6176adb607d602344ad38468"
+  dependencies:
+    babel-plugin-transform-es2015-modules-amd "^6.24.1"
+    babel-runtime "^6.22.0"
+    babel-template "^6.24.1"
+
+babel-plugin-transform-es2015-object-super@^6.24.1:
+  version "6.24.1"
+  resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz#24cef69ae21cb83a7f8603dad021f572eb278f8d"
+  dependencies:
+    babel-helper-replace-supers "^6.24.1"
+    babel-runtime "^6.22.0"
+
+babel-plugin-transform-es2015-parameters@^6.24.1:
+  version "6.24.1"
+  resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz#57ac351ab49caf14a97cd13b09f66fdf0a625f2b"
+  dependencies:
+    babel-helper-call-delegate "^6.24.1"
+    babel-helper-get-function-arity "^6.24.1"
+    babel-runtime "^6.22.0"
+    babel-template "^6.24.1"
+    babel-traverse "^6.24.1"
+    babel-types "^6.24.1"
+
+babel-plugin-transform-es2015-shorthand-properties@^6.24.1:
+  version "6.24.1"
+  resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz#24f875d6721c87661bbd99a4622e51f14de38aa0"
+  dependencies:
+    babel-runtime "^6.22.0"
+    babel-types "^6.24.1"
+
+babel-plugin-transform-es2015-spread@^6.22.0:
+  version "6.22.0"
+  resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.22.0.tgz#d6d68a99f89aedc4536c81a542e8dd9f1746f8d1"
+  dependencies:
+    babel-runtime "^6.22.0"
+
+babel-plugin-transform-es2015-sticky-regex@^6.24.1:
+  version "6.24.1"
+  resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz#00c1cdb1aca71112cdf0cf6126c2ed6b457ccdbc"
+  dependencies:
+    babel-helper-regex "^6.24.1"
+    babel-runtime "^6.22.0"
+    babel-types "^6.24.1"
+
+babel-plugin-transform-es2015-template-literals@^6.22.0:
+  version "6.22.0"
+  resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.22.0.tgz#a84b3450f7e9f8f1f6839d6d687da84bb1236d8d"
+  dependencies:
+    babel-runtime "^6.22.0"
+
+babel-plugin-transform-es2015-typeof-symbol@^6.22.0:
+  version "6.23.0"
+  resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz#dec09f1cddff94b52ac73d505c84df59dcceb372"
+  dependencies:
+    babel-runtime "^6.22.0"
+
+babel-plugin-transform-es2015-unicode-regex@^6.24.1:
+  version "6.24.1"
+  resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz#d38b12f42ea7323f729387f18a7c5ae1faeb35e9"
+  dependencies:
+    babel-helper-regex "^6.24.1"
+    babel-runtime "^6.22.0"
+    regexpu-core "^2.0.0"
+
+babel-plugin-transform-exponentiation-operator@^6.24.1:
+  version "6.24.1"
+  resolved "https://registry.yarnpkg.com/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.24.1.tgz#2ab0c9c7f3098fa48907772bb813fe41e8de3a0e"
+  dependencies:
+    babel-helper-builder-binary-assignment-operator-visitor "^6.24.1"
+    babel-plugin-syntax-exponentiation-operator "^6.8.0"
+    babel-runtime "^6.22.0"
+
+babel-plugin-transform-export-extensions@^6.22.0:
+  version "6.22.0"
+  resolved "https://registry.yarnpkg.com/babel-plugin-transform-export-extensions/-/babel-plugin-transform-export-extensions-6.22.0.tgz#53738b47e75e8218589eea946cbbd39109bbe653"
+  dependencies:
+    babel-plugin-syntax-export-extensions "^6.8.0"
+    babel-runtime "^6.22.0"
+
+babel-plugin-transform-flow-strip-types@^6.22.0:
+  version "6.22.0"
+  resolved "https://registry.yarnpkg.com/babel-plugin-transform-flow-strip-types/-/babel-plugin-transform-flow-strip-types-6.22.0.tgz#84cb672935d43714fdc32bce84568d87441cf7cf"
+  dependencies:
+    babel-plugin-syntax-flow "^6.18.0"
+    babel-runtime "^6.22.0"
+
+babel-plugin-transform-function-bind@^6.22.0:
+  version "6.22.0"
+  resolved "https://registry.yarnpkg.com/babel-plugin-transform-function-bind/-/babel-plugin-transform-function-bind-6.22.0.tgz#c6fb8e96ac296a310b8cf8ea401462407ddf6a97"
+  dependencies:
+    babel-plugin-syntax-function-bind "^6.8.0"
+    babel-runtime "^6.22.0"
+
+babel-plugin-transform-object-assign@^6.22.0:
+  version "6.22.0"
+  resolved "https://registry.yarnpkg.com/babel-plugin-transform-object-assign/-/babel-plugin-transform-object-assign-6.22.0.tgz#f99d2f66f1a0b0d498e346c5359684740caa20ba"
+  dependencies:
+    babel-runtime "^6.22.0"
+
+babel-plugin-transform-object-rest-spread@^6.22.0:
+  version "6.26.0"
+  resolved "https://registry.yarnpkg.com/babel-plugin-transform-object-rest-spread/-/babel-plugin-transform-object-rest-spread-6.26.0.tgz#0f36692d50fef6b7e2d4b3ac1478137a963b7b06"
+  dependencies:
+    babel-plugin-syntax-object-rest-spread "^6.8.0"
+    babel-runtime "^6.26.0"
+
+babel-plugin-transform-react-display-name@^6.23.0:
+  version "6.25.0"
+  resolved "https://registry.yarnpkg.com/babel-plugin-transform-react-display-name/-/babel-plugin-transform-react-display-name-6.25.0.tgz#67e2bf1f1e9c93ab08db96792e05392bf2cc28d1"
+  dependencies:
+    babel-runtime "^6.22.0"
+
+babel-plugin-transform-react-jsx-self@^6.22.0:
+  version "6.22.0"
+  resolved "https://registry.yarnpkg.com/babel-plugin-transform-react-jsx-self/-/babel-plugin-transform-react-jsx-self-6.22.0.tgz#df6d80a9da2612a121e6ddd7558bcbecf06e636e"
+  dependencies:
+    babel-plugin-syntax-jsx "^6.8.0"
+    babel-runtime "^6.22.0"
+
+babel-plugin-transform-react-jsx-source@^6.22.0:
+  version "6.22.0"
+  resolved "https://registry.yarnpkg.com/babel-plugin-transform-react-jsx-source/-/babel-plugin-transform-react-jsx-source-6.22.0.tgz#66ac12153f5cd2d17b3c19268f4bf0197f44ecd6"
+  dependencies:
+    babel-plugin-syntax-jsx "^6.8.0"
+    babel-runtime "^6.22.0"
+
+babel-plugin-transform-react-jsx@^6.24.1:
+  version "6.24.1"
+  resolved "https://registry.yarnpkg.com/babel-plugin-transform-react-jsx/-/babel-plugin-transform-react-jsx-6.24.1.tgz#840a028e7df460dfc3a2d29f0c0d91f6376e66a3"
+  dependencies:
+    babel-helper-builder-react-jsx "^6.24.1"
+    babel-plugin-syntax-jsx "^6.8.0"
+    babel-runtime "^6.22.0"
+
+babel-plugin-transform-regenerator@^6.24.1:
+  version "6.26.0"
+  resolved "https://registry.yarnpkg.com/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.26.0.tgz#e0703696fbde27f0a3efcacf8b4dca2f7b3a8f2f"
+  dependencies:
+    regenerator-transform "^0.10.0"
+
+babel-plugin-transform-strict-mode@^6.24.1:
+  version "6.24.1"
+  resolved "https://registry.yarnpkg.com/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz#d5faf7aa578a65bbe591cf5edae04a0c67020758"
+  dependencies:
+    babel-runtime "^6.22.0"
+    babel-types "^6.24.1"
+
+babel-plugin-undeclared-variables-check@^1.0.2:
+  version "1.0.2"
+  resolved "http://registry.npmjs.org/babel-plugin-undeclared-variables-check/-/babel-plugin-undeclared-variables-check-1.0.2.tgz#5cf1aa539d813ff64e99641290af620965f65dee"
+  dependencies:
+    leven "^1.0.2"
+
+babel-plugin-undefined-to-void@^1.1.6:
+  version "1.1.6"
+  resolved "https://registry.yarnpkg.com/babel-plugin-undefined-to-void/-/babel-plugin-undefined-to-void-1.1.6.tgz#7f578ef8b78dfae6003385d8417a61eda06e2f81"
+
+babel-preset-es2015@^6.1.18:
+  version "6.24.1"
+  resolved "https://registry.yarnpkg.com/babel-preset-es2015/-/babel-preset-es2015-6.24.1.tgz#d44050d6bc2c9feea702aaf38d727a0210538939"
+  dependencies:
+    babel-plugin-check-es2015-constants "^6.22.0"
+    babel-plugin-transform-es2015-arrow-functions "^6.22.0"
+    babel-plugin-transform-es2015-block-scoped-functions "^6.22.0"
+    babel-plugin-transform-es2015-block-scoping "^6.24.1"
+    babel-plugin-transform-es2015-classes "^6.24.1"
+    babel-plugin-transform-es2015-computed-properties "^6.24.1"
+    babel-plugin-transform-es2015-destructuring "^6.22.0"
+    babel-plugin-transform-es2015-duplicate-keys "^6.24.1"
+    babel-plugin-transform-es2015-for-of "^6.22.0"
+    babel-plugin-transform-es2015-function-name "^6.24.1"
+    babel-plugin-transform-es2015-literals "^6.22.0"
+    babel-plugin-transform-es2015-modules-amd "^6.24.1"
+    babel-plugin-transform-es2015-modules-commonjs "^6.24.1"
+    babel-plugin-transform-es2015-modules-systemjs "^6.24.1"
+    babel-plugin-transform-es2015-modules-umd "^6.24.1"
+    babel-plugin-transform-es2015-object-super "^6.24.1"
+    babel-plugin-transform-es2015-parameters "^6.24.1"
+    babel-plugin-transform-es2015-shorthand-properties "^6.24.1"
+    babel-plugin-transform-es2015-spread "^6.22.0"
+    babel-plugin-transform-es2015-sticky-regex "^6.24.1"
+    babel-plugin-transform-es2015-template-literals "^6.22.0"
+    babel-plugin-transform-es2015-typeof-symbol "^6.22.0"
+    babel-plugin-transform-es2015-unicode-regex "^6.24.1"
+    babel-plugin-transform-regenerator "^6.24.1"
+
+babel-preset-flow@^6.23.0:
+  version "6.23.0"
+  resolved "https://registry.yarnpkg.com/babel-preset-flow/-/babel-preset-flow-6.23.0.tgz#e71218887085ae9a24b5be4169affb599816c49d"
+  dependencies:
+    babel-plugin-transform-flow-strip-types "^6.22.0"
+
+babel-preset-react@^6.1.18:
+  version "6.24.1"
+  resolved "https://registry.yarnpkg.com/babel-preset-react/-/babel-preset-react-6.24.1.tgz#ba69dfaea45fc3ec639b6a4ecea6e17702c91380"
+  dependencies:
+    babel-plugin-syntax-jsx "^6.3.13"
+    babel-plugin-transform-react-display-name "^6.23.0"
+    babel-plugin-transform-react-jsx "^6.24.1"
+    babel-plugin-transform-react-jsx-self "^6.22.0"
+    babel-plugin-transform-react-jsx-source "^6.22.0"
+    babel-preset-flow "^6.23.0"
+
+babel-preset-stage-0@^6.5.0:
+  version "6.24.1"
+  resolved "https://registry.yarnpkg.com/babel-preset-stage-0/-/babel-preset-stage-0-6.24.1.tgz#5642d15042f91384d7e5af8bc88b1db95b039e6a"
+  dependencies:
+    babel-plugin-transform-do-expressions "^6.22.0"
+    babel-plugin-transform-function-bind "^6.22.0"
+    babel-preset-stage-1 "^6.24.1"
+
+babel-preset-stage-1@^6.24.1:
+  version "6.24.1"
+  resolved "https://registry.yarnpkg.com/babel-preset-stage-1/-/babel-preset-stage-1-6.24.1.tgz#7692cd7dcd6849907e6ae4a0a85589cfb9e2bfb0"
+  dependencies:
+    babel-plugin-transform-class-constructor-call "^6.24.1"
+    babel-plugin-transform-export-extensions "^6.22.0"
+    babel-preset-stage-2 "^6.24.1"
+
+babel-preset-stage-2@^6.24.1:
+  version "6.24.1"
+  resolved "https://registry.yarnpkg.com/babel-preset-stage-2/-/babel-preset-stage-2-6.24.1.tgz#d9e2960fb3d71187f0e64eec62bc07767219bdc1"
+  dependencies:
+    babel-plugin-syntax-dynamic-import "^6.18.0"
+    babel-plugin-transform-class-properties "^6.24.1"
+    babel-plugin-transform-decorators "^6.24.1"
+    babel-preset-stage-3 "^6.24.1"
+
+babel-preset-stage-3@^6.24.1:
+  version "6.24.1"
+  resolved "https://registry.yarnpkg.com/babel-preset-stage-3/-/babel-preset-stage-3-6.24.1.tgz#836ada0a9e7a7fa37cb138fb9326f87934a48395"
+  dependencies:
+    babel-plugin-syntax-trailing-function-commas "^6.22.0"
+    babel-plugin-transform-async-generator-functions "^6.24.1"
+    babel-plugin-transform-async-to-generator "^6.24.1"
+    babel-plugin-transform-exponentiation-operator "^6.24.1"
+    babel-plugin-transform-object-rest-spread "^6.22.0"
+
+babel-register@^6.26.0:
+  version "6.26.0"
+  resolved "https://registry.yarnpkg.com/babel-register/-/babel-register-6.26.0.tgz#6ed021173e2fcb486d7acb45c6009a856f647071"
+  dependencies:
+    babel-core "^6.26.0"
+    babel-runtime "^6.26.0"
+    core-js "^2.5.0"
+    home-or-tmp "^2.0.0"
+    lodash "^4.17.4"
+    mkdirp "^0.5.1"
+    source-map-support "^0.4.15"
+
+babel-runtime@^6.18.0, babel-runtime@^6.22.0, babel-runtime@^6.26.0:
+  version "6.26.0"
+  resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe"
+  dependencies:
+    core-js "^2.4.0"
+    regenerator-runtime "^0.11.0"
+
+babel-template@^6.24.1, babel-template@^6.26.0:
+  version "6.26.0"
+  resolved "https://registry.yarnpkg.com/babel-template/-/babel-template-6.26.0.tgz#de03e2d16396b069f46dd9fff8521fb1a0e35e02"
+  dependencies:
+    babel-runtime "^6.26.0"
+    babel-traverse "^6.26.0"
+    babel-types "^6.26.0"
+    babylon "^6.18.0"
+    lodash "^4.17.4"
+
+babel-traverse@^6.24.1, babel-traverse@^6.26.0:
+  version "6.26.0"
+  resolved "https://registry.yarnpkg.com/babel-traverse/-/babel-traverse-6.26.0.tgz#46a9cbd7edcc62c8e5c064e2d2d8d0f4035766ee"
+  dependencies:
+    babel-code-frame "^6.26.0"
+    babel-messages "^6.23.0"
+    babel-runtime "^6.26.0"
+    babel-types "^6.26.0"
+    babylon "^6.18.0"
+    debug "^2.6.8"
+    globals "^9.18.0"
+    invariant "^2.2.2"
+    lodash "^4.17.4"
+
+babel-types@^6.19.0, babel-types@^6.24.1, babel-types@^6.26.0:
+  version "6.26.0"
+  resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-6.26.0.tgz#a3b073f94ab49eb6fa55cd65227a334380632497"
+  dependencies:
+    babel-runtime "^6.26.0"
+    esutils "^2.0.2"
+    lodash "^4.17.4"
+    to-fast-properties "^1.0.3"
+
+babel@^6.5.2:
+  version "6.23.0"
+  resolved "https://registry.yarnpkg.com/babel/-/babel-6.23.0.tgz#d0d1e7d803e974765beea3232d4e153c0efb90f4"
+
+babylon@^5.8.38:
+  version "5.8.38"
+  resolved "http://registry.npmjs.org/babylon/-/babylon-5.8.38.tgz#ec9b120b11bf6ccd4173a18bf217e60b79859ffd"
+
+babylon@^6.18.0:
+  version "6.18.0"
+  resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.18.0.tgz#af2f3b88fa6f5c1e4c634d1a0f8eac4f55b395e3"
+
+backo2@1.0.2:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/backo2/-/backo2-1.0.2.tgz#31ab1ac8b129363463e35b3ebb69f4dfcfba7947"
+
+balanced-match@^0.4.2:
+  version "0.4.2"
+  resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-0.4.2.tgz#cb3f3e3c732dc0f01ee70b403f302e61d7709838"
+
+balanced-match@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767"
+
+base64-arraybuffer@0.1.5:
+  version "0.1.5"
+  resolved "https://registry.yarnpkg.com/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz#73926771923b5a19747ad666aa5cd4bf9c6e9ce8"
+
+base64-js@^1.0.2:
+  version "1.3.0"
+  resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.3.0.tgz#cab1e6118f051095e58b5281aea8c1cd22bfc0e3"
+
+base64id@1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/base64id/-/base64id-1.0.0.tgz#47688cb99bb6804f0e06d3e763b1c32e57d8e6b6"
+
+batch@0.6.1:
+  version "0.6.1"
+  resolved "https://registry.yarnpkg.com/batch/-/batch-0.6.1.tgz#dc34314f4e679318093fc760272525f94bf25c16"
+
+bcrypt-pbkdf@^1.0.0:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e"
+  dependencies:
+    tweetnacl "^0.14.3"
+
+better-assert@~1.0.0:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/better-assert/-/better-assert-1.0.2.tgz#40866b9e1b9e0b55b481894311e68faffaebc522"
+  dependencies:
+    callsite "1.0.0"
+
+big.js@^3.1.3:
+  version "3.2.0"
+  resolved "https://registry.yarnpkg.com/big.js/-/big.js-3.2.0.tgz#a5fc298b81b9e0dca2e458824784b65c52ba588e"
+
+binary-extensions@^1.0.0:
+  version "1.11.0"
+  resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.11.0.tgz#46aa1751fb6a2f93ee5e689bb1087d4b14c6c205"
+
+blob@0.0.4:
+  version "0.0.4"
+  resolved "https://registry.yarnpkg.com/blob/-/blob-0.0.4.tgz#bcf13052ca54463f30f9fc7e95b9a47630a94921"
+
+block-stream@*:
+  version "0.0.9"
+  resolved "https://registry.yarnpkg.com/block-stream/-/block-stream-0.0.9.tgz#13ebfe778a03205cfe03751481ebb4b3300c126a"
+  dependencies:
+    inherits "~2.0.0"
+
+bluebird@^2.9.33:
+  version "2.11.0"
+  resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-2.11.0.tgz#534b9033c022c9579c56ba3b3e5a5caafbb650e1"
+
+body-parser@1.18.2:
+  version "1.18.2"
+  resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.18.2.tgz#87678a19d84b47d859b83199bd59bce222b10454"
+  dependencies:
+    bytes "3.0.0"
+    content-type "~1.0.4"
+    debug "2.6.9"
+    depd "~1.1.1"
+    http-errors "~1.6.2"
+    iconv-lite "0.4.19"
+    on-finished "~2.3.0"
+    qs "6.5.1"
+    raw-body "2.3.2"
+    type-is "~1.6.15"
+
+brace-expansion@^1.0.0, brace-expansion@^1.1.7:
+  version "1.1.11"
+  resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd"
+  dependencies:
+    balanced-match "^1.0.0"
+    concat-map "0.0.1"
+
+braces@^1.8.2:
+  version "1.8.5"
+  resolved "https://registry.yarnpkg.com/braces/-/braces-1.8.5.tgz#ba77962e12dff969d6b76711e914b737857bf6a7"
+  dependencies:
+    expand-range "^1.8.1"
+    preserve "^0.2.0"
+    repeat-element "^1.1.2"
+
+breakable@~1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/breakable/-/breakable-1.0.0.tgz#784a797915a38ead27bad456b5572cb4bbaa78c1"
+
+browserify-zlib@~0.1.4:
+  version "0.1.4"
+  resolved "https://registry.yarnpkg.com/browserify-zlib/-/browserify-zlib-0.1.4.tgz#bb35f8a519f600e0fa6b8485241c979d0141fb2d"
+  dependencies:
+    pako "~0.2.0"
+
+browserslist@^1.3.6, browserslist@^1.5.2, browserslist@^1.7.6:
+  version "1.7.7"
+  resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-1.7.7.tgz#0bd76704258be829b2398bb50e4b62d1a166b0b9"
+  dependencies:
+    caniuse-db "^1.0.30000639"
+    electron-to-chromium "^1.2.7"
+
+buffer-from@^1.0.0:
+  version "1.1.1"
+  resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef"
+
+buffer@^4.9.0:
+  version "4.9.1"
+  resolved "http://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz#6d1bb601b07a4efced97094132093027c95bc298"
+  dependencies:
+    base64-js "^1.0.2"
+    ieee754 "^1.1.4"
+    isarray "^1.0.0"
+
+builtin-modules@^1.0.0:
+  version "1.1.1"
+  resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f"
+
+bytes@3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048"
+
+callsite@1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/callsite/-/callsite-1.0.0.tgz#280398e5d664bd74038b6f0905153e6e8af1bc20"
+
+camelcase-keys@^2.0.0:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/camelcase-keys/-/camelcase-keys-2.1.0.tgz#308beeaffdf28119051efa1d932213c91b8f92e7"
+  dependencies:
+    camelcase "^2.0.0"
+    map-obj "^1.0.0"
+
+camelcase@^1.0.2, camelcase@^1.2.1:
+  version "1.2.1"
+  resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-1.2.1.tgz#9bb5304d2e0b56698b2c758b08a3eaa9daa58a39"
+
+camelcase@^2.0.0:
+  version "2.1.1"
+  resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-2.1.1.tgz#7c1d16d679a1bbe59ca02cacecfb011e201f5a1f"
+
+camelcase@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-3.0.0.tgz#32fc4b9fcdaf845fcdf7e73bb97cac2261f0ab0a"
+
+caniuse-api@^1.5.2:
+  version "1.6.1"
+  resolved "https://registry.yarnpkg.com/caniuse-api/-/caniuse-api-1.6.1.tgz#b534e7c734c4f81ec5fbe8aca2ad24354b962c6c"
+  dependencies:
+    browserslist "^1.3.6"
+    caniuse-db "^1.0.30000529"
+    lodash.memoize "^4.1.2"
+    lodash.uniq "^4.5.0"
+
+caniuse-db@^1.0.30000529, caniuse-db@^1.0.30000634, caniuse-db@^1.0.30000639:
+  version "1.0.30000883"
+  resolved "https://registry.yarnpkg.com/caniuse-db/-/caniuse-db-1.0.30000883.tgz#976f22d6a9be119b342d5ce6c7ee98fc6e0bc94a"
+
+caseless@~0.12.0:
+  version "0.12.0"
+  resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc"
+
+center-align@^0.1.1:
+  version "0.1.3"
+  resolved "https://registry.yarnpkg.com/center-align/-/center-align-0.1.3.tgz#aa0d32629b6ee972200411cbd4461c907bc2b7ad"
+  dependencies:
+    align-text "^0.1.3"
+    lazy-cache "^1.0.3"
+
+chalk@^1.0.0, chalk@^1.1.1, chalk@^1.1.3:
+  version "1.1.3"
+  resolved "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98"
+  dependencies:
+    ansi-styles "^2.2.1"
+    escape-string-regexp "^1.0.2"
+    has-ansi "^2.0.0"
+    strip-ansi "^3.0.0"
+    supports-color "^2.0.0"
+
+chokidar@^1.0.0:
+  version "1.7.0"
+  resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-1.7.0.tgz#798e689778151c8076b4b360e5edd28cda2bb468"
+  dependencies:
+    anymatch "^1.3.0"
+    async-each "^1.0.0"
+    glob-parent "^2.0.0"
+    inherits "^2.0.1"
+    is-binary-path "^1.0.0"
+    is-glob "^2.0.0"
+    path-is-absolute "^1.0.0"
+    readdirp "^2.0.0"
+  optionalDependencies:
+    fsevents "^1.0.0"
+
+chownr@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.0.1.tgz#e2a75042a9551908bebd25b8523d5f9769d79181"
+
+circular-json@^0.3.1:
+  version "0.3.3"
+  resolved "https://registry.yarnpkg.com/circular-json/-/circular-json-0.3.3.tgz#815c99ea84f6809529d2f45791bdf82711352d66"
+
+clap@^1.0.9:
+  version "1.2.3"
+  resolved "https://registry.yarnpkg.com/clap/-/clap-1.2.3.tgz#4f36745b32008492557f46412d66d50cb99bce51"
+  dependencies:
+    chalk "^1.1.3"
+
+cli-cursor@^1.0.1:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-1.0.2.tgz#64da3f7d56a54412e59794bd62dc35295e8f2987"
+  dependencies:
+    restore-cursor "^1.0.1"
+
+cli-width@^1.0.1:
+  version "1.1.1"
+  resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-1.1.1.tgz#a4d293ef67ebb7b88d4a4d42c0ccf00c4d1e366d"
+
+cliui@^2.1.0:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/cliui/-/cliui-2.1.0.tgz#4b475760ff80264c762c3a1719032e91c7fea0d1"
+  dependencies:
+    center-align "^0.1.1"
+    right-align "^0.1.1"
+    wordwrap "0.0.2"
+
+cliui@^3.2.0:
+  version "3.2.0"
+  resolved "https://registry.yarnpkg.com/cliui/-/cliui-3.2.0.tgz#120601537a916d29940f934da3b48d585a39213d"
+  dependencies:
+    string-width "^1.0.1"
+    strip-ansi "^3.0.1"
+    wrap-ansi "^2.0.0"
+
+clone@^1.0.2:
+  version "1.0.4"
+  resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e"
+
+co@^4.6.0:
+  version "4.6.0"
+  resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184"
+
+coa@~1.0.1:
+  version "1.0.4"
+  resolved "https://registry.yarnpkg.com/coa/-/coa-1.0.4.tgz#a9ef153660d6a86a8bdec0289a5c684d217432fd"
+  dependencies:
+    q "^1.1.2"
+
+code-point-at@^1.0.0:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77"
+
+color-convert@^1.3.0:
+  version "1.9.3"
+  resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8"
+  dependencies:
+    color-name "1.1.3"
+
+color-name@1.1.3, color-name@^1.0.0:
+  version "1.1.3"
+  resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25"
+
+color-string@^0.3.0:
+  version "0.3.0"
+  resolved "https://registry.yarnpkg.com/color-string/-/color-string-0.3.0.tgz#27d46fb67025c5c2fa25993bfbf579e47841b991"
+  dependencies:
+    color-name "^1.0.0"
+
+color@^0.11.0:
+  version "0.11.4"
+  resolved "https://registry.yarnpkg.com/color/-/color-0.11.4.tgz#6d7b5c74fb65e841cd48792ad1ed5e07b904d764"
+  dependencies:
+    clone "^1.0.2"
+    color-convert "^1.3.0"
+    color-string "^0.3.0"
+
+colormin@^1.0.5:
+  version "1.1.2"
+  resolved "https://registry.yarnpkg.com/colormin/-/colormin-1.1.2.tgz#ea2f7420a72b96881a38aae59ec124a6f7298133"
+  dependencies:
+    color "^0.11.0"
+    css-color-names "0.0.4"
+    has "^1.0.1"
+
+colors@~1.1.2:
+  version "1.1.2"
+  resolved "https://registry.yarnpkg.com/colors/-/colors-1.1.2.tgz#168a4701756b6a7f51a12ce0c97bfa28c084ed63"
+
+combined-stream@1.0.6, combined-stream@~1.0.6:
+  version "1.0.6"
+  resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.6.tgz#723e7df6e801ac5613113a7e445a9b69cb632818"
+  dependencies:
+    delayed-stream "~1.0.0"
+
+commander@^2.5.0:
+  version "2.17.1"
+  resolved "https://registry.yarnpkg.com/commander/-/commander-2.17.1.tgz#bd77ab7de6de94205ceacc72f1716d29f20a77bf"
+
+commondir@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b"
+
+commoner@~0.10.3:
+  version "0.10.8"
+  resolved "https://registry.yarnpkg.com/commoner/-/commoner-0.10.8.tgz#34fc3672cd24393e8bb47e70caa0293811f4f2c5"
+  dependencies:
+    commander "^2.5.0"
+    detective "^4.3.1"
+    glob "^5.0.15"
+    graceful-fs "^4.1.2"
+    iconv-lite "^0.4.5"
+    mkdirp "^0.5.0"
+    private "^0.1.6"
+    q "^1.1.2"
+    recast "^0.11.17"
+
+component-bind@1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/component-bind/-/component-bind-1.0.0.tgz#00c608ab7dcd93897c0009651b1d3a8e1e73bbd1"
+
+component-emitter@1.1.2:
+  version "1.1.2"
+  resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.1.2.tgz#296594f2753daa63996d2af08d15a95116c9aec3"
+
+component-emitter@1.2.1:
+  version "1.2.1"
+  resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.2.1.tgz#137918d6d78283f7df7a6b7c5a63e140e69425e6"
+
+component-inherit@0.0.3:
+  version "0.0.3"
+  resolved "https://registry.yarnpkg.com/component-inherit/-/component-inherit-0.0.3.tgz#645fc4adf58b72b649d5cae65135619db26ff143"
+
+compressible@~2.0.14:
+  version "2.0.14"
+  resolved "https://registry.yarnpkg.com/compressible/-/compressible-2.0.14.tgz#326c5f507fbb055f54116782b969a81b67a29da7"
+  dependencies:
+    mime-db ">= 1.34.0 < 2"
+
+compression@^1.5.2:
+  version "1.7.3"
+  resolved "https://registry.yarnpkg.com/compression/-/compression-1.7.3.tgz#27e0e176aaf260f7f2c2813c3e440adb9f1993db"
+  dependencies:
+    accepts "~1.3.5"
+    bytes "3.0.0"
+    compressible "~2.0.14"
+    debug "2.6.9"
+    on-headers "~1.0.1"
+    safe-buffer "5.1.2"
+    vary "~1.1.2"
+
+concat-map@0.0.1:
+  version "0.0.1"
+  resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
+
+concat-stream@^1.4.6:
+  version "1.6.2"
+  resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34"
+  dependencies:
+    buffer-from "^1.0.0"
+    inherits "^2.0.3"
+    readable-stream "^2.2.2"
+    typedarray "^0.0.6"
+
+connect-history-api-fallback@1.1.0:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/connect-history-api-fallback/-/connect-history-api-fallback-1.1.0.tgz#5a6dee82d9a648cb29131d3f9dd400ffa4593742"
+
+console-browserify@^1.1.0:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/console-browserify/-/console-browserify-1.1.0.tgz#f0241c45730a9fc6323b206dbf38edc741d0bb10"
+  dependencies:
+    date-now "^0.1.4"
+
+console-control-strings@^1.0.0, console-control-strings@~1.1.0:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e"
+
+constants-browserify@0.0.1:
+  version "0.0.1"
+  resolved "https://registry.yarnpkg.com/constants-browserify/-/constants-browserify-0.0.1.tgz#92577db527ba6c4cf0a4568d84bc031f441e21f2"
+
+content-disposition@0.5.2:
+  version "0.5.2"
+  resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.2.tgz#0cf68bb9ddf5f2be7961c3a85178cb85dba78cb4"
+
+content-type@~1.0.4:
+  version "1.0.4"
+  resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b"
+
+convert-source-map@^1.1.0, convert-source-map@^1.5.1:
+  version "1.5.1"
+  resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.5.1.tgz#b8278097b9bc229365de5c62cf5fcaed8b5599e5"
+
+cookie-signature@1.0.6:
+  version "1.0.6"
+  resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c"
+
+cookie@0.3.1:
+  version "0.3.1"
+  resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.3.1.tgz#e7e0a1f9ef43b4c8ba925c5c5a96e806d16873bb"
+
+core-js@^1.0.0:
+  version "1.2.7"
+  resolved "https://registry.yarnpkg.com/core-js/-/core-js-1.2.7.tgz#652294c14651db28fa93bd2d5ff2983a4f08c636"
+
+core-js@^2.4.0, core-js@^2.5.0:
+  version "2.5.7"
+  resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.5.7.tgz#f972608ff0cead68b841a16a932d0b183791814e"
+
+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"
+
+create-react-class@^15.5.1:
+  version "15.6.3"
+  resolved "https://registry.yarnpkg.com/create-react-class/-/create-react-class-15.6.3.tgz#2d73237fb3f970ae6ebe011a9e66f46dbca80036"
+  dependencies:
+    fbjs "^0.8.9"
+    loose-envify "^1.3.1"
+    object-assign "^4.1.1"
+
+cross-env@^5.0.0:
+  version "5.2.0"
+  resolved "https://registry.yarnpkg.com/cross-env/-/cross-env-5.2.0.tgz#6ecd4c015d5773e614039ee529076669b9d126f2"
+  dependencies:
+    cross-spawn "^6.0.5"
+    is-windows "^1.0.0"
+
+cross-spawn@^3.0.0:
+  version "3.0.1"
+  resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-3.0.1.tgz#1256037ecb9f0c5f79e3d6ef135e30770184b982"
+  dependencies:
+    lru-cache "^4.0.1"
+    which "^1.2.9"
+
+cross-spawn@^6.0.5:
+  version "6.0.5"
+  resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4"
+  dependencies:
+    nice-try "^1.0.4"
+    path-key "^2.0.1"
+    semver "^5.5.0"
+    shebang-command "^1.2.0"
+    which "^1.2.9"
+
+crypto-browserify@~3.2.6:
+  version "3.2.8"
+  resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-3.2.8.tgz#b9b11dbe6d9651dd882a01e6cc467df718ecf189"
+  dependencies:
+    pbkdf2-compat "2.0.1"
+    ripemd160 "0.2.0"
+    sha.js "2.2.6"
+
+css-color-names@0.0.4:
+  version "0.0.4"
+  resolved "https://registry.yarnpkg.com/css-color-names/-/css-color-names-0.0.4.tgz#808adc2e79cf84738069b646cb20ec27beb629e0"
+
+css-loader@^0.19.0:
+  version "0.19.0"
+  resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-0.19.0.tgz#7383db6a20fcc42395bada4b8abc25c2735577b8"
+  dependencies:
+    css-selector-tokenizer "^0.5.1"
+    cssnano ">=2.6.1 <4"
+    loader-utils "~0.2.2"
+    postcss "^5.0.6"
+    postcss-modules-extract-imports "1.0.0-beta2"
+    postcss-modules-local-by-default "1.0.0-beta1"
+    postcss-modules-scope "1.0.0-beta2"
+    source-list-map "^0.1.4"
+
+css-selector-tokenizer@^0.5.0, css-selector-tokenizer@^0.5.1:
+  version "0.5.4"
+  resolved "https://registry.yarnpkg.com/css-selector-tokenizer/-/css-selector-tokenizer-0.5.4.tgz#139bafd34a35fd0c1428487049e0699e6f6a2c21"
+  dependencies:
+    cssesc "^0.1.0"
+    fastparse "^1.1.1"
+
+cssesc@^0.1.0:
+  version "0.1.0"
+  resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-0.1.0.tgz#c814903e45623371a0477b40109aaafbeeaddbb4"
+
+"cssnano@>=2.6.1 <4":
+  version "3.10.0"
+  resolved "https://registry.yarnpkg.com/cssnano/-/cssnano-3.10.0.tgz#4f38f6cea2b9b17fa01490f23f1dc68ea65c1c38"
+  dependencies:
+    autoprefixer "^6.3.1"
+    decamelize "^1.1.2"
+    defined "^1.0.0"
+    has "^1.0.1"
+    object-assign "^4.0.1"
+    postcss "^5.0.14"
+    postcss-calc "^5.2.0"
+    postcss-colormin "^2.1.8"
+    postcss-convert-values "^2.3.4"
+    postcss-discard-comments "^2.0.4"
+    postcss-discard-duplicates "^2.0.1"
+    postcss-discard-empty "^2.0.1"
+    postcss-discard-overridden "^0.1.1"
+    postcss-discard-unused "^2.2.1"
+    postcss-filter-plugins "^2.0.0"
+    postcss-merge-idents "^2.1.5"
+    postcss-merge-longhand "^2.0.1"
+    postcss-merge-rules "^2.0.3"
+    postcss-minify-font-values "^1.0.2"
+    postcss-minify-gradients "^1.0.1"
+    postcss-minify-params "^1.0.4"
+    postcss-minify-selectors "^2.0.4"
+    postcss-normalize-charset "^1.1.0"
+    postcss-normalize-url "^3.0.7"
+    postcss-ordered-values "^2.1.0"
+    postcss-reduce-idents "^2.2.2"
+    postcss-reduce-initial "^1.0.0"
+    postcss-reduce-transforms "^1.0.3"
+    postcss-svgo "^2.1.1"
+    postcss-unique-selectors "^2.0.2"
+    postcss-value-parser "^3.2.3"
+    postcss-zindex "^2.0.1"
+
+csso@~2.3.1:
+  version "2.3.2"
+  resolved "https://registry.yarnpkg.com/csso/-/csso-2.3.2.tgz#ddd52c587033f49e94b71fc55569f252e8ff5f85"
+  dependencies:
+    clap "^1.0.9"
+    source-map "^0.5.3"
+
+currently-unhandled@^0.4.1:
+  version "0.4.1"
+  resolved "https://registry.yarnpkg.com/currently-unhandled/-/currently-unhandled-0.4.1.tgz#988df33feab191ef799a61369dd76c17adf957ea"
+  dependencies:
+    array-find-index "^1.0.1"
+
+d@1:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/d/-/d-1.0.0.tgz#754bb5bfe55451da69a58b94d45f4c5b0462d58f"
+  dependencies:
+    es5-ext "^0.10.9"
+
+dashdash@^1.12.0:
+  version "1.14.1"
+  resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0"
+  dependencies:
+    assert-plus "^1.0.0"
+
+date-now@^0.1.4:
+  version "0.1.4"
+  resolved "https://registry.yarnpkg.com/date-now/-/date-now-0.1.4.tgz#eaf439fd4d4848ad74e5cc7dbef200672b9e345b"
+
+debug@2.2.0:
+  version "2.2.0"
+  resolved "https://registry.yarnpkg.com/debug/-/debug-2.2.0.tgz#f87057e995b1a1f6ae6a4960664137bc56f039da"
+  dependencies:
+    ms "0.7.1"
+
+debug@2.3.3:
+  version "2.3.3"
+  resolved "https://registry.yarnpkg.com/debug/-/debug-2.3.3.tgz#40c453e67e6e13c901ddec317af8986cda9eff8c"
+  dependencies:
+    ms "0.7.2"
+
+debug@2.6.9, debug@^2.1.1, debug@^2.1.2, debug@^2.6.8, debug@^2.6.9:
+  version "2.6.9"
+  resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
+  dependencies:
+    ms "2.0.0"
+
+debug@^3.1.0:
+  version "3.1.0"
+  resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261"
+  dependencies:
+    ms "2.0.0"
+
+decamelize@^1.0.0, decamelize@^1.1.1, decamelize@^1.1.2:
+  version "1.2.0"
+  resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290"
+
+deep-extend@^0.6.0:
+  version "0.6.0"
+  resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac"
+
+deep-is@~0.1.3:
+  version "0.1.3"
+  resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34"
+
+defined@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/defined/-/defined-1.0.0.tgz#c98d9bcef75674188e110969151199e39b1fa693"
+
+defs@~1.1.0:
+  version "1.1.1"
+  resolved "https://registry.yarnpkg.com/defs/-/defs-1.1.1.tgz#b22609f2c7a11ba7a3db116805c139b1caffa9d2"
+  dependencies:
+    alter "~0.2.0"
+    ast-traverse "~0.1.1"
+    breakable "~1.0.0"
+    esprima-fb "~15001.1001.0-dev-harmony-fb"
+    simple-fmt "~0.1.0"
+    simple-is "~0.2.0"
+    stringmap "~0.2.2"
+    stringset "~0.2.1"
+    tryor "~0.1.2"
+    yargs "~3.27.0"
+
+del@^2.0.2:
+  version "2.2.2"
+  resolved "https://registry.yarnpkg.com/del/-/del-2.2.2.tgz#c12c981d067846c84bcaf862cff930d907ffd1a8"
+  dependencies:
+    globby "^5.0.0"
+    is-path-cwd "^1.0.0"
+    is-path-in-cwd "^1.0.0"
+    object-assign "^4.0.1"
+    pify "^2.0.0"
+    pinkie-promise "^2.0.0"
+    rimraf "^2.2.8"
+
+delayed-stream@~1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619"
+
+delegates@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a"
+
+depd@1.1.1:
+  version "1.1.1"
+  resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.1.tgz#5783b4e1c459f06fa5ca27f991f3d06e7a310359"
+
+depd@~1.1.1, depd@~1.1.2:
+  version "1.1.2"
+  resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9"
+
+destroy@~1.0.4:
+  version "1.0.4"
+  resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80"
+
+detect-indent@^3.0.0:
+  version "3.0.1"
+  resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-3.0.1.tgz#9dc5e5ddbceef8325764b9451b02bc6d54084f75"
+  dependencies:
+    get-stdin "^4.0.1"
+    minimist "^1.1.0"
+    repeating "^1.1.0"
+
+detect-indent@^4.0.0:
+  version "4.0.0"
+  resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-4.0.0.tgz#f76d064352cdf43a1cb6ce619c4ee3a9475de208"
+  dependencies:
+    repeating "^2.0.0"
+
+detect-libc@^1.0.2:
+  version "1.0.3"
+  resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b"
+
+detective@^4.3.1:
+  version "4.7.1"
+  resolved "https://registry.yarnpkg.com/detective/-/detective-4.7.1.tgz#0eca7314338442febb6d65da54c10bb1c82b246e"
+  dependencies:
+    acorn "^5.2.1"
+    defined "^1.0.0"
+
+doctrine@^0.7.1:
+  version "0.7.2"
+  resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-0.7.2.tgz#7cb860359ba3be90e040b26b729ce4bfa654c523"
+  dependencies:
+    esutils "^1.1.6"
+    isarray "0.0.1"
+
+domain-browser@^1.1.1:
+  version "1.2.0"
+  resolved "https://registry.yarnpkg.com/domain-browser/-/domain-browser-1.2.0.tgz#3d31f50191a6749dd1375a7f522e823d42e54eda"
+
+ecc-jsbn@~0.1.1:
+  version "0.1.2"
+  resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9"
+  dependencies:
+    jsbn "~0.1.0"
+    safer-buffer "^2.1.0"
+
+ee-first@1.1.1:
+  version "1.1.1"
+  resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d"
+
+electron-to-chromium@^1.2.7:
+  version "1.3.62"
+  resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.62.tgz#2e8e2dc070c800ec8ce23ff9dfcceb585d6f9ed8"
+
+emojis-list@^2.0.0:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-2.1.0.tgz#4daa4d9db00f9819880c79fa457ae5b09a1fd389"
+
+encodeurl@~1.0.2:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59"
+
+encoding@^0.1.11:
+  version "0.1.12"
+  resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.12.tgz#538b66f3ee62cd1ab51ec323829d1f9480c74beb"
+  dependencies:
+    iconv-lite "~0.4.13"
+
+engine.io-client@~1.8.4:
+  version "1.8.5"
+  resolved "https://registry.yarnpkg.com/engine.io-client/-/engine.io-client-1.8.5.tgz#fe7fb60cb0dcf2fa2859489329cb5968dedeb11f"
+  dependencies:
+    component-emitter "1.2.1"
+    component-inherit "0.0.3"
+    debug "2.3.3"
+    engine.io-parser "1.3.2"
+    has-cors "1.1.0"
+    indexof "0.0.1"
+    parsejson "0.0.3"
+    parseqs "0.0.5"
+    parseuri "0.0.5"
+    ws "~1.1.5"
+    xmlhttprequest-ssl "1.5.3"
+    yeast "0.1.2"
+
+engine.io-parser@1.3.2:
+  version "1.3.2"
+  resolved "https://registry.yarnpkg.com/engine.io-parser/-/engine.io-parser-1.3.2.tgz#937b079f0007d0893ec56d46cb220b8cb435220a"
+  dependencies:
+    after "0.8.2"
+    arraybuffer.slice "0.0.6"
+    base64-arraybuffer "0.1.5"
+    blob "0.0.4"
+    has-binary "0.1.7"
+    wtf-8 "1.0.0"
+
+engine.io@~1.8.4:
+  version "1.8.5"
+  resolved "https://registry.yarnpkg.com/engine.io/-/engine.io-1.8.5.tgz#4ebe5e75c6dc123dee4afdce6e5fdced21eb93f6"
+  dependencies:
+    accepts "1.3.3"
+    base64id "1.0.0"
+    cookie "0.3.1"
+    debug "2.3.3"
+    engine.io-parser "1.3.2"
+    ws "~1.1.5"
+
+enhanced-resolve@~0.9.0:
+  version "0.9.1"
+  resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-0.9.1.tgz#4d6e689b3725f86090927ccc86cd9f1635b89e2e"
+  dependencies:
+    graceful-fs "^4.1.2"
+    memory-fs "^0.2.0"
+    tapable "^0.1.8"
+
+errno@^0.1.3:
+  version "0.1.7"
+  resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.7.tgz#4684d71779ad39af177e3f007996f7c67c852618"
+  dependencies:
+    prr "~1.0.1"
+
+error-ex@^1.2.0:
+  version "1.3.2"
+  resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf"
+  dependencies:
+    is-arrayish "^0.2.1"
+
+es5-ext@^0.10.14, es5-ext@^0.10.35, es5-ext@^0.10.9, es5-ext@~0.10.14:
+  version "0.10.46"
+  resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.46.tgz#efd99f67c5a7ec789baa3daa7f79870388f7f572"
+  dependencies:
+    es6-iterator "~2.0.3"
+    es6-symbol "~3.1.1"
+    next-tick "1"
+
+es6-iterator@^2.0.1, es6-iterator@~2.0.1, es6-iterator@~2.0.3:
+  version "2.0.3"
+  resolved "https://registry.yarnpkg.com/es6-iterator/-/es6-iterator-2.0.3.tgz#a7de889141a05a94b0854403b2d0a0fbfa98f3b7"
+  dependencies:
+    d "1"
+    es5-ext "^0.10.35"
+    es6-symbol "^3.1.1"
+
+es6-map@^0.1.3:
+  version "0.1.5"
+  resolved "https://registry.yarnpkg.com/es6-map/-/es6-map-0.1.5.tgz#9136e0503dcc06a301690f0bb14ff4e364e949f0"
+  dependencies:
+    d "1"
+    es5-ext "~0.10.14"
+    es6-iterator "~2.0.1"
+    es6-set "~0.1.5"
+    es6-symbol "~3.1.1"
+    event-emitter "~0.3.5"
+
+es6-set@~0.1.5:
+  version "0.1.5"
+  resolved "https://registry.yarnpkg.com/es6-set/-/es6-set-0.1.5.tgz#d2b3ec5d4d800ced818db538d28974db0a73ccb1"
+  dependencies:
+    d "1"
+    es5-ext "~0.10.14"
+    es6-iterator "~2.0.1"
+    es6-symbol "3.1.1"
+    event-emitter "~0.3.5"
+
+es6-symbol@3.1.1, es6-symbol@^3.1.1, es6-symbol@~3.1.1:
+  version "3.1.1"
+  resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.1.tgz#bf00ef4fdab6ba1b46ecb7b629b4c7ed5715cc77"
+  dependencies:
+    d "1"
+    es5-ext "~0.10.14"
+
+es6-weak-map@^2.0.1:
+  version "2.0.2"
+  resolved "https://registry.yarnpkg.com/es6-weak-map/-/es6-weak-map-2.0.2.tgz#5e3ab32251ffd1538a1f8e5ffa1357772f92d96f"
+  dependencies:
+    d "1"
+    es5-ext "^0.10.14"
+    es6-iterator "^2.0.1"
+    es6-symbol "^3.1.1"
+
+escape-html@~1.0.3:
+  version "1.0.3"
+  resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988"
+
+escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5:
+  version "1.0.5"
+  resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
+
+escope@^3.3.0:
+  version "3.6.0"
+  resolved "https://registry.yarnpkg.com/escope/-/escope-3.6.0.tgz#e01975e812781a163a6dadfdd80398dc64c889c3"
+  dependencies:
+    es6-map "^0.1.3"
+    es6-weak-map "^2.0.1"
+    esrecurse "^4.1.0"
+    estraverse "^4.1.1"
+
+eslint-config-airbnb@^2.0.0:
+  version "2.1.1"
+  resolved "https://registry.yarnpkg.com/eslint-config-airbnb/-/eslint-config-airbnb-2.1.1.tgz#7aade3205423d169f66eeb15284b3da3482be39a"
+
+eslint-plugin-react@^3.11.3:
+  version "3.16.1"
+  resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-3.16.1.tgz#262d96b77d7c4a42af809a73c0e527a58612293c"
+
+eslint@^1.10.3:
+  version "1.10.3"
+  resolved "https://registry.yarnpkg.com/eslint/-/eslint-1.10.3.tgz#fb19a91b13c158082bbca294b17d979bc8353a0a"
+  dependencies:
+    chalk "^1.0.0"
+    concat-stream "^1.4.6"
+    debug "^2.1.1"
+    doctrine "^0.7.1"
+    escape-string-regexp "^1.0.2"
+    escope "^3.3.0"
+    espree "^2.2.4"
+    estraverse "^4.1.1"
+    estraverse-fb "^1.3.1"
+    esutils "^2.0.2"
+    file-entry-cache "^1.1.1"
+    glob "^5.0.14"
+    globals "^8.11.0"
+    handlebars "^4.0.0"
+    inquirer "^0.11.0"
+    is-my-json-valid "^2.10.0"
+    is-resolvable "^1.0.0"
+    js-yaml "3.4.5"
+    json-stable-stringify "^1.0.0"
+    lodash.clonedeep "^3.0.1"
+    lodash.merge "^3.3.2"
+    lodash.omit "^3.1.0"
+    minimatch "^3.0.0"
+    mkdirp "^0.5.0"
+    object-assign "^4.0.1"
+    optionator "^0.6.0"
+    path-is-absolute "^1.0.0"
+    path-is-inside "^1.0.1"
+    shelljs "^0.5.3"
+    strip-json-comments "~1.0.1"
+    text-table "~0.2.0"
+    user-home "^2.0.0"
+    xml-escape "~1.0.0"
+
+espree@^2.2.4:
+  version "2.2.5"
+  resolved "https://registry.yarnpkg.com/espree/-/espree-2.2.5.tgz#df691b9310889402aeb29cc066708c56690b854b"
+
+esprima-fb@~15001.1001.0-dev-harmony-fb:
+  version "15001.1001.0-dev-harmony-fb"
+  resolved "https://registry.yarnpkg.com/esprima-fb/-/esprima-fb-15001.1001.0-dev-harmony-fb.tgz#43beb57ec26e8cf237d3dd8b33e42533577f2659"
+
+esprima@^2.5.0, esprima@^2.6.0:
+  version "2.7.3"
+  resolved "https://registry.yarnpkg.com/esprima/-/esprima-2.7.3.tgz#96e3b70d5779f6ad49cd032673d1c312767ba581"
+
+esprima@~3.1.0:
+  version "3.1.3"
+  resolved "https://registry.yarnpkg.com/esprima/-/esprima-3.1.3.tgz#fdca51cee6133895e3c88d535ce49dbff62a4633"
+
+esrecurse@^4.1.0:
+  version "4.2.1"
+  resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.2.1.tgz#007a3b9fdbc2b3bb87e4879ea19c92fdbd3942cf"
+  dependencies:
+    estraverse "^4.1.0"
+
+estraverse-fb@^1.3.1:
+  version "1.3.2"
+  resolved "https://registry.yarnpkg.com/estraverse-fb/-/estraverse-fb-1.3.2.tgz#d323a4cb5e5ac331cea033413a9253e1643e07c4"
+
+estraverse@^4.1.0, estraverse@^4.1.1:
+  version "4.2.0"
+  resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.2.0.tgz#0dee3fed31fcd469618ce7342099fc1afa0bdb13"
+
+esutils@^1.1.6:
+  version "1.1.6"
+  resolved "https://registry.yarnpkg.com/esutils/-/esutils-1.1.6.tgz#c01ccaa9ae4b897c6d0c3e210ae52f3c7a844375"
+
+esutils@^2.0.0, esutils@^2.0.2:
+  version "2.0.2"
+  resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.2.tgz#0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b"
+
+etag@~1.8.1:
+  version "1.8.1"
+  resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887"
+
+event-emitter@~0.3.5:
+  version "0.3.5"
+  resolved "https://registry.yarnpkg.com/event-emitter/-/event-emitter-0.3.5.tgz#df8c69eef1647923c7157b9ce83840610b02cc39"
+  dependencies:
+    d "1"
+    es5-ext "~0.10.14"
+
+eventemitter3@^3.0.0:
+  version "3.1.0"
+  resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-3.1.0.tgz#090b4d6cdbd645ed10bf750d4b5407942d7ba163"
+
+events@^1.0.0:
+  version "1.1.1"
+  resolved "https://registry.yarnpkg.com/events/-/events-1.1.1.tgz#9ebdb7635ad099c70dcc4c2a1f5004288e8bd924"
+
+exit-hook@^1.0.0:
+  version "1.1.1"
+  resolved "https://registry.yarnpkg.com/exit-hook/-/exit-hook-1.1.1.tgz#f05ca233b48c05d54fff07765df8507e95c02ff8"
+
+expand-brackets@^0.1.4:
+  version "0.1.5"
+  resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-0.1.5.tgz#df07284e342a807cd733ac5af72411e581d1177b"
+  dependencies:
+    is-posix-bracket "^0.1.0"
+
+expand-range@^1.8.1:
+  version "1.8.2"
+  resolved "https://registry.yarnpkg.com/expand-range/-/expand-range-1.8.2.tgz#a299effd335fe2721ebae8e257ec79644fc85337"
+  dependencies:
+    fill-range "^2.1.0"
+
+express@^4.13.3:
+  version "4.16.3"
+  resolved "https://registry.yarnpkg.com/express/-/express-4.16.3.tgz#6af8a502350db3246ecc4becf6b5a34d22f7ed53"
+  dependencies:
+    accepts "~1.3.5"
+    array-flatten "1.1.1"
+    body-parser "1.18.2"
+    content-disposition "0.5.2"
+    content-type "~1.0.4"
+    cookie "0.3.1"
+    cookie-signature "1.0.6"
+    debug "2.6.9"
+    depd "~1.1.2"
+    encodeurl "~1.0.2"
+    escape-html "~1.0.3"
+    etag "~1.8.1"
+    finalhandler "1.1.1"
+    fresh "0.5.2"
+    merge-descriptors "1.0.1"
+    methods "~1.1.2"
+    on-finished "~2.3.0"
+    parseurl "~1.3.2"
+    path-to-regexp "0.1.7"
+    proxy-addr "~2.0.3"
+    qs "6.5.1"
+    range-parser "~1.2.0"
+    safe-buffer "5.1.1"
+    send "0.16.2"
+    serve-static "1.13.2"
+    setprototypeof "1.1.0"
+    statuses "~1.4.0"
+    type-is "~1.6.16"
+    utils-merge "1.0.1"
+    vary "~1.1.2"
+
+extend@~3.0.2:
+  version "3.0.2"
+  resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa"
+
+extglob@^0.3.1:
+  version "0.3.2"
+  resolved "https://registry.yarnpkg.com/extglob/-/extglob-0.3.2.tgz#2e18ff3d2f49ab2765cec9023f011daa8d8349a1"
+  dependencies:
+    is-extglob "^1.0.0"
+
+extsprintf@1.3.0:
+  version "1.3.0"
+  resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05"
+
+extsprintf@^1.2.0:
+  version "1.4.0"
+  resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f"
+
+fast-deep-equal@^1.0.0:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz#c053477817c86b51daa853c81e059b733d023614"
+
+fast-json-stable-stringify@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2"
+
+fast-levenshtein@~1.0.6:
+  version "1.0.7"
+  resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-1.0.7.tgz#0178dcdee023b92905193af0959e8a7639cfdcb9"
+
+fastparse@^1.1.1:
+  version "1.1.1"
+  resolved "https://registry.yarnpkg.com/fastparse/-/fastparse-1.1.1.tgz#d1e2643b38a94d7583b479060e6c4affc94071f8"
+
+fbjs@^0.8.16, fbjs@^0.8.9:
+  version "0.8.17"
+  resolved "https://registry.yarnpkg.com/fbjs/-/fbjs-0.8.17.tgz#c4d598ead6949112653d6588b01a5cdcd9f90fdd"
+  dependencies:
+    core-js "^1.0.0"
+    isomorphic-fetch "^2.1.1"
+    loose-envify "^1.0.0"
+    object-assign "^4.1.0"
+    promise "^7.1.1"
+    setimmediate "^1.0.5"
+    ua-parser-js "^0.7.18"
+
+figures@^1.3.5:
+  version "1.7.0"
+  resolved "https://registry.yarnpkg.com/figures/-/figures-1.7.0.tgz#cbe1e3affcf1cd44b80cadfed28dc793a9701d2e"
+  dependencies:
+    escape-string-regexp "^1.0.5"
+    object-assign "^4.1.0"
+
+file-entry-cache@^1.1.1:
+  version "1.3.1"
+  resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-1.3.1.tgz#44c61ea607ae4be9c1402f41f44270cbfe334ff8"
+  dependencies:
+    flat-cache "^1.2.1"
+    object-assign "^4.0.1"
+
+filename-regex@^2.0.0:
+  version "2.0.1"
+  resolved "https://registry.yarnpkg.com/filename-regex/-/filename-regex-2.0.1.tgz#c1c4b9bee3e09725ddb106b75c1e301fe2f18b26"
+
+fill-range@^2.1.0:
+  version "2.2.4"
+  resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-2.2.4.tgz#eb1e773abb056dcd8df2bfdf6af59b8b3a936565"
+  dependencies:
+    is-number "^2.1.0"
+    isobject "^2.0.0"
+    randomatic "^3.0.0"
+    repeat-element "^1.1.2"
+    repeat-string "^1.5.2"
+
+finalhandler@1.1.1:
+  version "1.1.1"
+  resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.1.tgz#eebf4ed840079c83f4249038c9d703008301b105"
+  dependencies:
+    debug "2.6.9"
+    encodeurl "~1.0.2"
+    escape-html "~1.0.3"
+    on-finished "~2.3.0"
+    parseurl "~1.3.2"
+    statuses "~1.4.0"
+    unpipe "~1.0.0"
+
+find-cache-dir@^0.1.1:
+  version "0.1.1"
+  resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-0.1.1.tgz#c8defae57c8a52a8a784f9e31c57c742e993a0b9"
+  dependencies:
+    commondir "^1.0.1"
+    mkdirp "^0.5.1"
+    pkg-dir "^1.0.0"
+
+find-up@^1.0.0:
+  version "1.1.2"
+  resolved "https://registry.yarnpkg.com/find-up/-/find-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f"
+  dependencies:
+    path-exists "^2.0.0"
+    pinkie-promise "^2.0.0"
+
+flat-cache@^1.2.1:
+  version "1.3.0"
+  resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-1.3.0.tgz#d3030b32b38154f4e3b7e9c709f490f7ef97c481"
+  dependencies:
+    circular-json "^0.3.1"
+    del "^2.0.2"
+    graceful-fs "^4.1.2"
+    write "^0.2.1"
+
+flatten@^1.0.2:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/flatten/-/flatten-1.0.2.tgz#dae46a9d78fbe25292258cc1e780a41d95c03782"
+
+follow-redirects@^1.0.0:
+  version "1.5.7"
+  resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.5.7.tgz#a39e4804dacb90202bca76a9e2ac10433ca6a69a"
+  dependencies:
+    debug "^3.1.0"
+
+for-in@^1.0.1:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80"
+
+for-own@^0.1.4:
+  version "0.1.5"
+  resolved "https://registry.yarnpkg.com/for-own/-/for-own-0.1.5.tgz#5265c681a4f294dabbf17c9509b6763aa84510ce"
+  dependencies:
+    for-in "^1.0.1"
+
+forever-agent@~0.6.1:
+  version "0.6.1"
+  resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91"
+
+form-data@~2.3.2:
+  version "2.3.2"
+  resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.2.tgz#4970498be604c20c005d4f5c23aecd21d6b49099"
+  dependencies:
+    asynckit "^0.4.0"
+    combined-stream "1.0.6"
+    mime-types "^2.1.12"
+
+forwarded@~0.1.2:
+  version "0.1.2"
+  resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.1.2.tgz#98c23dab1175657b8c0573e8ceccd91b0ff18c84"
+
+fresh@0.5.2:
+  version "0.5.2"
+  resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7"
+
+fs-minipass@^1.2.5:
+  version "1.2.5"
+  resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-1.2.5.tgz#06c277218454ec288df77ada54a03b8702aacb9d"
+  dependencies:
+    minipass "^2.2.1"
+
+fs-readdir-recursive@^0.1.0:
+  version "0.1.2"
+  resolved "https://registry.yarnpkg.com/fs-readdir-recursive/-/fs-readdir-recursive-0.1.2.tgz#315b4fb8c1ca5b8c47defef319d073dad3568059"
+
+fs.realpath@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
+
+fsevents@^1.0.0:
+  version "1.2.4"
+  resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.2.4.tgz#f41dcb1af2582af3692da36fc55cbd8e1041c426"
+  dependencies:
+    nan "^2.9.2"
+    node-pre-gyp "^0.10.0"
+
+fstream@^1.0.0, fstream@^1.0.2:
+  version "1.0.11"
+  resolved "https://registry.yarnpkg.com/fstream/-/fstream-1.0.11.tgz#5c1fb1f117477114f0632a0eb4b71b3cb0fd3171"
+  dependencies:
+    graceful-fs "^4.1.2"
+    inherits "~2.0.0"
+    mkdirp ">=0.5 0"
+    rimraf "2"
+
+function-bind@^1.1.1:
+  version "1.1.1"
+  resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d"
+
+gauge@~2.7.3:
+  version "2.7.4"
+  resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7"
+  dependencies:
+    aproba "^1.0.3"
+    console-control-strings "^1.0.0"
+    has-unicode "^2.0.0"
+    object-assign "^4.1.0"
+    signal-exit "^3.0.0"
+    string-width "^1.0.1"
+    strip-ansi "^3.0.1"
+    wide-align "^1.1.0"
+
+gaze@^1.0.0:
+  version "1.1.3"
+  resolved "https://registry.yarnpkg.com/gaze/-/gaze-1.1.3.tgz#c441733e13b927ac8c0ff0b4c3b033f28812924a"
+  dependencies:
+    globule "^1.0.0"
+
+generate-function@^2.0.0:
+  version "2.2.0"
+  resolved "https://registry.yarnpkg.com/generate-function/-/generate-function-2.2.0.tgz#1aeac896147293d27bce65eb295ce5f3f094a292"
+
+generate-object-property@^1.1.0:
+  version "1.2.0"
+  resolved "https://registry.yarnpkg.com/generate-object-property/-/generate-object-property-1.2.0.tgz#9c0e1c40308ce804f4783618b937fa88f99d50d0"
+  dependencies:
+    is-property "^1.0.0"
+
+get-caller-file@^1.0.1:
+  version "1.0.3"
+  resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.3.tgz#f978fa4c90d1dfe7ff2d6beda2a515e713bdcf4a"
+
+get-stdin@^4.0.1:
+  version "4.0.1"
+  resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-4.0.1.tgz#b968c6b0a04384324902e8bf1a5df32579a450fe"
+
+getpass@^0.1.1:
+  version "0.1.7"
+  resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa"
+  dependencies:
+    assert-plus "^1.0.0"
+
+glob-base@^0.3.0:
+  version "0.3.0"
+  resolved "https://registry.yarnpkg.com/glob-base/-/glob-base-0.3.0.tgz#dbb164f6221b1c0b1ccf82aea328b497df0ea3c4"
+  dependencies:
+    glob-parent "^2.0.0"
+    is-glob "^2.0.0"
+
+glob-parent@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-2.0.0.tgz#81383d72db054fcccf5336daa902f182f6edbb28"
+  dependencies:
+    is-glob "^2.0.0"
+
+glob@^5.0.14, glob@^5.0.15:
+  version "5.0.15"
+  resolved "https://registry.yarnpkg.com/glob/-/glob-5.0.15.tgz#1bc936b9e02f4a603fcc222ecf7633d30b8b93b1"
+  dependencies:
+    inflight "^1.0.4"
+    inherits "2"
+    minimatch "2 || 3"
+    once "^1.3.0"
+    path-is-absolute "^1.0.0"
+
+glob@^7.0.0, glob@^7.0.3, glob@^7.0.5, glob@~7.1.1:
+  version "7.1.3"
+  resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.3.tgz#3960832d3f1574108342dafd3a67b332c0969df1"
+  dependencies:
+    fs.realpath "^1.0.0"
+    inflight "^1.0.4"
+    inherits "2"
+    minimatch "^3.0.4"
+    once "^1.3.0"
+    path-is-absolute "^1.0.0"
+
+globals@^6.4.0:
+  version "6.4.1"
+  resolved "https://registry.yarnpkg.com/globals/-/globals-6.4.1.tgz#8498032b3b6d1cc81eebc5f79690d8fe29fabf4f"
+
+globals@^8.11.0:
+  version "8.18.0"
+  resolved "https://registry.yarnpkg.com/globals/-/globals-8.18.0.tgz#93d4a62bdcac38cfafafc47d6b034768cb0ffcb4"
+
+globals@^9.18.0:
+  version "9.18.0"
+  resolved "https://registry.yarnpkg.com/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a"
+
+globby@^5.0.0:
+  version "5.0.0"
+  resolved "https://registry.yarnpkg.com/globby/-/globby-5.0.0.tgz#ebd84667ca0dbb330b99bcfc68eac2bc54370e0d"
+  dependencies:
+    array-union "^1.0.1"
+    arrify "^1.0.0"
+    glob "^7.0.3"
+    object-assign "^4.0.1"
+    pify "^2.0.0"
+    pinkie-promise "^2.0.0"
+
+globule@^1.0.0:
+  version "1.2.1"
+  resolved "https://registry.yarnpkg.com/globule/-/globule-1.2.1.tgz#5dffb1b191f22d20797a9369b49eab4e9839696d"
+  dependencies:
+    glob "~7.1.1"
+    lodash "~4.17.10"
+    minimatch "~3.0.2"
+
+graceful-fs@^4.1.2, graceful-fs@^4.1.4:
+  version "4.1.11"
+  resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658"
+
+handlebars@^4.0.0:
+  version "4.0.11"
+  resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.0.11.tgz#630a35dfe0294bc281edae6ffc5d329fc7982dcc"
+  dependencies:
+    async "^1.4.0"
+    optimist "^0.6.1"
+    source-map "^0.4.4"
+  optionalDependencies:
+    uglify-js "^2.6"
+
+har-schema@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92"
+
+har-validator@~5.1.0:
+  version "5.1.0"
+  resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.0.tgz#44657f5688a22cfd4b72486e81b3a3fb11742c29"
+  dependencies:
+    ajv "^5.3.0"
+    har-schema "^2.0.0"
+
+has-ansi@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91"
+  dependencies:
+    ansi-regex "^2.0.0"
+
+has-binary@0.1.7:
+  version "0.1.7"
+  resolved "https://registry.yarnpkg.com/has-binary/-/has-binary-0.1.7.tgz#68e61eb16210c9545a0a5cce06a873912fe1e68c"
+  dependencies:
+    isarray "0.0.1"
+
+has-cors@1.1.0:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/has-cors/-/has-cors-1.1.0.tgz#5e474793f7ea9843d1bb99c23eef49ff126fff39"
+
+has-flag@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa"
+
+has-unicode@^2.0.0:
+  version "2.0.1"
+  resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9"
+
+has@^1.0.1:
+  version "1.0.3"
+  resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796"
+  dependencies:
+    function-bind "^1.1.1"
+
+history@^3.0.0:
+  version "3.3.0"
+  resolved "https://registry.yarnpkg.com/history/-/history-3.3.0.tgz#fcedcce8f12975371545d735461033579a6dae9c"
+  dependencies:
+    invariant "^2.2.1"
+    loose-envify "^1.2.0"
+    query-string "^4.2.2"
+    warning "^3.0.0"
+
+hoist-non-react-statics@^1.0.5:
+  version "1.2.0"
+  resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-1.2.0.tgz#aa448cf0986d55cc40773b17174b7dd066cb7cfb"
+
+hoist-non-react-statics@^2.3.1:
+  version "2.5.5"
+  resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-2.5.5.tgz#c5903cf409c0dfd908f388e619d86b9c1174cb47"
+
+home-or-tmp@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/home-or-tmp/-/home-or-tmp-1.0.0.tgz#4b9f1e40800c3e50c6c27f781676afcce71f3985"
+  dependencies:
+    os-tmpdir "^1.0.1"
+    user-home "^1.1.1"
+
+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"
+  dependencies:
+    os-homedir "^1.0.0"
+    os-tmpdir "^1.0.1"
+
+hosted-git-info@^2.1.4:
+  version "2.7.1"
+  resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.7.1.tgz#97f236977bd6e125408930ff6de3eec6281ec047"
+
+html-comment-regex@^1.1.0:
+  version "1.1.1"
+  resolved "https://registry.yarnpkg.com/html-comment-regex/-/html-comment-regex-1.1.1.tgz#668b93776eaae55ebde8f3ad464b307a4963625e"
+
+http-browserify@^1.3.2:
+  version "1.7.0"
+  resolved "https://registry.yarnpkg.com/http-browserify/-/http-browserify-1.7.0.tgz#33795ade72df88acfbfd36773cefeda764735b20"
+  dependencies:
+    Base64 "~0.2.0"
+    inherits "~2.0.1"
+
+http-errors@1.6.2:
+  version "1.6.2"
+  resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.2.tgz#0a002cc85707192a7e7946ceedc11155f60ec736"
+  dependencies:
+    depd "1.1.1"
+    inherits "2.0.3"
+    setprototypeof "1.0.3"
+    statuses ">= 1.3.1 < 2"
+
+http-errors@~1.6.2:
+  version "1.6.3"
+  resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.3.tgz#8b55680bb4be283a0b5bf4ea2e38580be1d9320d"
+  dependencies:
+    depd "~1.1.2"
+    inherits "2.0.3"
+    setprototypeof "1.1.0"
+    statuses ">= 1.4.0 < 2"
+
+http-proxy@^1.11.2:
+  version "1.17.0"
+  resolved "https://registry.yarnpkg.com/http-proxy/-/http-proxy-1.17.0.tgz#7ad38494658f84605e2f6db4436df410f4e5be9a"
+  dependencies:
+    eventemitter3 "^3.0.0"
+    follow-redirects "^1.0.0"
+    requires-port "^1.0.0"
+
+http-signature@~1.2.0:
+  version "1.2.0"
+  resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1"
+  dependencies:
+    assert-plus "^1.0.0"
+    jsprim "^1.2.2"
+    sshpk "^1.7.0"
+
+https-browserify@0.0.0:
+  version "0.0.0"
+  resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-0.0.0.tgz#b3ffdfe734b2a3d4a9efd58e8654c91fce86eafd"
+
+iconv-lite@0.4.19:
+  version "0.4.19"
+  resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.19.tgz#f7468f60135f5e5dad3399c0a81be9a1603a082b"
+
+iconv-lite@^0.4.4, iconv-lite@^0.4.5, iconv-lite@~0.4.13:
+  version "0.4.24"
+  resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b"
+  dependencies:
+    safer-buffer ">= 2.1.2 < 3"
+
+ieee754@^1.1.4:
+  version "1.1.12"
+  resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.12.tgz#50bf24e5b9c8bb98af4964c941cdb0918da7b60b"
+
+ignore-walk@^3.0.1:
+  version "3.0.1"
+  resolved "https://registry.yarnpkg.com/ignore-walk/-/ignore-walk-3.0.1.tgz#a83e62e7d272ac0e3b551aaa82831a19b69f82f8"
+  dependencies:
+    minimatch "^3.0.4"
+
+in-publish@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/in-publish/-/in-publish-2.0.0.tgz#e20ff5e3a2afc2690320b6dc552682a9c7fadf51"
+
+indent-string@^2.1.0:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-2.1.0.tgz#8e2d48348742121b4a8218b7a137e9a52049dc80"
+  dependencies:
+    repeating "^2.0.0"
+
+indexes-of@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/indexes-of/-/indexes-of-1.0.1.tgz#f30f716c8e2bd346c7b67d3df3915566a7c05607"
+
+indexof@0.0.1:
+  version "0.0.1"
+  resolved "https://registry.yarnpkg.com/indexof/-/indexof-0.0.1.tgz#82dc336d232b9062179d05ab3293a66059fd435d"
+
+inflight@^1.0.4:
+  version "1.0.6"
+  resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9"
+  dependencies:
+    once "^1.3.0"
+    wrappy "1"
+
+inherits@2, inherits@2.0.3, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.0, inherits@~2.0.1, inherits@~2.0.3:
+  version "2.0.3"
+  resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de"
+
+inherits@2.0.1:
+  version "2.0.1"
+  resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.1.tgz#b17d08d326b4423e568eff719f91b0b1cbdf69f1"
+
+ini@~1.3.0:
+  version "1.3.5"
+  resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927"
+
+inquirer@^0.11.0:
+  version "0.11.4"
+  resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-0.11.4.tgz#81e3374e8361beaff2d97016206d359d0b32fa4d"
+  dependencies:
+    ansi-escapes "^1.1.0"
+    ansi-regex "^2.0.0"
+    chalk "^1.0.0"
+    cli-cursor "^1.0.1"
+    cli-width "^1.0.1"
+    figures "^1.3.5"
+    lodash "^3.3.1"
+    readline2 "^1.0.1"
+    run-async "^0.1.0"
+    rx-lite "^3.1.2"
+    string-width "^1.0.1"
+    strip-ansi "^3.0.0"
+    through "^2.3.6"
+
+interpret@^0.6.4:
+  version "0.6.6"
+  resolved "https://registry.yarnpkg.com/interpret/-/interpret-0.6.6.tgz#fecd7a18e7ce5ca6abfb953e1f86213a49f1625b"
+
+invariant@^2.2.1, invariant@^2.2.2:
+  version "2.2.4"
+  resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6"
+  dependencies:
+    loose-envify "^1.0.0"
+
+invert-kv@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-1.0.0.tgz#104a8e4aaca6d3d8cd157a8ef8bfab2d7a3ffdb6"
+
+ipaddr.js@1.8.0:
+  version "1.8.0"
+  resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.8.0.tgz#eaa33d6ddd7ace8f7f6fe0c9ca0440e706738b1e"
+
+is-absolute-url@^2.0.0:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/is-absolute-url/-/is-absolute-url-2.1.0.tgz#50530dfb84fcc9aa7dbe7852e83a37b93b9f2aa6"
+
+is-arrayish@^0.2.1:
+  version "0.2.1"
+  resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d"
+
+is-binary-path@^1.0.0:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-1.0.1.tgz#75f16642b480f187a711c814161fd3a4a7655898"
+  dependencies:
+    binary-extensions "^1.0.0"
+
+is-buffer@^1.1.5:
+  version "1.1.6"
+  resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be"
+
+is-builtin-module@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/is-builtin-module/-/is-builtin-module-1.0.0.tgz#540572d34f7ac3119f8f76c30cbc1b1e037affbe"
+  dependencies:
+    builtin-modules "^1.0.0"
+
+is-dotfile@^1.0.0:
+  version "1.0.3"
+  resolved "https://registry.yarnpkg.com/is-dotfile/-/is-dotfile-1.0.3.tgz#a6a2f32ffd2dfb04f5ca25ecd0f6b83cf798a1e1"
+
+is-equal-shallow@^0.1.3:
+  version "0.1.3"
+  resolved "https://registry.yarnpkg.com/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz#2238098fc221de0bcfa5d9eac4c45d638aa1c534"
+  dependencies:
+    is-primitive "^2.0.0"
+
+is-extendable@^0.1.1:
+  version "0.1.1"
+  resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89"
+
+is-extglob@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-1.0.0.tgz#ac468177c4943405a092fc8f29760c6ffc6206c0"
+
+is-finite@^1.0.0:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/is-finite/-/is-finite-1.0.2.tgz#cc6677695602be550ef11e8b4aa6305342b6d0aa"
+  dependencies:
+    number-is-nan "^1.0.0"
+
+is-fullwidth-code-point@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb"
+  dependencies:
+    number-is-nan "^1.0.0"
+
+is-fullwidth-code-point@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f"
+
+is-glob@^2.0.0, is-glob@^2.0.1:
+  version "2.0.1"
+  resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-2.0.1.tgz#d096f926a3ded5600f3fdfd91198cb0888c2d863"
+  dependencies:
+    is-extglob "^1.0.0"
+
+is-integer@^1.0.4:
+  version "1.0.7"
+  resolved "https://registry.yarnpkg.com/is-integer/-/is-integer-1.0.7.tgz#6bde81aacddf78b659b6629d629cadc51a886d5c"
+  dependencies:
+    is-finite "^1.0.0"
+
+is-my-ip-valid@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/is-my-ip-valid/-/is-my-ip-valid-1.0.0.tgz#7b351b8e8edd4d3995d4d066680e664d94696824"
+
+is-my-json-valid@^2.10.0:
+  version "2.19.0"
+  resolved "https://registry.yarnpkg.com/is-my-json-valid/-/is-my-json-valid-2.19.0.tgz#8fd6e40363cd06b963fa877d444bfb5eddc62175"
+  dependencies:
+    generate-function "^2.0.0"
+    generate-object-property "^1.1.0"
+    is-my-ip-valid "^1.0.0"
+    jsonpointer "^4.0.0"
+    xtend "^4.0.0"
+
+is-number@^2.1.0:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/is-number/-/is-number-2.1.0.tgz#01fcbbb393463a548f2f466cce16dece49db908f"
+  dependencies:
+    kind-of "^3.0.2"
+
+is-number@^4.0.0:
+  version "4.0.0"
+  resolved "https://registry.yarnpkg.com/is-number/-/is-number-4.0.0.tgz#0026e37f5454d73e356dfe6564699867c6a7f0ff"
+
+is-path-cwd@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/is-path-cwd/-/is-path-cwd-1.0.0.tgz#d225ec23132e89edd38fda767472e62e65f1106d"
+
+is-path-in-cwd@^1.0.0:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/is-path-in-cwd/-/is-path-in-cwd-1.0.1.tgz#5ac48b345ef675339bd6c7a48a912110b241cf52"
+  dependencies:
+    is-path-inside "^1.0.0"
+
+is-path-inside@^1.0.0:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-1.0.1.tgz#8ef5b7de50437a3fdca6b4e865ef7aa55cb48036"
+  dependencies:
+    path-is-inside "^1.0.1"
+
+is-plain-obj@^1.0.0:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e"
+
+is-posix-bracket@^0.1.0:
+  version "0.1.1"
+  resolved "https://registry.yarnpkg.com/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz#3334dc79774368e92f016e6fbc0a88f5cd6e6bc4"
+
+is-primitive@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/is-primitive/-/is-primitive-2.0.0.tgz#207bab91638499c07b2adf240a41a87210034575"
+
+is-property@^1.0.0:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/is-property/-/is-property-1.0.2.tgz#57fe1c4e48474edd65b09911f26b1cd4095dda84"
+
+is-resolvable@^1.0.0:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/is-resolvable/-/is-resolvable-1.1.0.tgz#fb18f87ce1feb925169c9a407c19318a3206ed88"
+
+is-stream@^1.0.1:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44"
+
+is-svg@^2.0.0:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/is-svg/-/is-svg-2.1.0.tgz#cf61090da0d9efbcab8722deba6f032208dbb0e9"
+  dependencies:
+    html-comment-regex "^1.1.0"
+
+is-typedarray@~1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a"
+
+is-utf8@^0.2.0:
+  version "0.2.1"
+  resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72"
+
+is-windows@^1.0.0:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d"
+
+isarray@0.0.1:
+  version "0.0.1"
+  resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf"
+
+isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11"
+
+isexe@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10"
+
+isobject@^2.0.0:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89"
+  dependencies:
+    isarray "1.0.0"
+
+isomorphic-fetch@^2.1.1:
+  version "2.2.1"
+  resolved "https://registry.yarnpkg.com/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz#611ae1acf14f5e81f729507472819fe9733558a9"
+  dependencies:
+    node-fetch "^1.0.1"
+    whatwg-fetch ">=0.10.0"
+
+isstream@~0.1.2:
+  version "0.1.2"
+  resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a"
+
+js-base64@^2.1.8, js-base64@^2.1.9:
+  version "2.4.9"
+  resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-2.4.9.tgz#748911fb04f48a60c4771b375cac45a80df11c03"
+
+js-tokens@1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-1.0.1.tgz#cc435a5c8b94ad15acb7983140fc80182c89aeae"
+
+"js-tokens@^3.0.0 || ^4.0.0":
+  version "4.0.0"
+  resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
+
+js-tokens@^3.0.2:
+  version "3.0.2"
+  resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b"
+
+js-yaml@3.4.5:
+  version "3.4.5"
+  resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.4.5.tgz#c3403797df12b91866574f2de23646fe8cafb44d"
+  dependencies:
+    argparse "^1.0.2"
+    esprima "^2.6.0"
+
+js-yaml@~3.7.0:
+  version "3.7.0"
+  resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.7.0.tgz#5c967ddd837a9bfdca5f2de84253abe8a1c03b80"
+  dependencies:
+    argparse "^1.0.7"
+    esprima "^2.6.0"
+
+jsbn@~0.1.0:
+  version "0.1.1"
+  resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513"
+
+jsesc@^1.3.0:
+  version "1.3.0"
+  resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-1.3.0.tgz#46c3fec8c1892b12b0833db9bc7622176dbab34b"
+
+jsesc@~0.5.0:
+  version "0.5.0"
+  resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d"
+
+json-schema-traverse@^0.3.0:
+  version "0.3.1"
+  resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz#349a6d44c53a51de89b40805c5d5e59b417d3340"
+
+json-schema@0.2.3:
+  version "0.2.3"
+  resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13"
+
+json-stable-stringify@^1.0.0:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz#9a759d39c5f2ff503fd5300646ed445f88c4f9af"
+  dependencies:
+    jsonify "~0.0.0"
+
+json-stringify-safe@~5.0.1:
+  version "5.0.1"
+  resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb"
+
+json3@3.3.2:
+  version "3.3.2"
+  resolved "https://registry.yarnpkg.com/json3/-/json3-3.3.2.tgz#3c0434743df93e2f5c42aee7b19bcb483575f4e1"
+
+json5@^0.4.0:
+  version "0.4.0"
+  resolved "https://registry.yarnpkg.com/json5/-/json5-0.4.0.tgz#054352e4c4c80c86c0923877d449de176a732c8d"
+
+json5@^0.5.0, json5@^0.5.1:
+  version "0.5.1"
+  resolved "https://registry.yarnpkg.com/json5/-/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821"
+
+jsonify@~0.0.0:
+  version "0.0.0"
+  resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73"
+
+jsonpointer@^4.0.0:
+  version "4.0.1"
+  resolved "https://registry.yarnpkg.com/jsonpointer/-/jsonpointer-4.0.1.tgz#4fd92cb34e0e9db3c89c8622ecf51f9b978c6cb9"
+
+jsprim@^1.2.2:
+  version "1.4.1"
+  resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2"
+  dependencies:
+    assert-plus "1.0.0"
+    extsprintf "1.3.0"
+    json-schema "0.2.3"
+    verror "1.10.0"
+
+kind-of@^3.0.2:
+  version "3.2.2"
+  resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64"
+  dependencies:
+    is-buffer "^1.1.5"
+
+kind-of@^6.0.0:
+  version "6.0.2"
+  resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.2.tgz#01146b36a6218e64e58f3a8d66de5d7fc6f6d051"
+
+lazy-cache@^1.0.3:
+  version "1.0.4"
+  resolved "https://registry.yarnpkg.com/lazy-cache/-/lazy-cache-1.0.4.tgz#a1d78fc3a50474cb80845d3b3b6e1da49a446e8e"
+
+lcid@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/lcid/-/lcid-1.0.0.tgz#308accafa0bc483a3867b4b6f2b9506251d1b835"
+  dependencies:
+    invert-kv "^1.0.0"
+
+leven@^1.0.2:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/leven/-/leven-1.0.2.tgz#9144b6eebca5f1d0680169f1a6770dcea60b75c3"
+
+levn@~0.2.5:
+  version "0.2.5"
+  resolved "https://registry.yarnpkg.com/levn/-/levn-0.2.5.tgz#ba8d339d0ca4a610e3a3f145b9caf48807155054"
+  dependencies:
+    prelude-ls "~1.1.0"
+    type-check "~0.3.1"
+
+load-json-file@^1.0.0:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0"
+  dependencies:
+    graceful-fs "^4.1.2"
+    parse-json "^2.2.0"
+    pify "^2.0.0"
+    pinkie-promise "^2.0.0"
+    strip-bom "^2.0.0"
+
+loader-utils@^0.2.11, loader-utils@^0.2.16, loader-utils@^0.2.5, loader-utils@^0.2.7, loader-utils@~0.2.2:
+  version "0.2.17"
+  resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-0.2.17.tgz#f86e6374d43205a6e6c60e9196f17c0299bfb348"
+  dependencies:
+    big.js "^3.1.3"
+    emojis-list "^2.0.0"
+    json5 "^0.5.0"
+    object-assign "^4.0.1"
+
+lodash._arraycopy@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/lodash._arraycopy/-/lodash._arraycopy-3.0.0.tgz#76e7b7c1f1fb92547374878a562ed06a3e50f6e1"
+
+lodash._arrayeach@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/lodash._arrayeach/-/lodash._arrayeach-3.0.0.tgz#bab156b2a90d3f1bbd5c653403349e5e5933ef9e"
+
+lodash._arraymap@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/lodash._arraymap/-/lodash._arraymap-3.0.0.tgz#1a8fd0f4c0df4b61dea076d717cdc97f0a3c3e66"
+
+lodash._baseassign@^3.0.0:
+  version "3.2.0"
+  resolved "https://registry.yarnpkg.com/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz#8c38a099500f215ad09e59f1722fd0c52bfe0a4e"
+  dependencies:
+    lodash._basecopy "^3.0.0"
+    lodash.keys "^3.0.0"
+
+lodash._baseclone@^3.0.0:
+  version "3.3.0"
+  resolved "https://registry.yarnpkg.com/lodash._baseclone/-/lodash._baseclone-3.3.0.tgz#303519bf6393fe7e42f34d8b630ef7794e3542b7"
+  dependencies:
+    lodash._arraycopy "^3.0.0"
+    lodash._arrayeach "^3.0.0"
+    lodash._baseassign "^3.0.0"
+    lodash._basefor "^3.0.0"
+    lodash.isarray "^3.0.0"
+    lodash.keys "^3.0.0"
+
+lodash._basecopy@^3.0.0:
+  version "3.0.1"
+  resolved "https://registry.yarnpkg.com/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz#8da0e6a876cf344c0ad8a54882111dd3c5c7ca36"
+
+lodash._basedifference@^3.0.0:
+  version "3.0.3"
+  resolved "https://registry.yarnpkg.com/lodash._basedifference/-/lodash._basedifference-3.0.3.tgz#f2c204296c2a78e02b389081b6edcac933cf629c"
+  dependencies:
+    lodash._baseindexof "^3.0.0"
+    lodash._cacheindexof "^3.0.0"
+    lodash._createcache "^3.0.0"
+
+lodash._baseflatten@^3.0.0:
+  version "3.1.4"
+  resolved "https://registry.yarnpkg.com/lodash._baseflatten/-/lodash._baseflatten-3.1.4.tgz#0770ff80131af6e34f3b511796a7ba5214e65ff7"
+  dependencies:
+    lodash.isarguments "^3.0.0"
+    lodash.isarray "^3.0.0"
+
+lodash._basefor@^3.0.0:
+  version "3.0.3"
+  resolved "https://registry.yarnpkg.com/lodash._basefor/-/lodash._basefor-3.0.3.tgz#7550b4e9218ef09fad24343b612021c79b4c20c2"
+
+lodash._baseindexof@^3.0.0:
+  version "3.1.0"
+  resolved "https://registry.yarnpkg.com/lodash._baseindexof/-/lodash._baseindexof-3.1.0.tgz#fe52b53a1c6761e42618d654e4a25789ed61822c"
+
+lodash._bindcallback@^3.0.0:
+  version "3.0.1"
+  resolved "https://registry.yarnpkg.com/lodash._bindcallback/-/lodash._bindcallback-3.0.1.tgz#e531c27644cf8b57a99e17ed95b35c748789392e"
+
+lodash._cacheindexof@^3.0.0:
+  version "3.0.2"
+  resolved "https://registry.yarnpkg.com/lodash._cacheindexof/-/lodash._cacheindexof-3.0.2.tgz#3dc69ac82498d2ee5e3ce56091bafd2adc7bde92"
+
+lodash._createassigner@^3.0.0:
+  version "3.1.1"
+  resolved "https://registry.yarnpkg.com/lodash._createassigner/-/lodash._createassigner-3.1.1.tgz#838a5bae2fdaca63ac22dee8e19fa4e6d6970b11"
+  dependencies:
+    lodash._bindcallback "^3.0.0"
+    lodash._isiterateecall "^3.0.0"
+    lodash.restparam "^3.0.0"
+
+lodash._createcache@^3.0.0:
+  version "3.1.2"
+  resolved "https://registry.yarnpkg.com/lodash._createcache/-/lodash._createcache-3.1.2.tgz#56d6a064017625e79ebca6b8018e17440bdcf093"
+  dependencies:
+    lodash._getnative "^3.0.0"
+
+lodash._getnative@^3.0.0:
+  version "3.9.1"
+  resolved "https://registry.yarnpkg.com/lodash._getnative/-/lodash._getnative-3.9.1.tgz#570bc7dede46d61cdcde687d65d3eecbaa3aaff5"
+
+lodash._isiterateecall@^3.0.0:
+  version "3.0.9"
+  resolved "https://registry.yarnpkg.com/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz#5203ad7ba425fae842460e696db9cf3e6aac057c"
+
+lodash._pickbyarray@^3.0.0:
+  version "3.0.2"
+  resolved "https://registry.yarnpkg.com/lodash._pickbyarray/-/lodash._pickbyarray-3.0.2.tgz#1f898d9607eb560b0e167384b77c7c6d108aa4c5"
+
+lodash._pickbycallback@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/lodash._pickbycallback/-/lodash._pickbycallback-3.0.0.tgz#ff61b9a017a7b3af7d30e6c53de28afa19b8750a"
+  dependencies:
+    lodash._basefor "^3.0.0"
+    lodash.keysin "^3.0.0"
+
+lodash.assign@^3.2.0:
+  version "3.2.0"
+  resolved "https://registry.yarnpkg.com/lodash.assign/-/lodash.assign-3.2.0.tgz#3ce9f0234b4b2223e296b8fa0ac1fee8ebca64fa"
+  dependencies:
+    lodash._baseassign "^3.0.0"
+    lodash._createassigner "^3.0.0"
+    lodash.keys "^3.0.0"
+
+lodash.assign@^4.2.0:
+  version "4.2.0"
+  resolved "https://registry.yarnpkg.com/lodash.assign/-/lodash.assign-4.2.0.tgz#0d99f3ccd7a6d261d19bdaeb9245005d285808e7"
+
+lodash.clonedeep@^3.0.1:
+  version "3.0.2"
+  resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-3.0.2.tgz#a0a1e40d82a5ea89ff5b147b8444ed63d92827db"
+  dependencies:
+    lodash._baseclone "^3.0.0"
+    lodash._bindcallback "^3.0.0"
+
+lodash.clonedeep@^4.3.2:
+  version "4.5.0"
+  resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef"
+
+lodash.isarguments@^3.0.0:
+  version "3.1.0"
+  resolved "https://registry.yarnpkg.com/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz#2f573d85c6a24289ff00663b491c1d338ff3458a"
+
+lodash.isarray@^3.0.0:
+  version "3.0.4"
+  resolved "https://registry.yarnpkg.com/lodash.isarray/-/lodash.isarray-3.0.4.tgz#79e4eb88c36a8122af86f844aa9bcd851b5fbb55"
+
+lodash.isplainobject@^3.0.0:
+  version "3.2.0"
+  resolved "https://registry.yarnpkg.com/lodash.isplainobject/-/lodash.isplainobject-3.2.0.tgz#9a8238ae16b200432960cd7346512d0123fbf4c5"
+  dependencies:
+    lodash._basefor "^3.0.0"
+    lodash.isarguments "^3.0.0"
+    lodash.keysin "^3.0.0"
+
+lodash.istypedarray@^3.0.0:
+  version "3.0.6"
+  resolved "https://registry.yarnpkg.com/lodash.istypedarray/-/lodash.istypedarray-3.0.6.tgz#c9a477498607501d8e8494d283b87c39281cef62"
+
+lodash.keys@^3.0.0:
+  version "3.1.2"
+  resolved "https://registry.yarnpkg.com/lodash.keys/-/lodash.keys-3.1.2.tgz#4dbc0472b156be50a0b286855d1bd0b0c656098a"
+  dependencies:
+    lodash._getnative "^3.0.0"
+    lodash.isarguments "^3.0.0"
+    lodash.isarray "^3.0.0"
+
+lodash.keysin@^3.0.0:
+  version "3.0.8"
+  resolved "https://registry.yarnpkg.com/lodash.keysin/-/lodash.keysin-3.0.8.tgz#22c4493ebbedb1427962a54b445b2c8a767fb47f"
+  dependencies:
+    lodash.isarguments "^3.0.0"
+    lodash.isarray "^3.0.0"
+
+lodash.memoize@^4.1.2:
+  version "4.1.2"
+  resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe"
+
+lodash.merge@^3.3.2:
+  version "3.3.2"
+  resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-3.3.2.tgz#0d90d93ed637b1878437bb3e21601260d7afe994"
+  dependencies:
+    lodash._arraycopy "^3.0.0"
+    lodash._arrayeach "^3.0.0"
+    lodash._createassigner "^3.0.0"
+    lodash._getnative "^3.0.0"
+    lodash.isarguments "^3.0.0"
+    lodash.isarray "^3.0.0"
+    lodash.isplainobject "^3.0.0"
+    lodash.istypedarray "^3.0.0"
+    lodash.keys "^3.0.0"
+    lodash.keysin "^3.0.0"
+    lodash.toplainobject "^3.0.0"
+
+lodash.omit@^3.1.0:
+  version "3.1.0"
+  resolved "https://registry.yarnpkg.com/lodash.omit/-/lodash.omit-3.1.0.tgz#897fe382e6413d9ac97c61f78ed1e057a00af9f3"
+  dependencies:
+    lodash._arraymap "^3.0.0"
+    lodash._basedifference "^3.0.0"
+    lodash._baseflatten "^3.0.0"
+    lodash._bindcallback "^3.0.0"
+    lodash._pickbyarray "^3.0.0"
+    lodash._pickbycallback "^3.0.0"
+    lodash.keysin "^3.0.0"
+    lodash.restparam "^3.0.0"
+
+lodash.pick@^3.1.0:
+  version "3.1.0"
+  resolved "https://registry.yarnpkg.com/lodash.pick/-/lodash.pick-3.1.0.tgz#f252a855b2046b61bcd3904b26f76bd2efc65550"
+  dependencies:
+    lodash._baseflatten "^3.0.0"
+    lodash._bindcallback "^3.0.0"
+    lodash._pickbyarray "^3.0.0"
+    lodash._pickbycallback "^3.0.0"
+    lodash.restparam "^3.0.0"
+
+lodash.restparam@^3.0.0:
+  version "3.6.1"
+  resolved "https://registry.yarnpkg.com/lodash.restparam/-/lodash.restparam-3.6.1.tgz#936a4e309ef330a7645ed4145986c85ae5b20805"
+
+lodash.toplainobject@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/lodash.toplainobject/-/lodash.toplainobject-3.0.0.tgz#28790ad942d293d78aa663a07ecf7f52ca04198d"
+  dependencies:
+    lodash._basecopy "^3.0.0"
+    lodash.keysin "^3.0.0"
+
+lodash.uniq@^4.5.0:
+  version "4.5.0"
+  resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773"
+
+lodash@^3.10.0, lodash@^3.3.1, lodash@^3.9.3:
+  version "3.10.1"
+  resolved "http://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz#5bf45e8e49ba4189e17d482789dfd15bd140b7b6"
+
+lodash@^4.0.0, lodash@^4.17.4, lodash@^4.6.1, lodash@~4.17.10:
+  version "4.17.10"
+  resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.10.tgz#1b7793cf7259ea38fb3661d4d38b3260af8ae4e7"
+
+longest@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/longest/-/longest-1.0.1.tgz#30a0b2da38f73770e8294a0d22e6625ed77d0097"
+
+loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.2.0, loose-envify@^1.3.1:
+  version "1.4.0"
+  resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf"
+  dependencies:
+    js-tokens "^3.0.0 || ^4.0.0"
+
+loud-rejection@^1.0.0:
+  version "1.6.0"
+  resolved "https://registry.yarnpkg.com/loud-rejection/-/loud-rejection-1.6.0.tgz#5b46f80147edee578870f086d04821cf998e551f"
+  dependencies:
+    currently-unhandled "^0.4.1"
+    signal-exit "^3.0.0"
+
+lru-cache@^4.0.1:
+  version "4.1.3"
+  resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.3.tgz#a1175cf3496dfc8436c156c334b4955992bce69c"
+  dependencies:
+    pseudomap "^1.0.2"
+    yallist "^2.1.2"
+
+map-obj@^1.0.0, map-obj@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-1.0.1.tgz#d933ceb9205d82bdcf4886f6742bdc2b4dea146d"
+
+math-expression-evaluator@^1.2.14:
+  version "1.2.17"
+  resolved "https://registry.yarnpkg.com/math-expression-evaluator/-/math-expression-evaluator-1.2.17.tgz#de819fdbcd84dccd8fae59c6aeb79615b9d266ac"
+
+math-random@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/math-random/-/math-random-1.0.1.tgz#8b3aac588b8a66e4975e3cdea67f7bb329601fac"
+
+media-typer@0.3.0:
+  version "0.3.0"
+  resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748"
+
+memory-fs@^0.2.0:
+  version "0.2.0"
+  resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.2.0.tgz#f2bb25368bc121e391c2520de92969caee0a0290"
+
+memory-fs@~0.3.0:
+  version "0.3.0"
+  resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.3.0.tgz#7bcc6b629e3a43e871d7e29aca6ae8a7f15cbb20"
+  dependencies:
+    errno "^0.1.3"
+    readable-stream "^2.0.1"
+
+memory-fs@~0.4.1:
+  version "0.4.1"
+  resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.4.1.tgz#3a9a20b8462523e447cfbc7e8bb80ed667bfc552"
+  dependencies:
+    errno "^0.1.3"
+    readable-stream "^2.0.1"
+
+meow@^3.7.0:
+  version "3.7.0"
+  resolved "https://registry.yarnpkg.com/meow/-/meow-3.7.0.tgz#72cb668b425228290abbfa856892587308a801fb"
+  dependencies:
+    camelcase-keys "^2.0.0"
+    decamelize "^1.1.2"
+    loud-rejection "^1.0.0"
+    map-obj "^1.0.1"
+    minimist "^1.1.3"
+    normalize-package-data "^2.3.4"
+    object-assign "^4.0.1"
+    read-pkg-up "^1.0.1"
+    redent "^1.0.0"
+    trim-newlines "^1.0.0"
+
+merge-descriptors@1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61"
+
+methods@~1.1.2:
+  version "1.1.2"
+  resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee"
+
+micromatch@^2.1.5:
+  version "2.3.11"
+  resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-2.3.11.tgz#86677c97d1720b363431d04d0d15293bd38c1565"
+  dependencies:
+    arr-diff "^2.0.0"
+    array-unique "^0.2.1"
+    braces "^1.8.2"
+    expand-brackets "^0.1.4"
+    extglob "^0.3.1"
+    filename-regex "^2.0.0"
+    is-extglob "^1.0.0"
+    is-glob "^2.0.1"
+    kind-of "^3.0.2"
+    normalize-path "^2.0.1"
+    object.omit "^2.0.0"
+    parse-glob "^3.0.4"
+    regex-cache "^0.4.2"
+
+"mime-db@>= 1.34.0 < 2", mime-db@~1.36.0:
+  version "1.36.0"
+  resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.36.0.tgz#5020478db3c7fe93aad7bbcc4dcf869c43363397"
+
+mime-types@^2.1.12, mime-types@~2.1.11, mime-types@~2.1.17, mime-types@~2.1.18, mime-types@~2.1.19:
+  version "2.1.20"
+  resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.20.tgz#930cb719d571e903738520f8470911548ca2cc19"
+  dependencies:
+    mime-db "~1.36.0"
+
+mime@1.4.1:
+  version "1.4.1"
+  resolved "https://registry.yarnpkg.com/mime/-/mime-1.4.1.tgz#121f9ebc49e3766f311a76e1fa1c8003c4b03aa6"
+
+mime@^1.5.0:
+  version "1.6.0"
+  resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1"
+
+"minimatch@2 || 3", minimatch@^3.0.0, minimatch@^3.0.2, minimatch@^3.0.4, minimatch@~3.0.2:
+  version "3.0.4"
+  resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083"
+  dependencies:
+    brace-expansion "^1.1.7"
+
+minimatch@^2.0.3:
+  version "2.0.10"
+  resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-2.0.10.tgz#8d087c39c6b38c001b97fca7ce6d0e1e80afbac7"
+  dependencies:
+    brace-expansion "^1.0.0"
+
+minimist@0.0.8:
+  version "0.0.8"
+  resolved "http://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d"
+
+minimist@^1.1.0, minimist@^1.1.3, minimist@^1.2.0:
+  version "1.2.0"
+  resolved "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284"
+
+minimist@~0.0.1:
+  version "0.0.10"
+  resolved "http://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz#de3f98543dbf96082be48ad1a0c7cda836301dcf"
+
+minipass@^2.2.1, minipass@^2.3.3:
+  version "2.3.4"
+  resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.3.4.tgz#4768d7605ed6194d6d576169b9e12ef71e9d9957"
+  dependencies:
+    safe-buffer "^5.1.2"
+    yallist "^3.0.0"
+
+minizlib@^1.1.0:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-1.1.0.tgz#11e13658ce46bc3a70a267aac58359d1e0c29ceb"
+  dependencies:
+    minipass "^2.2.1"
+
+"mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.0, mkdirp@~0.5.1:
+  version "0.5.1"
+  resolved "http://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903"
+  dependencies:
+    minimist "0.0.8"
+
+ms@0.7.1:
+  version "0.7.1"
+  resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.1.tgz#9cd13c03adbff25b65effde7ce864ee952017098"
+
+ms@0.7.2:
+  version "0.7.2"
+  resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.2.tgz#ae25cf2512b3885a1d95d7f037868d8431124765"
+
+ms@2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
+
+mute-stream@0.0.5:
+  version "0.0.5"
+  resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.5.tgz#8fbfabb0a98a253d3184331f9e8deb7372fac6c0"
+
+nan@^2.3.2, nan@^2.9.2:
+  version "2.11.0"
+  resolved "https://registry.yarnpkg.com/nan/-/nan-2.11.0.tgz#574e360e4d954ab16966ec102c0c049fd961a099"
+
+needle@^2.2.1:
+  version "2.2.2"
+  resolved "https://registry.yarnpkg.com/needle/-/needle-2.2.2.tgz#1120ca4c41f2fcc6976fd28a8968afe239929418"
+  dependencies:
+    debug "^2.1.2"
+    iconv-lite "^0.4.4"
+    sax "^1.2.4"
+
+negotiator@0.6.1:
+  version "0.6.1"
+  resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.1.tgz#2b327184e8992101177b28563fb5e7102acd0ca9"
+
+next-tick@1:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-1.0.0.tgz#ca86d1fe8828169b0120208e3dc8424b9db8342c"
+
+nice-try@^1.0.4:
+  version "1.0.5"
+  resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366"
+
+node-fetch@^1.0.1:
+  version "1.7.3"
+  resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-1.7.3.tgz#980f6f72d85211a5347c6b2bc18c5b84c3eb47ef"
+  dependencies:
+    encoding "^0.1.11"
+    is-stream "^1.0.1"
+
+node-gyp@^3.3.1:
+  version "3.8.0"
+  resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-3.8.0.tgz#540304261c330e80d0d5edce253a68cb3964218c"
+  dependencies:
+    fstream "^1.0.0"
+    glob "^7.0.3"
+    graceful-fs "^4.1.2"
+    mkdirp "^0.5.0"
+    nopt "2 || 3"
+    npmlog "0 || 1 || 2 || 3 || 4"
+    osenv "0"
+    request "^2.87.0"
+    rimraf "2"
+    semver "~5.3.0"
+    tar "^2.0.0"
+    which "1"
+
+"node-libs-browser@>= 0.4.0 <=0.6.0":
+  version "0.6.0"
+  resolved "https://registry.yarnpkg.com/node-libs-browser/-/node-libs-browser-0.6.0.tgz#244806d44d319e048bc8607b5cc4eaf9a29d2e3c"
+  dependencies:
+    assert "^1.1.1"
+    browserify-zlib "~0.1.4"
+    buffer "^4.9.0"
+    console-browserify "^1.1.0"
+    constants-browserify "0.0.1"
+    crypto-browserify "~3.2.6"
+    domain-browser "^1.1.1"
+    events "^1.0.0"
+    http-browserify "^1.3.2"
+    https-browserify "0.0.0"
+    os-browserify "~0.1.2"
+    path-browserify "0.0.0"
+    process "^0.11.0"
+    punycode "^1.2.4"
+    querystring-es3 "~0.2.0"
+    readable-stream "^1.1.13"
+    stream-browserify "^1.0.0"
+    string_decoder "~0.10.25"
+    timers-browserify "^1.0.1"
+    tty-browserify "0.0.0"
+    url "~0.10.1"
+    util "~0.10.3"
+    vm-browserify "0.0.4"
+
+node-pre-gyp@^0.10.0:
+  version "0.10.3"
+  resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.10.3.tgz#3070040716afdc778747b61b6887bf78880b80fc"
+  dependencies:
+    detect-libc "^1.0.2"
+    mkdirp "^0.5.1"
+    needle "^2.2.1"
+    nopt "^4.0.1"
+    npm-packlist "^1.1.6"
+    npmlog "^4.0.2"
+    rc "^1.2.7"
+    rimraf "^2.6.1"
+    semver "^5.3.0"
+    tar "^4"
+
+node-sass@^3.3.x:
+  version "3.13.1"
+  resolved "https://registry.yarnpkg.com/node-sass/-/node-sass-3.13.1.tgz#7240fbbff2396304b4223527ed3020589c004fc2"
+  dependencies:
+    async-foreach "^0.1.3"
+    chalk "^1.1.1"
+    cross-spawn "^3.0.0"
+    gaze "^1.0.0"
+    get-stdin "^4.0.1"
+    glob "^7.0.3"
+    in-publish "^2.0.0"
+    lodash.assign "^4.2.0"
+    lodash.clonedeep "^4.3.2"
+    meow "^3.7.0"
+    mkdirp "^0.5.1"
+    nan "^2.3.2"
+    node-gyp "^3.3.1"
+    npmlog "^4.0.0"
+    request "^2.61.0"
+    sass-graph "^2.1.1"
+
+"nopt@2 || 3":
+  version "3.0.6"
+  resolved "https://registry.yarnpkg.com/nopt/-/nopt-3.0.6.tgz#c6465dbf08abcd4db359317f79ac68a646b28ff9"
+  dependencies:
+    abbrev "1"
+
+nopt@^4.0.1:
+  version "4.0.1"
+  resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.1.tgz#d0d4685afd5415193c8c7505602d0d17cd64474d"
+  dependencies:
+    abbrev "1"
+    osenv "^0.1.4"
+
+normalize-package-data@^2.3.2, normalize-package-data@^2.3.4:
+  version "2.4.0"
+  resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.4.0.tgz#12f95a307d58352075a04907b84ac8be98ac012f"
+  dependencies:
+    hosted-git-info "^2.1.4"
+    is-builtin-module "^1.0.0"
+    semver "2 || 3 || 4 || 5"
+    validate-npm-package-license "^3.0.1"
+
+normalize-path@^2.0.0, normalize-path@^2.0.1:
+  version "2.1.1"
+  resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9"
+  dependencies:
+    remove-trailing-separator "^1.0.1"
+
+normalize-range@^0.1.2:
+  version "0.1.2"
+  resolved "https://registry.yarnpkg.com/normalize-range/-/normalize-range-0.1.2.tgz#2d10c06bdfd312ea9777695a4d28439456b75942"
+
+normalize-url@^1.4.0:
+  version "1.9.1"
+  resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-1.9.1.tgz#2cc0d66b31ea23036458436e3620d85954c66c3c"
+  dependencies:
+    object-assign "^4.0.1"
+    prepend-http "^1.0.0"
+    query-string "^4.1.0"
+    sort-keys "^1.0.0"
+
+npm-bundled@^1.0.1:
+  version "1.0.5"
+  resolved "https://registry.yarnpkg.com/npm-bundled/-/npm-bundled-1.0.5.tgz#3c1732b7ba936b3a10325aef616467c0ccbcc979"
+
+npm-packlist@^1.1.6:
+  version "1.1.11"
+  resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-1.1.11.tgz#84e8c683cbe7867d34b1d357d893ce29e28a02de"
+  dependencies:
+    ignore-walk "^3.0.1"
+    npm-bundled "^1.0.1"
+
+"npmlog@0 || 1 || 2 || 3 || 4", npmlog@^4.0.0, npmlog@^4.0.2:
+  version "4.1.2"
+  resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b"
+  dependencies:
+    are-we-there-yet "~1.1.2"
+    console-control-strings "~1.1.0"
+    gauge "~2.7.3"
+    set-blocking "~2.0.0"
+
+num2fraction@^1.2.2:
+  version "1.2.2"
+  resolved "https://registry.yarnpkg.com/num2fraction/-/num2fraction-1.2.2.tgz#6f682b6a027a4e9ddfa4564cd2589d1d4e669ede"
+
+number-is-nan@^1.0.0:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d"
+
+oauth-sign@~0.9.0:
+  version "0.9.0"
+  resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455"
+
+object-assign@4.1.0:
+  version "4.1.0"
+  resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.0.tgz#7a3b3d0e98063d43f4c03f2e8ae6cd51a86883a0"
+
+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"
+
+object-component@0.0.3:
+  version "0.0.3"
+  resolved "https://registry.yarnpkg.com/object-component/-/object-component-0.0.3.tgz#f0c69aa50efc95b866c186f400a33769cb2f1291"
+
+object-unfreeze@^1.0.2:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/object-unfreeze/-/object-unfreeze-1.1.0.tgz#69628bea1f3c9d29f4eb0ba63b38002d70ea3ce9"
+
+object.omit@^2.0.0:
+  version "2.0.1"
+  resolved "https://registry.yarnpkg.com/object.omit/-/object.omit-2.0.1.tgz#1a9c744829f39dbb858c76ca3579ae2a54ebd1fa"
+  dependencies:
+    for-own "^0.1.4"
+    is-extendable "^0.1.1"
+
+on-finished@~2.3.0:
+  version "2.3.0"
+  resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947"
+  dependencies:
+    ee-first "1.1.1"
+
+on-headers@~1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/on-headers/-/on-headers-1.0.1.tgz#928f5d0f470d49342651ea6794b0857c100693f7"
+
+once@^1.3.0:
+  version "1.4.0"
+  resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
+  dependencies:
+    wrappy "1"
+
+onetime@^1.0.0:
+  version "1.1.0"
+  resolved "http://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz#a1f7838f8314c516f05ecefcbc4ccfe04b4ed789"
+
+optimist@^0.6.1, optimist@~0.6.0:
+  version "0.6.1"
+  resolved "https://registry.yarnpkg.com/optimist/-/optimist-0.6.1.tgz#da3ea74686fa21a19a111c326e90eb15a0196686"
+  dependencies:
+    minimist "~0.0.1"
+    wordwrap "~0.0.2"
+
+optionator@^0.6.0:
+  version "0.6.0"
+  resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.6.0.tgz#b63ecbbf0e315fad4bc9827b45dc7ba45284fcb6"
+  dependencies:
+    deep-is "~0.1.3"
+    fast-levenshtein "~1.0.6"
+    levn "~0.2.5"
+    prelude-ls "~1.1.1"
+    type-check "~0.3.1"
+    wordwrap "~0.0.2"
+
+options@>=0.0.5:
+  version "0.0.6"
+  resolved "https://registry.yarnpkg.com/options/-/options-0.0.6.tgz#ec22d312806bb53e731773e7cdaefcf1c643128f"
+
+os-browserify@~0.1.2:
+  version "0.1.2"
+  resolved "https://registry.yarnpkg.com/os-browserify/-/os-browserify-0.1.2.tgz#49ca0293e0b19590a5f5de10c7f265a617d8fe54"
+
+os-homedir@^1.0.0:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3"
+
+os-locale@^1.4.0:
+  version "1.4.0"
+  resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-1.4.0.tgz#20f9f17ae29ed345e8bde583b13d2009803c14d9"
+  dependencies:
+    lcid "^1.0.0"
+
+os-tmpdir@^1.0.0, os-tmpdir@^1.0.1:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274"
+
+osenv@0, osenv@^0.1.4:
+  version "0.1.5"
+  resolved "https://registry.yarnpkg.com/osenv/-/osenv-0.1.5.tgz#85cdfafaeb28e8677f416e287592b5f3f49ea410"
+  dependencies:
+    os-homedir "^1.0.0"
+    os-tmpdir "^1.0.0"
+
+output-file-sync@^1.1.0:
+  version "1.1.2"
+  resolved "https://registry.yarnpkg.com/output-file-sync/-/output-file-sync-1.1.2.tgz#d0a33eefe61a205facb90092e826598d5245ce76"
+  dependencies:
+    graceful-fs "^4.1.4"
+    mkdirp "^0.5.1"
+    object-assign "^4.1.0"
+
+pako@~0.2.0:
+  version "0.2.9"
+  resolved "https://registry.yarnpkg.com/pako/-/pako-0.2.9.tgz#f3f7522f4ef782348da8161bad9ecfd51bf83a75"
+
+parse-glob@^3.0.4:
+  version "3.0.4"
+  resolved "https://registry.yarnpkg.com/parse-glob/-/parse-glob-3.0.4.tgz#b2c376cfb11f35513badd173ef0bb6e3a388391c"
+  dependencies:
+    glob-base "^0.3.0"
+    is-dotfile "^1.0.0"
+    is-extglob "^1.0.0"
+    is-glob "^2.0.0"
+
+parse-json@^2.2.0:
+  version "2.2.0"
+  resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9"
+  dependencies:
+    error-ex "^1.2.0"
+
+parsejson@0.0.3:
+  version "0.0.3"
+  resolved "https://registry.yarnpkg.com/parsejson/-/parsejson-0.0.3.tgz#ab7e3759f209ece99437973f7d0f1f64ae0e64ab"
+  dependencies:
+    better-assert "~1.0.0"
+
+parseqs@0.0.5:
+  version "0.0.5"
+  resolved "https://registry.yarnpkg.com/parseqs/-/parseqs-0.0.5.tgz#d5208a3738e46766e291ba2ea173684921a8b89d"
+  dependencies:
+    better-assert "~1.0.0"
+
+parseuri@0.0.5:
+  version "0.0.5"
+  resolved "https://registry.yarnpkg.com/parseuri/-/parseuri-0.0.5.tgz#80204a50d4dbb779bfdc6ebe2778d90e4bce320a"
+  dependencies:
+    better-assert "~1.0.0"
+
+parseurl@~1.3.2:
+  version "1.3.2"
+  resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.2.tgz#fc289d4ed8993119460c156253262cdc8de65bf3"
+
+path-browserify@0.0.0:
+  version "0.0.0"
+  resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-0.0.0.tgz#a0b870729aae214005b7d5032ec2cbbb0fb4451a"
+
+path-exists@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-1.0.0.tgz#d5a8998eb71ef37a74c34eb0d9eba6e878eea081"
+
+path-exists@^2.0.0:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-2.1.0.tgz#0feb6c64f0fc518d9a754dd5efb62c7022761f4b"
+  dependencies:
+    pinkie-promise "^2.0.0"
+
+path-is-absolute@^1.0.0, path-is-absolute@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
+
+path-is-inside@^1.0.1:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53"
+
+path-key@^2.0.1:
+  version "2.0.1"
+  resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40"
+
+path-parse@^1.0.5:
+  version "1.0.6"
+  resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c"
+
+path-to-regexp@0.1.7:
+  version "0.1.7"
+  resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c"
+
+path-type@^1.0.0:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/path-type/-/path-type-1.1.0.tgz#59c44f7ee491da704da415da5a4070ba4f8fe441"
+  dependencies:
+    graceful-fs "^4.1.2"
+    pify "^2.0.0"
+    pinkie-promise "^2.0.0"
+
+pbkdf2-compat@2.0.1:
+  version "2.0.1"
+  resolved "https://registry.yarnpkg.com/pbkdf2-compat/-/pbkdf2-compat-2.0.1.tgz#b6e0c8fa99494d94e0511575802a59a5c142f288"
+
+performance-now@^2.1.0:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b"
+
+pify@^2.0.0:
+  version "2.3.0"
+  resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c"
+
+pinkie-promise@^2.0.0:
+  version "2.0.1"
+  resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa"
+  dependencies:
+    pinkie "^2.0.0"
+
+pinkie@^2.0.0:
+  version "2.0.4"
+  resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870"
+
+pkg-dir@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-1.0.0.tgz#7a4b508a8d5bb2d629d447056ff4e9c9314cf3d4"
+  dependencies:
+    find-up "^1.0.0"
+
+postcss-calc@^5.2.0:
+  version "5.3.1"
+  resolved "https://registry.yarnpkg.com/postcss-calc/-/postcss-calc-5.3.1.tgz#77bae7ca928ad85716e2fda42f261bf7c1d65b5e"
+  dependencies:
+    postcss "^5.0.2"
+    postcss-message-helpers "^2.0.0"
+    reduce-css-calc "^1.2.6"
+
+postcss-colormin@^2.1.8:
+  version "2.2.2"
+  resolved "https://registry.yarnpkg.com/postcss-colormin/-/postcss-colormin-2.2.2.tgz#6631417d5f0e909a3d7ec26b24c8a8d1e4f96e4b"
+  dependencies:
+    colormin "^1.0.5"
+    postcss "^5.0.13"
+    postcss-value-parser "^3.2.3"
+
+postcss-convert-values@^2.3.4:
+  version "2.6.1"
+  resolved "https://registry.yarnpkg.com/postcss-convert-values/-/postcss-convert-values-2.6.1.tgz#bbd8593c5c1fd2e3d1c322bb925dcae8dae4d62d"
+  dependencies:
+    postcss "^5.0.11"
+    postcss-value-parser "^3.1.2"
+
+postcss-discard-comments@^2.0.4:
+  version "2.0.4"
+  resolved "https://registry.yarnpkg.com/postcss-discard-comments/-/postcss-discard-comments-2.0.4.tgz#befe89fafd5b3dace5ccce51b76b81514be00e3d"
+  dependencies:
+    postcss "^5.0.14"
+
+postcss-discard-duplicates@^2.0.1:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/postcss-discard-duplicates/-/postcss-discard-duplicates-2.1.0.tgz#b9abf27b88ac188158a5eb12abcae20263b91932"
+  dependencies:
+    postcss "^5.0.4"
+
+postcss-discard-empty@^2.0.1:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/postcss-discard-empty/-/postcss-discard-empty-2.1.0.tgz#d2b4bd9d5ced5ebd8dcade7640c7d7cd7f4f92b5"
+  dependencies:
+    postcss "^5.0.14"
+
+postcss-discard-overridden@^0.1.1:
+  version "0.1.1"
+  resolved "https://registry.yarnpkg.com/postcss-discard-overridden/-/postcss-discard-overridden-0.1.1.tgz#8b1eaf554f686fb288cd874c55667b0aa3668d58"
+  dependencies:
+    postcss "^5.0.16"
+
+postcss-discard-unused@^2.2.1:
+  version "2.2.3"
+  resolved "https://registry.yarnpkg.com/postcss-discard-unused/-/postcss-discard-unused-2.2.3.tgz#bce30b2cc591ffc634322b5fb3464b6d934f4433"
+  dependencies:
+    postcss "^5.0.14"
+    uniqs "^2.0.0"
+
+postcss-filter-plugins@^2.0.0:
+  version "2.0.3"
+  resolved "https://registry.yarnpkg.com/postcss-filter-plugins/-/postcss-filter-plugins-2.0.3.tgz#82245fdf82337041645e477114d8e593aa18b8ec"
+  dependencies:
+    postcss "^5.0.4"
+
+postcss-loader@^0.6.0:
+  version "0.6.0"
+  resolved "https://registry.yarnpkg.com/postcss-loader/-/postcss-loader-0.6.0.tgz#984f9c9add2f8b153d754909dad04fbbb6b02f39"
+  dependencies:
+    loader-utils "^0.2.11"
+    postcss "^5.0.0"
+
+postcss-merge-idents@^2.1.5:
+  version "2.1.7"
+  resolved "https://registry.yarnpkg.com/postcss-merge-idents/-/postcss-merge-idents-2.1.7.tgz#4c5530313c08e1d5b3bbf3d2bbc747e278eea270"
+  dependencies:
+    has "^1.0.1"
+    postcss "^5.0.10"
+    postcss-value-parser "^3.1.1"
+
+postcss-merge-longhand@^2.0.1:
+  version "2.0.2"
+  resolved "https://registry.yarnpkg.com/postcss-merge-longhand/-/postcss-merge-longhand-2.0.2.tgz#23d90cd127b0a77994915332739034a1a4f3d658"
+  dependencies:
+    postcss "^5.0.4"
+
+postcss-merge-rules@^2.0.3:
+  version "2.1.2"
+  resolved "https://registry.yarnpkg.com/postcss-merge-rules/-/postcss-merge-rules-2.1.2.tgz#d1df5dfaa7b1acc3be553f0e9e10e87c61b5f721"
+  dependencies:
+    browserslist "^1.5.2"
+    caniuse-api "^1.5.2"
+    postcss "^5.0.4"
+    postcss-selector-parser "^2.2.2"
+    vendors "^1.0.0"
+
+postcss-message-helpers@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/postcss-message-helpers/-/postcss-message-helpers-2.0.0.tgz#a4f2f4fab6e4fe002f0aed000478cdf52f9ba60e"
+
+postcss-minify-font-values@^1.0.2:
+  version "1.0.5"
+  resolved "https://registry.yarnpkg.com/postcss-minify-font-values/-/postcss-minify-font-values-1.0.5.tgz#4b58edb56641eba7c8474ab3526cafd7bbdecb69"
+  dependencies:
+    object-assign "^4.0.1"
+    postcss "^5.0.4"
+    postcss-value-parser "^3.0.2"
+
+postcss-minify-gradients@^1.0.1:
+  version "1.0.5"
+  resolved "https://registry.yarnpkg.com/postcss-minify-gradients/-/postcss-minify-gradients-1.0.5.tgz#5dbda11373703f83cfb4a3ea3881d8d75ff5e6e1"
+  dependencies:
+    postcss "^5.0.12"
+    postcss-value-parser "^3.3.0"
+
+postcss-minify-params@^1.0.4:
+  version "1.2.2"
+  resolved "https://registry.yarnpkg.com/postcss-minify-params/-/postcss-minify-params-1.2.2.tgz#ad2ce071373b943b3d930a3fa59a358c28d6f1f3"
+  dependencies:
+    alphanum-sort "^1.0.1"
+    postcss "^5.0.2"
+    postcss-value-parser "^3.0.2"
+    uniqs "^2.0.0"
+
+postcss-minify-selectors@^2.0.4:
+  version "2.1.1"
+  resolved "https://registry.yarnpkg.com/postcss-minify-selectors/-/postcss-minify-selectors-2.1.1.tgz#b2c6a98c0072cf91b932d1a496508114311735bf"
+  dependencies:
+    alphanum-sort "^1.0.2"
+    has "^1.0.1"
+    postcss "^5.0.14"
+    postcss-selector-parser "^2.0.0"
+
+postcss-modules-extract-imports@1.0.0-beta2:
+  version "1.0.0-beta2"
+  resolved "https://registry.yarnpkg.com/postcss-modules-extract-imports/-/postcss-modules-extract-imports-1.0.0-beta2.tgz#f1d3533eea3fe79dffa97a2371cc916393401dc5"
+  dependencies:
+    postcss "^5.0.4"
+
+postcss-modules-local-by-default@1.0.0-beta1:
+  version "1.0.0-beta1"
+  resolved "https://registry.yarnpkg.com/postcss-modules-local-by-default/-/postcss-modules-local-by-default-1.0.0-beta1.tgz#89b3ad65f669973386804953948aad23b7330d5f"
+  dependencies:
+    css-selector-tokenizer "^0.5.1"
+    postcss "^5.0.4"
+
+postcss-modules-scope@1.0.0-beta2:
+  version "1.0.0-beta2"
+  resolved "https://registry.yarnpkg.com/postcss-modules-scope/-/postcss-modules-scope-1.0.0-beta2.tgz#76af8b0008ede646bb9db675e27bc4ee3aa044bc"
+  dependencies:
+    css-selector-tokenizer "^0.5.0"
+    postcss "^5.0.4"
+
+postcss-normalize-charset@^1.1.0:
+  version "1.1.1"
+  resolved "https://registry.yarnpkg.com/postcss-normalize-charset/-/postcss-normalize-charset-1.1.1.tgz#ef9ee71212d7fe759c78ed162f61ed62b5cb93f1"
+  dependencies:
+    postcss "^5.0.5"
+
+postcss-normalize-url@^3.0.7:
+  version "3.0.8"
+  resolved "https://registry.yarnpkg.com/postcss-normalize-url/-/postcss-normalize-url-3.0.8.tgz#108f74b3f2fcdaf891a2ffa3ea4592279fc78222"
+  dependencies:
+    is-absolute-url "^2.0.0"
+    normalize-url "^1.4.0"
+    postcss "^5.0.14"
+    postcss-value-parser "^3.2.3"
+
+postcss-ordered-values@^2.1.0:
+  version "2.2.3"
+  resolved "https://registry.yarnpkg.com/postcss-ordered-values/-/postcss-ordered-values-2.2.3.tgz#eec6c2a67b6c412a8db2042e77fe8da43f95c11d"
+  dependencies:
+    postcss "^5.0.4"
+    postcss-value-parser "^3.0.1"
+
+postcss-reduce-idents@^2.2.2:
+  version "2.4.0"
+  resolved "https://registry.yarnpkg.com/postcss-reduce-idents/-/postcss-reduce-idents-2.4.0.tgz#c2c6d20cc958284f6abfbe63f7609bf409059ad3"
+  dependencies:
+    postcss "^5.0.4"
+    postcss-value-parser "^3.0.2"
+
+postcss-reduce-initial@^1.0.0:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/postcss-reduce-initial/-/postcss-reduce-initial-1.0.1.tgz#68f80695f045d08263a879ad240df8dd64f644ea"
+  dependencies:
+    postcss "^5.0.4"
+
+postcss-reduce-transforms@^1.0.3:
+  version "1.0.4"
+  resolved "https://registry.yarnpkg.com/postcss-reduce-transforms/-/postcss-reduce-transforms-1.0.4.tgz#ff76f4d8212437b31c298a42d2e1444025771ae1"
+  dependencies:
+    has "^1.0.1"
+    postcss "^5.0.8"
+    postcss-value-parser "^3.0.1"
+
+postcss-selector-parser@^2.0.0, postcss-selector-parser@^2.2.2:
+  version "2.2.3"
+  resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-2.2.3.tgz#f9437788606c3c9acee16ffe8d8b16297f27bb90"
+  dependencies:
+    flatten "^1.0.2"
+    indexes-of "^1.0.1"
+    uniq "^1.0.1"
+
+postcss-svgo@^2.1.1:
+  version "2.1.6"
+  resolved "https://registry.yarnpkg.com/postcss-svgo/-/postcss-svgo-2.1.6.tgz#b6df18aa613b666e133f08adb5219c2684ac108d"
+  dependencies:
+    is-svg "^2.0.0"
+    postcss "^5.0.14"
+    postcss-value-parser "^3.2.3"
+    svgo "^0.7.0"
+
+postcss-unique-selectors@^2.0.2:
+  version "2.0.2"
+  resolved "https://registry.yarnpkg.com/postcss-unique-selectors/-/postcss-unique-selectors-2.0.2.tgz#981d57d29ddcb33e7b1dfe1fd43b8649f933ca1d"
+  dependencies:
+    alphanum-sort "^1.0.1"
+    postcss "^5.0.4"
+    uniqs "^2.0.0"
+
+postcss-value-parser@^3.0.1, postcss-value-parser@^3.0.2, postcss-value-parser@^3.1.1, postcss-value-parser@^3.1.2, postcss-value-parser@^3.2.3, postcss-value-parser@^3.3.0:
+  version "3.3.0"
+  resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-3.3.0.tgz#87f38f9f18f774a4ab4c8a232f5c5ce8872a9d15"
+
+postcss-zindex@^2.0.1:
+  version "2.2.0"
+  resolved "https://registry.yarnpkg.com/postcss-zindex/-/postcss-zindex-2.2.0.tgz#d2109ddc055b91af67fc4cb3b025946639d2af22"
+  dependencies:
+    has "^1.0.1"
+    postcss "^5.0.4"
+    uniqs "^2.0.0"
+
+postcss@^5.0.0, postcss@^5.0.10, postcss@^5.0.11, postcss@^5.0.12, postcss@^5.0.13, postcss@^5.0.14, postcss@^5.0.16, postcss@^5.0.2, postcss@^5.0.4, postcss@^5.0.5, postcss@^5.0.6, postcss@^5.0.8, postcss@^5.2.16:
+  version "5.2.18"
+  resolved "https://registry.yarnpkg.com/postcss/-/postcss-5.2.18.tgz#badfa1497d46244f6390f58b319830d9107853c5"
+  dependencies:
+    chalk "^1.1.3"
+    js-base64 "^2.1.9"
+    source-map "^0.5.6"
+    supports-color "^3.2.3"
+
+prelude-ls@~1.1.0, prelude-ls@~1.1.1, prelude-ls@~1.1.2:
+  version "1.1.2"
+  resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54"
+
+prepend-http@^1.0.0:
+  version "1.0.4"
+  resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-1.0.4.tgz#d4f4562b0ce3696e41ac52d0e002e57a635dc6dc"
+
+preserve@^0.2.0:
+  version "0.2.0"
+  resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b"
+
+private@^0.1.6, private@^0.1.8, private@~0.1.5:
+  version "0.1.8"
+  resolved "https://registry.yarnpkg.com/private/-/private-0.1.8.tgz#2381edb3689f7a53d653190060fcf822d2f368ff"
+
+process-nextick-args@~2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.0.tgz#a37d732f4271b4ab1ad070d35508e8290788ffaa"
+
+process@^0.11.0, process@~0.11.0:
+  version "0.11.10"
+  resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182"
+
+promise@^7.1.1:
+  version "7.3.1"
+  resolved "https://registry.yarnpkg.com/promise/-/promise-7.3.1.tgz#064b72602b18f90f29192b8b1bc418ffd1ebd3bf"
+  dependencies:
+    asap "~2.0.3"
+
+prop-types@^15.5.10, prop-types@^15.5.6, prop-types@^15.6.0:
+  version "15.6.2"
+  resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.6.2.tgz#05d5ca77b4453e985d60fc7ff8c859094a497102"
+  dependencies:
+    loose-envify "^1.3.1"
+    object-assign "^4.1.1"
+
+proxy-addr@~2.0.3:
+  version "2.0.4"
+  resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.4.tgz#ecfc733bf22ff8c6f407fa275327b9ab67e48b93"
+  dependencies:
+    forwarded "~0.1.2"
+    ipaddr.js "1.8.0"
+
+prr@~1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476"
+
+pseudomap@^1.0.2:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3"
+
+psl@^1.1.24:
+  version "1.1.29"
+  resolved "https://registry.yarnpkg.com/psl/-/psl-1.1.29.tgz#60f580d360170bb722a797cc704411e6da850c67"
+
+punycode@1.3.2:
+  version "1.3.2"
+  resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d"
+
+punycode@^1.2.4, punycode@^1.4.1:
+  version "1.4.1"
+  resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e"
+
+q@^1.1.2:
+  version "1.5.1"
+  resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7"
+
+qs@6.5.1:
+  version "6.5.1"
+  resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.1.tgz#349cdf6eef89ec45c12d7d5eb3fc0c870343a6d8"
+
+qs@~6.5.2:
+  version "6.5.2"
+  resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36"
+
+query-string@^4.1.0, query-string@^4.2.2:
+  version "4.3.4"
+  resolved "https://registry.yarnpkg.com/query-string/-/query-string-4.3.4.tgz#bbb693b9ca915c232515b228b1a02b609043dbeb"
+  dependencies:
+    object-assign "^4.1.0"
+    strict-uri-encode "^1.0.0"
+
+querystring-es3@~0.2.0:
+  version "0.2.1"
+  resolved "https://registry.yarnpkg.com/querystring-es3/-/querystring-es3-0.2.1.tgz#9ec61f79049875707d69414596fd907a4d711e73"
+
+querystring@0.2.0:
+  version "0.2.0"
+  resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620"
+
+randomatic@^3.0.0:
+  version "3.1.0"
+  resolved "https://registry.yarnpkg.com/randomatic/-/randomatic-3.1.0.tgz#36f2ca708e9e567f5ed2ec01949026d50aa10116"
+  dependencies:
+    is-number "^4.0.0"
+    kind-of "^6.0.0"
+    math-random "^1.0.1"
+
+range-parser@^1.0.3, range-parser@~1.2.0:
+  version "1.2.0"
+  resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.0.tgz#f49be6b487894ddc40dcc94a322f611092e00d5e"
+
+raw-body@2.3.2:
+  version "2.3.2"
+  resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.3.2.tgz#bcd60c77d3eb93cde0050295c3f379389bc88f89"
+  dependencies:
+    bytes "3.0.0"
+    http-errors "1.6.2"
+    iconv-lite "0.4.19"
+    unpipe "1.0.0"
+
+rc@^1.2.7:
+  version "1.2.8"
+  resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed"
+  dependencies:
+    deep-extend "^0.6.0"
+    ini "~1.3.0"
+    minimist "^1.2.0"
+    strip-json-comments "~2.0.1"
+
+react-addons-test-utils@^15.6.2:
+  version "15.6.2"
+  resolved "https://registry.yarnpkg.com/react-addons-test-utils/-/react-addons-test-utils-15.6.2.tgz#c12b6efdc2247c10da7b8770d185080a7b047156"
+
+react-css-modules@^3.5.0:
+  version "3.7.10"
+  resolved "https://registry.yarnpkg.com/react-css-modules/-/react-css-modules-3.7.10.tgz#300da561e550eeec5ebc0bc8c7d51d77d88ae2d7"
+  dependencies:
+    hoist-non-react-statics "^1.0.5"
+    lodash "^4.6.1"
+    object-unfreeze "^1.0.2"
+
+react-dom@^16.2.0:
+  version "16.4.2"
+  resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.4.2.tgz#4afed569689f2c561d2b8da0b819669c38a0bda4"
+  dependencies:
+    fbjs "^0.8.16"
+    loose-envify "^1.1.0"
+    object-assign "^4.1.1"
+    prop-types "^15.6.0"
+
+react-router@^3.0.0:
+  version "3.2.1"
+  resolved "https://registry.yarnpkg.com/react-router/-/react-router-3.2.1.tgz#b9a3279962bdfbe684c8bd0482b81ef288f0f244"
+  dependencies:
+    create-react-class "^15.5.1"
+    history "^3.0.0"
+    hoist-non-react-statics "^2.3.1"
+    invariant "^2.2.1"
+    loose-envify "^1.2.0"
+    prop-types "^15.5.6"
+    warning "^3.0.0"
+
+react@^16.2.0:
+  version "16.4.2"
+  resolved "https://registry.yarnpkg.com/react/-/react-16.4.2.tgz#2cd90154e3a9d9dd8da2991149fdca3c260e129f"
+  dependencies:
+    fbjs "^0.8.16"
+    loose-envify "^1.1.0"
+    object-assign "^4.1.1"
+    prop-types "^15.6.0"
+
+read-pkg-up@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-1.0.1.tgz#9d63c13276c065918d57f002a57f40a1b643fb02"
+  dependencies:
+    find-up "^1.0.0"
+    read-pkg "^1.0.0"
+
+read-pkg@^1.0.0:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-1.1.0.tgz#f5ffaa5ecd29cb31c0474bca7d756b6bb29e3f28"
+  dependencies:
+    load-json-file "^1.0.0"
+    normalize-package-data "^2.3.2"
+    path-type "^1.0.0"
+
+readable-stream@^1.0.27-1, readable-stream@^1.1.13:
+  version "1.1.14"
+  resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.1.14.tgz#7cf4c54ef648e3813084c636dd2079e166c081d9"
+  dependencies:
+    core-util-is "~1.0.0"
+    inherits "~2.0.1"
+    isarray "0.0.1"
+    string_decoder "~0.10.x"
+
+readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.6, readable-stream@^2.2.2:
+  version "2.3.6"
+  resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf"
+  dependencies:
+    core-util-is "~1.0.0"
+    inherits "~2.0.3"
+    isarray "~1.0.0"
+    process-nextick-args "~2.0.0"
+    safe-buffer "~5.1.1"
+    string_decoder "~1.1.1"
+    util-deprecate "~1.0.1"
+
+readdirp@^2.0.0:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-2.1.0.tgz#4ed0ad060df3073300c48440373f72d1cc642d78"
+  dependencies:
+    graceful-fs "^4.1.2"
+    minimatch "^3.0.2"
+    readable-stream "^2.0.2"
+    set-immediate-shim "^1.0.1"
+
+readline2@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/readline2/-/readline2-1.0.1.tgz#41059608ffc154757b715d9989d199ffbf372e35"
+  dependencies:
+    code-point-at "^1.0.0"
+    is-fullwidth-code-point "^1.0.0"
+    mute-stream "0.0.5"
+
+recast@0.10.33:
+  version "0.10.33"
+  resolved "https://registry.yarnpkg.com/recast/-/recast-0.10.33.tgz#942808f7aa016f1fa7142c461d7e5704aaa8d697"
+  dependencies:
+    ast-types "0.8.12"
+    esprima-fb "~15001.1001.0-dev-harmony-fb"
+    private "~0.1.5"
+    source-map "~0.5.0"
+
+recast@^0.10.10:
+  version "0.10.43"
+  resolved "https://registry.yarnpkg.com/recast/-/recast-0.10.43.tgz#b95d50f6d60761a5f6252e15d80678168491ce7f"
+  dependencies:
+    ast-types "0.8.15"
+    esprima-fb "~15001.1001.0-dev-harmony-fb"
+    private "~0.1.5"
+    source-map "~0.5.0"
+
+recast@^0.11.17:
+  version "0.11.23"
+  resolved "https://registry.yarnpkg.com/recast/-/recast-0.11.23.tgz#451fd3004ab1e4df9b4e4b66376b2a21912462d3"
+  dependencies:
+    ast-types "0.9.6"
+    esprima "~3.1.0"
+    private "~0.1.5"
+    source-map "~0.5.0"
+
+redent@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/redent/-/redent-1.0.0.tgz#cf916ab1fd5f1f16dfb20822dd6ec7f730c2afde"
+  dependencies:
+    indent-string "^2.1.0"
+    strip-indent "^1.0.1"
+
+reduce-css-calc@^1.2.6:
+  version "1.3.0"
+  resolved "https://registry.yarnpkg.com/reduce-css-calc/-/reduce-css-calc-1.3.0.tgz#747c914e049614a4c9cfbba629871ad1d2927716"
+  dependencies:
+    balanced-match "^0.4.2"
+    math-expression-evaluator "^1.2.14"
+    reduce-function-call "^1.0.1"
+
+reduce-function-call@^1.0.1:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/reduce-function-call/-/reduce-function-call-1.0.2.tgz#5a200bf92e0e37751752fe45b0ab330fd4b6be99"
+  dependencies:
+    balanced-match "^0.4.2"
+
+regenerate@^1.2.1:
+  version "1.4.0"
+  resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.0.tgz#4a856ec4b56e4077c557589cae85e7a4c8869a11"
+
+regenerator-runtime@^0.11.0:
+  version "0.11.1"
+  resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9"
+
+regenerator-transform@^0.10.0:
+  version "0.10.1"
+  resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.10.1.tgz#1e4996837231da8b7f3cf4114d71b5691a0680dd"
+  dependencies:
+    babel-runtime "^6.18.0"
+    babel-types "^6.19.0"
+    private "^0.1.6"
+
+regenerator@0.8.40:
+  version "0.8.40"
+  resolved "https://registry.yarnpkg.com/regenerator/-/regenerator-0.8.40.tgz#a0e457c58ebdbae575c9f8cd75127e93756435d8"
+  dependencies:
+    commoner "~0.10.3"
+    defs "~1.1.0"
+    esprima-fb "~15001.1001.0-dev-harmony-fb"
+    private "~0.1.5"
+    recast "0.10.33"
+    through "~2.3.8"
+
+regex-cache@^0.4.2:
+  version "0.4.4"
+  resolved "https://registry.yarnpkg.com/regex-cache/-/regex-cache-0.4.4.tgz#75bdc58a2a1496cec48a12835bc54c8d562336dd"
+  dependencies:
+    is-equal-shallow "^0.1.3"
+
+regexpu-core@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-2.0.0.tgz#49d038837b8dcf8bfa5b9a42139938e6ea2ae240"
+  dependencies:
+    regenerate "^1.2.1"
+    regjsgen "^0.2.0"
+    regjsparser "^0.1.4"
+
+regexpu@^1.3.0:
+  version "1.3.0"
+  resolved "https://registry.yarnpkg.com/regexpu/-/regexpu-1.3.0.tgz#e534dc991a9e5846050c98de6d7dd4a55c9ea16d"
+  dependencies:
+    esprima "^2.6.0"
+    recast "^0.10.10"
+    regenerate "^1.2.1"
+    regjsgen "^0.2.0"
+    regjsparser "^0.1.4"
+
+regjsgen@^0.2.0:
+  version "0.2.0"
+  resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.2.0.tgz#6c016adeac554f75823fe37ac05b92d5a4edb1f7"
+
+regjsparser@^0.1.4:
+  version "0.1.5"
+  resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.1.5.tgz#7ee8f84dc6fa792d3fd0ae228d24bd949ead205c"
+  dependencies:
+    jsesc "~0.5.0"
+
+remove-trailing-separator@^1.0.1:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef"
+
+repeat-element@^1.1.2:
+  version "1.1.3"
+  resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.3.tgz#782e0d825c0c5a3bb39731f84efee6b742e6b1ce"
+
+repeat-string@^1.5.2:
+  version "1.6.1"
+  resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637"
+
+repeating@^1.1.0, repeating@^1.1.2:
+  version "1.1.3"
+  resolved "https://registry.yarnpkg.com/repeating/-/repeating-1.1.3.tgz#3d4114218877537494f97f77f9785fab810fa4ac"
+  dependencies:
+    is-finite "^1.0.0"
+
+repeating@^2.0.0:
+  version "2.0.1"
+  resolved "https://registry.yarnpkg.com/repeating/-/repeating-2.0.1.tgz#5214c53a926d3552707527fbab415dbc08d06dda"
+  dependencies:
+    is-finite "^1.0.0"
+
+request@^2.61.0, request@^2.87.0:
+  version "2.88.0"
+  resolved "https://registry.yarnpkg.com/request/-/request-2.88.0.tgz#9c2fca4f7d35b592efe57c7f0a55e81052124fef"
+  dependencies:
+    aws-sign2 "~0.7.0"
+    aws4 "^1.8.0"
+    caseless "~0.12.0"
+    combined-stream "~1.0.6"
+    extend "~3.0.2"
+    forever-agent "~0.6.1"
+    form-data "~2.3.2"
+    har-validator "~5.1.0"
+    http-signature "~1.2.0"
+    is-typedarray "~1.0.0"
+    isstream "~0.1.2"
+    json-stringify-safe "~5.0.1"
+    mime-types "~2.1.19"
+    oauth-sign "~0.9.0"
+    performance-now "^2.1.0"
+    qs "~6.5.2"
+    safe-buffer "^5.1.2"
+    tough-cookie "~2.4.3"
+    tunnel-agent "^0.6.0"
+    uuid "^3.3.2"
+
+require-directory@^2.1.1:
+  version "2.1.1"
+  resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42"
+
+require-main-filename@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-1.0.1.tgz#97f717b69d48784f5f526a6c5aa8ffdda055a4d1"
+
+requires-port@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff"
+
+resolve@^1.1.6:
+  version "1.8.1"
+  resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.8.1.tgz#82f1ec19a423ac1fbd080b0bab06ba36e84a7a26"
+  dependencies:
+    path-parse "^1.0.5"
+
+restore-cursor@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-1.0.1.tgz#34661f46886327fed2991479152252df92daa541"
+  dependencies:
+    exit-hook "^1.0.0"
+    onetime "^1.0.0"
+
+right-align@^0.1.1:
+  version "0.1.3"
+  resolved "https://registry.yarnpkg.com/right-align/-/right-align-0.1.3.tgz#61339b722fe6a3515689210d24e14c96148613ef"
+  dependencies:
+    align-text "^0.1.1"
+
+rimraf@2, rimraf@^2.2.8, rimraf@^2.6.1:
+  version "2.6.2"
+  resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.2.tgz#2ed8150d24a16ea8651e6d6ef0f47c4158ce7a36"
+  dependencies:
+    glob "^7.0.5"
+
+ripemd160@0.2.0:
+  version "0.2.0"
+  resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-0.2.0.tgz#2bf198bde167cacfa51c0a928e84b68bbe171fce"
+
+run-async@^0.1.0:
+  version "0.1.0"
+  resolved "https://registry.yarnpkg.com/run-async/-/run-async-0.1.0.tgz#c8ad4a5e110661e402a7d21b530e009f25f8e389"
+  dependencies:
+    once "^1.3.0"
+
+rx-lite@^3.1.2:
+  version "3.1.2"
+  resolved "https://registry.yarnpkg.com/rx-lite/-/rx-lite-3.1.2.tgz#19ce502ca572665f3b647b10939f97fd1615f102"
+
+safe-buffer@5.1.1:
+  version "5.1.1"
+  resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.1.tgz#893312af69b2123def71f57889001671eeb2c853"
+
+safe-buffer@5.1.2, safe-buffer@^5.0.1, safe-buffer@^5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1:
+  version "5.1.2"
+  resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d"
+
+"safer-buffer@>= 2.1.2 < 3", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0:
+  version "2.1.2"
+  resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
+
+sass-graph@^2.1.1:
+  version "2.2.4"
+  resolved "https://registry.yarnpkg.com/sass-graph/-/sass-graph-2.2.4.tgz#13fbd63cd1caf0908b9fd93476ad43a51d1e0b49"
+  dependencies:
+    glob "^7.0.0"
+    lodash "^4.0.0"
+    scss-tokenizer "^0.2.3"
+    yargs "^7.0.0"
+
+sass-loader@^3.0.0:
+  version "3.2.3"
+  resolved "https://registry.yarnpkg.com/sass-loader/-/sass-loader-3.2.3.tgz#742e81fd8170a8771a979e18622501674a88e355"
+  dependencies:
+    async "^1.4.0"
+    loader-utils "^0.2.5"
+    object-assign "^4.0.1"
+
+sax@^1.2.4, sax@~1.2.1:
+  version "1.2.4"
+  resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9"
+
+scss-tokenizer@^0.2.3:
+  version "0.2.3"
+  resolved "https://registry.yarnpkg.com/scss-tokenizer/-/scss-tokenizer-0.2.3.tgz#8eb06db9a9723333824d3f5530641149847ce5d1"
+  dependencies:
+    js-base64 "^2.1.8"
+    source-map "^0.4.2"
+
+"semver@2 || 3 || 4 || 5", semver@^5.3.0, semver@^5.5.0:
+  version "5.5.1"
+  resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.1.tgz#7dfdd8814bdb7cabc7be0fb1d734cfb66c940477"
+
+semver@~5.3.0:
+  version "5.3.0"
+  resolved "https://registry.yarnpkg.com/semver/-/semver-5.3.0.tgz#9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f"
+
+send@0.16.2:
+  version "0.16.2"
+  resolved "https://registry.yarnpkg.com/send/-/send-0.16.2.tgz#6ecca1e0f8c156d141597559848df64730a6bbc1"
+  dependencies:
+    debug "2.6.9"
+    depd "~1.1.2"
+    destroy "~1.0.4"
+    encodeurl "~1.0.2"
+    escape-html "~1.0.3"
+    etag "~1.8.1"
+    fresh "0.5.2"
+    http-errors "~1.6.2"
+    mime "1.4.1"
+    ms "2.0.0"
+    on-finished "~2.3.0"
+    range-parser "~1.2.0"
+    statuses "~1.4.0"
+
+serve-index@^1.7.2:
+  version "1.9.1"
+  resolved "https://registry.yarnpkg.com/serve-index/-/serve-index-1.9.1.tgz#d3768d69b1e7d82e5ce050fff5b453bea12a9239"
+  dependencies:
+    accepts "~1.3.4"
+    batch "0.6.1"
+    debug "2.6.9"
+    escape-html "~1.0.3"
+    http-errors "~1.6.2"
+    mime-types "~2.1.17"
+    parseurl "~1.3.2"
+
+serve-static@1.13.2:
+  version "1.13.2"
+  resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.13.2.tgz#095e8472fd5b46237db50ce486a43f4b86c6cec1"
+  dependencies:
+    encodeurl "~1.0.2"
+    escape-html "~1.0.3"
+    parseurl "~1.3.2"
+    send "0.16.2"
+
+set-blocking@^2.0.0, set-blocking@~2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7"
+
+set-immediate-shim@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz#4b2b1b27eb808a9f8dcc481a58e5e56f599f3f61"
+
+setimmediate@^1.0.5:
+  version "1.0.5"
+  resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285"
+
+setprototypeof@1.0.3:
+  version "1.0.3"
+  resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.0.3.tgz#66567e37043eeb4f04d91bd658c0cbefb55b8e04"
+
+setprototypeof@1.1.0:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.0.tgz#d0bd85536887b6fe7c0d818cb962d9d91c54e656"
+
+sha.js@2.2.6:
+  version "2.2.6"
+  resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.2.6.tgz#17ddeddc5f722fb66501658895461977867315ba"
+
+shebang-command@^1.2.0:
+  version "1.2.0"
+  resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea"
+  dependencies:
+    shebang-regex "^1.0.0"
+
+shebang-regex@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3"
+
+shelljs@^0.5.3:
+  version "0.5.3"
+  resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.5.3.tgz#c54982b996c76ef0c1e6b59fbdc5825f5b713113"
+
+signal-exit@^3.0.0:
+  version "3.0.2"
+  resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d"
+
+simple-fmt@~0.1.0:
+  version "0.1.0"
+  resolved "https://registry.yarnpkg.com/simple-fmt/-/simple-fmt-0.1.0.tgz#191bf566a59e6530482cb25ab53b4a8dc85c3a6b"
+
+simple-is@~0.2.0:
+  version "0.2.0"
+  resolved "https://registry.yarnpkg.com/simple-is/-/simple-is-0.2.0.tgz#2abb75aade39deb5cc815ce10e6191164850baf0"
+
+slash@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/slash/-/slash-1.0.0.tgz#c41f2f6c39fc16d1cd17ad4b5d896114ae470d55"
+
+socket.io-adapter@0.5.0:
+  version "0.5.0"
+  resolved "https://registry.yarnpkg.com/socket.io-adapter/-/socket.io-adapter-0.5.0.tgz#cb6d4bb8bec81e1078b99677f9ced0046066bb8b"
+  dependencies:
+    debug "2.3.3"
+    socket.io-parser "2.3.1"
+
+socket.io-client@1.7.4, socket.io-client@^1.3.6:
+  version "1.7.4"
+  resolved "https://registry.yarnpkg.com/socket.io-client/-/socket.io-client-1.7.4.tgz#ec9f820356ed99ef6d357f0756d648717bdd4281"
+  dependencies:
+    backo2 "1.0.2"
+    component-bind "1.0.0"
+    component-emitter "1.2.1"
+    debug "2.3.3"
+    engine.io-client "~1.8.4"
+    has-binary "0.1.7"
+    indexof "0.0.1"
+    object-component "0.0.3"
+    parseuri "0.0.5"
+    socket.io-parser "2.3.1"
+    to-array "0.1.4"
+
+socket.io-parser@2.3.1:
+  version "2.3.1"
+  resolved "https://registry.yarnpkg.com/socket.io-parser/-/socket.io-parser-2.3.1.tgz#dd532025103ce429697326befd64005fcfe5b4a0"
+  dependencies:
+    component-emitter "1.1.2"
+    debug "2.2.0"
+    isarray "0.0.1"
+    json3 "3.3.2"
+
+socket.io@^1.3.6:
+  version "1.7.4"
+  resolved "https://registry.yarnpkg.com/socket.io/-/socket.io-1.7.4.tgz#2f7ecedc3391bf2d5c73e291fe233e6e34d4dd00"
+  dependencies:
+    debug "2.3.3"
+    engine.io "~1.8.4"
+    has-binary "0.1.7"
+    object-assign "4.1.0"
+    socket.io-adapter "0.5.0"
+    socket.io-client "1.7.4"
+    socket.io-parser "2.3.1"
+
+sort-keys@^1.0.0:
+  version "1.1.2"
+  resolved "https://registry.yarnpkg.com/sort-keys/-/sort-keys-1.1.2.tgz#441b6d4d346798f1b4e49e8920adfba0e543f9ad"
+  dependencies:
+    is-plain-obj "^1.0.0"
+
+source-list-map@^0.1.4, source-list-map@~0.1.7:
+  version "0.1.8"
+  resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-0.1.8.tgz#c550b2ab5427f6b3f21f5afead88c4f5587b2106"
+
+source-map-support@^0.2.10:
+  version "0.2.10"
+  resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.2.10.tgz#ea5a3900a1c1cb25096a0ae8cc5c2b4b10ded3dc"
+  dependencies:
+    source-map "0.1.32"
+
+source-map-support@^0.4.15:
+  version "0.4.18"
+  resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.4.18.tgz#0286a6de8be42641338594e97ccea75f0a2c585f"
+  dependencies:
+    source-map "^0.5.6"
+
+source-map@0.1.32:
+  version "0.1.32"
+  resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.1.32.tgz#c8b6c167797ba4740a8ea33252162ff08591b266"
+  dependencies:
+    amdefine ">=0.0.4"
+
+source-map@^0.4.2, source-map@^0.4.4, source-map@~0.4.1:
+  version "0.4.4"
+  resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.4.4.tgz#eba4f5da9c0dc999de68032d8b4f76173652036b"
+  dependencies:
+    amdefine ">=0.0.4"
+
+source-map@^0.5.0, source-map@^0.5.3, source-map@^0.5.6, source-map@^0.5.7, source-map@~0.5.0, source-map@~0.5.1:
+  version "0.5.7"
+  resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc"
+
+spdx-correct@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.0.0.tgz#05a5b4d7153a195bc92c3c425b69f3b2a9524c82"
+  dependencies:
+    spdx-expression-parse "^3.0.0"
+    spdx-license-ids "^3.0.0"
+
+spdx-exceptions@^2.1.0:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.1.0.tgz#2c7ae61056c714a5b9b9b2b2af7d311ef5c78fe9"
+
+spdx-expression-parse@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz#99e119b7a5da00e05491c9fa338b7904823b41d0"
+  dependencies:
+    spdx-exceptions "^2.1.0"
+    spdx-license-ids "^3.0.0"
+
+spdx-license-ids@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.0.tgz#7a7cd28470cc6d3a1cfe6d66886f6bc430d3ac87"
+
+sprintf-js@~1.0.2:
+  version "1.0.3"
+  resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c"
+
+sshpk@^1.7.0:
+  version "1.14.2"
+  resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.14.2.tgz#c6fc61648a3d9c4e764fd3fcdf4ea105e492ba98"
+  dependencies:
+    asn1 "~0.2.3"
+    assert-plus "^1.0.0"
+    dashdash "^1.12.0"
+    getpass "^0.1.1"
+    safer-buffer "^2.0.2"
+  optionalDependencies:
+    bcrypt-pbkdf "^1.0.0"
+    ecc-jsbn "~0.1.1"
+    jsbn "~0.1.0"
+    tweetnacl "~0.14.0"
+
+stable@~0.1.3:
+  version "0.1.8"
+  resolved "https://registry.yarnpkg.com/stable/-/stable-0.1.8.tgz#836eb3c8382fe2936feaf544631017ce7d47a3cf"
+
+"statuses@>= 1.3.1 < 2", "statuses@>= 1.4.0 < 2":
+  version "1.5.0"
+  resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c"
+
+statuses@~1.4.0:
+  version "1.4.0"
+  resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.4.0.tgz#bb73d446da2796106efcc1b601a253d6c46bd087"
+
+stream-browserify@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/stream-browserify/-/stream-browserify-1.0.0.tgz#bf9b4abfb42b274d751479e44e0ff2656b6f1193"
+  dependencies:
+    inherits "~2.0.1"
+    readable-stream "^1.0.27-1"
+
+stream-cache@~0.0.1:
+  version "0.0.2"
+  resolved "https://registry.yarnpkg.com/stream-cache/-/stream-cache-0.0.2.tgz#1ac5ad6832428ca55667dbdee395dad4e6db118f"
+
+strict-uri-encode@^1.0.0:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz#279b225df1d582b1f54e65addd4352e18faa0713"
+
+string-width@^1.0.1, string-width@^1.0.2:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3"
+  dependencies:
+    code-point-at "^1.0.0"
+    is-fullwidth-code-point "^1.0.0"
+    strip-ansi "^3.0.0"
+
+"string-width@^1.0.2 || 2":
+  version "2.1.1"
+  resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e"
+  dependencies:
+    is-fullwidth-code-point "^2.0.0"
+    strip-ansi "^4.0.0"
+
+string_decoder@~0.10.25, string_decoder@~0.10.x:
+  version "0.10.31"
+  resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94"
+
+string_decoder@~1.1.1:
+  version "1.1.1"
+  resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8"
+  dependencies:
+    safe-buffer "~5.1.0"
+
+stringmap@~0.2.2:
+  version "0.2.2"
+  resolved "https://registry.yarnpkg.com/stringmap/-/stringmap-0.2.2.tgz#556c137b258f942b8776f5b2ef582aa069d7d1b1"
+
+stringset@~0.2.1:
+  version "0.2.1"
+  resolved "https://registry.yarnpkg.com/stringset/-/stringset-0.2.1.tgz#ef259c4e349344377fcd1c913dd2e848c9c042b5"
+
+strip-ansi@^3.0.0, strip-ansi@^3.0.1:
+  version "3.0.1"
+  resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf"
+  dependencies:
+    ansi-regex "^2.0.0"
+
+strip-ansi@^4.0.0:
+  version "4.0.0"
+  resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f"
+  dependencies:
+    ansi-regex "^3.0.0"
+
+strip-bom@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-2.0.0.tgz#6219a85616520491f35788bdbf1447a99c7e6b0e"
+  dependencies:
+    is-utf8 "^0.2.0"
+
+strip-indent@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-1.0.1.tgz#0c7962a6adefa7bbd4ac366460a638552ae1a0a2"
+  dependencies:
+    get-stdin "^4.0.1"
+
+strip-json-comments@~1.0.1:
+  version "1.0.4"
+  resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-1.0.4.tgz#1e15fbcac97d3ee99bf2d73b4c656b082bbafb91"
+
+strip-json-comments@~2.0.1:
+  version "2.0.1"
+  resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a"
+
+style-loader@0.12.x:
+  version "0.12.4"
+  resolved "https://registry.yarnpkg.com/style-loader/-/style-loader-0.12.4.tgz#ae7d0665dc4dc653daa2fe97bb90914bc1d22d9b"
+  dependencies:
+    loader-utils "^0.2.7"
+
+supports-color@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7"
+
+supports-color@^3.1.0, supports-color@^3.1.1, supports-color@^3.2.3:
+  version "3.2.3"
+  resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.2.3.tgz#65ac0504b3954171d8a64946b2ae3cbb8a5f54f6"
+  dependencies:
+    has-flag "^1.0.0"
+
+svgo@^0.7.0:
+  version "0.7.2"
+  resolved "https://registry.yarnpkg.com/svgo/-/svgo-0.7.2.tgz#9f5772413952135c6fefbf40afe6a4faa88b4bb5"
+  dependencies:
+    coa "~1.0.1"
+    colors "~1.1.2"
+    csso "~2.3.1"
+    js-yaml "~3.7.0"
+    mkdirp "~0.5.1"
+    sax "~1.2.1"
+    whet.extend "~0.9.9"
+
+tapable@^0.1.8, tapable@~0.1.8:
+  version "0.1.10"
+  resolved "https://registry.yarnpkg.com/tapable/-/tapable-0.1.10.tgz#29c35707c2b70e50d07482b5d202e8ed446dafd4"
+
+tar@^2.0.0:
+  version "2.2.1"
+  resolved "https://registry.yarnpkg.com/tar/-/tar-2.2.1.tgz#8e4d2a256c0e2185c6b18ad694aec968b83cb1d1"
+  dependencies:
+    block-stream "*"
+    fstream "^1.0.2"
+    inherits "2"
+
+tar@^4:
+  version "4.4.6"
+  resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.6.tgz#63110f09c00b4e60ac8bcfe1bf3c8660235fbc9b"
+  dependencies:
+    chownr "^1.0.1"
+    fs-minipass "^1.2.5"
+    minipass "^2.3.3"
+    minizlib "^1.1.0"
+    mkdirp "^0.5.0"
+    safe-buffer "^5.1.2"
+    yallist "^3.0.2"
+
+text-table@~0.2.0:
+  version "0.2.0"
+  resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4"
+
+through@^2.3.6, through@~2.3.8:
+  version "2.3.8"
+  resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5"
+
+time-stamp@^2.0.0:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/time-stamp/-/time-stamp-2.1.0.tgz#6c5c0b2bc835a244616abcfddf81ce13a1975c9f"
+
+timers-browserify@^1.0.1:
+  version "1.4.2"
+  resolved "https://registry.yarnpkg.com/timers-browserify/-/timers-browserify-1.4.2.tgz#c9c58b575be8407375cb5e2462dacee74359f41d"
+  dependencies:
+    process "~0.11.0"
+
+to-array@0.1.4:
+  version "0.1.4"
+  resolved "https://registry.yarnpkg.com/to-array/-/to-array-0.1.4.tgz#17e6c11f73dd4f3d74cda7a4ff3238e9ad9bf890"
+
+to-fast-properties@^1.0.0, to-fast-properties@^1.0.3:
+  version "1.0.3"
+  resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.3.tgz#b83571fa4d8c25b82e231b06e3a3055de4ca1a47"
+
+tough-cookie@~2.4.3:
+  version "2.4.3"
+  resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.4.3.tgz#53f36da3f47783b0925afa06ff9f3b165280f781"
+  dependencies:
+    psl "^1.1.24"
+    punycode "^1.4.1"
+
+trim-newlines@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-1.0.0.tgz#5887966bb582a4503a41eb524f7d35011815a613"
+
+trim-right@^1.0.0, trim-right@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003"
+
+try-resolve@^1.0.0:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/try-resolve/-/try-resolve-1.0.1.tgz#cfde6fabd72d63e5797cfaab873abbe8e700e912"
+
+tryor@~0.1.2:
+  version "0.1.2"
+  resolved "https://registry.yarnpkg.com/tryor/-/tryor-0.1.2.tgz#8145e4ca7caff40acde3ccf946e8b8bb75b4172b"
+
+tty-browserify@0.0.0:
+  version "0.0.0"
+  resolved "https://registry.yarnpkg.com/tty-browserify/-/tty-browserify-0.0.0.tgz#a157ba402da24e9bf957f9aa69d524eed42901a6"
+
+tunnel-agent@^0.6.0:
+  version "0.6.0"
+  resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd"
+  dependencies:
+    safe-buffer "^5.0.1"
+
+tweetnacl@^0.14.3, tweetnacl@~0.14.0:
+  version "0.14.5"
+  resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64"
+
+type-check@~0.3.1:
+  version "0.3.2"
+  resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72"
+  dependencies:
+    prelude-ls "~1.1.2"
+
+type-is@~1.6.15, type-is@~1.6.16:
+  version "1.6.16"
+  resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.16.tgz#f89ce341541c672b25ee7ae3c73dee3b2be50194"
+  dependencies:
+    media-typer "0.3.0"
+    mime-types "~2.1.18"
+
+typedarray@^0.0.6:
+  version "0.0.6"
+  resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
+
+ua-parser-js@^0.7.18:
+  version "0.7.18"
+  resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.18.tgz#a7bfd92f56edfb117083b69e31d2aa8882d4b1ed"
+
+uglify-js@^2.6:
+  version "2.8.29"
+  resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-2.8.29.tgz#29c5733148057bb4e1f75df35b7a9cb72e6a59dd"
+  dependencies:
+    source-map "~0.5.1"
+    yargs "~3.10.0"
+  optionalDependencies:
+    uglify-to-browserify "~1.0.0"
+
+uglify-js@~2.6.0:
+  version "2.6.4"
+  resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-2.6.4.tgz#65ea2fb3059c9394692f15fed87c2b36c16b9adf"
+  dependencies:
+    async "~0.2.6"
+    source-map "~0.5.1"
+    uglify-to-browserify "~1.0.0"
+    yargs "~3.10.0"
+
+uglify-to-browserify@~1.0.0:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz#6e0924d6bda6b5afe349e39a6d632850a0f882b7"
+
+ultron@1.0.x:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/ultron/-/ultron-1.0.2.tgz#ace116ab557cd197386a4e88f4685378c8b2e4fa"
+
+uniq@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/uniq/-/uniq-1.0.1.tgz#b31c5ae8254844a3a8281541ce2b04b865a734ff"
+
+uniqs@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/uniqs/-/uniqs-2.0.0.tgz#ffede4b36b25290696e6e165d4a59edb998e6b02"
+
+unpipe@1.0.0, unpipe@~1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec"
+
+url@~0.10.1:
+  version "0.10.3"
+  resolved "https://registry.yarnpkg.com/url/-/url-0.10.3.tgz#021e4d9c7705f21bbf37d03ceb58767402774c64"
+  dependencies:
+    punycode "1.3.2"
+    querystring "0.2.0"
+
+user-home@^1.1.1:
+  version "1.1.1"
+  resolved "https://registry.yarnpkg.com/user-home/-/user-home-1.1.1.tgz#2b5be23a32b63a7c9deb8d0f28d485724a3df190"
+
+user-home@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/user-home/-/user-home-2.0.0.tgz#9c70bfd8169bc1dcbf48604e0f04b8b49cde9e9f"
+  dependencies:
+    os-homedir "^1.0.0"
+
+util-deprecate@~1.0.1:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
+
+util@0.10.3:
+  version "0.10.3"
+  resolved "https://registry.yarnpkg.com/util/-/util-0.10.3.tgz#7afb1afe50805246489e3db7fe0ed379336ac0f9"
+  dependencies:
+    inherits "2.0.1"
+
+util@~0.10.3:
+  version "0.10.4"
+  resolved "https://registry.yarnpkg.com/util/-/util-0.10.4.tgz#3aa0125bfe668a4672de58857d3ace27ecb76901"
+  dependencies:
+    inherits "2.0.3"
+
+utils-merge@1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713"
+
+uuid@^3.3.2:
+  version "3.3.2"
+  resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.2.tgz#1b4af4955eb3077c501c23872fc6513811587131"
+
+validate-npm-package-license@^3.0.1:
+  version "3.0.4"
+  resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a"
+  dependencies:
+    spdx-correct "^3.0.0"
+    spdx-expression-parse "^3.0.0"
+
+vary@~1.1.2:
+  version "1.1.2"
+  resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc"
+
+vendors@^1.0.0:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/vendors/-/vendors-1.0.2.tgz#7fcb5eef9f5623b156bcea89ec37d63676f21801"
+
+verror@1.10.0:
+  version "1.10.0"
+  resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400"
+  dependencies:
+    assert-plus "^1.0.0"
+    core-util-is "1.0.2"
+    extsprintf "^1.2.0"
+
+vm-browserify@0.0.4:
+  version "0.0.4"
+  resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-0.0.4.tgz#5d7ea45bbef9e4a6ff65f95438e0a87c357d5a73"
+  dependencies:
+    indexof "0.0.1"
+
+warning@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/warning/-/warning-3.0.0.tgz#32e5377cb572de4ab04753bdf8821c01ed605b7c"
+  dependencies:
+    loose-envify "^1.0.0"
+
+watchpack@^0.2.1:
+  version "0.2.9"
+  resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-0.2.9.tgz#62eaa4ab5e5ba35fdfc018275626e3c0f5e3fb0b"
+  dependencies:
+    async "^0.9.0"
+    chokidar "^1.0.0"
+    graceful-fs "^4.1.2"
+
+webpack-core@~0.6.0:
+  version "0.6.9"
+  resolved "https://registry.yarnpkg.com/webpack-core/-/webpack-core-0.6.9.tgz#fc571588c8558da77be9efb6debdc5a3b172bdc2"
+  dependencies:
+    source-list-map "~0.1.7"
+    source-map "~0.4.1"
+
+webpack-dev-middleware@^1.2.0:
+  version "1.12.2"
+  resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-1.12.2.tgz#f8fc1120ce3b4fc5680ceecb43d777966b21105e"
+  dependencies:
+    memory-fs "~0.4.1"
+    mime "^1.5.0"
+    path-is-absolute "^1.0.0"
+    range-parser "^1.0.3"
+    time-stamp "^2.0.0"
+
+webpack-dev-server@1.12.x:
+  version "1.12.1"
+  resolved "http://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-1.12.1.tgz#c6dc855520c8ee9cba9256241b3390c1348b0d5c"
+  dependencies:
+    compression "^1.5.2"
+    connect-history-api-fallback "1.1.0"
+    express "^4.13.3"
+    http-proxy "^1.11.2"
+    optimist "~0.6.0"
+    serve-index "^1.7.2"
+    socket.io "^1.3.6"
+    socket.io-client "^1.3.6"
+    stream-cache "~0.0.1"
+    strip-ansi "^3.0.0"
+    supports-color "^3.1.1"
+    webpack-dev-middleware "^1.2.0"
+
+webpack@1.12.x:
+  version "1.12.15"
+  resolved "https://registry.yarnpkg.com/webpack/-/webpack-1.12.15.tgz#d4611335a5d455269850aeb9b4ae74cc35192286"
+  dependencies:
+    async "^1.3.0"
+    clone "^1.0.2"
+    enhanced-resolve "~0.9.0"
+    esprima "^2.5.0"
+    interpret "^0.6.4"
+    loader-utils "^0.2.11"
+    memory-fs "~0.3.0"
+    mkdirp "~0.5.0"
+    node-libs-browser ">= 0.4.0 <=0.6.0"
+    optimist "~0.6.0"
+    supports-color "^3.1.0"
+    tapable "~0.1.8"
+    uglify-js "~2.6.0"
+    watchpack "^0.2.1"
+    webpack-core "~0.6.0"
+
+whatwg-fetch@>=0.10.0:
+  version "2.0.4"
+  resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-2.0.4.tgz#dde6a5df315f9d39991aa17621853d720b85566f"
+
+whet.extend@~0.9.9:
+  version "0.9.9"
+  resolved "https://registry.yarnpkg.com/whet.extend/-/whet.extend-0.9.9.tgz#f877d5bf648c97e5aa542fadc16d6a259b9c11a1"
+
+which-module@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/which-module/-/which-module-1.0.0.tgz#bba63ca861948994ff307736089e3b96026c2a4f"
+
+which@1, which@^1.2.9:
+  version "1.3.1"
+  resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a"
+  dependencies:
+    isexe "^2.0.0"
+
+wide-align@^1.1.0:
+  version "1.1.3"
+  resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457"
+  dependencies:
+    string-width "^1.0.2 || 2"
+
+window-size@0.1.0:
+  version "0.1.0"
+  resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.1.0.tgz#5438cd2ea93b202efa3a19fe8887aee7c94f9c9d"
+
+window-size@^0.1.2:
+  version "0.1.4"
+  resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.1.4.tgz#f8e1aa1ee5a53ec5bf151ffa09742a6ad7697876"
+
+wordwrap@0.0.2:
+  version "0.0.2"
+  resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.2.tgz#b79669bb42ecb409f83d583cad52ca17eaa1643f"
+
+wordwrap@~0.0.2:
+  version "0.0.3"
+  resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.3.tgz#a3d5da6cd5c0bc0008d37234bbaf1bed63059107"
+
+wrap-ansi@^2.0.0:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-2.1.0.tgz#d8fc3d284dd05794fe84973caecdd1cf824fdd85"
+  dependencies:
+    string-width "^1.0.1"
+    strip-ansi "^3.0.1"
+
+wrappy@1:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
+
+write@^0.2.1:
+  version "0.2.1"
+  resolved "https://registry.yarnpkg.com/write/-/write-0.2.1.tgz#5fc03828e264cea3fe91455476f7a3c566cb0757"
+  dependencies:
+    mkdirp "^0.5.1"
+
+ws@~1.1.5:
+  version "1.1.5"
+  resolved "https://registry.yarnpkg.com/ws/-/ws-1.1.5.tgz#cbd9e6e75e09fc5d2c90015f21f0c40875e0dd51"
+  dependencies:
+    options ">=0.0.5"
+    ultron "1.0.x"
+
+wtf-8@1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/wtf-8/-/wtf-8-1.0.0.tgz#392d8ba2d0f1c34d1ee2d630f15d0efb68e1048a"
+
+xml-escape@~1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/xml-escape/-/xml-escape-1.0.0.tgz#00963d697b2adf0c185c4e04e73174ba9b288eb2"
+
+xmlhttprequest-ssl@1.5.3:
+  version "1.5.3"
+  resolved "https://registry.yarnpkg.com/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.3.tgz#185a888c04eca46c3e4070d99f7b49de3528992d"
+
+xtend@^4.0.0:
+  version "4.0.1"
+  resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af"
+
+y18n@^3.2.0, y18n@^3.2.1:
+  version "3.2.1"
+  resolved "https://registry.yarnpkg.com/y18n/-/y18n-3.2.1.tgz#6d15fba884c08679c0d77e88e7759e811e07fa41"
+
+yallist@^2.1.2:
+  version "2.1.2"
+  resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52"
+
+yallist@^3.0.0, yallist@^3.0.2:
+  version "3.0.2"
+  resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.0.2.tgz#8452b4bb7e83c7c188d8041c1a837c773d6d8bb9"
+
+yargs-parser@^5.0.0:
+  version "5.0.0"
+  resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-5.0.0.tgz#275ecf0d7ffe05c77e64e7c86e4cd94bf0e1228a"
+  dependencies:
+    camelcase "^3.0.0"
+
+yargs@^7.0.0:
+  version "7.1.0"
+  resolved "https://registry.yarnpkg.com/yargs/-/yargs-7.1.0.tgz#6ba318eb16961727f5d284f8ea003e8d6154d0c8"
+  dependencies:
+    camelcase "^3.0.0"
+    cliui "^3.2.0"
+    decamelize "^1.1.1"
+    get-caller-file "^1.0.1"
+    os-locale "^1.4.0"
+    read-pkg-up "^1.0.1"
+    require-directory "^2.1.1"
+    require-main-filename "^1.0.1"
+    set-blocking "^2.0.0"
+    string-width "^1.0.2"
+    which-module "^1.0.0"
+    y18n "^3.2.1"
+    yargs-parser "^5.0.0"
+
+yargs@~3.10.0:
+  version "3.10.0"
+  resolved "https://registry.yarnpkg.com/yargs/-/yargs-3.10.0.tgz#f7ee7bd857dd7c1d2d38c0e74efbd681d1431fd1"
+  dependencies:
+    camelcase "^1.0.2"
+    cliui "^2.1.0"
+    decamelize "^1.0.0"
+    window-size "0.1.0"
+
+yargs@~3.27.0:
+  version "3.27.0"
+  resolved "https://registry.yarnpkg.com/yargs/-/yargs-3.27.0.tgz#21205469316e939131d59f2da0c6d7f98221ea40"
+  dependencies:
+    camelcase "^1.2.1"
+    cliui "^2.1.0"
+    decamelize "^1.0.0"
+    os-locale "^1.4.0"
+    window-size "^0.1.2"
+    y18n "^3.2.0"
+
+yeast@0.1.2:
+  version "0.1.2"
+  resolved "https://registry.yarnpkg.com/yeast/-/yeast-0.1.2.tgz#008e06d8094320c372dbc2f8ed76a0ca6c8ac419"
Index: node_modules/react-is/LICENSE
===================================================================
--- node_modules/react-is/LICENSE	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
+++ node_modules/react-is/LICENSE	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) Facebook, Inc. and its affiliates.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
Index: node_modules/react-is/README.md
===================================================================
--- node_modules/react-is/README.md	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
+++ node_modules/react-is/README.md	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
@@ -0,0 +1,104 @@
+# `react-is`
+
+This package allows you to test arbitrary values and see if they're a particular React element type.
+
+## Installation
+
+```sh
+# Yarn
+yarn add react-is
+
+# NPM
+npm install react-is
+```
+
+## Usage
+
+### Determining if a Component is Valid
+
+```js
+import React from "react";
+import * as ReactIs from "react-is";
+
+class ClassComponent extends React.Component {
+  render() {
+    return React.createElement("div");
+  }
+}
+
+const FunctionComponent = () => React.createElement("div");
+
+const ForwardRefComponent = React.forwardRef((props, ref) =>
+  React.createElement(Component, { forwardedRef: ref, ...props })
+);
+
+const Context = React.createContext(false);
+
+ReactIs.isValidElementType("div"); // true
+ReactIs.isValidElementType(ClassComponent); // true
+ReactIs.isValidElementType(FunctionComponent); // true
+ReactIs.isValidElementType(ForwardRefComponent); // true
+ReactIs.isValidElementType(Context.Provider); // true
+ReactIs.isValidElementType(Context.Consumer); // true
+ReactIs.isValidElementType(React.createFactory("div")); // true
+```
+
+### Determining an Element's Type
+
+#### Context
+
+```js
+import React from "react";
+import * as ReactIs from 'react-is';
+
+const ThemeContext = React.createContext("blue");
+
+ReactIs.isContextConsumer(<ThemeContext.Consumer />); // true
+ReactIs.isContextProvider(<ThemeContext.Provider />); // true
+ReactIs.typeOf(<ThemeContext.Provider />) === ReactIs.ContextProvider; // true
+ReactIs.typeOf(<ThemeContext.Consumer />) === ReactIs.ContextConsumer; // true
+```
+
+#### Element
+
+```js
+import React from "react";
+import * as ReactIs from 'react-is';
+
+ReactIs.isElement(<div />); // true
+ReactIs.typeOf(<div />) === ReactIs.Element; // true
+```
+
+#### Fragment
+
+```js
+import React from "react";
+import * as ReactIs from 'react-is';
+
+ReactIs.isFragment(<></>); // true
+ReactIs.typeOf(<></>) === ReactIs.Fragment; // true
+```
+
+#### Portal
+
+```js
+import React from "react";
+import ReactDOM from "react-dom";
+import * as ReactIs from 'react-is';
+
+const div = document.createElement("div");
+const portal = ReactDOM.createPortal(<div />, div);
+
+ReactIs.isPortal(portal); // true
+ReactIs.typeOf(portal) === ReactIs.Portal; // true
+```
+
+#### StrictMode
+
+```js
+import React from "react";
+import * as ReactIs from 'react-is';
+
+ReactIs.isStrictMode(<React.StrictMode />); // true
+ReactIs.typeOf(<React.StrictMode />) === ReactIs.StrictMode; // true
+```
Index: node_modules/react-is/build-info.json
===================================================================
--- node_modules/react-is/build-info.json	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
+++ node_modules/react-is/build-info.json	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
@@ -0,0 +1,8 @@
+{
+  "branch": "pull/18344",
+  "buildNumber": "106499",
+  "checksum": "7fe5a2e",
+  "commit": "da834083c",
+  "environment": "ci",
+  "reactVersion": "16.12.0-da834083c"
+}
Index: node_modules/react-is/cjs/react-is.development.js
===================================================================
--- node_modules/react-is/cjs/react-is.development.js	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
+++ node_modules/react-is/cjs/react-is.development.js	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
@@ -0,0 +1,181 @@
+/** @license React v16.13.1
+ * react-is.development.js
+ *
+ * Copyright (c) Facebook, Inc. and its affiliates.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+'use strict';
+
+
+
+if (process.env.NODE_ENV !== "production") {
+  (function() {
+'use strict';
+
+// The Symbol used to tag the ReactElement-like types. If there is no native Symbol
+// nor polyfill, then a plain number is used for performance.
+var hasSymbol = typeof Symbol === 'function' && Symbol.for;
+var REACT_ELEMENT_TYPE = hasSymbol ? Symbol.for('react.element') : 0xeac7;
+var REACT_PORTAL_TYPE = hasSymbol ? Symbol.for('react.portal') : 0xeaca;
+var REACT_FRAGMENT_TYPE = hasSymbol ? Symbol.for('react.fragment') : 0xeacb;
+var REACT_STRICT_MODE_TYPE = hasSymbol ? Symbol.for('react.strict_mode') : 0xeacc;
+var REACT_PROFILER_TYPE = hasSymbol ? Symbol.for('react.profiler') : 0xead2;
+var REACT_PROVIDER_TYPE = hasSymbol ? Symbol.for('react.provider') : 0xeacd;
+var REACT_CONTEXT_TYPE = hasSymbol ? Symbol.for('react.context') : 0xeace; // TODO: We don't use AsyncMode or ConcurrentMode anymore. They were temporary
+// (unstable) APIs that have been removed. Can we remove the symbols?
+
+var REACT_ASYNC_MODE_TYPE = hasSymbol ? Symbol.for('react.async_mode') : 0xeacf;
+var REACT_CONCURRENT_MODE_TYPE = hasSymbol ? Symbol.for('react.concurrent_mode') : 0xeacf;
+var REACT_FORWARD_REF_TYPE = hasSymbol ? Symbol.for('react.forward_ref') : 0xead0;
+var REACT_SUSPENSE_TYPE = hasSymbol ? Symbol.for('react.suspense') : 0xead1;
+var REACT_SUSPENSE_LIST_TYPE = hasSymbol ? Symbol.for('react.suspense_list') : 0xead8;
+var REACT_MEMO_TYPE = hasSymbol ? Symbol.for('react.memo') : 0xead3;
+var REACT_LAZY_TYPE = hasSymbol ? Symbol.for('react.lazy') : 0xead4;
+var REACT_BLOCK_TYPE = hasSymbol ? Symbol.for('react.block') : 0xead9;
+var REACT_FUNDAMENTAL_TYPE = hasSymbol ? Symbol.for('react.fundamental') : 0xead5;
+var REACT_RESPONDER_TYPE = hasSymbol ? Symbol.for('react.responder') : 0xead6;
+var REACT_SCOPE_TYPE = hasSymbol ? Symbol.for('react.scope') : 0xead7;
+
+function isValidElementType(type) {
+  return typeof type === 'string' || typeof type === 'function' || // Note: its typeof might be other than 'symbol' or 'number' if it's a polyfill.
+  type === REACT_FRAGMENT_TYPE || type === REACT_CONCURRENT_MODE_TYPE || type === REACT_PROFILER_TYPE || type === REACT_STRICT_MODE_TYPE || type === REACT_SUSPENSE_TYPE || type === REACT_SUSPENSE_LIST_TYPE || typeof type === 'object' && type !== null && (type.$$typeof === REACT_LAZY_TYPE || type.$$typeof === REACT_MEMO_TYPE || type.$$typeof === REACT_PROVIDER_TYPE || type.$$typeof === REACT_CONTEXT_TYPE || type.$$typeof === REACT_FORWARD_REF_TYPE || type.$$typeof === REACT_FUNDAMENTAL_TYPE || type.$$typeof === REACT_RESPONDER_TYPE || type.$$typeof === REACT_SCOPE_TYPE || type.$$typeof === REACT_BLOCK_TYPE);
+}
+
+function typeOf(object) {
+  if (typeof object === 'object' && object !== null) {
+    var $$typeof = object.$$typeof;
+
+    switch ($$typeof) {
+      case REACT_ELEMENT_TYPE:
+        var type = object.type;
+
+        switch (type) {
+          case REACT_ASYNC_MODE_TYPE:
+          case REACT_CONCURRENT_MODE_TYPE:
+          case REACT_FRAGMENT_TYPE:
+          case REACT_PROFILER_TYPE:
+          case REACT_STRICT_MODE_TYPE:
+          case REACT_SUSPENSE_TYPE:
+            return type;
+
+          default:
+            var $$typeofType = type && type.$$typeof;
+
+            switch ($$typeofType) {
+              case REACT_CONTEXT_TYPE:
+              case REACT_FORWARD_REF_TYPE:
+              case REACT_LAZY_TYPE:
+              case REACT_MEMO_TYPE:
+              case REACT_PROVIDER_TYPE:
+                return $$typeofType;
+
+              default:
+                return $$typeof;
+            }
+
+        }
+
+      case REACT_PORTAL_TYPE:
+        return $$typeof;
+    }
+  }
+
+  return undefined;
+} // AsyncMode is deprecated along with isAsyncMode
+
+var AsyncMode = REACT_ASYNC_MODE_TYPE;
+var ConcurrentMode = REACT_CONCURRENT_MODE_TYPE;
+var ContextConsumer = REACT_CONTEXT_TYPE;
+var ContextProvider = REACT_PROVIDER_TYPE;
+var Element = REACT_ELEMENT_TYPE;
+var ForwardRef = REACT_FORWARD_REF_TYPE;
+var Fragment = REACT_FRAGMENT_TYPE;
+var Lazy = REACT_LAZY_TYPE;
+var Memo = REACT_MEMO_TYPE;
+var Portal = REACT_PORTAL_TYPE;
+var Profiler = REACT_PROFILER_TYPE;
+var StrictMode = REACT_STRICT_MODE_TYPE;
+var Suspense = REACT_SUSPENSE_TYPE;
+var hasWarnedAboutDeprecatedIsAsyncMode = false; // AsyncMode should be deprecated
+
+function isAsyncMode(object) {
+  {
+    if (!hasWarnedAboutDeprecatedIsAsyncMode) {
+      hasWarnedAboutDeprecatedIsAsyncMode = true; // Using console['warn'] to evade Babel and ESLint
+
+      console['warn']('The ReactIs.isAsyncMode() alias has been deprecated, ' + 'and will be removed in React 17+. Update your code to use ' + 'ReactIs.isConcurrentMode() instead. It has the exact same API.');
+    }
+  }
+
+  return isConcurrentMode(object) || typeOf(object) === REACT_ASYNC_MODE_TYPE;
+}
+function isConcurrentMode(object) {
+  return typeOf(object) === REACT_CONCURRENT_MODE_TYPE;
+}
+function isContextConsumer(object) {
+  return typeOf(object) === REACT_CONTEXT_TYPE;
+}
+function isContextProvider(object) {
+  return typeOf(object) === REACT_PROVIDER_TYPE;
+}
+function isElement(object) {
+  return typeof object === 'object' && object !== null && object.$$typeof === REACT_ELEMENT_TYPE;
+}
+function isForwardRef(object) {
+  return typeOf(object) === REACT_FORWARD_REF_TYPE;
+}
+function isFragment(object) {
+  return typeOf(object) === REACT_FRAGMENT_TYPE;
+}
+function isLazy(object) {
+  return typeOf(object) === REACT_LAZY_TYPE;
+}
+function isMemo(object) {
+  return typeOf(object) === REACT_MEMO_TYPE;
+}
+function isPortal(object) {
+  return typeOf(object) === REACT_PORTAL_TYPE;
+}
+function isProfiler(object) {
+  return typeOf(object) === REACT_PROFILER_TYPE;
+}
+function isStrictMode(object) {
+  return typeOf(object) === REACT_STRICT_MODE_TYPE;
+}
+function isSuspense(object) {
+  return typeOf(object) === REACT_SUSPENSE_TYPE;
+}
+
+exports.AsyncMode = AsyncMode;
+exports.ConcurrentMode = ConcurrentMode;
+exports.ContextConsumer = ContextConsumer;
+exports.ContextProvider = ContextProvider;
+exports.Element = Element;
+exports.ForwardRef = ForwardRef;
+exports.Fragment = Fragment;
+exports.Lazy = Lazy;
+exports.Memo = Memo;
+exports.Portal = Portal;
+exports.Profiler = Profiler;
+exports.StrictMode = StrictMode;
+exports.Suspense = Suspense;
+exports.isAsyncMode = isAsyncMode;
+exports.isConcurrentMode = isConcurrentMode;
+exports.isContextConsumer = isContextConsumer;
+exports.isContextProvider = isContextProvider;
+exports.isElement = isElement;
+exports.isForwardRef = isForwardRef;
+exports.isFragment = isFragment;
+exports.isLazy = isLazy;
+exports.isMemo = isMemo;
+exports.isPortal = isPortal;
+exports.isProfiler = isProfiler;
+exports.isStrictMode = isStrictMode;
+exports.isSuspense = isSuspense;
+exports.isValidElementType = isValidElementType;
+exports.typeOf = typeOf;
+  })();
+}
Index: node_modules/react-is/cjs/react-is.production.min.js
===================================================================
--- node_modules/react-is/cjs/react-is.production.min.js	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
+++ node_modules/react-is/cjs/react-is.production.min.js	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
@@ -0,0 +1,15 @@
+/** @license React v16.13.1
+ * react-is.production.min.js
+ *
+ * Copyright (c) Facebook, Inc. and its affiliates.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+'use strict';var b="function"===typeof Symbol&&Symbol.for,c=b?Symbol.for("react.element"):60103,d=b?Symbol.for("react.portal"):60106,e=b?Symbol.for("react.fragment"):60107,f=b?Symbol.for("react.strict_mode"):60108,g=b?Symbol.for("react.profiler"):60114,h=b?Symbol.for("react.provider"):60109,k=b?Symbol.for("react.context"):60110,l=b?Symbol.for("react.async_mode"):60111,m=b?Symbol.for("react.concurrent_mode"):60111,n=b?Symbol.for("react.forward_ref"):60112,p=b?Symbol.for("react.suspense"):60113,q=b?
+Symbol.for("react.suspense_list"):60120,r=b?Symbol.for("react.memo"):60115,t=b?Symbol.for("react.lazy"):60116,v=b?Symbol.for("react.block"):60121,w=b?Symbol.for("react.fundamental"):60117,x=b?Symbol.for("react.responder"):60118,y=b?Symbol.for("react.scope"):60119;
+function z(a){if("object"===typeof a&&null!==a){var u=a.$$typeof;switch(u){case c:switch(a=a.type,a){case l:case m:case e:case g:case f:case p:return a;default:switch(a=a&&a.$$typeof,a){case k:case n:case t:case r:case h:return a;default:return u}}case d:return u}}}function A(a){return z(a)===m}exports.AsyncMode=l;exports.ConcurrentMode=m;exports.ContextConsumer=k;exports.ContextProvider=h;exports.Element=c;exports.ForwardRef=n;exports.Fragment=e;exports.Lazy=t;exports.Memo=r;exports.Portal=d;
+exports.Profiler=g;exports.StrictMode=f;exports.Suspense=p;exports.isAsyncMode=function(a){return A(a)||z(a)===l};exports.isConcurrentMode=A;exports.isContextConsumer=function(a){return z(a)===k};exports.isContextProvider=function(a){return z(a)===h};exports.isElement=function(a){return"object"===typeof a&&null!==a&&a.$$typeof===c};exports.isForwardRef=function(a){return z(a)===n};exports.isFragment=function(a){return z(a)===e};exports.isLazy=function(a){return z(a)===t};
+exports.isMemo=function(a){return z(a)===r};exports.isPortal=function(a){return z(a)===d};exports.isProfiler=function(a){return z(a)===g};exports.isStrictMode=function(a){return z(a)===f};exports.isSuspense=function(a){return z(a)===p};
+exports.isValidElementType=function(a){return"string"===typeof a||"function"===typeof a||a===e||a===m||a===g||a===f||a===p||a===q||"object"===typeof a&&null!==a&&(a.$$typeof===t||a.$$typeof===r||a.$$typeof===h||a.$$typeof===k||a.$$typeof===n||a.$$typeof===w||a.$$typeof===x||a.$$typeof===y||a.$$typeof===v)};exports.typeOf=z;
Index: node_modules/react-is/index.js
===================================================================
--- node_modules/react-is/index.js	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
+++ node_modules/react-is/index.js	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
@@ -0,0 +1,7 @@
+'use strict';
+
+if (process.env.NODE_ENV === 'production') {
+  module.exports = require('./cjs/react-is.production.min.js');
+} else {
+  module.exports = require('./cjs/react-is.development.js');
+}
Index: node_modules/react-is/package.json
===================================================================
--- node_modules/react-is/package.json	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
+++ node_modules/react-is/package.json	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
@@ -0,0 +1,27 @@
+{
+  "name": "react-is",
+  "version": "16.13.1",
+  "description": "Brand checking of React Elements.",
+  "main": "index.js",
+  "repository": {
+    "type": "git",
+    "url": "https://github.com/facebook/react.git",
+    "directory": "packages/react-is"
+  },
+  "keywords": [
+    "react"
+  ],
+  "license": "MIT",
+  "bugs": {
+    "url": "https://github.com/facebook/react/issues"
+  },
+  "homepage": "https://reactjs.org/",
+  "files": [
+    "LICENSE",
+    "README.md",
+    "build-info.json",
+    "index.js",
+    "cjs/",
+    "umd/"
+  ]
+}
Index: node_modules/react-is/umd/react-is.development.js
===================================================================
--- node_modules/react-is/umd/react-is.development.js	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
+++ node_modules/react-is/umd/react-is.development.js	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
@@ -0,0 +1,181 @@
+/** @license React v16.13.1
+ * react-is.development.js
+ *
+ * Copyright (c) Facebook, Inc. and its affiliates.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+'use strict';
+
+(function (global, factory) {
+  typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
+  typeof define === 'function' && define.amd ? define(['exports'], factory) :
+  (global = global || self, factory(global.ReactIs = {}));
+}(this, (function (exports) { 'use strict';
+
+  // The Symbol used to tag the ReactElement-like types. If there is no native Symbol
+  // nor polyfill, then a plain number is used for performance.
+  var hasSymbol = typeof Symbol === 'function' && Symbol.for;
+  var REACT_ELEMENT_TYPE = hasSymbol ? Symbol.for('react.element') : 0xeac7;
+  var REACT_PORTAL_TYPE = hasSymbol ? Symbol.for('react.portal') : 0xeaca;
+  var REACT_FRAGMENT_TYPE = hasSymbol ? Symbol.for('react.fragment') : 0xeacb;
+  var REACT_STRICT_MODE_TYPE = hasSymbol ? Symbol.for('react.strict_mode') : 0xeacc;
+  var REACT_PROFILER_TYPE = hasSymbol ? Symbol.for('react.profiler') : 0xead2;
+  var REACT_PROVIDER_TYPE = hasSymbol ? Symbol.for('react.provider') : 0xeacd;
+  var REACT_CONTEXT_TYPE = hasSymbol ? Symbol.for('react.context') : 0xeace; // TODO: We don't use AsyncMode or ConcurrentMode anymore. They were temporary
+  // (unstable) APIs that have been removed. Can we remove the symbols?
+
+  var REACT_ASYNC_MODE_TYPE = hasSymbol ? Symbol.for('react.async_mode') : 0xeacf;
+  var REACT_CONCURRENT_MODE_TYPE = hasSymbol ? Symbol.for('react.concurrent_mode') : 0xeacf;
+  var REACT_FORWARD_REF_TYPE = hasSymbol ? Symbol.for('react.forward_ref') : 0xead0;
+  var REACT_SUSPENSE_TYPE = hasSymbol ? Symbol.for('react.suspense') : 0xead1;
+  var REACT_SUSPENSE_LIST_TYPE = hasSymbol ? Symbol.for('react.suspense_list') : 0xead8;
+  var REACT_MEMO_TYPE = hasSymbol ? Symbol.for('react.memo') : 0xead3;
+  var REACT_LAZY_TYPE = hasSymbol ? Symbol.for('react.lazy') : 0xead4;
+  var REACT_BLOCK_TYPE = hasSymbol ? Symbol.for('react.block') : 0xead9;
+  var REACT_FUNDAMENTAL_TYPE = hasSymbol ? Symbol.for('react.fundamental') : 0xead5;
+  var REACT_RESPONDER_TYPE = hasSymbol ? Symbol.for('react.responder') : 0xead6;
+  var REACT_SCOPE_TYPE = hasSymbol ? Symbol.for('react.scope') : 0xead7;
+
+  function isValidElementType(type) {
+    return typeof type === 'string' || typeof type === 'function' || // Note: its typeof might be other than 'symbol' or 'number' if it's a polyfill.
+    type === REACT_FRAGMENT_TYPE || type === REACT_CONCURRENT_MODE_TYPE || type === REACT_PROFILER_TYPE || type === REACT_STRICT_MODE_TYPE || type === REACT_SUSPENSE_TYPE || type === REACT_SUSPENSE_LIST_TYPE || typeof type === 'object' && type !== null && (type.$$typeof === REACT_LAZY_TYPE || type.$$typeof === REACT_MEMO_TYPE || type.$$typeof === REACT_PROVIDER_TYPE || type.$$typeof === REACT_CONTEXT_TYPE || type.$$typeof === REACT_FORWARD_REF_TYPE || type.$$typeof === REACT_FUNDAMENTAL_TYPE || type.$$typeof === REACT_RESPONDER_TYPE || type.$$typeof === REACT_SCOPE_TYPE || type.$$typeof === REACT_BLOCK_TYPE);
+  }
+
+  function typeOf(object) {
+    if (typeof object === 'object' && object !== null) {
+      var $$typeof = object.$$typeof;
+
+      switch ($$typeof) {
+        case REACT_ELEMENT_TYPE:
+          var type = object.type;
+
+          switch (type) {
+            case REACT_ASYNC_MODE_TYPE:
+            case REACT_CONCURRENT_MODE_TYPE:
+            case REACT_FRAGMENT_TYPE:
+            case REACT_PROFILER_TYPE:
+            case REACT_STRICT_MODE_TYPE:
+            case REACT_SUSPENSE_TYPE:
+              return type;
+
+            default:
+              var $$typeofType = type && type.$$typeof;
+
+              switch ($$typeofType) {
+                case REACT_CONTEXT_TYPE:
+                case REACT_FORWARD_REF_TYPE:
+                case REACT_LAZY_TYPE:
+                case REACT_MEMO_TYPE:
+                case REACT_PROVIDER_TYPE:
+                  return $$typeofType;
+
+                default:
+                  return $$typeof;
+              }
+
+          }
+
+        case REACT_PORTAL_TYPE:
+          return $$typeof;
+      }
+    }
+
+    return undefined;
+  } // AsyncMode is deprecated along with isAsyncMode
+
+  var AsyncMode = REACT_ASYNC_MODE_TYPE;
+  var ConcurrentMode = REACT_CONCURRENT_MODE_TYPE;
+  var ContextConsumer = REACT_CONTEXT_TYPE;
+  var ContextProvider = REACT_PROVIDER_TYPE;
+  var Element = REACT_ELEMENT_TYPE;
+  var ForwardRef = REACT_FORWARD_REF_TYPE;
+  var Fragment = REACT_FRAGMENT_TYPE;
+  var Lazy = REACT_LAZY_TYPE;
+  var Memo = REACT_MEMO_TYPE;
+  var Portal = REACT_PORTAL_TYPE;
+  var Profiler = REACT_PROFILER_TYPE;
+  var StrictMode = REACT_STRICT_MODE_TYPE;
+  var Suspense = REACT_SUSPENSE_TYPE;
+  var hasWarnedAboutDeprecatedIsAsyncMode = false; // AsyncMode should be deprecated
+
+  function isAsyncMode(object) {
+    {
+      if (!hasWarnedAboutDeprecatedIsAsyncMode) {
+        hasWarnedAboutDeprecatedIsAsyncMode = true; // Using console['warn'] to evade Babel and ESLint
+
+        console['warn']('The ReactIs.isAsyncMode() alias has been deprecated, ' + 'and will be removed in React 17+. Update your code to use ' + 'ReactIs.isConcurrentMode() instead. It has the exact same API.');
+      }
+    }
+
+    return isConcurrentMode(object) || typeOf(object) === REACT_ASYNC_MODE_TYPE;
+  }
+  function isConcurrentMode(object) {
+    return typeOf(object) === REACT_CONCURRENT_MODE_TYPE;
+  }
+  function isContextConsumer(object) {
+    return typeOf(object) === REACT_CONTEXT_TYPE;
+  }
+  function isContextProvider(object) {
+    return typeOf(object) === REACT_PROVIDER_TYPE;
+  }
+  function isElement(object) {
+    return typeof object === 'object' && object !== null && object.$$typeof === REACT_ELEMENT_TYPE;
+  }
+  function isForwardRef(object) {
+    return typeOf(object) === REACT_FORWARD_REF_TYPE;
+  }
+  function isFragment(object) {
+    return typeOf(object) === REACT_FRAGMENT_TYPE;
+  }
+  function isLazy(object) {
+    return typeOf(object) === REACT_LAZY_TYPE;
+  }
+  function isMemo(object) {
+    return typeOf(object) === REACT_MEMO_TYPE;
+  }
+  function isPortal(object) {
+    return typeOf(object) === REACT_PORTAL_TYPE;
+  }
+  function isProfiler(object) {
+    return typeOf(object) === REACT_PROFILER_TYPE;
+  }
+  function isStrictMode(object) {
+    return typeOf(object) === REACT_STRICT_MODE_TYPE;
+  }
+  function isSuspense(object) {
+    return typeOf(object) === REACT_SUSPENSE_TYPE;
+  }
+
+  exports.AsyncMode = AsyncMode;
+  exports.ConcurrentMode = ConcurrentMode;
+  exports.ContextConsumer = ContextConsumer;
+  exports.ContextProvider = ContextProvider;
+  exports.Element = Element;
+  exports.ForwardRef = ForwardRef;
+  exports.Fragment = Fragment;
+  exports.Lazy = Lazy;
+  exports.Memo = Memo;
+  exports.Portal = Portal;
+  exports.Profiler = Profiler;
+  exports.StrictMode = StrictMode;
+  exports.Suspense = Suspense;
+  exports.isAsyncMode = isAsyncMode;
+  exports.isConcurrentMode = isConcurrentMode;
+  exports.isContextConsumer = isContextConsumer;
+  exports.isContextProvider = isContextProvider;
+  exports.isElement = isElement;
+  exports.isForwardRef = isForwardRef;
+  exports.isFragment = isFragment;
+  exports.isLazy = isLazy;
+  exports.isMemo = isMemo;
+  exports.isPortal = isPortal;
+  exports.isProfiler = isProfiler;
+  exports.isStrictMode = isStrictMode;
+  exports.isSuspense = isSuspense;
+  exports.isValidElementType = isValidElementType;
+  exports.typeOf = typeOf;
+
+})));
Index: node_modules/react-is/umd/react-is.production.min.js
===================================================================
--- node_modules/react-is/umd/react-is.production.min.js	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
+++ node_modules/react-is/umd/react-is.production.min.js	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
@@ -0,0 +1,13 @@
+/** @license React v16.13.1
+ * react-is.production.min.js
+ *
+ * Copyright (c) Facebook, Inc. and its affiliates.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+'use strict';(function(b,d){"object"===typeof exports&&"undefined"!==typeof module?d(exports):"function"===typeof define&&define.amd?define(["exports"],d):(b=b||self,d(b.ReactIs={}))})(this,function(b){function d(a){if("object"===typeof a&&null!==a){var b=a.$$typeof;switch(b){case r:switch(a=a.type,a){case t:case e:case f:case g:case h:case k:return a;default:switch(a=a&&a.$$typeof,a){case l:case m:case n:case p:case q:return a;default:return b}}case u:return b}}}function v(a){return d(a)===e}var c=
+"function"===typeof Symbol&&Symbol.for,r=c?Symbol.for("react.element"):60103,u=c?Symbol.for("react.portal"):60106,f=c?Symbol.for("react.fragment"):60107,h=c?Symbol.for("react.strict_mode"):60108,g=c?Symbol.for("react.profiler"):60114,q=c?Symbol.for("react.provider"):60109,l=c?Symbol.for("react.context"):60110,t=c?Symbol.for("react.async_mode"):60111,e=c?Symbol.for("react.concurrent_mode"):60111,m=c?Symbol.for("react.forward_ref"):60112,k=c?Symbol.for("react.suspense"):60113,w=c?Symbol.for("react.suspense_list"):
+60120,p=c?Symbol.for("react.memo"):60115,n=c?Symbol.for("react.lazy"):60116,x=c?Symbol.for("react.block"):60121,y=c?Symbol.for("react.fundamental"):60117,z=c?Symbol.for("react.responder"):60118,A=c?Symbol.for("react.scope"):60119;b.AsyncMode=t;b.ConcurrentMode=e;b.ContextConsumer=l;b.ContextProvider=q;b.Element=r;b.ForwardRef=m;b.Fragment=f;b.Lazy=n;b.Memo=p;b.Portal=u;b.Profiler=g;b.StrictMode=h;b.Suspense=k;b.isAsyncMode=function(a){return v(a)||d(a)===t};b.isConcurrentMode=v;b.isContextConsumer=
+function(a){return d(a)===l};b.isContextProvider=function(a){return d(a)===q};b.isElement=function(a){return"object"===typeof a&&null!==a&&a.$$typeof===r};b.isForwardRef=function(a){return d(a)===m};b.isFragment=function(a){return d(a)===f};b.isLazy=function(a){return d(a)===n};b.isMemo=function(a){return d(a)===p};b.isPortal=function(a){return d(a)===u};b.isProfiler=function(a){return d(a)===g};b.isStrictMode=function(a){return d(a)===h};b.isSuspense=function(a){return d(a)===k};b.isValidElementType=
+function(a){return"string"===typeof a||"function"===typeof a||a===f||a===e||a===g||a===h||a===k||a===w||"object"===typeof a&&null!==a&&(a.$$typeof===n||a.$$typeof===p||a.$$typeof===q||a.$$typeof===l||a.$$typeof===m||a.$$typeof===y||a.$$typeof===z||a.$$typeof===A||a.$$typeof===x)};b.typeOf=d});
Index: node_modules/react/LICENSE
===================================================================
--- node_modules/react/LICENSE	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
+++ node_modules/react/LICENSE	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) Facebook, Inc. and its affiliates.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
Index: node_modules/react/README.md
===================================================================
--- node_modules/react/README.md	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
+++ node_modules/react/README.md	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
@@ -0,0 +1,13 @@
+# `react`
+
+React is a JavaScript library for creating user interfaces.
+
+The `react` package contains only the functionality necessary to define React components. It is typically used together with a React renderer like `react-dom` for the web, or `react-native` for the native environments.
+
+**Note:** by default, React will be in development mode. The development version includes extra warnings about common mistakes, whereas the production version includes extra performance optimizations and strips all error messages. Don't forget to use the [production build](https://reactjs.org/docs/optimizing-performance.html#use-the-production-build) when deploying your application.
+
+## Example Usage
+
+```js
+var React = require('react');
+```
Index: node_modules/react/build-info.json
===================================================================
--- node_modules/react/build-info.json	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
+++ node_modules/react/build-info.json	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
@@ -0,0 +1,8 @@
+{
+  "branch": "pull/18344",
+  "buildNumber": "106499",
+  "checksum": "7fe5a2e",
+  "commit": "da834083c",
+  "environment": "ci",
+  "reactVersion": "16.12.0-da834083c"
+}
Index: node_modules/react/cjs/react-jsx-dev-runtime.development.js
===================================================================
--- node_modules/react/cjs/react-jsx-dev-runtime.development.js	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
+++ node_modules/react/cjs/react-jsx-dev-runtime.development.js	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
@@ -0,0 +1,889 @@
+/** @license React v16.14.0
+ * react-jsx-dev-runtime.development.js
+ *
+ * Copyright (c) Facebook, Inc. and its affiliates.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+'use strict';
+
+if (process.env.NODE_ENV !== "production") {
+  (function() {
+'use strict';
+
+var React = require('react');
+
+// ATTENTION
+// When adding new symbols to this file,
+// Please consider also adding to 'react-devtools-shared/src/backend/ReactSymbols'
+// The Symbol used to tag the ReactElement-like types. If there is no native Symbol
+// nor polyfill, then a plain number is used for performance.
+var REACT_ELEMENT_TYPE = 0xeac7;
+var REACT_PORTAL_TYPE = 0xeaca;
+exports.Fragment = 0xeacb;
+var REACT_STRICT_MODE_TYPE = 0xeacc;
+var REACT_PROFILER_TYPE = 0xead2;
+var REACT_PROVIDER_TYPE = 0xeacd;
+var REACT_CONTEXT_TYPE = 0xeace;
+var REACT_FORWARD_REF_TYPE = 0xead0;
+var REACT_SUSPENSE_TYPE = 0xead1;
+var REACT_SUSPENSE_LIST_TYPE = 0xead8;
+var REACT_MEMO_TYPE = 0xead3;
+var REACT_LAZY_TYPE = 0xead4;
+var REACT_BLOCK_TYPE = 0xead9;
+var REACT_SERVER_BLOCK_TYPE = 0xeada;
+var REACT_FUNDAMENTAL_TYPE = 0xead5;
+var REACT_SCOPE_TYPE = 0xead7;
+var REACT_OPAQUE_ID_TYPE = 0xeae0;
+var REACT_DEBUG_TRACING_MODE_TYPE = 0xeae1;
+var REACT_OFFSCREEN_TYPE = 0xeae2;
+var REACT_LEGACY_HIDDEN_TYPE = 0xeae3;
+
+if (typeof Symbol === 'function' && Symbol.for) {
+  var symbolFor = Symbol.for;
+  REACT_ELEMENT_TYPE = symbolFor('react.element');
+  REACT_PORTAL_TYPE = symbolFor('react.portal');
+  exports.Fragment = symbolFor('react.fragment');
+  REACT_STRICT_MODE_TYPE = symbolFor('react.strict_mode');
+  REACT_PROFILER_TYPE = symbolFor('react.profiler');
+  REACT_PROVIDER_TYPE = symbolFor('react.provider');
+  REACT_CONTEXT_TYPE = symbolFor('react.context');
+  REACT_FORWARD_REF_TYPE = symbolFor('react.forward_ref');
+  REACT_SUSPENSE_TYPE = symbolFor('react.suspense');
+  REACT_SUSPENSE_LIST_TYPE = symbolFor('react.suspense_list');
+  REACT_MEMO_TYPE = symbolFor('react.memo');
+  REACT_LAZY_TYPE = symbolFor('react.lazy');
+  REACT_BLOCK_TYPE = symbolFor('react.block');
+  REACT_SERVER_BLOCK_TYPE = symbolFor('react.server.block');
+  REACT_FUNDAMENTAL_TYPE = symbolFor('react.fundamental');
+  REACT_SCOPE_TYPE = symbolFor('react.scope');
+  REACT_OPAQUE_ID_TYPE = symbolFor('react.opaque.id');
+  REACT_DEBUG_TRACING_MODE_TYPE = symbolFor('react.debug_trace_mode');
+  REACT_OFFSCREEN_TYPE = symbolFor('react.offscreen');
+  REACT_LEGACY_HIDDEN_TYPE = symbolFor('react.legacy_hidden');
+}
+
+var MAYBE_ITERATOR_SYMBOL = typeof Symbol === 'function' && Symbol.iterator;
+var FAUX_ITERATOR_SYMBOL = '@@iterator';
+function getIteratorFn(maybeIterable) {
+  if (maybeIterable === null || typeof maybeIterable !== 'object') {
+    return null;
+  }
+
+  var maybeIterator = MAYBE_ITERATOR_SYMBOL && maybeIterable[MAYBE_ITERATOR_SYMBOL] || maybeIterable[FAUX_ITERATOR_SYMBOL];
+
+  if (typeof maybeIterator === 'function') {
+    return maybeIterator;
+  }
+
+  return null;
+}
+
+var ReactSharedInternals = React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED;
+
+function error(format) {
+  {
+    for (var _len2 = arguments.length, args = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {
+      args[_key2 - 1] = arguments[_key2];
+    }
+
+    printWarning('error', format, args);
+  }
+}
+
+function printWarning(level, format, args) {
+  // When changing this logic, you might want to also
+  // update consoleWithStackDev.www.js as well.
+  {
+    var ReactDebugCurrentFrame = ReactSharedInternals.ReactDebugCurrentFrame;
+    var stack = '';
+
+    if (currentlyValidatingElement) {
+      var name = getComponentName(currentlyValidatingElement.type);
+      var owner = currentlyValidatingElement._owner;
+      stack += describeComponentFrame(name, currentlyValidatingElement._source, owner && getComponentName(owner.type));
+    }
+
+    stack += ReactDebugCurrentFrame.getStackAddendum();
+
+
+    if (stack !== '') {
+      format += '%s';
+      args = args.concat([stack]);
+    }
+
+    var argsWithFormat = args.map(function (item) {
+      return '' + item;
+    }); // Careful: RN currently depends on this prefix
+
+    argsWithFormat.unshift('Warning: ' + format); // We intentionally don't use spread (or .apply) directly because it
+    // breaks IE9: https://github.com/facebook/react/issues/13610
+    // eslint-disable-next-line react-internal/no-production-logging
+
+    Function.prototype.apply.call(console[level], console, argsWithFormat);
+  }
+}
+
+// Filter certain DOM attributes (e.g. src, href) if their values are empty strings.
+
+var enableScopeAPI = false; // Experimental Create Event Handle API.
+
+function isValidElementType(type) {
+  if (typeof type === 'string' || typeof type === 'function') {
+    return true;
+  } // Note: typeof might be other than 'symbol' or 'number' (e.g. if it's a polyfill).
+
+
+  if (type === exports.Fragment || type === REACT_PROFILER_TYPE || type === REACT_DEBUG_TRACING_MODE_TYPE || type === REACT_STRICT_MODE_TYPE || type === REACT_SUSPENSE_TYPE || type === REACT_SUSPENSE_LIST_TYPE || type === REACT_LEGACY_HIDDEN_TYPE || enableScopeAPI ) {
+    return true;
+  }
+
+  if (typeof type === 'object' && type !== null) {
+    if (type.$$typeof === REACT_LAZY_TYPE || type.$$typeof === REACT_MEMO_TYPE || type.$$typeof === REACT_PROVIDER_TYPE || type.$$typeof === REACT_CONTEXT_TYPE || type.$$typeof === REACT_FORWARD_REF_TYPE || type.$$typeof === REACT_FUNDAMENTAL_TYPE || type.$$typeof === REACT_BLOCK_TYPE || type[0] === REACT_SERVER_BLOCK_TYPE) {
+      return true;
+    }
+  }
+
+  return false;
+}
+var BEFORE_SLASH_RE = /^(.*)[\\\/]/;
+function describeComponentFrame (name, source, ownerName) {
+  var sourceInfo = '';
+
+  if (source) {
+    var path = source.fileName;
+    var fileName = path.replace(BEFORE_SLASH_RE, '');
+
+    {
+      // In DEV, include code for a common special case:
+      // prefer "folder/index.js" instead of just "index.js".
+      if (/^index\./.test(fileName)) {
+        var match = path.match(BEFORE_SLASH_RE);
+
+        if (match) {
+          var pathBeforeSlash = match[1];
+
+          if (pathBeforeSlash) {
+            var folderName = pathBeforeSlash.replace(BEFORE_SLASH_RE, '');
+            fileName = folderName + '/' + fileName;
+          }
+        }
+      }
+    }
+
+    sourceInfo = ' (at ' + fileName + ':' + source.lineNumber + ')';
+  } else if (ownerName) {
+    sourceInfo = ' (created by ' + ownerName + ')';
+  }
+
+  return '\n    in ' + (name || 'Unknown') + sourceInfo;
+}
+
+var Resolved = 1;
+function refineResolvedLazyComponent(lazyComponent) {
+  return lazyComponent._status === Resolved ? lazyComponent._result : null;
+}
+
+function getWrappedName(outerType, innerType, wrapperName) {
+  var functionName = innerType.displayName || innerType.name || '';
+  return outerType.displayName || (functionName !== '' ? wrapperName + "(" + functionName + ")" : wrapperName);
+}
+
+function getComponentName(type) {
+  if (type == null) {
+    // Host root, text node or just invalid type.
+    return null;
+  }
+
+  {
+    if (typeof type.tag === 'number') {
+      error('Received an unexpected object in getComponentName(). ' + 'This is likely a bug in React. Please file an issue.');
+    }
+  }
+
+  if (typeof type === 'function') {
+    return type.displayName || type.name || null;
+  }
+
+  if (typeof type === 'string') {
+    return type;
+  }
+
+  switch (type) {
+    case exports.Fragment:
+      return 'Fragment';
+
+    case REACT_PORTAL_TYPE:
+      return 'Portal';
+
+    case REACT_PROFILER_TYPE:
+      return "Profiler";
+
+    case REACT_STRICT_MODE_TYPE:
+      return 'StrictMode';
+
+    case REACT_SUSPENSE_TYPE:
+      return 'Suspense';
+
+    case REACT_SUSPENSE_LIST_TYPE:
+      return 'SuspenseList';
+  }
+
+  if (typeof type === 'object') {
+    switch (type.$$typeof) {
+      case REACT_CONTEXT_TYPE:
+        return 'Context.Consumer';
+
+      case REACT_PROVIDER_TYPE:
+        return 'Context.Provider';
+
+      case REACT_FORWARD_REF_TYPE:
+        return getWrappedName(type, type.render, 'ForwardRef');
+
+      case REACT_MEMO_TYPE:
+        return getComponentName(type.type);
+
+      case REACT_BLOCK_TYPE:
+        return getComponentName(type.render);
+
+      case REACT_LAZY_TYPE:
+        {
+          var thenable = type;
+          var resolvedThenable = refineResolvedLazyComponent(thenable);
+
+          if (resolvedThenable) {
+            return getComponentName(resolvedThenable);
+          }
+
+          break;
+        }
+    }
+  }
+
+  return null;
+}
+var loggedTypeFailures = {};
+var ReactDebugCurrentFrame = ReactSharedInternals.ReactDebugCurrentFrame;
+var currentlyValidatingElement = null;
+
+function setCurrentlyValidatingElement(element) {
+  currentlyValidatingElement = element;
+}
+
+function checkPropTypes(typeSpecs, values, location, componentName, element) {
+  {
+    // $FlowFixMe This is okay but Flow doesn't know it.
+    var has = Function.call.bind(Object.prototype.hasOwnProperty);
+
+    for (var typeSpecName in typeSpecs) {
+      if (has(typeSpecs, typeSpecName)) {
+        var error$1 = void 0; // Prop type validation may throw. In case they do, we don't want to
+        // fail the render phase where it didn't fail before. So we log it.
+        // After these have been cleaned up, we'll let them throw.
+
+        try {
+          // This is intentionally an invariant that gets caught. It's the same
+          // behavior as without this statement except with a better message.
+          if (typeof typeSpecs[typeSpecName] !== 'function') {
+            var err = Error((componentName || 'React class') + ': ' + location + ' type `' + typeSpecName + '` is invalid; ' + 'it must be a function, usually from the `prop-types` package, but received `' + typeof typeSpecs[typeSpecName] + '`.' + 'This often happens because of typos such as `PropTypes.function` instead of `PropTypes.func`.');
+            err.name = 'Invariant Violation';
+            throw err;
+          }
+
+          error$1 = typeSpecs[typeSpecName](values, typeSpecName, componentName, location, null, 'SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED');
+        } catch (ex) {
+          error$1 = ex;
+        }
+
+        if (error$1 && !(error$1 instanceof Error)) {
+          setCurrentlyValidatingElement(element);
+
+          error('%s: type specification of %s' + ' `%s` is invalid; the type checker ' + 'function must return `null` or an `Error` but returned a %s. ' + 'You may have forgotten to pass an argument to the type checker ' + 'creator (arrayOf, instanceOf, objectOf, oneOf, oneOfType, and ' + 'shape all require an argument).', componentName || 'React class', location, typeSpecName, typeof error$1);
+
+          setCurrentlyValidatingElement(null);
+        }
+
+        if (error$1 instanceof Error && !(error$1.message in loggedTypeFailures)) {
+          // Only monitor this failure once because there tends to be a lot of the
+          // same error.
+          loggedTypeFailures[error$1.message] = true;
+          setCurrentlyValidatingElement(element);
+
+          error('Failed %s type: %s', location, error$1.message);
+
+          setCurrentlyValidatingElement(null);
+        }
+      }
+    }
+  }
+}
+
+var ReactCurrentOwner = ReactSharedInternals.ReactCurrentOwner;
+var hasOwnProperty = Object.prototype.hasOwnProperty;
+var RESERVED_PROPS = {
+  key: true,
+  ref: true,
+  __self: true,
+  __source: true
+};
+var specialPropKeyWarningShown;
+var specialPropRefWarningShown;
+var didWarnAboutStringRefs;
+
+{
+  didWarnAboutStringRefs = {};
+}
+
+function hasValidRef(config) {
+  {
+    if (hasOwnProperty.call(config, 'ref')) {
+      var getter = Object.getOwnPropertyDescriptor(config, 'ref').get;
+
+      if (getter && getter.isReactWarning) {
+        return false;
+      }
+    }
+  }
+
+  return config.ref !== undefined;
+}
+
+function hasValidKey(config) {
+  {
+    if (hasOwnProperty.call(config, 'key')) {
+      var getter = Object.getOwnPropertyDescriptor(config, 'key').get;
+
+      if (getter && getter.isReactWarning) {
+        return false;
+      }
+    }
+  }
+
+  return config.key !== undefined;
+}
+
+function warnIfStringRefCannotBeAutoConverted(config, self) {
+  {
+    if (typeof config.ref === 'string' && ReactCurrentOwner.current && self && ReactCurrentOwner.current.stateNode !== self) {
+      var componentName = getComponentName(ReactCurrentOwner.current.type);
+
+      if (!didWarnAboutStringRefs[componentName]) {
+        error('Component "%s" contains the string ref "%s". ' + 'Support for string refs will be removed in a future major release. ' + 'This case cannot be automatically converted to an arrow function. ' + 'We ask you to manually fix this case by using useRef() or createRef() instead. ' + 'Learn more about using refs safely here: ' + 'https://reactjs.org/link/strict-mode-string-ref', getComponentName(ReactCurrentOwner.current.type), config.ref);
+
+        didWarnAboutStringRefs[componentName] = true;
+      }
+    }
+  }
+}
+
+function defineKeyPropWarningGetter(props, displayName) {
+  {
+    var warnAboutAccessingKey = function () {
+      if (!specialPropKeyWarningShown) {
+        specialPropKeyWarningShown = true;
+
+        error('%s: `key` is not a prop. Trying to access it will result ' + 'in `undefined` being returned. If you need to access the same ' + 'value within the child component, you should pass it as a different ' + 'prop. (https://reactjs.org/link/special-props)', displayName);
+      }
+    };
+
+    warnAboutAccessingKey.isReactWarning = true;
+    Object.defineProperty(props, 'key', {
+      get: warnAboutAccessingKey,
+      configurable: true
+    });
+  }
+}
+
+function defineRefPropWarningGetter(props, displayName) {
+  {
+    var warnAboutAccessingRef = function () {
+      if (!specialPropRefWarningShown) {
+        specialPropRefWarningShown = true;
+
+        error('%s: `ref` is not a prop. Trying to access it will result ' + 'in `undefined` being returned. If you need to access the same ' + 'value within the child component, you should pass it as a different ' + 'prop. (https://reactjs.org/link/special-props)', displayName);
+      }
+    };
+
+    warnAboutAccessingRef.isReactWarning = true;
+    Object.defineProperty(props, 'ref', {
+      get: warnAboutAccessingRef,
+      configurable: true
+    });
+  }
+}
+/**
+ * Factory method to create a new React element. This no longer adheres to
+ * the class pattern, so do not use new to call it. Also, instanceof check
+ * will not work. Instead test $$typeof field against Symbol.for('react.element') to check
+ * if something is a React Element.
+ *
+ * @param {*} type
+ * @param {*} props
+ * @param {*} key
+ * @param {string|object} ref
+ * @param {*} owner
+ * @param {*} self A *temporary* helper to detect places where `this` is
+ * different from the `owner` when React.createElement is called, so that we
+ * can warn. We want to get rid of owner and replace string `ref`s with arrow
+ * functions, and as long as `this` and owner are the same, there will be no
+ * change in behavior.
+ * @param {*} source An annotation object (added by a transpiler or otherwise)
+ * indicating filename, line number, and/or other information.
+ * @internal
+ */
+
+
+var ReactElement = function (type, key, ref, self, source, owner, props) {
+  var element = {
+    // This tag allows us to uniquely identify this as a React Element
+    $$typeof: REACT_ELEMENT_TYPE,
+    // Built-in properties that belong on the element
+    type: type,
+    key: key,
+    ref: ref,
+    props: props,
+    // Record the component responsible for creating this element.
+    _owner: owner
+  };
+
+  {
+    // The validation flag is currently mutative. We put it on
+    // an external backing store so that we can freeze the whole object.
+    // This can be replaced with a WeakMap once they are implemented in
+    // commonly used development environments.
+    element._store = {}; // To make comparing ReactElements easier for testing purposes, we make
+    // the validation flag non-enumerable (where possible, which should
+    // include every environment we run tests in), so the test framework
+    // ignores it.
+
+    Object.defineProperty(element._store, 'validated', {
+      configurable: false,
+      enumerable: false,
+      writable: true,
+      value: false
+    }); // self and source are DEV only properties.
+
+    Object.defineProperty(element, '_self', {
+      configurable: false,
+      enumerable: false,
+      writable: false,
+      value: self
+    }); // Two elements created in two different places should be considered
+    // equal for testing purposes and therefore we hide it from enumeration.
+
+    Object.defineProperty(element, '_source', {
+      configurable: false,
+      enumerable: false,
+      writable: false,
+      value: source
+    });
+
+    if (Object.freeze) {
+      Object.freeze(element.props);
+      Object.freeze(element);
+    }
+  }
+
+  return element;
+};
+/**
+ * https://github.com/reactjs/rfcs/pull/107
+ * @param {*} type
+ * @param {object} props
+ * @param {string} key
+ */
+
+function jsxDEV(type, config, maybeKey, source, self) {
+  {
+    var propName; // Reserved names are extracted
+
+    var props = {};
+    var key = null;
+    var ref = null; // Currently, key can be spread in as a prop. This causes a potential
+    // issue if key is also explicitly declared (ie. <div {...props} key="Hi" />
+    // or <div key="Hi" {...props} /> ). We want to deprecate key spread,
+    // but as an intermediary step, we will use jsxDEV for everything except
+    // <div {...props} key="Hi" />, because we aren't currently able to tell if
+    // key is explicitly declared to be undefined or not.
+
+    if (maybeKey !== undefined) {
+      key = '' + maybeKey;
+    }
+
+    if (hasValidKey(config)) {
+      key = '' + config.key;
+    }
+
+    if (hasValidRef(config)) {
+      ref = config.ref;
+      warnIfStringRefCannotBeAutoConverted(config, self);
+    } // Remaining properties are added to a new props object
+
+
+    for (propName in config) {
+      if (hasOwnProperty.call(config, propName) && !RESERVED_PROPS.hasOwnProperty(propName)) {
+        props[propName] = config[propName];
+      }
+    } // Resolve default props
+
+
+    if (type && type.defaultProps) {
+      var defaultProps = type.defaultProps;
+
+      for (propName in defaultProps) {
+        if (props[propName] === undefined) {
+          props[propName] = defaultProps[propName];
+        }
+      }
+    }
+
+    if (key || ref) {
+      var displayName = typeof type === 'function' ? type.displayName || type.name || 'Unknown' : type;
+
+      if (key) {
+        defineKeyPropWarningGetter(props, displayName);
+      }
+
+      if (ref) {
+        defineRefPropWarningGetter(props, displayName);
+      }
+    }
+
+    return ReactElement(type, key, ref, self, source, ReactCurrentOwner.current, props);
+  }
+}
+
+var ReactCurrentOwner$1 = ReactSharedInternals.ReactCurrentOwner;
+var ReactDebugCurrentFrame$1 = ReactSharedInternals.ReactDebugCurrentFrame;
+
+function setCurrentlyValidatingElement$1(element) {
+  currentlyValidatingElement = element;
+}
+
+var propTypesMisspellWarningShown;
+
+{
+  propTypesMisspellWarningShown = false;
+}
+/**
+ * Verifies the object is a ReactElement.
+ * See https://reactjs.org/docs/react-api.html#isvalidelement
+ * @param {?object} object
+ * @return {boolean} True if `object` is a ReactElement.
+ * @final
+ */
+
+function isValidElement(object) {
+  {
+    return typeof object === 'object' && object !== null && object.$$typeof === REACT_ELEMENT_TYPE;
+  }
+}
+
+function getDeclarationErrorAddendum() {
+  {
+    if (ReactCurrentOwner$1.current) {
+      var name = getComponentName(ReactCurrentOwner$1.current.type);
+
+      if (name) {
+        return '\n\nCheck the render method of `' + name + '`.';
+      }
+    }
+
+    return '';
+  }
+}
+
+function getSourceInfoErrorAddendum(source) {
+  {
+    if (source !== undefined) {
+      var fileName = source.fileName.replace(/^.*[\\\/]/, '');
+      var lineNumber = source.lineNumber;
+      return '\n\nCheck your code at ' + fileName + ':' + lineNumber + '.';
+    }
+
+    return '';
+  }
+}
+/**
+ * Warn if there's no key explicitly set on dynamic arrays of children or
+ * object keys are not valid. This allows us to keep track of children between
+ * updates.
+ */
+
+
+var ownerHasKeyUseWarning = {};
+
+function getCurrentComponentErrorInfo(parentType) {
+  {
+    var info = getDeclarationErrorAddendum();
+
+    if (!info) {
+      var parentName = typeof parentType === 'string' ? parentType : parentType.displayName || parentType.name;
+
+      if (parentName) {
+        info = "\n\nCheck the top-level render call using <" + parentName + ">.";
+      }
+    }
+
+    return info;
+  }
+}
+/**
+ * Warn if the element doesn't have an explicit key assigned to it.
+ * This element is in an array. The array could grow and shrink or be
+ * reordered. All children that haven't already been validated are required to
+ * have a "key" property assigned to it. Error statuses are cached so a warning
+ * will only be shown once.
+ *
+ * @internal
+ * @param {ReactElement} element Element that requires a key.
+ * @param {*} parentType element's parent's type.
+ */
+
+
+function validateExplicitKey(element, parentType) {
+  {
+    if (!element._store || element._store.validated || element.key != null) {
+      return;
+    }
+
+    element._store.validated = true;
+    var currentComponentErrorInfo = getCurrentComponentErrorInfo(parentType);
+
+    if (ownerHasKeyUseWarning[currentComponentErrorInfo]) {
+      return;
+    }
+
+    ownerHasKeyUseWarning[currentComponentErrorInfo] = true; // Usually the current owner is the offender, but if it accepts children as a
+    // property, it may be the creator of the child that's responsible for
+    // assigning it a key.
+
+    var childOwner = '';
+
+    if (element && element._owner && element._owner !== ReactCurrentOwner$1.current) {
+      // Give the component that originally created this child.
+      childOwner = " It was passed a child from " + getComponentName(element._owner.type) + ".";
+    }
+
+    setCurrentlyValidatingElement$1(element);
+
+    error('Each child in a list should have a unique "key" prop.' + '%s%s See https://reactjs.org/link/warning-keys for more information.', currentComponentErrorInfo, childOwner);
+
+    setCurrentlyValidatingElement$1(null);
+  }
+}
+/**
+ * Ensure that every element either is passed in a static location, in an
+ * array with an explicit keys property defined, or in an object literal
+ * with valid key property.
+ *
+ * @internal
+ * @param {ReactNode} node Statically passed child of any type.
+ * @param {*} parentType node's parent's type.
+ */
+
+
+function validateChildKeys(node, parentType) {
+  {
+    if (typeof node !== 'object') {
+      return;
+    }
+
+    if (Array.isArray(node)) {
+      for (var i = 0; i < node.length; i++) {
+        var child = node[i];
+
+        if (isValidElement(child)) {
+          validateExplicitKey(child, parentType);
+        }
+      }
+    } else if (isValidElement(node)) {
+      // This element was passed in a valid location.
+      if (node._store) {
+        node._store.validated = true;
+      }
+    } else if (node) {
+      var iteratorFn = getIteratorFn(node);
+
+      if (typeof iteratorFn === 'function') {
+        // Entry iterators used to provide implicit keys,
+        // but now we print a separate warning for them later.
+        if (iteratorFn !== node.entries) {
+          var iterator = iteratorFn.call(node);
+          var step;
+
+          while (!(step = iterator.next()).done) {
+            if (isValidElement(step.value)) {
+              validateExplicitKey(step.value, parentType);
+            }
+          }
+        }
+      }
+    }
+  }
+}
+/**
+ * Given an element, validate that its props follow the propTypes definition,
+ * provided by the type.
+ *
+ * @param {ReactElement} element
+ */
+
+
+function validatePropTypes(element) {
+  {
+    var type = element.type;
+
+    if (type === null || type === undefined || typeof type === 'string') {
+      return;
+    }
+
+    var propTypes;
+
+    if (typeof type === 'function') {
+      propTypes = type.propTypes;
+    } else if (typeof type === 'object' && (type.$$typeof === REACT_FORWARD_REF_TYPE || // Note: Memo only checks outer props here.
+    // Inner props are checked in the reconciler.
+    type.$$typeof === REACT_MEMO_TYPE)) {
+      propTypes = type.propTypes;
+    } else {
+      return;
+    }
+
+    if (propTypes) {
+      // Intentionally inside to avoid triggering lazy initializers:
+      var name = getComponentName(type);
+      checkPropTypes(propTypes, element.props, 'prop', name, element);
+    } else if (type.PropTypes !== undefined && !propTypesMisspellWarningShown) {
+      propTypesMisspellWarningShown = true; // Intentionally inside to avoid triggering lazy initializers:
+
+      var _name = getComponentName(type);
+
+      error('Component %s declared `PropTypes` instead of `propTypes`. Did you misspell the property assignment?', _name || 'Unknown');
+    }
+
+    if (typeof type.getDefaultProps === 'function' && !type.getDefaultProps.isReactClassApproved) {
+      error('getDefaultProps is only used on classic React.createClass ' + 'definitions. Use a static property named `defaultProps` instead.');
+    }
+  }
+}
+/**
+ * Given a fragment, validate that it can only be provided with fragment props
+ * @param {ReactElement} fragment
+ */
+
+
+function validateFragmentProps(fragment) {
+  {
+    var keys = Object.keys(fragment.props);
+
+    for (var i = 0; i < keys.length; i++) {
+      var key = keys[i];
+
+      if (key !== 'children' && key !== 'key') {
+        setCurrentlyValidatingElement$1(fragment);
+
+        error('Invalid prop `%s` supplied to `React.Fragment`. ' + 'React.Fragment can only have `key` and `children` props.', key);
+
+        setCurrentlyValidatingElement$1(null);
+        break;
+      }
+    }
+
+    if (fragment.ref !== null) {
+      setCurrentlyValidatingElement$1(fragment);
+
+      error('Invalid attribute `ref` supplied to `React.Fragment`.');
+
+      setCurrentlyValidatingElement$1(null);
+    }
+  }
+}
+
+function jsxWithValidation(type, props, key, isStaticChildren, source, self) {
+  {
+    var validType = isValidElementType(type); // We warn in this case but don't throw. We expect the element creation to
+    // succeed and there will likely be errors in render.
+
+    if (!validType) {
+      var info = '';
+
+      if (type === undefined || typeof type === 'object' && type !== null && Object.keys(type).length === 0) {
+        info += ' You likely forgot to export your component from the file ' + "it's defined in, or you might have mixed up default and named imports.";
+      }
+
+      var sourceInfo = getSourceInfoErrorAddendum(source);
+
+      if (sourceInfo) {
+        info += sourceInfo;
+      } else {
+        info += getDeclarationErrorAddendum();
+      }
+
+      var typeString;
+
+      if (type === null) {
+        typeString = 'null';
+      } else if (Array.isArray(type)) {
+        typeString = 'array';
+      } else if (type !== undefined && type.$$typeof === REACT_ELEMENT_TYPE) {
+        typeString = "<" + (getComponentName(type.type) || 'Unknown') + " />";
+        info = ' Did you accidentally export a JSX literal instead of a component?';
+      } else {
+        typeString = typeof type;
+      }
+
+      error('React.jsx: type is invalid -- expected a string (for ' + 'built-in components) or a class/function (for composite ' + 'components) but got: %s.%s', typeString, info);
+    }
+
+    var element = jsxDEV(type, props, key, source, self); // The result can be nullish if a mock or a custom function is used.
+    // TODO: Drop this when these are no longer allowed as the type argument.
+
+    if (element == null) {
+      return element;
+    } // Skip key warning if the type isn't valid since our key validation logic
+    // doesn't expect a non-string/function type and can throw confusing errors.
+    // We don't want exception behavior to differ between dev and prod.
+    // (Rendering will throw with a helpful message and as soon as the type is
+    // fixed, the key warnings will appear.)
+
+
+    if (validType) {
+      var children = props.children;
+
+      if (children !== undefined) {
+        if (isStaticChildren) {
+          if (Array.isArray(children)) {
+            for (var i = 0; i < children.length; i++) {
+              validateChildKeys(children[i], type);
+            }
+
+            if (Object.freeze) {
+              Object.freeze(children);
+            }
+          } else {
+            error('React.jsx: Static children should always be an array. ' + 'You are likely explicitly calling React.jsxs or React.jsxDEV. ' + 'Use the Babel transform instead.');
+          }
+        } else {
+          validateChildKeys(children, type);
+        }
+      }
+    }
+
+    if (type === exports.Fragment) {
+      validateFragmentProps(element);
+    } else {
+      validatePropTypes(element);
+    }
+
+    return element;
+  }
+} // These two functions exist to still get child warnings in dev
+
+var jsxDEV$1 =  jsxWithValidation ;
+
+exports.jsxDEV = jsxDEV$1;
+  })();
+}
Index: node_modules/react/cjs/react-jsx-dev-runtime.production.min.js
===================================================================
--- node_modules/react/cjs/react-jsx-dev-runtime.production.min.js	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
+++ node_modules/react/cjs/react-jsx-dev-runtime.production.min.js	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
@@ -0,0 +1,9 @@
+/** @license React v16.14.0
+ * react-jsx-dev-runtime.production.min.js
+ *
+ * Copyright (c) Facebook, Inc. and its affiliates.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+'use strict';require("react");exports.Fragment=60107;if("function"===typeof Symbol&&Symbol.for){var a=Symbol.for;exports.Fragment=a("react.fragment")}exports.jsxDEV=void 0;
Index: node_modules/react/cjs/react-jsx-runtime.development.js
===================================================================
--- node_modules/react/cjs/react-jsx-runtime.development.js	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
+++ node_modules/react/cjs/react-jsx-runtime.development.js	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
@@ -0,0 +1,911 @@
+/** @license React v16.14.0
+ * react-jsx-runtime.development.js
+ *
+ * Copyright (c) Facebook, Inc. and its affiliates.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+'use strict';
+
+if (process.env.NODE_ENV !== "production") {
+  (function() {
+'use strict';
+
+var React = require('react');
+
+// ATTENTION
+// When adding new symbols to this file,
+// Please consider also adding to 'react-devtools-shared/src/backend/ReactSymbols'
+// The Symbol used to tag the ReactElement-like types. If there is no native Symbol
+// nor polyfill, then a plain number is used for performance.
+var REACT_ELEMENT_TYPE = 0xeac7;
+var REACT_PORTAL_TYPE = 0xeaca;
+exports.Fragment = 0xeacb;
+var REACT_STRICT_MODE_TYPE = 0xeacc;
+var REACT_PROFILER_TYPE = 0xead2;
+var REACT_PROVIDER_TYPE = 0xeacd;
+var REACT_CONTEXT_TYPE = 0xeace;
+var REACT_FORWARD_REF_TYPE = 0xead0;
+var REACT_SUSPENSE_TYPE = 0xead1;
+var REACT_SUSPENSE_LIST_TYPE = 0xead8;
+var REACT_MEMO_TYPE = 0xead3;
+var REACT_LAZY_TYPE = 0xead4;
+var REACT_BLOCK_TYPE = 0xead9;
+var REACT_SERVER_BLOCK_TYPE = 0xeada;
+var REACT_FUNDAMENTAL_TYPE = 0xead5;
+var REACT_SCOPE_TYPE = 0xead7;
+var REACT_OPAQUE_ID_TYPE = 0xeae0;
+var REACT_DEBUG_TRACING_MODE_TYPE = 0xeae1;
+var REACT_OFFSCREEN_TYPE = 0xeae2;
+var REACT_LEGACY_HIDDEN_TYPE = 0xeae3;
+
+if (typeof Symbol === 'function' && Symbol.for) {
+  var symbolFor = Symbol.for;
+  REACT_ELEMENT_TYPE = symbolFor('react.element');
+  REACT_PORTAL_TYPE = symbolFor('react.portal');
+  exports.Fragment = symbolFor('react.fragment');
+  REACT_STRICT_MODE_TYPE = symbolFor('react.strict_mode');
+  REACT_PROFILER_TYPE = symbolFor('react.profiler');
+  REACT_PROVIDER_TYPE = symbolFor('react.provider');
+  REACT_CONTEXT_TYPE = symbolFor('react.context');
+  REACT_FORWARD_REF_TYPE = symbolFor('react.forward_ref');
+  REACT_SUSPENSE_TYPE = symbolFor('react.suspense');
+  REACT_SUSPENSE_LIST_TYPE = symbolFor('react.suspense_list');
+  REACT_MEMO_TYPE = symbolFor('react.memo');
+  REACT_LAZY_TYPE = symbolFor('react.lazy');
+  REACT_BLOCK_TYPE = symbolFor('react.block');
+  REACT_SERVER_BLOCK_TYPE = symbolFor('react.server.block');
+  REACT_FUNDAMENTAL_TYPE = symbolFor('react.fundamental');
+  REACT_SCOPE_TYPE = symbolFor('react.scope');
+  REACT_OPAQUE_ID_TYPE = symbolFor('react.opaque.id');
+  REACT_DEBUG_TRACING_MODE_TYPE = symbolFor('react.debug_trace_mode');
+  REACT_OFFSCREEN_TYPE = symbolFor('react.offscreen');
+  REACT_LEGACY_HIDDEN_TYPE = symbolFor('react.legacy_hidden');
+}
+
+var MAYBE_ITERATOR_SYMBOL = typeof Symbol === 'function' && Symbol.iterator;
+var FAUX_ITERATOR_SYMBOL = '@@iterator';
+function getIteratorFn(maybeIterable) {
+  if (maybeIterable === null || typeof maybeIterable !== 'object') {
+    return null;
+  }
+
+  var maybeIterator = MAYBE_ITERATOR_SYMBOL && maybeIterable[MAYBE_ITERATOR_SYMBOL] || maybeIterable[FAUX_ITERATOR_SYMBOL];
+
+  if (typeof maybeIterator === 'function') {
+    return maybeIterator;
+  }
+
+  return null;
+}
+
+var ReactSharedInternals = React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED;
+
+function error(format) {
+  {
+    for (var _len2 = arguments.length, args = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {
+      args[_key2 - 1] = arguments[_key2];
+    }
+
+    printWarning('error', format, args);
+  }
+}
+
+function printWarning(level, format, args) {
+  // When changing this logic, you might want to also
+  // update consoleWithStackDev.www.js as well.
+  {
+    var ReactDebugCurrentFrame = ReactSharedInternals.ReactDebugCurrentFrame;
+    var stack = '';
+
+    if (currentlyValidatingElement) {
+      var name = getComponentName(currentlyValidatingElement.type);
+      var owner = currentlyValidatingElement._owner;
+      stack += describeComponentFrame(name, currentlyValidatingElement._source, owner && getComponentName(owner.type));
+    }
+
+    stack += ReactDebugCurrentFrame.getStackAddendum();
+
+    if (stack !== '') {
+      format += '%s';
+      args = args.concat([stack]);
+    }
+
+    var argsWithFormat = args.map(function (item) {
+      return '' + item;
+    }); // Careful: RN currently depends on this prefix
+
+    argsWithFormat.unshift('Warning: ' + format); // We intentionally don't use spread (or .apply) directly because it
+    // breaks IE9: https://github.com/facebook/react/issues/13610
+    // eslint-disable-next-line react-internal/no-production-logging
+
+    Function.prototype.apply.call(console[level], console, argsWithFormat);
+  }
+}
+
+// Filter certain DOM attributes (e.g. src, href) if their values are empty strings.
+
+var enableScopeAPI = false; // Experimental Create Event Handle API.
+
+function isValidElementType(type) {
+  if (typeof type === 'string' || typeof type === 'function') {
+    return true;
+  } // Note: typeof might be other than 'symbol' or 'number' (e.g. if it's a polyfill).
+
+
+  if (type === exports.Fragment || type === REACT_PROFILER_TYPE || type === REACT_DEBUG_TRACING_MODE_TYPE || type === REACT_STRICT_MODE_TYPE || type === REACT_SUSPENSE_TYPE || type === REACT_SUSPENSE_LIST_TYPE || type === REACT_LEGACY_HIDDEN_TYPE || enableScopeAPI ) {
+    return true;
+  }
+
+  if (typeof type === 'object' && type !== null) {
+    if (type.$$typeof === REACT_LAZY_TYPE || type.$$typeof === REACT_MEMO_TYPE || type.$$typeof === REACT_PROVIDER_TYPE || type.$$typeof === REACT_CONTEXT_TYPE || type.$$typeof === REACT_FORWARD_REF_TYPE || type.$$typeof === REACT_FUNDAMENTAL_TYPE || type.$$typeof === REACT_BLOCK_TYPE || type[0] === REACT_SERVER_BLOCK_TYPE) {
+      return true;
+    }
+  }
+
+  return false;
+}
+
+
+var BEFORE_SLASH_RE = /^(.*)[\\\/]/;
+function describeComponentFrame (name, source, ownerName) {
+  var sourceInfo = '';
+
+  if (source) {
+    var path = source.fileName;
+    var fileName = path.replace(BEFORE_SLASH_RE, '');
+
+    {
+      // In DEV, include code for a common special case:
+      // prefer "folder/index.js" instead of just "index.js".
+      if (/^index\./.test(fileName)) {
+        var match = path.match(BEFORE_SLASH_RE);
+
+        if (match) {
+          var pathBeforeSlash = match[1];
+
+          if (pathBeforeSlash) {
+            var folderName = pathBeforeSlash.replace(BEFORE_SLASH_RE, '');
+            fileName = folderName + '/' + fileName;
+          }
+        }
+      }
+    }
+
+    sourceInfo = ' (at ' + fileName + ':' + source.lineNumber + ')';
+  } else if (ownerName) {
+    sourceInfo = ' (created by ' + ownerName + ')';
+  }
+
+  return '\n    in ' + (name || 'Unknown') + sourceInfo;
+}
+
+var Resolved = 1;
+function refineResolvedLazyComponent(lazyComponent) {
+  return lazyComponent._status === Resolved ? lazyComponent._result : null;
+}
+
+function getWrappedName(outerType, innerType, wrapperName) {
+  var functionName = innerType.displayName || innerType.name || '';
+  return outerType.displayName || (functionName !== '' ? wrapperName + "(" + functionName + ")" : wrapperName);
+}
+
+function getComponentName(type) {
+  if (type == null) {
+    // Host root, text node or just invalid type.
+    return null;
+  }
+
+  {
+    if (typeof type.tag === 'number') {
+      error('Received an unexpected object in getComponentName(). ' + 'This is likely a bug in React. Please file an issue.');
+    }
+  }
+
+  if (typeof type === 'function') {
+    return type.displayName || type.name || null;
+  }
+
+  if (typeof type === 'string') {
+    return type;
+  }
+
+  switch (type) {
+    case exports.Fragment:
+      return 'Fragment';
+
+    case REACT_PORTAL_TYPE:
+      return 'Portal';
+
+    case REACT_PROFILER_TYPE:
+      return "Profiler";
+
+    case REACT_STRICT_MODE_TYPE:
+      return 'StrictMode';
+
+    case REACT_SUSPENSE_TYPE:
+      return 'Suspense';
+
+    case REACT_SUSPENSE_LIST_TYPE:
+      return 'SuspenseList';
+  }
+
+  if (typeof type === 'object') {
+    switch (type.$$typeof) {
+      case REACT_CONTEXT_TYPE:
+        return 'Context.Consumer';
+
+      case REACT_PROVIDER_TYPE:
+        return 'Context.Provider';
+
+      case REACT_FORWARD_REF_TYPE:
+        return getWrappedName(type, type.render, 'ForwardRef');
+
+      case REACT_MEMO_TYPE:
+        return getComponentName(type.type);
+
+      case REACT_BLOCK_TYPE:
+        return getComponentName(type.render);
+
+      case REACT_LAZY_TYPE:
+        {
+          var thenable = type;
+          var resolvedThenable = refineResolvedLazyComponent(thenable);
+
+          if (resolvedThenable) {
+            return getComponentName(resolvedThenable);
+          }
+
+          break;
+        }
+    }
+  }
+
+  return null;
+}
+
+var loggedTypeFailures = {};
+var ReactDebugCurrentFrame = ReactSharedInternals.ReactDebugCurrentFrame;
+var currentlyValidatingElement = null;
+
+function setCurrentlyValidatingElement(element) {
+  {
+    currentlyValidatingElement = element;
+  }
+}
+
+function checkPropTypes(typeSpecs, values, location, componentName, element) {
+  {
+    // $FlowFixMe This is okay but Flow doesn't know it.
+    var has = Function.call.bind(Object.prototype.hasOwnProperty);
+
+    for (var typeSpecName in typeSpecs) {
+      if (has(typeSpecs, typeSpecName)) {
+        var error$1 = void 0; // Prop type validation may throw. In case they do, we don't want to
+        // fail the render phase where it didn't fail before. So we log it.
+        // After these have been cleaned up, we'll let them throw.
+
+        try {
+          // This is intentionally an invariant that gets caught. It's the same
+          // behavior as without this statement except with a better message.
+          if (typeof typeSpecs[typeSpecName] !== 'function') {
+            var err = Error((componentName || 'React class') + ': ' + location + ' type `' + typeSpecName + '` is invalid; ' + 'it must be a function, usually from the `prop-types` package, but received `' + typeof typeSpecs[typeSpecName] + '`.' + 'This often happens because of typos such as `PropTypes.function` instead of `PropTypes.func`.');
+            err.name = 'Invariant Violation';
+            throw err;
+          }
+
+          error$1 = typeSpecs[typeSpecName](values, typeSpecName, componentName, location, null, 'SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED');
+        } catch (ex) {
+          error$1 = ex;
+        }
+
+        if (error$1 && !(error$1 instanceof Error)) {
+          setCurrentlyValidatingElement(element);
+
+          error('%s: type specification of %s' + ' `%s` is invalid; the type checker ' + 'function must return `null` or an `Error` but returned a %s. ' + 'You may have forgotten to pass an argument to the type checker ' + 'creator (arrayOf, instanceOf, objectOf, oneOf, oneOfType, and ' + 'shape all require an argument).', componentName || 'React class', location, typeSpecName, typeof error$1);
+
+          setCurrentlyValidatingElement(null);
+        }
+
+        if (error$1 instanceof Error && !(error$1.message in loggedTypeFailures)) {
+          // Only monitor this failure once because there tends to be a lot of the
+          // same error.
+          loggedTypeFailures[error$1.message] = true;
+          setCurrentlyValidatingElement(element);
+
+          error('Failed %s type: %s', location, error$1.message);
+
+          setCurrentlyValidatingElement(null);
+        }
+      }
+    }
+  }
+}
+
+var ReactCurrentOwner = ReactSharedInternals.ReactCurrentOwner;
+var hasOwnProperty = Object.prototype.hasOwnProperty;
+var RESERVED_PROPS = {
+  key: true,
+  ref: true,
+  __self: true,
+  __source: true
+};
+var specialPropKeyWarningShown;
+var specialPropRefWarningShown;
+var didWarnAboutStringRefs;
+
+{
+  didWarnAboutStringRefs = {};
+}
+
+function hasValidRef(config) {
+  {
+    if (hasOwnProperty.call(config, 'ref')) {
+      var getter = Object.getOwnPropertyDescriptor(config, 'ref').get;
+
+      if (getter && getter.isReactWarning) {
+        return false;
+      }
+    }
+  }
+
+  return config.ref !== undefined;
+}
+
+function hasValidKey(config) {
+  {
+    if (hasOwnProperty.call(config, 'key')) {
+      var getter = Object.getOwnPropertyDescriptor(config, 'key').get;
+
+      if (getter && getter.isReactWarning) {
+        return false;
+      }
+    }
+  }
+
+  return config.key !== undefined;
+}
+
+function warnIfStringRefCannotBeAutoConverted(config, self) {
+  {
+    if (typeof config.ref === 'string' && ReactCurrentOwner.current && self && ReactCurrentOwner.current.stateNode !== self) {
+      var componentName = getComponentName(ReactCurrentOwner.current.type);
+
+      if (!didWarnAboutStringRefs[componentName]) {
+        error('Component "%s" contains the string ref "%s". ' + 'Support for string refs will be removed in a future major release. ' + 'This case cannot be automatically converted to an arrow function. ' + 'We ask you to manually fix this case by using useRef() or createRef() instead. ' + 'Learn more about using refs safely here: ' + 'https://reactjs.org/link/strict-mode-string-ref', getComponentName(ReactCurrentOwner.current.type), config.ref);
+
+        didWarnAboutStringRefs[componentName] = true;
+      }
+    }
+  }
+}
+
+function defineKeyPropWarningGetter(props, displayName) {
+  {
+    var warnAboutAccessingKey = function () {
+      if (!specialPropKeyWarningShown) {
+        specialPropKeyWarningShown = true;
+
+        error('%s: `key` is not a prop. Trying to access it will result ' + 'in `undefined` being returned. If you need to access the same ' + 'value within the child component, you should pass it as a different ' + 'prop. (https://reactjs.org/link/special-props)', displayName);
+      }
+    };
+
+    warnAboutAccessingKey.isReactWarning = true;
+    Object.defineProperty(props, 'key', {
+      get: warnAboutAccessingKey,
+      configurable: true
+    });
+  }
+}
+
+function defineRefPropWarningGetter(props, displayName) {
+  {
+    var warnAboutAccessingRef = function () {
+      if (!specialPropRefWarningShown) {
+        specialPropRefWarningShown = true;
+
+        error('%s: `ref` is not a prop. Trying to access it will result ' + 'in `undefined` being returned. If you need to access the same ' + 'value within the child component, you should pass it as a different ' + 'prop. (https://reactjs.org/link/special-props)', displayName);
+      }
+    };
+
+    warnAboutAccessingRef.isReactWarning = true;
+    Object.defineProperty(props, 'ref', {
+      get: warnAboutAccessingRef,
+      configurable: true
+    });
+  }
+}
+/**
+ * Factory method to create a new React element. This no longer adheres to
+ * the class pattern, so do not use new to call it. Also, instanceof check
+ * will not work. Instead test $$typeof field against Symbol.for('react.element') to check
+ * if something is a React Element.
+ *
+ * @param {*} type
+ * @param {*} props
+ * @param {*} key
+ * @param {string|object} ref
+ * @param {*} owner
+ * @param {*} self A *temporary* helper to detect places where `this` is
+ * different from the `owner` when React.createElement is called, so that we
+ * can warn. We want to get rid of owner and replace string `ref`s with arrow
+ * functions, and as long as `this` and owner are the same, there will be no
+ * change in behavior.
+ * @param {*} source An annotation object (added by a transpiler or otherwise)
+ * indicating filename, line number, and/or other information.
+ * @internal
+ */
+
+
+var ReactElement = function (type, key, ref, self, source, owner, props) {
+  var element = {
+    // This tag allows us to uniquely identify this as a React Element
+    $$typeof: REACT_ELEMENT_TYPE,
+    // Built-in properties that belong on the element
+    type: type,
+    key: key,
+    ref: ref,
+    props: props,
+    // Record the component responsible for creating this element.
+    _owner: owner
+  };
+
+  {
+    // The validation flag is currently mutative. We put it on
+    // an external backing store so that we can freeze the whole object.
+    // This can be replaced with a WeakMap once they are implemented in
+    // commonly used development environments.
+    element._store = {}; // To make comparing ReactElements easier for testing purposes, we make
+    // the validation flag non-enumerable (where possible, which should
+    // include every environment we run tests in), so the test framework
+    // ignores it.
+
+    Object.defineProperty(element._store, 'validated', {
+      configurable: false,
+      enumerable: false,
+      writable: true,
+      value: false
+    }); // self and source are DEV only properties.
+
+    Object.defineProperty(element, '_self', {
+      configurable: false,
+      enumerable: false,
+      writable: false,
+      value: self
+    }); // Two elements created in two different places should be considered
+    // equal for testing purposes and therefore we hide it from enumeration.
+
+    Object.defineProperty(element, '_source', {
+      configurable: false,
+      enumerable: false,
+      writable: false,
+      value: source
+    });
+
+    if (Object.freeze) {
+      Object.freeze(element.props);
+      Object.freeze(element);
+    }
+  }
+
+  return element;
+};
+/**
+ * https://github.com/reactjs/rfcs/pull/107
+ * @param {*} type
+ * @param {object} props
+ * @param {string} key
+ */
+
+function jsxDEV(type, config, maybeKey, source, self) {
+  {
+    var propName; // Reserved names are extracted
+
+    var props = {};
+    var key = null;
+    var ref = null; // Currently, key can be spread in as a prop. This causes a potential
+    // issue if key is also explicitly declared (ie. <div {...props} key="Hi" />
+    // or <div key="Hi" {...props} /> ). We want to deprecate key spread,
+    // but as an intermediary step, we will use jsxDEV for everything except
+    // <div {...props} key="Hi" />, because we aren't currently able to tell if
+    // key is explicitly declared to be undefined or not.
+
+    if (maybeKey !== undefined) {
+      key = '' + maybeKey;
+    }
+
+    if (hasValidKey(config)) {
+      key = '' + config.key;
+    }
+
+    if (hasValidRef(config)) {
+      ref = config.ref;
+      warnIfStringRefCannotBeAutoConverted(config, self);
+    } // Remaining properties are added to a new props object
+
+
+    for (propName in config) {
+      if (hasOwnProperty.call(config, propName) && !RESERVED_PROPS.hasOwnProperty(propName)) {
+        props[propName] = config[propName];
+      }
+    } // Resolve default props
+
+
+    if (type && type.defaultProps) {
+      var defaultProps = type.defaultProps;
+
+      for (propName in defaultProps) {
+        if (props[propName] === undefined) {
+          props[propName] = defaultProps[propName];
+        }
+      }
+    }
+
+    if (key || ref) {
+      var displayName = typeof type === 'function' ? type.displayName || type.name || 'Unknown' : type;
+
+      if (key) {
+        defineKeyPropWarningGetter(props, displayName);
+      }
+
+      if (ref) {
+        defineRefPropWarningGetter(props, displayName);
+      }
+    }
+
+    return ReactElement(type, key, ref, self, source, ReactCurrentOwner.current, props);
+  }
+}
+
+var ReactCurrentOwner$1 = ReactSharedInternals.ReactCurrentOwner;
+var ReactDebugCurrentFrame$1 = ReactSharedInternals.ReactDebugCurrentFrame;
+
+function setCurrentlyValidatingElement$1(element) {
+  currentlyValidatingElement = element;
+}
+
+var propTypesMisspellWarningShown;
+
+{
+  propTypesMisspellWarningShown = false;
+}
+/**
+ * Verifies the object is a ReactElement.
+ * See https://reactjs.org/docs/react-api.html#isvalidelement
+ * @param {?object} object
+ * @return {boolean} True if `object` is a ReactElement.
+ * @final
+ */
+
+function isValidElement(object) {
+  {
+    return typeof object === 'object' && object !== null && object.$$typeof === REACT_ELEMENT_TYPE;
+  }
+}
+
+function getDeclarationErrorAddendum() {
+  {
+    if (ReactCurrentOwner$1.current) {
+      var name = getComponentName(ReactCurrentOwner$1.current.type);
+
+      if (name) {
+        return '\n\nCheck the render method of `' + name + '`.';
+      }
+    }
+
+    return '';
+  }
+}
+
+function getSourceInfoErrorAddendum(source) {
+  {
+    if (source !== undefined) {
+      var fileName = source.fileName.replace(/^.*[\\\/]/, '');
+      var lineNumber = source.lineNumber;
+      return '\n\nCheck your code at ' + fileName + ':' + lineNumber + '.';
+    }
+
+    return '';
+  }
+}
+/**
+ * Warn if there's no key explicitly set on dynamic arrays of children or
+ * object keys are not valid. This allows us to keep track of children between
+ * updates.
+ */
+
+
+var ownerHasKeyUseWarning = {};
+
+function getCurrentComponentErrorInfo(parentType) {
+  {
+    var info = getDeclarationErrorAddendum();
+
+    if (!info) {
+      var parentName = typeof parentType === 'string' ? parentType : parentType.displayName || parentType.name;
+
+      if (parentName) {
+        info = "\n\nCheck the top-level render call using <" + parentName + ">.";
+      }
+    }
+
+    return info;
+  }
+}
+/**
+ * Warn if the element doesn't have an explicit key assigned to it.
+ * This element is in an array. The array could grow and shrink or be
+ * reordered. All children that haven't already been validated are required to
+ * have a "key" property assigned to it. Error statuses are cached so a warning
+ * will only be shown once.
+ *
+ * @internal
+ * @param {ReactElement} element Element that requires a key.
+ * @param {*} parentType element's parent's type.
+ */
+
+
+function validateExplicitKey(element, parentType) {
+  {
+    if (!element._store || element._store.validated || element.key != null) {
+      return;
+    }
+
+    element._store.validated = true;
+    var currentComponentErrorInfo = getCurrentComponentErrorInfo(parentType);
+
+    if (ownerHasKeyUseWarning[currentComponentErrorInfo]) {
+      return;
+    }
+
+    ownerHasKeyUseWarning[currentComponentErrorInfo] = true; // Usually the current owner is the offender, but if it accepts children as a
+    // property, it may be the creator of the child that's responsible for
+    // assigning it a key.
+
+    var childOwner = '';
+
+    if (element && element._owner && element._owner !== ReactCurrentOwner$1.current) {
+      // Give the component that originally created this child.
+      childOwner = " It was passed a child from " + getComponentName(element._owner.type) + ".";
+    }
+
+    setCurrentlyValidatingElement$1(element);
+
+    error('Each child in a list should have a unique "key" prop.' + '%s%s See https://reactjs.org/link/warning-keys for more information.', currentComponentErrorInfo, childOwner);
+
+    setCurrentlyValidatingElement$1(null);
+  }
+}
+/**
+ * Ensure that every element either is passed in a static location, in an
+ * array with an explicit keys property defined, or in an object literal
+ * with valid key property.
+ *
+ * @internal
+ * @param {ReactNode} node Statically passed child of any type.
+ * @param {*} parentType node's parent's type.
+ */
+
+
+function validateChildKeys(node, parentType) {
+  {
+    if (typeof node !== 'object') {
+      return;
+    }
+
+    if (Array.isArray(node)) {
+      for (var i = 0; i < node.length; i++) {
+        var child = node[i];
+
+        if (isValidElement(child)) {
+          validateExplicitKey(child, parentType);
+        }
+      }
+    } else if (isValidElement(node)) {
+      // This element was passed in a valid location.
+      if (node._store) {
+        node._store.validated = true;
+      }
+    } else if (node) {
+      var iteratorFn = getIteratorFn(node);
+
+      if (typeof iteratorFn === 'function') {
+        // Entry iterators used to provide implicit keys,
+        // but now we print a separate warning for them later.
+        if (iteratorFn !== node.entries) {
+          var iterator = iteratorFn.call(node);
+          var step;
+
+          while (!(step = iterator.next()).done) {
+            if (isValidElement(step.value)) {
+              validateExplicitKey(step.value, parentType);
+            }
+          }
+        }
+      }
+    }
+  }
+}
+/**
+ * Given an element, validate that its props follow the propTypes definition,
+ * provided by the type.
+ *
+ * @param {ReactElement} element
+ */
+
+
+function validatePropTypes(element) {
+  {
+    var type = element.type;
+
+    if (type === null || type === undefined || typeof type === 'string') {
+      return;
+    }
+
+    var propTypes;
+
+    if (typeof type === 'function') {
+      propTypes = type.propTypes;
+    } else if (typeof type === 'object' && (type.$$typeof === REACT_FORWARD_REF_TYPE || // Note: Memo only checks outer props here.
+    // Inner props are checked in the reconciler.
+    type.$$typeof === REACT_MEMO_TYPE)) {
+      propTypes = type.propTypes;
+    } else {
+      return;
+    }
+
+    if (propTypes) {
+      // Intentionally inside to avoid triggering lazy initializers:
+      var name = getComponentName(type);
+      checkPropTypes(propTypes, element.props, 'prop', name, element);
+    } else if (type.PropTypes !== undefined && !propTypesMisspellWarningShown) {
+      propTypesMisspellWarningShown = true; // Intentionally inside to avoid triggering lazy initializers:
+
+      var _name = getComponentName(type);
+
+      error('Component %s declared `PropTypes` instead of `propTypes`. Did you misspell the property assignment?', _name || 'Unknown');
+    }
+
+    if (typeof type.getDefaultProps === 'function' && !type.getDefaultProps.isReactClassApproved) {
+      error('getDefaultProps is only used on classic React.createClass ' + 'definitions. Use a static property named `defaultProps` instead.');
+    }
+  }
+}
+/**
+ * Given a fragment, validate that it can only be provided with fragment props
+ * @param {ReactElement} fragment
+ */
+
+
+function validateFragmentProps(fragment) {
+  {
+    var keys = Object.keys(fragment.props);
+
+    for (var i = 0; i < keys.length; i++) {
+      var key = keys[i];
+
+      if (key !== 'children' && key !== 'key') {
+        setCurrentlyValidatingElement$1(fragment);
+
+        error('Invalid prop `%s` supplied to `React.Fragment`. ' + 'React.Fragment can only have `key` and `children` props.', key);
+
+        setCurrentlyValidatingElement$1(null);
+        break;
+      }
+    }
+
+    if (fragment.ref !== null) {
+      setCurrentlyValidatingElement$1(fragment);
+
+      error('Invalid attribute `ref` supplied to `React.Fragment`.');
+
+      setCurrentlyValidatingElement$1(null);
+    }
+  }
+}
+
+function jsxWithValidation(type, props, key, isStaticChildren, source, self) {
+  {
+    var validType = isValidElementType(type); // We warn in this case but don't throw. We expect the element creation to
+    // succeed and there will likely be errors in render.
+
+    if (!validType) {
+      var info = '';
+
+      if (type === undefined || typeof type === 'object' && type !== null && Object.keys(type).length === 0) {
+        info += ' You likely forgot to export your component from the file ' + "it's defined in, or you might have mixed up default and named imports.";
+      }
+
+      var sourceInfo = getSourceInfoErrorAddendum(source);
+
+      if (sourceInfo) {
+        info += sourceInfo;
+      } else {
+        info += getDeclarationErrorAddendum();
+      }
+
+      var typeString;
+
+      if (type === null) {
+        typeString = 'null';
+      } else if (Array.isArray(type)) {
+        typeString = 'array';
+      } else if (type !== undefined && type.$$typeof === REACT_ELEMENT_TYPE) {
+        typeString = "<" + (getComponentName(type.type) || 'Unknown') + " />";
+        info = ' Did you accidentally export a JSX literal instead of a component?';
+      } else {
+        typeString = typeof type;
+      }
+
+      error('React.jsx: type is invalid -- expected a string (for ' + 'built-in components) or a class/function (for composite ' + 'components) but got: %s.%s', typeString, info);
+    }
+
+    var element = jsxDEV(type, props, key, source, self); // The result can be nullish if a mock or a custom function is used.
+    // TODO: Drop this when these are no longer allowed as the type argument.
+
+    if (element == null) {
+      return element;
+    } // Skip key warning if the type isn't valid since our key validation logic
+    // doesn't expect a non-string/function type and can throw confusing errors.
+    // We don't want exception behavior to differ between dev and prod.
+    // (Rendering will throw with a helpful message and as soon as the type is
+    // fixed, the key warnings will appear.)
+
+
+    if (validType) {
+      var children = props.children;
+
+      if (children !== undefined) {
+        if (isStaticChildren) {
+          if (Array.isArray(children)) {
+            for (var i = 0; i < children.length; i++) {
+              validateChildKeys(children[i], type);
+            }
+
+            if (Object.freeze) {
+              Object.freeze(children);
+            }
+          } else {
+            error('React.jsx: Static children should always be an array. ' + 'You are likely explicitly calling React.jsxs or React.jsxDEV. ' + 'Use the Babel transform instead.');
+          }
+        } else {
+          validateChildKeys(children, type);
+        }
+      }
+    }
+
+    if (type === exports.Fragment) {
+      validateFragmentProps(element);
+    } else {
+      validatePropTypes(element);
+    }
+
+    return element;
+  }
+} // These two functions exist to still get child warnings in dev
+// even with the prod transform. This means that jsxDEV is purely
+// opt-in behavior for better messages but that we won't stop
+// giving you warnings if you use production apis.
+
+function jsxWithValidationStatic(type, props, key) {
+  {
+    return jsxWithValidation(type, props, key, true);
+  }
+}
+function jsxWithValidationDynamic(type, props, key) {
+  {
+    return jsxWithValidation(type, props, key, false);
+  }
+}
+
+var jsx =  jsxWithValidationDynamic ; // we may want to special case jsxs internally to take advantage of static children.
+// for now we can ship identical prod functions
+
+var jsxs =  jsxWithValidationStatic ;
+
+exports.jsx = jsx;
+exports.jsxs = jsxs;
+  })();
+}
Index: node_modules/react/cjs/react-jsx-runtime.production.min.js
===================================================================
--- node_modules/react/cjs/react-jsx-runtime.production.min.js	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
+++ node_modules/react/cjs/react-jsx-runtime.production.min.js	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
@@ -0,0 +1,10 @@
+/** @license React v16.14.0
+ * react-jsx-runtime.production.min.js
+ *
+ * Copyright (c) Facebook, Inc. and its affiliates.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+'use strict';var f=require("react"),g=60103;exports.Fragment=60107;if("function"===typeof Symbol&&Symbol.for){var h=Symbol.for;g=h("react.element");exports.Fragment=h("react.fragment")}var m=f.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.ReactCurrentOwner,n=Object.prototype.hasOwnProperty,p={key:!0,ref:!0,__self:!0,__source:!0};
+function q(c,a,k){var b,d={},e=null,l=null;void 0!==k&&(e=""+k);void 0!==a.key&&(e=""+a.key);void 0!==a.ref&&(l=a.ref);for(b in a)n.call(a,b)&&!p.hasOwnProperty(b)&&(d[b]=a[b]);if(c&&c.defaultProps)for(b in a=c.defaultProps,a)void 0===d[b]&&(d[b]=a[b]);return{$$typeof:g,type:c,key:e,ref:l,props:d,_owner:m.current}}exports.jsx=q;exports.jsxs=q;
Index: node_modules/react/cjs/react.development.js
===================================================================
--- node_modules/react/cjs/react.development.js	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
+++ node_modules/react/cjs/react.development.js	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
@@ -0,0 +1,1912 @@
+/** @license React v16.14.0
+ * react.development.js
+ *
+ * Copyright (c) Facebook, Inc. and its affiliates.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+'use strict';
+
+
+
+if (process.env.NODE_ENV !== "production") {
+  (function() {
+'use strict';
+
+var _assign = require('object-assign');
+var checkPropTypes = require('prop-types/checkPropTypes');
+
+var ReactVersion = '16.14.0';
+
+// The Symbol used to tag the ReactElement-like types. If there is no native Symbol
+// nor polyfill, then a plain number is used for performance.
+var hasSymbol = typeof Symbol === 'function' && Symbol.for;
+var REACT_ELEMENT_TYPE = hasSymbol ? Symbol.for('react.element') : 0xeac7;
+var REACT_PORTAL_TYPE = hasSymbol ? Symbol.for('react.portal') : 0xeaca;
+var REACT_FRAGMENT_TYPE = hasSymbol ? Symbol.for('react.fragment') : 0xeacb;
+var REACT_STRICT_MODE_TYPE = hasSymbol ? Symbol.for('react.strict_mode') : 0xeacc;
+var REACT_PROFILER_TYPE = hasSymbol ? Symbol.for('react.profiler') : 0xead2;
+var REACT_PROVIDER_TYPE = hasSymbol ? Symbol.for('react.provider') : 0xeacd;
+var REACT_CONTEXT_TYPE = hasSymbol ? Symbol.for('react.context') : 0xeace; // TODO: We don't use AsyncMode or ConcurrentMode anymore. They were temporary
+var REACT_CONCURRENT_MODE_TYPE = hasSymbol ? Symbol.for('react.concurrent_mode') : 0xeacf;
+var REACT_FORWARD_REF_TYPE = hasSymbol ? Symbol.for('react.forward_ref') : 0xead0;
+var REACT_SUSPENSE_TYPE = hasSymbol ? Symbol.for('react.suspense') : 0xead1;
+var REACT_SUSPENSE_LIST_TYPE = hasSymbol ? Symbol.for('react.suspense_list') : 0xead8;
+var REACT_MEMO_TYPE = hasSymbol ? Symbol.for('react.memo') : 0xead3;
+var REACT_LAZY_TYPE = hasSymbol ? Symbol.for('react.lazy') : 0xead4;
+var REACT_BLOCK_TYPE = hasSymbol ? Symbol.for('react.block') : 0xead9;
+var REACT_FUNDAMENTAL_TYPE = hasSymbol ? Symbol.for('react.fundamental') : 0xead5;
+var REACT_RESPONDER_TYPE = hasSymbol ? Symbol.for('react.responder') : 0xead6;
+var REACT_SCOPE_TYPE = hasSymbol ? Symbol.for('react.scope') : 0xead7;
+var MAYBE_ITERATOR_SYMBOL = typeof Symbol === 'function' && Symbol.iterator;
+var FAUX_ITERATOR_SYMBOL = '@@iterator';
+function getIteratorFn(maybeIterable) {
+  if (maybeIterable === null || typeof maybeIterable !== 'object') {
+    return null;
+  }
+
+  var maybeIterator = MAYBE_ITERATOR_SYMBOL && maybeIterable[MAYBE_ITERATOR_SYMBOL] || maybeIterable[FAUX_ITERATOR_SYMBOL];
+
+  if (typeof maybeIterator === 'function') {
+    return maybeIterator;
+  }
+
+  return null;
+}
+
+/**
+ * Keeps track of the current dispatcher.
+ */
+var ReactCurrentDispatcher = {
+  /**
+   * @internal
+   * @type {ReactComponent}
+   */
+  current: null
+};
+
+/**
+ * Keeps track of the current batch's configuration such as how long an update
+ * should suspend for if it needs to.
+ */
+var ReactCurrentBatchConfig = {
+  suspense: null
+};
+
+/**
+ * Keeps track of the current owner.
+ *
+ * The current owner is the component who should own any components that are
+ * currently being constructed.
+ */
+var ReactCurrentOwner = {
+  /**
+   * @internal
+   * @type {ReactComponent}
+   */
+  current: null
+};
+
+var BEFORE_SLASH_RE = /^(.*)[\\\/]/;
+function describeComponentFrame (name, source, ownerName) {
+  var sourceInfo = '';
+
+  if (source) {
+    var path = source.fileName;
+    var fileName = path.replace(BEFORE_SLASH_RE, '');
+
+    {
+      // In DEV, include code for a common special case:
+      // prefer "folder/index.js" instead of just "index.js".
+      if (/^index\./.test(fileName)) {
+        var match = path.match(BEFORE_SLASH_RE);
+
+        if (match) {
+          var pathBeforeSlash = match[1];
+
+          if (pathBeforeSlash) {
+            var folderName = pathBeforeSlash.replace(BEFORE_SLASH_RE, '');
+            fileName = folderName + '/' + fileName;
+          }
+        }
+      }
+    }
+
+    sourceInfo = ' (at ' + fileName + ':' + source.lineNumber + ')';
+  } else if (ownerName) {
+    sourceInfo = ' (created by ' + ownerName + ')';
+  }
+
+  return '\n    in ' + (name || 'Unknown') + sourceInfo;
+}
+
+var Resolved = 1;
+function refineResolvedLazyComponent(lazyComponent) {
+  return lazyComponent._status === Resolved ? lazyComponent._result : null;
+}
+
+function getWrappedName(outerType, innerType, wrapperName) {
+  var functionName = innerType.displayName || innerType.name || '';
+  return outerType.displayName || (functionName !== '' ? wrapperName + "(" + functionName + ")" : wrapperName);
+}
+
+function getComponentName(type) {
+  if (type == null) {
+    // Host root, text node or just invalid type.
+    return null;
+  }
+
+  {
+    if (typeof type.tag === 'number') {
+      error('Received an unexpected object in getComponentName(). ' + 'This is likely a bug in React. Please file an issue.');
+    }
+  }
+
+  if (typeof type === 'function') {
+    return type.displayName || type.name || null;
+  }
+
+  if (typeof type === 'string') {
+    return type;
+  }
+
+  switch (type) {
+    case REACT_FRAGMENT_TYPE:
+      return 'Fragment';
+
+    case REACT_PORTAL_TYPE:
+      return 'Portal';
+
+    case REACT_PROFILER_TYPE:
+      return "Profiler";
+
+    case REACT_STRICT_MODE_TYPE:
+      return 'StrictMode';
+
+    case REACT_SUSPENSE_TYPE:
+      return 'Suspense';
+
+    case REACT_SUSPENSE_LIST_TYPE:
+      return 'SuspenseList';
+  }
+
+  if (typeof type === 'object') {
+    switch (type.$$typeof) {
+      case REACT_CONTEXT_TYPE:
+        return 'Context.Consumer';
+
+      case REACT_PROVIDER_TYPE:
+        return 'Context.Provider';
+
+      case REACT_FORWARD_REF_TYPE:
+        return getWrappedName(type, type.render, 'ForwardRef');
+
+      case REACT_MEMO_TYPE:
+        return getComponentName(type.type);
+
+      case REACT_BLOCK_TYPE:
+        return getComponentName(type.render);
+
+      case REACT_LAZY_TYPE:
+        {
+          var thenable = type;
+          var resolvedThenable = refineResolvedLazyComponent(thenable);
+
+          if (resolvedThenable) {
+            return getComponentName(resolvedThenable);
+          }
+
+          break;
+        }
+    }
+  }
+
+  return null;
+}
+
+var ReactDebugCurrentFrame = {};
+var currentlyValidatingElement = null;
+function setCurrentlyValidatingElement(element) {
+  {
+    currentlyValidatingElement = element;
+  }
+}
+
+{
+  // Stack implementation injected by the current renderer.
+  ReactDebugCurrentFrame.getCurrentStack = null;
+
+  ReactDebugCurrentFrame.getStackAddendum = function () {
+    var stack = ''; // Add an extra top frame while an element is being validated
+
+    if (currentlyValidatingElement) {
+      var name = getComponentName(currentlyValidatingElement.type);
+      var owner = currentlyValidatingElement._owner;
+      stack += describeComponentFrame(name, currentlyValidatingElement._source, owner && getComponentName(owner.type));
+    } // Delegate to the injected renderer-specific implementation
+
+
+    var impl = ReactDebugCurrentFrame.getCurrentStack;
+
+    if (impl) {
+      stack += impl() || '';
+    }
+
+    return stack;
+  };
+}
+
+/**
+ * Used by act() to track whether you're inside an act() scope.
+ */
+var IsSomeRendererActing = {
+  current: false
+};
+
+var ReactSharedInternals = {
+  ReactCurrentDispatcher: ReactCurrentDispatcher,
+  ReactCurrentBatchConfig: ReactCurrentBatchConfig,
+  ReactCurrentOwner: ReactCurrentOwner,
+  IsSomeRendererActing: IsSomeRendererActing,
+  // Used by renderers to avoid bundling object-assign twice in UMD bundles:
+  assign: _assign
+};
+
+{
+  _assign(ReactSharedInternals, {
+    // These should not be included in production.
+    ReactDebugCurrentFrame: ReactDebugCurrentFrame,
+    // Shim for React DOM 16.0.0 which still destructured (but not used) this.
+    // TODO: remove in React 17.0.
+    ReactComponentTreeHook: {}
+  });
+}
+
+// by calls to these methods by a Babel plugin.
+//
+// In PROD (or in packages without access to React internals),
+// they are left as they are instead.
+
+function warn(format) {
+  {
+    for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
+      args[_key - 1] = arguments[_key];
+    }
+
+    printWarning('warn', format, args);
+  }
+}
+function error(format) {
+  {
+    for (var _len2 = arguments.length, args = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {
+      args[_key2 - 1] = arguments[_key2];
+    }
+
+    printWarning('error', format, args);
+  }
+}
+
+function printWarning(level, format, args) {
+  // When changing this logic, you might want to also
+  // update consoleWithStackDev.www.js as well.
+  {
+    var hasExistingStack = args.length > 0 && typeof args[args.length - 1] === 'string' && args[args.length - 1].indexOf('\n    in') === 0;
+
+    if (!hasExistingStack) {
+      var ReactDebugCurrentFrame = ReactSharedInternals.ReactDebugCurrentFrame;
+      var stack = ReactDebugCurrentFrame.getStackAddendum();
+
+      if (stack !== '') {
+        format += '%s';
+        args = args.concat([stack]);
+      }
+    }
+
+    var argsWithFormat = args.map(function (item) {
+      return '' + item;
+    }); // Careful: RN currently depends on this prefix
+
+    argsWithFormat.unshift('Warning: ' + format); // We intentionally don't use spread (or .apply) directly because it
+    // breaks IE9: https://github.com/facebook/react/issues/13610
+    // eslint-disable-next-line react-internal/no-production-logging
+
+    Function.prototype.apply.call(console[level], console, argsWithFormat);
+
+    try {
+      // --- Welcome to debugging React ---
+      // This error was thrown as a convenience so that you can use this stack
+      // to find the callsite that caused this warning to fire.
+      var argIndex = 0;
+      var message = 'Warning: ' + format.replace(/%s/g, function () {
+        return args[argIndex++];
+      });
+      throw new Error(message);
+    } catch (x) {}
+  }
+}
+
+var didWarnStateUpdateForUnmountedComponent = {};
+
+function warnNoop(publicInstance, callerName) {
+  {
+    var _constructor = publicInstance.constructor;
+    var componentName = _constructor && (_constructor.displayName || _constructor.name) || 'ReactClass';
+    var warningKey = componentName + "." + callerName;
+
+    if (didWarnStateUpdateForUnmountedComponent[warningKey]) {
+      return;
+    }
+
+    error("Can't call %s on a component that is not yet mounted. " + 'This is a no-op, but it might indicate a bug in your application. ' + 'Instead, assign to `this.state` directly or define a `state = {};` ' + 'class property with the desired state in the %s component.', callerName, componentName);
+
+    didWarnStateUpdateForUnmountedComponent[warningKey] = true;
+  }
+}
+/**
+ * This is the abstract API for an update queue.
+ */
+
+
+var ReactNoopUpdateQueue = {
+  /**
+   * Checks whether or not this composite component is mounted.
+   * @param {ReactClass} publicInstance The instance we want to test.
+   * @return {boolean} True if mounted, false otherwise.
+   * @protected
+   * @final
+   */
+  isMounted: function (publicInstance) {
+    return false;
+  },
+
+  /**
+   * Forces an update. This should only be invoked when it is known with
+   * certainty that we are **not** in a DOM transaction.
+   *
+   * You may want to call this when you know that some deeper aspect of the
+   * component's state has changed but `setState` was not called.
+   *
+   * This will not invoke `shouldComponentUpdate`, but it will invoke
+   * `componentWillUpdate` and `componentDidUpdate`.
+   *
+   * @param {ReactClass} publicInstance The instance that should rerender.
+   * @param {?function} callback Called after component is updated.
+   * @param {?string} callerName name of the calling function in the public API.
+   * @internal
+   */
+  enqueueForceUpdate: function (publicInstance, callback, callerName) {
+    warnNoop(publicInstance, 'forceUpdate');
+  },
+
+  /**
+   * Replaces all of the state. Always use this or `setState` to mutate state.
+   * You should treat `this.state` as immutable.
+   *
+   * There is no guarantee that `this.state` will be immediately updated, so
+   * accessing `this.state` after calling this method may return the old value.
+   *
+   * @param {ReactClass} publicInstance The instance that should rerender.
+   * @param {object} completeState Next state.
+   * @param {?function} callback Called after component is updated.
+   * @param {?string} callerName name of the calling function in the public API.
+   * @internal
+   */
+  enqueueReplaceState: function (publicInstance, completeState, callback, callerName) {
+    warnNoop(publicInstance, 'replaceState');
+  },
+
+  /**
+   * Sets a subset of the state. This only exists because _pendingState is
+   * internal. This provides a merging strategy that is not available to deep
+   * properties which is confusing. TODO: Expose pendingState or don't use it
+   * during the merge.
+   *
+   * @param {ReactClass} publicInstance The instance that should rerender.
+   * @param {object} partialState Next partial state to be merged with state.
+   * @param {?function} callback Called after component is updated.
+   * @param {?string} Name of the calling function in the public API.
+   * @internal
+   */
+  enqueueSetState: function (publicInstance, partialState, callback, callerName) {
+    warnNoop(publicInstance, 'setState');
+  }
+};
+
+var emptyObject = {};
+
+{
+  Object.freeze(emptyObject);
+}
+/**
+ * Base class helpers for the updating state of a component.
+ */
+
+
+function Component(props, context, updater) {
+  this.props = props;
+  this.context = context; // If a component has string refs, we will assign a different object later.
+
+  this.refs = emptyObject; // We initialize the default updater but the real one gets injected by the
+  // renderer.
+
+  this.updater = updater || ReactNoopUpdateQueue;
+}
+
+Component.prototype.isReactComponent = {};
+/**
+ * Sets a subset of the state. Always use this to mutate
+ * state. You should treat `this.state` as immutable.
+ *
+ * There is no guarantee that `this.state` will be immediately updated, so
+ * accessing `this.state` after calling this method may return the old value.
+ *
+ * There is no guarantee that calls to `setState` will run synchronously,
+ * as they may eventually be batched together.  You can provide an optional
+ * callback that will be executed when the call to setState is actually
+ * completed.
+ *
+ * When a function is provided to setState, it will be called at some point in
+ * the future (not synchronously). It will be called with the up to date
+ * component arguments (state, props, context). These values can be different
+ * from this.* because your function may be called after receiveProps but before
+ * shouldComponentUpdate, and this new state, props, and context will not yet be
+ * assigned to this.
+ *
+ * @param {object|function} partialState Next partial state or function to
+ *        produce next partial state to be merged with current state.
+ * @param {?function} callback Called after state is updated.
+ * @final
+ * @protected
+ */
+
+Component.prototype.setState = function (partialState, callback) {
+  if (!(typeof partialState === 'object' || typeof partialState === 'function' || partialState == null)) {
+    {
+      throw Error( "setState(...): takes an object of state variables to update or a function which returns an object of state variables." );
+    }
+  }
+
+  this.updater.enqueueSetState(this, partialState, callback, 'setState');
+};
+/**
+ * Forces an update. This should only be invoked when it is known with
+ * certainty that we are **not** in a DOM transaction.
+ *
+ * You may want to call this when you know that some deeper aspect of the
+ * component's state has changed but `setState` was not called.
+ *
+ * This will not invoke `shouldComponentUpdate`, but it will invoke
+ * `componentWillUpdate` and `componentDidUpdate`.
+ *
+ * @param {?function} callback Called after update is complete.
+ * @final
+ * @protected
+ */
+
+
+Component.prototype.forceUpdate = function (callback) {
+  this.updater.enqueueForceUpdate(this, callback, 'forceUpdate');
+};
+/**
+ * Deprecated APIs. These APIs used to exist on classic React classes but since
+ * we would like to deprecate them, we're not going to move them over to this
+ * modern base class. Instead, we define a getter that warns if it's accessed.
+ */
+
+
+{
+  var deprecatedAPIs = {
+    isMounted: ['isMounted', 'Instead, make sure to clean up subscriptions and pending requests in ' + 'componentWillUnmount to prevent memory leaks.'],
+    replaceState: ['replaceState', 'Refactor your code to use setState instead (see ' + 'https://github.com/facebook/react/issues/3236).']
+  };
+
+  var defineDeprecationWarning = function (methodName, info) {
+    Object.defineProperty(Component.prototype, methodName, {
+      get: function () {
+        warn('%s(...) is deprecated in plain JavaScript React classes. %s', info[0], info[1]);
+
+        return undefined;
+      }
+    });
+  };
+
+  for (var fnName in deprecatedAPIs) {
+    if (deprecatedAPIs.hasOwnProperty(fnName)) {
+      defineDeprecationWarning(fnName, deprecatedAPIs[fnName]);
+    }
+  }
+}
+
+function ComponentDummy() {}
+
+ComponentDummy.prototype = Component.prototype;
+/**
+ * Convenience component with default shallow equality check for sCU.
+ */
+
+function PureComponent(props, context, updater) {
+  this.props = props;
+  this.context = context; // If a component has string refs, we will assign a different object later.
+
+  this.refs = emptyObject;
+  this.updater = updater || ReactNoopUpdateQueue;
+}
+
+var pureComponentPrototype = PureComponent.prototype = new ComponentDummy();
+pureComponentPrototype.constructor = PureComponent; // Avoid an extra prototype jump for these methods.
+
+_assign(pureComponentPrototype, Component.prototype);
+
+pureComponentPrototype.isPureReactComponent = true;
+
+// an immutable object with a single mutable value
+function createRef() {
+  var refObject = {
+    current: null
+  };
+
+  {
+    Object.seal(refObject);
+  }
+
+  return refObject;
+}
+
+var hasOwnProperty = Object.prototype.hasOwnProperty;
+var RESERVED_PROPS = {
+  key: true,
+  ref: true,
+  __self: true,
+  __source: true
+};
+var specialPropKeyWarningShown, specialPropRefWarningShown, didWarnAboutStringRefs;
+
+{
+  didWarnAboutStringRefs = {};
+}
+
+function hasValidRef(config) {
+  {
+    if (hasOwnProperty.call(config, 'ref')) {
+      var getter = Object.getOwnPropertyDescriptor(config, 'ref').get;
+
+      if (getter && getter.isReactWarning) {
+        return false;
+      }
+    }
+  }
+
+  return config.ref !== undefined;
+}
+
+function hasValidKey(config) {
+  {
+    if (hasOwnProperty.call(config, 'key')) {
+      var getter = Object.getOwnPropertyDescriptor(config, 'key').get;
+
+      if (getter && getter.isReactWarning) {
+        return false;
+      }
+    }
+  }
+
+  return config.key !== undefined;
+}
+
+function defineKeyPropWarningGetter(props, displayName) {
+  var warnAboutAccessingKey = function () {
+    {
+      if (!specialPropKeyWarningShown) {
+        specialPropKeyWarningShown = true;
+
+        error('%s: `key` is not a prop. Trying to access it will result ' + 'in `undefined` being returned. If you need to access the same ' + 'value within the child component, you should pass it as a different ' + 'prop. (https://fb.me/react-special-props)', displayName);
+      }
+    }
+  };
+
+  warnAboutAccessingKey.isReactWarning = true;
+  Object.defineProperty(props, 'key', {
+    get: warnAboutAccessingKey,
+    configurable: true
+  });
+}
+
+function defineRefPropWarningGetter(props, displayName) {
+  var warnAboutAccessingRef = function () {
+    {
+      if (!specialPropRefWarningShown) {
+        specialPropRefWarningShown = true;
+
+        error('%s: `ref` is not a prop. Trying to access it will result ' + 'in `undefined` being returned. If you need to access the same ' + 'value within the child component, you should pass it as a different ' + 'prop. (https://fb.me/react-special-props)', displayName);
+      }
+    }
+  };
+
+  warnAboutAccessingRef.isReactWarning = true;
+  Object.defineProperty(props, 'ref', {
+    get: warnAboutAccessingRef,
+    configurable: true
+  });
+}
+
+function warnIfStringRefCannotBeAutoConverted(config) {
+  {
+    if (typeof config.ref === 'string' && ReactCurrentOwner.current && config.__self && ReactCurrentOwner.current.stateNode !== config.__self) {
+      var componentName = getComponentName(ReactCurrentOwner.current.type);
+
+      if (!didWarnAboutStringRefs[componentName]) {
+        error('Component "%s" contains the string ref "%s". ' + 'Support for string refs will be removed in a future major release. ' + 'This case cannot be automatically converted to an arrow function. ' + 'We ask you to manually fix this case by using useRef() or createRef() instead. ' + 'Learn more about using refs safely here: ' + 'https://fb.me/react-strict-mode-string-ref', getComponentName(ReactCurrentOwner.current.type), config.ref);
+
+        didWarnAboutStringRefs[componentName] = true;
+      }
+    }
+  }
+}
+/**
+ * Factory method to create a new React element. This no longer adheres to
+ * the class pattern, so do not use new to call it. Also, instanceof check
+ * will not work. Instead test $$typeof field against Symbol.for('react.element') to check
+ * if something is a React Element.
+ *
+ * @param {*} type
+ * @param {*} props
+ * @param {*} key
+ * @param {string|object} ref
+ * @param {*} owner
+ * @param {*} self A *temporary* helper to detect places where `this` is
+ * different from the `owner` when React.createElement is called, so that we
+ * can warn. We want to get rid of owner and replace string `ref`s with arrow
+ * functions, and as long as `this` and owner are the same, there will be no
+ * change in behavior.
+ * @param {*} source An annotation object (added by a transpiler or otherwise)
+ * indicating filename, line number, and/or other information.
+ * @internal
+ */
+
+
+var ReactElement = function (type, key, ref, self, source, owner, props) {
+  var element = {
+    // This tag allows us to uniquely identify this as a React Element
+    $$typeof: REACT_ELEMENT_TYPE,
+    // Built-in properties that belong on the element
+    type: type,
+    key: key,
+    ref: ref,
+    props: props,
+    // Record the component responsible for creating this element.
+    _owner: owner
+  };
+
+  {
+    // The validation flag is currently mutative. We put it on
+    // an external backing store so that we can freeze the whole object.
+    // This can be replaced with a WeakMap once they are implemented in
+    // commonly used development environments.
+    element._store = {}; // To make comparing ReactElements easier for testing purposes, we make
+    // the validation flag non-enumerable (where possible, which should
+    // include every environment we run tests in), so the test framework
+    // ignores it.
+
+    Object.defineProperty(element._store, 'validated', {
+      configurable: false,
+      enumerable: false,
+      writable: true,
+      value: false
+    }); // self and source are DEV only properties.
+
+    Object.defineProperty(element, '_self', {
+      configurable: false,
+      enumerable: false,
+      writable: false,
+      value: self
+    }); // Two elements created in two different places should be considered
+    // equal for testing purposes and therefore we hide it from enumeration.
+
+    Object.defineProperty(element, '_source', {
+      configurable: false,
+      enumerable: false,
+      writable: false,
+      value: source
+    });
+
+    if (Object.freeze) {
+      Object.freeze(element.props);
+      Object.freeze(element);
+    }
+  }
+
+  return element;
+};
+/**
+ * Create and return a new ReactElement of the given type.
+ * See https://reactjs.org/docs/react-api.html#createelement
+ */
+
+function createElement(type, config, children) {
+  var propName; // Reserved names are extracted
+
+  var props = {};
+  var key = null;
+  var ref = null;
+  var self = null;
+  var source = null;
+
+  if (config != null) {
+    if (hasValidRef(config)) {
+      ref = config.ref;
+
+      {
+        warnIfStringRefCannotBeAutoConverted(config);
+      }
+    }
+
+    if (hasValidKey(config)) {
+      key = '' + config.key;
+    }
+
+    self = config.__self === undefined ? null : config.__self;
+    source = config.__source === undefined ? null : config.__source; // Remaining properties are added to a new props object
+
+    for (propName in config) {
+      if (hasOwnProperty.call(config, propName) && !RESERVED_PROPS.hasOwnProperty(propName)) {
+        props[propName] = config[propName];
+      }
+    }
+  } // Children can be more than one argument, and those are transferred onto
+  // the newly allocated props object.
+
+
+  var childrenLength = arguments.length - 2;
+
+  if (childrenLength === 1) {
+    props.children = children;
+  } else if (childrenLength > 1) {
+    var childArray = Array(childrenLength);
+
+    for (var i = 0; i < childrenLength; i++) {
+      childArray[i] = arguments[i + 2];
+    }
+
+    {
+      if (Object.freeze) {
+        Object.freeze(childArray);
+      }
+    }
+
+    props.children = childArray;
+  } // Resolve default props
+
+
+  if (type && type.defaultProps) {
+    var defaultProps = type.defaultProps;
+
+    for (propName in defaultProps) {
+      if (props[propName] === undefined) {
+        props[propName] = defaultProps[propName];
+      }
+    }
+  }
+
+  {
+    if (key || ref) {
+      var displayName = typeof type === 'function' ? type.displayName || type.name || 'Unknown' : type;
+
+      if (key) {
+        defineKeyPropWarningGetter(props, displayName);
+      }
+
+      if (ref) {
+        defineRefPropWarningGetter(props, displayName);
+      }
+    }
+  }
+
+  return ReactElement(type, key, ref, self, source, ReactCurrentOwner.current, props);
+}
+function cloneAndReplaceKey(oldElement, newKey) {
+  var newElement = ReactElement(oldElement.type, newKey, oldElement.ref, oldElement._self, oldElement._source, oldElement._owner, oldElement.props);
+  return newElement;
+}
+/**
+ * Clone and return a new ReactElement using element as the starting point.
+ * See https://reactjs.org/docs/react-api.html#cloneelement
+ */
+
+function cloneElement(element, config, children) {
+  if (!!(element === null || element === undefined)) {
+    {
+      throw Error( "React.cloneElement(...): The argument must be a React element, but you passed " + element + "." );
+    }
+  }
+
+  var propName; // Original props are copied
+
+  var props = _assign({}, element.props); // Reserved names are extracted
+
+
+  var key = element.key;
+  var ref = element.ref; // Self is preserved since the owner is preserved.
+
+  var self = element._self; // Source is preserved since cloneElement is unlikely to be targeted by a
+  // transpiler, and the original source is probably a better indicator of the
+  // true owner.
+
+  var source = element._source; // Owner will be preserved, unless ref is overridden
+
+  var owner = element._owner;
+
+  if (config != null) {
+    if (hasValidRef(config)) {
+      // Silently steal the ref from the parent.
+      ref = config.ref;
+      owner = ReactCurrentOwner.current;
+    }
+
+    if (hasValidKey(config)) {
+      key = '' + config.key;
+    } // Remaining properties override existing props
+
+
+    var defaultProps;
+
+    if (element.type && element.type.defaultProps) {
+      defaultProps = element.type.defaultProps;
+    }
+
+    for (propName in config) {
+      if (hasOwnProperty.call(config, propName) && !RESERVED_PROPS.hasOwnProperty(propName)) {
+        if (config[propName] === undefined && defaultProps !== undefined) {
+          // Resolve default props
+          props[propName] = defaultProps[propName];
+        } else {
+          props[propName] = config[propName];
+        }
+      }
+    }
+  } // Children can be more than one argument, and those are transferred onto
+  // the newly allocated props object.
+
+
+  var childrenLength = arguments.length - 2;
+
+  if (childrenLength === 1) {
+    props.children = children;
+  } else if (childrenLength > 1) {
+    var childArray = Array(childrenLength);
+
+    for (var i = 0; i < childrenLength; i++) {
+      childArray[i] = arguments[i + 2];
+    }
+
+    props.children = childArray;
+  }
+
+  return ReactElement(element.type, key, ref, self, source, owner, props);
+}
+/**
+ * Verifies the object is a ReactElement.
+ * See https://reactjs.org/docs/react-api.html#isvalidelement
+ * @param {?object} object
+ * @return {boolean} True if `object` is a ReactElement.
+ * @final
+ */
+
+function isValidElement(object) {
+  return typeof object === 'object' && object !== null && object.$$typeof === REACT_ELEMENT_TYPE;
+}
+
+var SEPARATOR = '.';
+var SUBSEPARATOR = ':';
+/**
+ * Escape and wrap key so it is safe to use as a reactid
+ *
+ * @param {string} key to be escaped.
+ * @return {string} the escaped key.
+ */
+
+function escape(key) {
+  var escapeRegex = /[=:]/g;
+  var escaperLookup = {
+    '=': '=0',
+    ':': '=2'
+  };
+  var escapedString = ('' + key).replace(escapeRegex, function (match) {
+    return escaperLookup[match];
+  });
+  return '$' + escapedString;
+}
+/**
+ * TODO: Test that a single child and an array with one item have the same key
+ * pattern.
+ */
+
+
+var didWarnAboutMaps = false;
+var userProvidedKeyEscapeRegex = /\/+/g;
+
+function escapeUserProvidedKey(text) {
+  return ('' + text).replace(userProvidedKeyEscapeRegex, '$&/');
+}
+
+var POOL_SIZE = 10;
+var traverseContextPool = [];
+
+function getPooledTraverseContext(mapResult, keyPrefix, mapFunction, mapContext) {
+  if (traverseContextPool.length) {
+    var traverseContext = traverseContextPool.pop();
+    traverseContext.result = mapResult;
+    traverseContext.keyPrefix = keyPrefix;
+    traverseContext.func = mapFunction;
+    traverseContext.context = mapContext;
+    traverseContext.count = 0;
+    return traverseContext;
+  } else {
+    return {
+      result: mapResult,
+      keyPrefix: keyPrefix,
+      func: mapFunction,
+      context: mapContext,
+      count: 0
+    };
+  }
+}
+
+function releaseTraverseContext(traverseContext) {
+  traverseContext.result = null;
+  traverseContext.keyPrefix = null;
+  traverseContext.func = null;
+  traverseContext.context = null;
+  traverseContext.count = 0;
+
+  if (traverseContextPool.length < POOL_SIZE) {
+    traverseContextPool.push(traverseContext);
+  }
+}
+/**
+ * @param {?*} children Children tree container.
+ * @param {!string} nameSoFar Name of the key path so far.
+ * @param {!function} callback Callback to invoke with each child found.
+ * @param {?*} traverseContext Used to pass information throughout the traversal
+ * process.
+ * @return {!number} The number of children in this subtree.
+ */
+
+
+function traverseAllChildrenImpl(children, nameSoFar, callback, traverseContext) {
+  var type = typeof children;
+
+  if (type === 'undefined' || type === 'boolean') {
+    // All of the above are perceived as null.
+    children = null;
+  }
+
+  var invokeCallback = false;
+
+  if (children === null) {
+    invokeCallback = true;
+  } else {
+    switch (type) {
+      case 'string':
+      case 'number':
+        invokeCallback = true;
+        break;
+
+      case 'object':
+        switch (children.$$typeof) {
+          case REACT_ELEMENT_TYPE:
+          case REACT_PORTAL_TYPE:
+            invokeCallback = true;
+        }
+
+    }
+  }
+
+  if (invokeCallback) {
+    callback(traverseContext, children, // If it's the only child, treat the name as if it was wrapped in an array
+    // so that it's consistent if the number of children grows.
+    nameSoFar === '' ? SEPARATOR + getComponentKey(children, 0) : nameSoFar);
+    return 1;
+  }
+
+  var child;
+  var nextName;
+  var subtreeCount = 0; // Count of children found in the current subtree.
+
+  var nextNamePrefix = nameSoFar === '' ? SEPARATOR : nameSoFar + SUBSEPARATOR;
+
+  if (Array.isArray(children)) {
+    for (var i = 0; i < children.length; i++) {
+      child = children[i];
+      nextName = nextNamePrefix + getComponentKey(child, i);
+      subtreeCount += traverseAllChildrenImpl(child, nextName, callback, traverseContext);
+    }
+  } else {
+    var iteratorFn = getIteratorFn(children);
+
+    if (typeof iteratorFn === 'function') {
+
+      {
+        // Warn about using Maps as children
+        if (iteratorFn === children.entries) {
+          if (!didWarnAboutMaps) {
+            warn('Using Maps as children is deprecated and will be removed in ' + 'a future major release. Consider converting children to ' + 'an array of keyed ReactElements instead.');
+          }
+
+          didWarnAboutMaps = true;
+        }
+      }
+
+      var iterator = iteratorFn.call(children);
+      var step;
+      var ii = 0;
+
+      while (!(step = iterator.next()).done) {
+        child = step.value;
+        nextName = nextNamePrefix + getComponentKey(child, ii++);
+        subtreeCount += traverseAllChildrenImpl(child, nextName, callback, traverseContext);
+      }
+    } else if (type === 'object') {
+      var addendum = '';
+
+      {
+        addendum = ' If you meant to render a collection of children, use an array ' + 'instead.' + ReactDebugCurrentFrame.getStackAddendum();
+      }
+
+      var childrenString = '' + children;
+
+      {
+        {
+          throw Error( "Objects are not valid as a React child (found: " + (childrenString === '[object Object]' ? 'object with keys {' + Object.keys(children).join(', ') + '}' : childrenString) + ")." + addendum );
+        }
+      }
+    }
+  }
+
+  return subtreeCount;
+}
+/**
+ * Traverses children that are typically specified as `props.children`, but
+ * might also be specified through attributes:
+ *
+ * - `traverseAllChildren(this.props.children, ...)`
+ * - `traverseAllChildren(this.props.leftPanelChildren, ...)`
+ *
+ * The `traverseContext` is an optional argument that is passed through the
+ * entire traversal. It can be used to store accumulations or anything else that
+ * the callback might find relevant.
+ *
+ * @param {?*} children Children tree object.
+ * @param {!function} callback To invoke upon traversing each child.
+ * @param {?*} traverseContext Context for traversal.
+ * @return {!number} The number of children in this subtree.
+ */
+
+
+function traverseAllChildren(children, callback, traverseContext) {
+  if (children == null) {
+    return 0;
+  }
+
+  return traverseAllChildrenImpl(children, '', callback, traverseContext);
+}
+/**
+ * Generate a key string that identifies a component within a set.
+ *
+ * @param {*} component A component that could contain a manual key.
+ * @param {number} index Index that is used if a manual key is not provided.
+ * @return {string}
+ */
+
+
+function getComponentKey(component, index) {
+  // Do some typechecking here since we call this blindly. We want to ensure
+  // that we don't block potential future ES APIs.
+  if (typeof component === 'object' && component !== null && component.key != null) {
+    // Explicit key
+    return escape(component.key);
+  } // Implicit key determined by the index in the set
+
+
+  return index.toString(36);
+}
+
+function forEachSingleChild(bookKeeping, child, name) {
+  var func = bookKeeping.func,
+      context = bookKeeping.context;
+  func.call(context, child, bookKeeping.count++);
+}
+/**
+ * Iterates through children that are typically specified as `props.children`.
+ *
+ * See https://reactjs.org/docs/react-api.html#reactchildrenforeach
+ *
+ * The provided forEachFunc(child, index) will be called for each
+ * leaf child.
+ *
+ * @param {?*} children Children tree container.
+ * @param {function(*, int)} forEachFunc
+ * @param {*} forEachContext Context for forEachContext.
+ */
+
+
+function forEachChildren(children, forEachFunc, forEachContext) {
+  if (children == null) {
+    return children;
+  }
+
+  var traverseContext = getPooledTraverseContext(null, null, forEachFunc, forEachContext);
+  traverseAllChildren(children, forEachSingleChild, traverseContext);
+  releaseTraverseContext(traverseContext);
+}
+
+function mapSingleChildIntoContext(bookKeeping, child, childKey) {
+  var result = bookKeeping.result,
+      keyPrefix = bookKeeping.keyPrefix,
+      func = bookKeeping.func,
+      context = bookKeeping.context;
+  var mappedChild = func.call(context, child, bookKeeping.count++);
+
+  if (Array.isArray(mappedChild)) {
+    mapIntoWithKeyPrefixInternal(mappedChild, result, childKey, function (c) {
+      return c;
+    });
+  } else if (mappedChild != null) {
+    if (isValidElement(mappedChild)) {
+      mappedChild = cloneAndReplaceKey(mappedChild, // Keep both the (mapped) and old keys if they differ, just as
+      // traverseAllChildren used to do for objects as children
+      keyPrefix + (mappedChild.key && (!child || child.key !== mappedChild.key) ? escapeUserProvidedKey(mappedChild.key) + '/' : '') + childKey);
+    }
+
+    result.push(mappedChild);
+  }
+}
+
+function mapIntoWithKeyPrefixInternal(children, array, prefix, func, context) {
+  var escapedPrefix = '';
+
+  if (prefix != null) {
+    escapedPrefix = escapeUserProvidedKey(prefix) + '/';
+  }
+
+  var traverseContext = getPooledTraverseContext(array, escapedPrefix, func, context);
+  traverseAllChildren(children, mapSingleChildIntoContext, traverseContext);
+  releaseTraverseContext(traverseContext);
+}
+/**
+ * Maps children that are typically specified as `props.children`.
+ *
+ * See https://reactjs.org/docs/react-api.html#reactchildrenmap
+ *
+ * The provided mapFunction(child, key, index) will be called for each
+ * leaf child.
+ *
+ * @param {?*} children Children tree container.
+ * @param {function(*, int)} func The map function.
+ * @param {*} context Context for mapFunction.
+ * @return {object} Object containing the ordered map of results.
+ */
+
+
+function mapChildren(children, func, context) {
+  if (children == null) {
+    return children;
+  }
+
+  var result = [];
+  mapIntoWithKeyPrefixInternal(children, result, null, func, context);
+  return result;
+}
+/**
+ * Count the number of children that are typically specified as
+ * `props.children`.
+ *
+ * See https://reactjs.org/docs/react-api.html#reactchildrencount
+ *
+ * @param {?*} children Children tree container.
+ * @return {number} The number of children.
+ */
+
+
+function countChildren(children) {
+  return traverseAllChildren(children, function () {
+    return null;
+  }, null);
+}
+/**
+ * Flatten a children object (typically specified as `props.children`) and
+ * return an array with appropriately re-keyed children.
+ *
+ * See https://reactjs.org/docs/react-api.html#reactchildrentoarray
+ */
+
+
+function toArray(children) {
+  var result = [];
+  mapIntoWithKeyPrefixInternal(children, result, null, function (child) {
+    return child;
+  });
+  return result;
+}
+/**
+ * Returns the first child in a collection of children and verifies that there
+ * is only one child in the collection.
+ *
+ * See https://reactjs.org/docs/react-api.html#reactchildrenonly
+ *
+ * The current implementation of this function assumes that a single child gets
+ * passed without a wrapper, but the purpose of this helper function is to
+ * abstract away the particular structure of children.
+ *
+ * @param {?object} children Child collection structure.
+ * @return {ReactElement} The first and only `ReactElement` contained in the
+ * structure.
+ */
+
+
+function onlyChild(children) {
+  if (!isValidElement(children)) {
+    {
+      throw Error( "React.Children.only expected to receive a single React element child." );
+    }
+  }
+
+  return children;
+}
+
+function createContext(defaultValue, calculateChangedBits) {
+  if (calculateChangedBits === undefined) {
+    calculateChangedBits = null;
+  } else {
+    {
+      if (calculateChangedBits !== null && typeof calculateChangedBits !== 'function') {
+        error('createContext: Expected the optional second argument to be a ' + 'function. Instead received: %s', calculateChangedBits);
+      }
+    }
+  }
+
+  var context = {
+    $$typeof: REACT_CONTEXT_TYPE,
+    _calculateChangedBits: calculateChangedBits,
+    // As a workaround to support multiple concurrent renderers, we categorize
+    // some renderers as primary and others as secondary. We only expect
+    // there to be two concurrent renderers at most: React Native (primary) and
+    // Fabric (secondary); React DOM (primary) and React ART (secondary).
+    // Secondary renderers store their context values on separate fields.
+    _currentValue: defaultValue,
+    _currentValue2: defaultValue,
+    // Used to track how many concurrent renderers this context currently
+    // supports within in a single renderer. Such as parallel server rendering.
+    _threadCount: 0,
+    // These are circular
+    Provider: null,
+    Consumer: null
+  };
+  context.Provider = {
+    $$typeof: REACT_PROVIDER_TYPE,
+    _context: context
+  };
+  var hasWarnedAboutUsingNestedContextConsumers = false;
+  var hasWarnedAboutUsingConsumerProvider = false;
+
+  {
+    // A separate object, but proxies back to the original context object for
+    // backwards compatibility. It has a different $$typeof, so we can properly
+    // warn for the incorrect usage of Context as a Consumer.
+    var Consumer = {
+      $$typeof: REACT_CONTEXT_TYPE,
+      _context: context,
+      _calculateChangedBits: context._calculateChangedBits
+    }; // $FlowFixMe: Flow complains about not setting a value, which is intentional here
+
+    Object.defineProperties(Consumer, {
+      Provider: {
+        get: function () {
+          if (!hasWarnedAboutUsingConsumerProvider) {
+            hasWarnedAboutUsingConsumerProvider = true;
+
+            error('Rendering <Context.Consumer.Provider> is not supported and will be removed in ' + 'a future major release. Did you mean to render <Context.Provider> instead?');
+          }
+
+          return context.Provider;
+        },
+        set: function (_Provider) {
+          context.Provider = _Provider;
+        }
+      },
+      _currentValue: {
+        get: function () {
+          return context._currentValue;
+        },
+        set: function (_currentValue) {
+          context._currentValue = _currentValue;
+        }
+      },
+      _currentValue2: {
+        get: function () {
+          return context._currentValue2;
+        },
+        set: function (_currentValue2) {
+          context._currentValue2 = _currentValue2;
+        }
+      },
+      _threadCount: {
+        get: function () {
+          return context._threadCount;
+        },
+        set: function (_threadCount) {
+          context._threadCount = _threadCount;
+        }
+      },
+      Consumer: {
+        get: function () {
+          if (!hasWarnedAboutUsingNestedContextConsumers) {
+            hasWarnedAboutUsingNestedContextConsumers = true;
+
+            error('Rendering <Context.Consumer.Consumer> is not supported and will be removed in ' + 'a future major release. Did you mean to render <Context.Consumer> instead?');
+          }
+
+          return context.Consumer;
+        }
+      }
+    }); // $FlowFixMe: Flow complains about missing properties because it doesn't understand defineProperty
+
+    context.Consumer = Consumer;
+  }
+
+  {
+    context._currentRenderer = null;
+    context._currentRenderer2 = null;
+  }
+
+  return context;
+}
+
+function lazy(ctor) {
+  var lazyType = {
+    $$typeof: REACT_LAZY_TYPE,
+    _ctor: ctor,
+    // React uses these fields to store the result.
+    _status: -1,
+    _result: null
+  };
+
+  {
+    // In production, this would just set it on the object.
+    var defaultProps;
+    var propTypes;
+    Object.defineProperties(lazyType, {
+      defaultProps: {
+        configurable: true,
+        get: function () {
+          return defaultProps;
+        },
+        set: function (newDefaultProps) {
+          error('React.lazy(...): It is not supported to assign `defaultProps` to ' + 'a lazy component import. Either specify them where the component ' + 'is defined, or create a wrapping component around it.');
+
+          defaultProps = newDefaultProps; // Match production behavior more closely:
+
+          Object.defineProperty(lazyType, 'defaultProps', {
+            enumerable: true
+          });
+        }
+      },
+      propTypes: {
+        configurable: true,
+        get: function () {
+          return propTypes;
+        },
+        set: function (newPropTypes) {
+          error('React.lazy(...): It is not supported to assign `propTypes` to ' + 'a lazy component import. Either specify them where the component ' + 'is defined, or create a wrapping component around it.');
+
+          propTypes = newPropTypes; // Match production behavior more closely:
+
+          Object.defineProperty(lazyType, 'propTypes', {
+            enumerable: true
+          });
+        }
+      }
+    });
+  }
+
+  return lazyType;
+}
+
+function forwardRef(render) {
+  {
+    if (render != null && render.$$typeof === REACT_MEMO_TYPE) {
+      error('forwardRef requires a render function but received a `memo` ' + 'component. Instead of forwardRef(memo(...)), use ' + 'memo(forwardRef(...)).');
+    } else if (typeof render !== 'function') {
+      error('forwardRef requires a render function but was given %s.', render === null ? 'null' : typeof render);
+    } else {
+      if (render.length !== 0 && render.length !== 2) {
+        error('forwardRef render functions accept exactly two parameters: props and ref. %s', render.length === 1 ? 'Did you forget to use the ref parameter?' : 'Any additional parameter will be undefined.');
+      }
+    }
+
+    if (render != null) {
+      if (render.defaultProps != null || render.propTypes != null) {
+        error('forwardRef render functions do not support propTypes or defaultProps. ' + 'Did you accidentally pass a React component?');
+      }
+    }
+  }
+
+  return {
+    $$typeof: REACT_FORWARD_REF_TYPE,
+    render: render
+  };
+}
+
+function isValidElementType(type) {
+  return typeof type === 'string' || typeof type === 'function' || // Note: its typeof might be other than 'symbol' or 'number' if it's a polyfill.
+  type === REACT_FRAGMENT_TYPE || type === REACT_CONCURRENT_MODE_TYPE || type === REACT_PROFILER_TYPE || type === REACT_STRICT_MODE_TYPE || type === REACT_SUSPENSE_TYPE || type === REACT_SUSPENSE_LIST_TYPE || typeof type === 'object' && type !== null && (type.$$typeof === REACT_LAZY_TYPE || type.$$typeof === REACT_MEMO_TYPE || type.$$typeof === REACT_PROVIDER_TYPE || type.$$typeof === REACT_CONTEXT_TYPE || type.$$typeof === REACT_FORWARD_REF_TYPE || type.$$typeof === REACT_FUNDAMENTAL_TYPE || type.$$typeof === REACT_RESPONDER_TYPE || type.$$typeof === REACT_SCOPE_TYPE || type.$$typeof === REACT_BLOCK_TYPE);
+}
+
+function memo(type, compare) {
+  {
+    if (!isValidElementType(type)) {
+      error('memo: The first argument must be a component. Instead ' + 'received: %s', type === null ? 'null' : typeof type);
+    }
+  }
+
+  return {
+    $$typeof: REACT_MEMO_TYPE,
+    type: type,
+    compare: compare === undefined ? null : compare
+  };
+}
+
+function resolveDispatcher() {
+  var dispatcher = ReactCurrentDispatcher.current;
+
+  if (!(dispatcher !== null)) {
+    {
+      throw Error( "Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:\n1. You might have mismatching versions of React and the renderer (such as React DOM)\n2. You might be breaking the Rules of Hooks\n3. You might have more than one copy of React in the same app\nSee https://fb.me/react-invalid-hook-call for tips about how to debug and fix this problem." );
+    }
+  }
+
+  return dispatcher;
+}
+
+function useContext(Context, unstable_observedBits) {
+  var dispatcher = resolveDispatcher();
+
+  {
+    if (unstable_observedBits !== undefined) {
+      error('useContext() second argument is reserved for future ' + 'use in React. Passing it is not supported. ' + 'You passed: %s.%s', unstable_observedBits, typeof unstable_observedBits === 'number' && Array.isArray(arguments[2]) ? '\n\nDid you call array.map(useContext)? ' + 'Calling Hooks inside a loop is not supported. ' + 'Learn more at https://fb.me/rules-of-hooks' : '');
+    } // TODO: add a more generic warning for invalid values.
+
+
+    if (Context._context !== undefined) {
+      var realContext = Context._context; // Don't deduplicate because this legitimately causes bugs
+      // and nobody should be using this in existing code.
+
+      if (realContext.Consumer === Context) {
+        error('Calling useContext(Context.Consumer) is not supported, may cause bugs, and will be ' + 'removed in a future major release. Did you mean to call useContext(Context) instead?');
+      } else if (realContext.Provider === Context) {
+        error('Calling useContext(Context.Provider) is not supported. ' + 'Did you mean to call useContext(Context) instead?');
+      }
+    }
+  }
+
+  return dispatcher.useContext(Context, unstable_observedBits);
+}
+function useState(initialState) {
+  var dispatcher = resolveDispatcher();
+  return dispatcher.useState(initialState);
+}
+function useReducer(reducer, initialArg, init) {
+  var dispatcher = resolveDispatcher();
+  return dispatcher.useReducer(reducer, initialArg, init);
+}
+function useRef(initialValue) {
+  var dispatcher = resolveDispatcher();
+  return dispatcher.useRef(initialValue);
+}
+function useEffect(create, deps) {
+  var dispatcher = resolveDispatcher();
+  return dispatcher.useEffect(create, deps);
+}
+function useLayoutEffect(create, deps) {
+  var dispatcher = resolveDispatcher();
+  return dispatcher.useLayoutEffect(create, deps);
+}
+function useCallback(callback, deps) {
+  var dispatcher = resolveDispatcher();
+  return dispatcher.useCallback(callback, deps);
+}
+function useMemo(create, deps) {
+  var dispatcher = resolveDispatcher();
+  return dispatcher.useMemo(create, deps);
+}
+function useImperativeHandle(ref, create, deps) {
+  var dispatcher = resolveDispatcher();
+  return dispatcher.useImperativeHandle(ref, create, deps);
+}
+function useDebugValue(value, formatterFn) {
+  {
+    var dispatcher = resolveDispatcher();
+    return dispatcher.useDebugValue(value, formatterFn);
+  }
+}
+
+var propTypesMisspellWarningShown;
+
+{
+  propTypesMisspellWarningShown = false;
+}
+
+function getDeclarationErrorAddendum() {
+  if (ReactCurrentOwner.current) {
+    var name = getComponentName(ReactCurrentOwner.current.type);
+
+    if (name) {
+      return '\n\nCheck the render method of `' + name + '`.';
+    }
+  }
+
+  return '';
+}
+
+function getSourceInfoErrorAddendum(source) {
+  if (source !== undefined) {
+    var fileName = source.fileName.replace(/^.*[\\\/]/, '');
+    var lineNumber = source.lineNumber;
+    return '\n\nCheck your code at ' + fileName + ':' + lineNumber + '.';
+  }
+
+  return '';
+}
+
+function getSourceInfoErrorAddendumForProps(elementProps) {
+  if (elementProps !== null && elementProps !== undefined) {
+    return getSourceInfoErrorAddendum(elementProps.__source);
+  }
+
+  return '';
+}
+/**
+ * Warn if there's no key explicitly set on dynamic arrays of children or
+ * object keys are not valid. This allows us to keep track of children between
+ * updates.
+ */
+
+
+var ownerHasKeyUseWarning = {};
+
+function getCurrentComponentErrorInfo(parentType) {
+  var info = getDeclarationErrorAddendum();
+
+  if (!info) {
+    var parentName = typeof parentType === 'string' ? parentType : parentType.displayName || parentType.name;
+
+    if (parentName) {
+      info = "\n\nCheck the top-level render call using <" + parentName + ">.";
+    }
+  }
+
+  return info;
+}
+/**
+ * Warn if the element doesn't have an explicit key assigned to it.
+ * This element is in an array. The array could grow and shrink or be
+ * reordered. All children that haven't already been validated are required to
+ * have a "key" property assigned to it. Error statuses are cached so a warning
+ * will only be shown once.
+ *
+ * @internal
+ * @param {ReactElement} element Element that requires a key.
+ * @param {*} parentType element's parent's type.
+ */
+
+
+function validateExplicitKey(element, parentType) {
+  if (!element._store || element._store.validated || element.key != null) {
+    return;
+  }
+
+  element._store.validated = true;
+  var currentComponentErrorInfo = getCurrentComponentErrorInfo(parentType);
+
+  if (ownerHasKeyUseWarning[currentComponentErrorInfo]) {
+    return;
+  }
+
+  ownerHasKeyUseWarning[currentComponentErrorInfo] = true; // Usually the current owner is the offender, but if it accepts children as a
+  // property, it may be the creator of the child that's responsible for
+  // assigning it a key.
+
+  var childOwner = '';
+
+  if (element && element._owner && element._owner !== ReactCurrentOwner.current) {
+    // Give the component that originally created this child.
+    childOwner = " It was passed a child from " + getComponentName(element._owner.type) + ".";
+  }
+
+  setCurrentlyValidatingElement(element);
+
+  {
+    error('Each child in a list should have a unique "key" prop.' + '%s%s See https://fb.me/react-warning-keys for more information.', currentComponentErrorInfo, childOwner);
+  }
+
+  setCurrentlyValidatingElement(null);
+}
+/**
+ * Ensure that every element either is passed in a static location, in an
+ * array with an explicit keys property defined, or in an object literal
+ * with valid key property.
+ *
+ * @internal
+ * @param {ReactNode} node Statically passed child of any type.
+ * @param {*} parentType node's parent's type.
+ */
+
+
+function validateChildKeys(node, parentType) {
+  if (typeof node !== 'object') {
+    return;
+  }
+
+  if (Array.isArray(node)) {
+    for (var i = 0; i < node.length; i++) {
+      var child = node[i];
+
+      if (isValidElement(child)) {
+        validateExplicitKey(child, parentType);
+      }
+    }
+  } else if (isValidElement(node)) {
+    // This element was passed in a valid location.
+    if (node._store) {
+      node._store.validated = true;
+    }
+  } else if (node) {
+    var iteratorFn = getIteratorFn(node);
+
+    if (typeof iteratorFn === 'function') {
+      // Entry iterators used to provide implicit keys,
+      // but now we print a separate warning for them later.
+      if (iteratorFn !== node.entries) {
+        var iterator = iteratorFn.call(node);
+        var step;
+
+        while (!(step = iterator.next()).done) {
+          if (isValidElement(step.value)) {
+            validateExplicitKey(step.value, parentType);
+          }
+        }
+      }
+    }
+  }
+}
+/**
+ * Given an element, validate that its props follow the propTypes definition,
+ * provided by the type.
+ *
+ * @param {ReactElement} element
+ */
+
+
+function validatePropTypes(element) {
+  {
+    var type = element.type;
+
+    if (type === null || type === undefined || typeof type === 'string') {
+      return;
+    }
+
+    var name = getComponentName(type);
+    var propTypes;
+
+    if (typeof type === 'function') {
+      propTypes = type.propTypes;
+    } else if (typeof type === 'object' && (type.$$typeof === REACT_FORWARD_REF_TYPE || // Note: Memo only checks outer props here.
+    // Inner props are checked in the reconciler.
+    type.$$typeof === REACT_MEMO_TYPE)) {
+      propTypes = type.propTypes;
+    } else {
+      return;
+    }
+
+    if (propTypes) {
+      setCurrentlyValidatingElement(element);
+      checkPropTypes(propTypes, element.props, 'prop', name, ReactDebugCurrentFrame.getStackAddendum);
+      setCurrentlyValidatingElement(null);
+    } else if (type.PropTypes !== undefined && !propTypesMisspellWarningShown) {
+      propTypesMisspellWarningShown = true;
+
+      error('Component %s declared `PropTypes` instead of `propTypes`. Did you misspell the property assignment?', name || 'Unknown');
+    }
+
+    if (typeof type.getDefaultProps === 'function' && !type.getDefaultProps.isReactClassApproved) {
+      error('getDefaultProps is only used on classic React.createClass ' + 'definitions. Use a static property named `defaultProps` instead.');
+    }
+  }
+}
+/**
+ * Given a fragment, validate that it can only be provided with fragment props
+ * @param {ReactElement} fragment
+ */
+
+
+function validateFragmentProps(fragment) {
+  {
+    setCurrentlyValidatingElement(fragment);
+    var keys = Object.keys(fragment.props);
+
+    for (var i = 0; i < keys.length; i++) {
+      var key = keys[i];
+
+      if (key !== 'children' && key !== 'key') {
+        error('Invalid prop `%s` supplied to `React.Fragment`. ' + 'React.Fragment can only have `key` and `children` props.', key);
+
+        break;
+      }
+    }
+
+    if (fragment.ref !== null) {
+      error('Invalid attribute `ref` supplied to `React.Fragment`.');
+    }
+
+    setCurrentlyValidatingElement(null);
+  }
+}
+function createElementWithValidation(type, props, children) {
+  var validType = isValidElementType(type); // We warn in this case but don't throw. We expect the element creation to
+  // succeed and there will likely be errors in render.
+
+  if (!validType) {
+    var info = '';
+
+    if (type === undefined || typeof type === 'object' && type !== null && Object.keys(type).length === 0) {
+      info += ' You likely forgot to export your component from the file ' + "it's defined in, or you might have mixed up default and named imports.";
+    }
+
+    var sourceInfo = getSourceInfoErrorAddendumForProps(props);
+
+    if (sourceInfo) {
+      info += sourceInfo;
+    } else {
+      info += getDeclarationErrorAddendum();
+    }
+
+    var typeString;
+
+    if (type === null) {
+      typeString = 'null';
+    } else if (Array.isArray(type)) {
+      typeString = 'array';
+    } else if (type !== undefined && type.$$typeof === REACT_ELEMENT_TYPE) {
+      typeString = "<" + (getComponentName(type.type) || 'Unknown') + " />";
+      info = ' Did you accidentally export a JSX literal instead of a component?';
+    } else {
+      typeString = typeof type;
+    }
+
+    {
+      error('React.createElement: type is invalid -- expected a string (for ' + 'built-in components) or a class/function (for composite ' + 'components) but got: %s.%s', typeString, info);
+    }
+  }
+
+  var element = createElement.apply(this, arguments); // The result can be nullish if a mock or a custom function is used.
+  // TODO: Drop this when these are no longer allowed as the type argument.
+
+  if (element == null) {
+    return element;
+  } // Skip key warning if the type isn't valid since our key validation logic
+  // doesn't expect a non-string/function type and can throw confusing errors.
+  // We don't want exception behavior to differ between dev and prod.
+  // (Rendering will throw with a helpful message and as soon as the type is
+  // fixed, the key warnings will appear.)
+
+
+  if (validType) {
+    for (var i = 2; i < arguments.length; i++) {
+      validateChildKeys(arguments[i], type);
+    }
+  }
+
+  if (type === REACT_FRAGMENT_TYPE) {
+    validateFragmentProps(element);
+  } else {
+    validatePropTypes(element);
+  }
+
+  return element;
+}
+var didWarnAboutDeprecatedCreateFactory = false;
+function createFactoryWithValidation(type) {
+  var validatedFactory = createElementWithValidation.bind(null, type);
+  validatedFactory.type = type;
+
+  {
+    if (!didWarnAboutDeprecatedCreateFactory) {
+      didWarnAboutDeprecatedCreateFactory = true;
+
+      warn('React.createFactory() is deprecated and will be removed in ' + 'a future major release. Consider using JSX ' + 'or use React.createElement() directly instead.');
+    } // Legacy hook: remove it
+
+
+    Object.defineProperty(validatedFactory, 'type', {
+      enumerable: false,
+      get: function () {
+        warn('Factory.type is deprecated. Access the class directly ' + 'before passing it to createFactory.');
+
+        Object.defineProperty(this, 'type', {
+          value: type
+        });
+        return type;
+      }
+    });
+  }
+
+  return validatedFactory;
+}
+function cloneElementWithValidation(element, props, children) {
+  var newElement = cloneElement.apply(this, arguments);
+
+  for (var i = 2; i < arguments.length; i++) {
+    validateChildKeys(arguments[i], newElement.type);
+  }
+
+  validatePropTypes(newElement);
+  return newElement;
+}
+
+{
+
+  try {
+    var frozenObject = Object.freeze({});
+    var testMap = new Map([[frozenObject, null]]);
+    var testSet = new Set([frozenObject]); // This is necessary for Rollup to not consider these unused.
+    // https://github.com/rollup/rollup/issues/1771
+    // TODO: we can remove these if Rollup fixes the bug.
+
+    testMap.set(0, 0);
+    testSet.add(0);
+  } catch (e) {
+  }
+}
+
+var createElement$1 =  createElementWithValidation ;
+var cloneElement$1 =  cloneElementWithValidation ;
+var createFactory =  createFactoryWithValidation ;
+var Children = {
+  map: mapChildren,
+  forEach: forEachChildren,
+  count: countChildren,
+  toArray: toArray,
+  only: onlyChild
+};
+
+exports.Children = Children;
+exports.Component = Component;
+exports.Fragment = REACT_FRAGMENT_TYPE;
+exports.Profiler = REACT_PROFILER_TYPE;
+exports.PureComponent = PureComponent;
+exports.StrictMode = REACT_STRICT_MODE_TYPE;
+exports.Suspense = REACT_SUSPENSE_TYPE;
+exports.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED = ReactSharedInternals;
+exports.cloneElement = cloneElement$1;
+exports.createContext = createContext;
+exports.createElement = createElement$1;
+exports.createFactory = createFactory;
+exports.createRef = createRef;
+exports.forwardRef = forwardRef;
+exports.isValidElement = isValidElement;
+exports.lazy = lazy;
+exports.memo = memo;
+exports.useCallback = useCallback;
+exports.useContext = useContext;
+exports.useDebugValue = useDebugValue;
+exports.useEffect = useEffect;
+exports.useImperativeHandle = useImperativeHandle;
+exports.useLayoutEffect = useLayoutEffect;
+exports.useMemo = useMemo;
+exports.useReducer = useReducer;
+exports.useRef = useRef;
+exports.useState = useState;
+exports.version = ReactVersion;
+  })();
+}
Index: node_modules/react/cjs/react.production.min.js
===================================================================
--- node_modules/react/cjs/react.production.min.js	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
+++ node_modules/react/cjs/react.production.min.js	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
@@ -0,0 +1,25 @@
+/** @license React v16.14.0
+ * react.production.min.js
+ *
+ * Copyright (c) Facebook, Inc. and its affiliates.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+'use strict';var l=require("object-assign"),n="function"===typeof Symbol&&Symbol.for,p=n?Symbol.for("react.element"):60103,q=n?Symbol.for("react.portal"):60106,r=n?Symbol.for("react.fragment"):60107,t=n?Symbol.for("react.strict_mode"):60108,u=n?Symbol.for("react.profiler"):60114,v=n?Symbol.for("react.provider"):60109,w=n?Symbol.for("react.context"):60110,x=n?Symbol.for("react.forward_ref"):60112,y=n?Symbol.for("react.suspense"):60113,z=n?Symbol.for("react.memo"):60115,A=n?Symbol.for("react.lazy"):
+60116,B="function"===typeof Symbol&&Symbol.iterator;function C(a){for(var b="https://reactjs.org/docs/error-decoder.html?invariant="+a,c=1;c<arguments.length;c++)b+="&args[]="+encodeURIComponent(arguments[c]);return"Minified React error #"+a+"; visit "+b+" for the full message or use the non-minified dev environment for full errors and additional helpful warnings."}
+var D={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},E={};function F(a,b,c){this.props=a;this.context=b;this.refs=E;this.updater=c||D}F.prototype.isReactComponent={};F.prototype.setState=function(a,b){if("object"!==typeof a&&"function"!==typeof a&&null!=a)throw Error(C(85));this.updater.enqueueSetState(this,a,b,"setState")};F.prototype.forceUpdate=function(a){this.updater.enqueueForceUpdate(this,a,"forceUpdate")};
+function G(){}G.prototype=F.prototype;function H(a,b,c){this.props=a;this.context=b;this.refs=E;this.updater=c||D}var I=H.prototype=new G;I.constructor=H;l(I,F.prototype);I.isPureReactComponent=!0;var J={current:null},K=Object.prototype.hasOwnProperty,L={key:!0,ref:!0,__self:!0,__source:!0};
+function M(a,b,c){var e,d={},g=null,k=null;if(null!=b)for(e in void 0!==b.ref&&(k=b.ref),void 0!==b.key&&(g=""+b.key),b)K.call(b,e)&&!L.hasOwnProperty(e)&&(d[e]=b[e]);var f=arguments.length-2;if(1===f)d.children=c;else if(1<f){for(var h=Array(f),m=0;m<f;m++)h[m]=arguments[m+2];d.children=h}if(a&&a.defaultProps)for(e in f=a.defaultProps,f)void 0===d[e]&&(d[e]=f[e]);return{$$typeof:p,type:a,key:g,ref:k,props:d,_owner:J.current}}
+function N(a,b){return{$$typeof:p,type:a.type,key:b,ref:a.ref,props:a.props,_owner:a._owner}}function O(a){return"object"===typeof a&&null!==a&&a.$$typeof===p}function escape(a){var b={"=":"=0",":":"=2"};return"$"+(""+a).replace(/[=:]/g,function(a){return b[a]})}var P=/\/+/g,Q=[];function R(a,b,c,e){if(Q.length){var d=Q.pop();d.result=a;d.keyPrefix=b;d.func=c;d.context=e;d.count=0;return d}return{result:a,keyPrefix:b,func:c,context:e,count:0}}
+function S(a){a.result=null;a.keyPrefix=null;a.func=null;a.context=null;a.count=0;10>Q.length&&Q.push(a)}
+function T(a,b,c,e){var d=typeof a;if("undefined"===d||"boolean"===d)a=null;var g=!1;if(null===a)g=!0;else switch(d){case "string":case "number":g=!0;break;case "object":switch(a.$$typeof){case p:case q:g=!0}}if(g)return c(e,a,""===b?"."+U(a,0):b),1;g=0;b=""===b?".":b+":";if(Array.isArray(a))for(var k=0;k<a.length;k++){d=a[k];var f=b+U(d,k);g+=T(d,f,c,e)}else if(null===a||"object"!==typeof a?f=null:(f=B&&a[B]||a["@@iterator"],f="function"===typeof f?f:null),"function"===typeof f)for(a=f.call(a),k=
+0;!(d=a.next()).done;)d=d.value,f=b+U(d,k++),g+=T(d,f,c,e);else if("object"===d)throw c=""+a,Error(C(31,"[object Object]"===c?"object with keys {"+Object.keys(a).join(", ")+"}":c,""));return g}function V(a,b,c){return null==a?0:T(a,"",b,c)}function U(a,b){return"object"===typeof a&&null!==a&&null!=a.key?escape(a.key):b.toString(36)}function W(a,b){a.func.call(a.context,b,a.count++)}
+function aa(a,b,c){var e=a.result,d=a.keyPrefix;a=a.func.call(a.context,b,a.count++);Array.isArray(a)?X(a,e,c,function(a){return a}):null!=a&&(O(a)&&(a=N(a,d+(!a.key||b&&b.key===a.key?"":(""+a.key).replace(P,"$&/")+"/")+c)),e.push(a))}function X(a,b,c,e,d){var g="";null!=c&&(g=(""+c).replace(P,"$&/")+"/");b=R(b,g,e,d);V(a,aa,b);S(b)}var Y={current:null};function Z(){var a=Y.current;if(null===a)throw Error(C(321));return a}
+var ba={ReactCurrentDispatcher:Y,ReactCurrentBatchConfig:{suspense:null},ReactCurrentOwner:J,IsSomeRendererActing:{current:!1},assign:l};exports.Children={map:function(a,b,c){if(null==a)return a;var e=[];X(a,e,null,b,c);return e},forEach:function(a,b,c){if(null==a)return a;b=R(null,null,b,c);V(a,W,b);S(b)},count:function(a){return V(a,function(){return null},null)},toArray:function(a){var b=[];X(a,b,null,function(a){return a});return b},only:function(a){if(!O(a))throw Error(C(143));return a}};
+exports.Component=F;exports.Fragment=r;exports.Profiler=u;exports.PureComponent=H;exports.StrictMode=t;exports.Suspense=y;exports.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED=ba;
+exports.cloneElement=function(a,b,c){if(null===a||void 0===a)throw Error(C(267,a));var e=l({},a.props),d=a.key,g=a.ref,k=a._owner;if(null!=b){void 0!==b.ref&&(g=b.ref,k=J.current);void 0!==b.key&&(d=""+b.key);if(a.type&&a.type.defaultProps)var f=a.type.defaultProps;for(h in b)K.call(b,h)&&!L.hasOwnProperty(h)&&(e[h]=void 0===b[h]&&void 0!==f?f[h]:b[h])}var h=arguments.length-2;if(1===h)e.children=c;else if(1<h){f=Array(h);for(var m=0;m<h;m++)f[m]=arguments[m+2];e.children=f}return{$$typeof:p,type:a.type,
+key:d,ref:g,props:e,_owner:k}};exports.createContext=function(a,b){void 0===b&&(b=null);a={$$typeof:w,_calculateChangedBits:b,_currentValue:a,_currentValue2:a,_threadCount:0,Provider:null,Consumer:null};a.Provider={$$typeof:v,_context:a};return a.Consumer=a};exports.createElement=M;exports.createFactory=function(a){var b=M.bind(null,a);b.type=a;return b};exports.createRef=function(){return{current:null}};exports.forwardRef=function(a){return{$$typeof:x,render:a}};exports.isValidElement=O;
+exports.lazy=function(a){return{$$typeof:A,_ctor:a,_status:-1,_result:null}};exports.memo=function(a,b){return{$$typeof:z,type:a,compare:void 0===b?null:b}};exports.useCallback=function(a,b){return Z().useCallback(a,b)};exports.useContext=function(a,b){return Z().useContext(a,b)};exports.useDebugValue=function(){};exports.useEffect=function(a,b){return Z().useEffect(a,b)};exports.useImperativeHandle=function(a,b,c){return Z().useImperativeHandle(a,b,c)};
+exports.useLayoutEffect=function(a,b){return Z().useLayoutEffect(a,b)};exports.useMemo=function(a,b){return Z().useMemo(a,b)};exports.useReducer=function(a,b,c){return Z().useReducer(a,b,c)};exports.useRef=function(a){return Z().useRef(a)};exports.useState=function(a){return Z().useState(a)};exports.version="16.14.0";
Index: node_modules/react/index.js
===================================================================
--- node_modules/react/index.js	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
+++ node_modules/react/index.js	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
@@ -0,0 +1,7 @@
+'use strict';
+
+if (process.env.NODE_ENV === 'production') {
+  module.exports = require('./cjs/react.production.min.js');
+} else {
+  module.exports = require('./cjs/react.development.js');
+}
Index: node_modules/react/jsx-dev-runtime.js
===================================================================
--- node_modules/react/jsx-dev-runtime.js	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
+++ node_modules/react/jsx-dev-runtime.js	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
@@ -0,0 +1,7 @@
+'use strict';
+
+if (process.env.NODE_ENV === 'production') {
+  module.exports = require('./cjs/react-jsx-dev-runtime.production.min.js');
+} else {
+  module.exports = require('./cjs/react-jsx-dev-runtime.development.js');
+}
Index: node_modules/react/jsx-runtime.js
===================================================================
--- node_modules/react/jsx-runtime.js	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
+++ node_modules/react/jsx-runtime.js	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
@@ -0,0 +1,7 @@
+'use strict';
+
+if (process.env.NODE_ENV === 'production') {
+  module.exports = require('./cjs/react-jsx-runtime.production.min.js');
+} else {
+  module.exports = require('./cjs/react-jsx-runtime.development.js');
+}
Index: node_modules/react/package.json
===================================================================
--- node_modules/react/package.json	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
+++ node_modules/react/package.json	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
@@ -0,0 +1,44 @@
+{
+  "browserify": {
+    "transform": [
+      "loose-envify"
+    ]
+  },
+  "bugs": {
+    "url": "https://github.com/facebook/react/issues"
+  },
+  "bundleDependencies": false,
+  "dependencies": {
+    "loose-envify": "^1.1.0",
+    "object-assign": "^4.1.1",
+    "prop-types": "^15.6.2"
+  },
+  "deprecated": false,
+  "description": "React is a JavaScript library for building user interfaces.",
+  "engines": {
+    "node": ">=0.10.0"
+  },
+  "files": [
+    "LICENSE",
+    "README.md",
+    "build-info.json",
+    "index.js",
+    "cjs/",
+    "umd/",
+    "jsx-runtime.js",
+    "jsx-dev-runtime.js"
+  ],
+  "homepage": "https://reactjs.org/",
+  "keywords": [
+    "react"
+  ],
+  "license": "MIT",
+  "main": "index.js",
+  "name": "react",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/facebook/react.git",
+    "directory": "packages/react"
+  },
+  "version": "16.14.0"
+}
Index: node_modules/react/umd/react.development.js
===================================================================
--- node_modules/react/umd/react.development.js	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
+++ node_modules/react/umd/react.development.js	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
@@ -0,0 +1,3318 @@
+/** @license React v16.14.0
+ * react.development.js
+ *
+ * Copyright (c) Facebook, Inc. and its affiliates.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+'use strict';
+
+(function (global, factory) {
+  typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
+  typeof define === 'function' && define.amd ? define(['exports'], factory) :
+  (global = global || self, factory(global.React = {}));
+}(this, (function (exports) { 'use strict';
+
+  var ReactVersion = '16.14.0';
+
+  // The Symbol used to tag the ReactElement-like types. If there is no native Symbol
+  // nor polyfill, then a plain number is used for performance.
+  var hasSymbol = typeof Symbol === 'function' && Symbol.for;
+  var REACT_ELEMENT_TYPE = hasSymbol ? Symbol.for('react.element') : 0xeac7;
+  var REACT_PORTAL_TYPE = hasSymbol ? Symbol.for('react.portal') : 0xeaca;
+  var REACT_FRAGMENT_TYPE = hasSymbol ? Symbol.for('react.fragment') : 0xeacb;
+  var REACT_STRICT_MODE_TYPE = hasSymbol ? Symbol.for('react.strict_mode') : 0xeacc;
+  var REACT_PROFILER_TYPE = hasSymbol ? Symbol.for('react.profiler') : 0xead2;
+  var REACT_PROVIDER_TYPE = hasSymbol ? Symbol.for('react.provider') : 0xeacd;
+  var REACT_CONTEXT_TYPE = hasSymbol ? Symbol.for('react.context') : 0xeace; // TODO: We don't use AsyncMode or ConcurrentMode anymore. They were temporary
+  var REACT_CONCURRENT_MODE_TYPE = hasSymbol ? Symbol.for('react.concurrent_mode') : 0xeacf;
+  var REACT_FORWARD_REF_TYPE = hasSymbol ? Symbol.for('react.forward_ref') : 0xead0;
+  var REACT_SUSPENSE_TYPE = hasSymbol ? Symbol.for('react.suspense') : 0xead1;
+  var REACT_SUSPENSE_LIST_TYPE = hasSymbol ? Symbol.for('react.suspense_list') : 0xead8;
+  var REACT_MEMO_TYPE = hasSymbol ? Symbol.for('react.memo') : 0xead3;
+  var REACT_LAZY_TYPE = hasSymbol ? Symbol.for('react.lazy') : 0xead4;
+  var REACT_BLOCK_TYPE = hasSymbol ? Symbol.for('react.block') : 0xead9;
+  var REACT_FUNDAMENTAL_TYPE = hasSymbol ? Symbol.for('react.fundamental') : 0xead5;
+  var REACT_RESPONDER_TYPE = hasSymbol ? Symbol.for('react.responder') : 0xead6;
+  var REACT_SCOPE_TYPE = hasSymbol ? Symbol.for('react.scope') : 0xead7;
+  var MAYBE_ITERATOR_SYMBOL = typeof Symbol === 'function' && Symbol.iterator;
+  var FAUX_ITERATOR_SYMBOL = '@@iterator';
+  function getIteratorFn(maybeIterable) {
+    if (maybeIterable === null || typeof maybeIterable !== 'object') {
+      return null;
+    }
+
+    var maybeIterator = MAYBE_ITERATOR_SYMBOL && maybeIterable[MAYBE_ITERATOR_SYMBOL] || maybeIterable[FAUX_ITERATOR_SYMBOL];
+
+    if (typeof maybeIterator === 'function') {
+      return maybeIterator;
+    }
+
+    return null;
+  }
+
+  /*
+  object-assign
+  (c) Sindre Sorhus
+  @license MIT
+  */
+  /* eslint-disable no-unused-vars */
+  var getOwnPropertySymbols = Object.getOwnPropertySymbols;
+  var hasOwnProperty = Object.prototype.hasOwnProperty;
+  var propIsEnumerable = Object.prototype.propertyIsEnumerable;
+
+  function toObject(val) {
+  	if (val === null || val === undefined) {
+  		throw new TypeError('Object.assign cannot be called with null or undefined');
+  	}
+
+  	return Object(val);
+  }
+
+  function shouldUseNative() {
+  	try {
+  		if (!Object.assign) {
+  			return false;
+  		}
+
+  		// Detect buggy property enumeration order in older V8 versions.
+
+  		// https://bugs.chromium.org/p/v8/issues/detail?id=4118
+  		var test1 = new String('abc');  // eslint-disable-line no-new-wrappers
+  		test1[5] = 'de';
+  		if (Object.getOwnPropertyNames(test1)[0] === '5') {
+  			return false;
+  		}
+
+  		// https://bugs.chromium.org/p/v8/issues/detail?id=3056
+  		var test2 = {};
+  		for (var i = 0; i < 10; i++) {
+  			test2['_' + String.fromCharCode(i)] = i;
+  		}
+  		var order2 = Object.getOwnPropertyNames(test2).map(function (n) {
+  			return test2[n];
+  		});
+  		if (order2.join('') !== '0123456789') {
+  			return false;
+  		}
+
+  		// https://bugs.chromium.org/p/v8/issues/detail?id=3056
+  		var test3 = {};
+  		'abcdefghijklmnopqrst'.split('').forEach(function (letter) {
+  			test3[letter] = letter;
+  		});
+  		if (Object.keys(Object.assign({}, test3)).join('') !==
+  				'abcdefghijklmnopqrst') {
+  			return false;
+  		}
+
+  		return true;
+  	} catch (err) {
+  		// We don't expect any of the above to throw, but better to be safe.
+  		return false;
+  	}
+  }
+
+  var objectAssign = shouldUseNative() ? Object.assign : function (target, source) {
+  	var from;
+  	var to = toObject(target);
+  	var symbols;
+
+  	for (var s = 1; s < arguments.length; s++) {
+  		from = Object(arguments[s]);
+
+  		for (var key in from) {
+  			if (hasOwnProperty.call(from, key)) {
+  				to[key] = from[key];
+  			}
+  		}
+
+  		if (getOwnPropertySymbols) {
+  			symbols = getOwnPropertySymbols(from);
+  			for (var i = 0; i < symbols.length; i++) {
+  				if (propIsEnumerable.call(from, symbols[i])) {
+  					to[symbols[i]] = from[symbols[i]];
+  				}
+  			}
+  		}
+  	}
+
+  	return to;
+  };
+
+  /**
+   * Keeps track of the current dispatcher.
+   */
+  var ReactCurrentDispatcher = {
+    /**
+     * @internal
+     * @type {ReactComponent}
+     */
+    current: null
+  };
+
+  /**
+   * Keeps track of the current batch's configuration such as how long an update
+   * should suspend for if it needs to.
+   */
+  var ReactCurrentBatchConfig = {
+    suspense: null
+  };
+
+  /**
+   * Keeps track of the current owner.
+   *
+   * The current owner is the component who should own any components that are
+   * currently being constructed.
+   */
+  var ReactCurrentOwner = {
+    /**
+     * @internal
+     * @type {ReactComponent}
+     */
+    current: null
+  };
+
+  var BEFORE_SLASH_RE = /^(.*)[\\\/]/;
+  function describeComponentFrame (name, source, ownerName) {
+    var sourceInfo = '';
+
+    if (source) {
+      var path = source.fileName;
+      var fileName = path.replace(BEFORE_SLASH_RE, '');
+
+      {
+        // In DEV, include code for a common special case:
+        // prefer "folder/index.js" instead of just "index.js".
+        if (/^index\./.test(fileName)) {
+          var match = path.match(BEFORE_SLASH_RE);
+
+          if (match) {
+            var pathBeforeSlash = match[1];
+
+            if (pathBeforeSlash) {
+              var folderName = pathBeforeSlash.replace(BEFORE_SLASH_RE, '');
+              fileName = folderName + '/' + fileName;
+            }
+          }
+        }
+      }
+
+      sourceInfo = ' (at ' + fileName + ':' + source.lineNumber + ')';
+    } else if (ownerName) {
+      sourceInfo = ' (created by ' + ownerName + ')';
+    }
+
+    return '\n    in ' + (name || 'Unknown') + sourceInfo;
+  }
+
+  var Resolved = 1;
+  function refineResolvedLazyComponent(lazyComponent) {
+    return lazyComponent._status === Resolved ? lazyComponent._result : null;
+  }
+
+  function getWrappedName(outerType, innerType, wrapperName) {
+    var functionName = innerType.displayName || innerType.name || '';
+    return outerType.displayName || (functionName !== '' ? wrapperName + "(" + functionName + ")" : wrapperName);
+  }
+
+  function getComponentName(type) {
+    if (type == null) {
+      // Host root, text node or just invalid type.
+      return null;
+    }
+
+    {
+      if (typeof type.tag === 'number') {
+        error('Received an unexpected object in getComponentName(). ' + 'This is likely a bug in React. Please file an issue.');
+      }
+    }
+
+    if (typeof type === 'function') {
+      return type.displayName || type.name || null;
+    }
+
+    if (typeof type === 'string') {
+      return type;
+    }
+
+    switch (type) {
+      case REACT_FRAGMENT_TYPE:
+        return 'Fragment';
+
+      case REACT_PORTAL_TYPE:
+        return 'Portal';
+
+      case REACT_PROFILER_TYPE:
+        return "Profiler";
+
+      case REACT_STRICT_MODE_TYPE:
+        return 'StrictMode';
+
+      case REACT_SUSPENSE_TYPE:
+        return 'Suspense';
+
+      case REACT_SUSPENSE_LIST_TYPE:
+        return 'SuspenseList';
+    }
+
+    if (typeof type === 'object') {
+      switch (type.$$typeof) {
+        case REACT_CONTEXT_TYPE:
+          return 'Context.Consumer';
+
+        case REACT_PROVIDER_TYPE:
+          return 'Context.Provider';
+
+        case REACT_FORWARD_REF_TYPE:
+          return getWrappedName(type, type.render, 'ForwardRef');
+
+        case REACT_MEMO_TYPE:
+          return getComponentName(type.type);
+
+        case REACT_BLOCK_TYPE:
+          return getComponentName(type.render);
+
+        case REACT_LAZY_TYPE:
+          {
+            var thenable = type;
+            var resolvedThenable = refineResolvedLazyComponent(thenable);
+
+            if (resolvedThenable) {
+              return getComponentName(resolvedThenable);
+            }
+
+            break;
+          }
+      }
+    }
+
+    return null;
+  }
+
+  var ReactDebugCurrentFrame = {};
+  var currentlyValidatingElement = null;
+  function setCurrentlyValidatingElement(element) {
+    {
+      currentlyValidatingElement = element;
+    }
+  }
+
+  {
+    // Stack implementation injected by the current renderer.
+    ReactDebugCurrentFrame.getCurrentStack = null;
+
+    ReactDebugCurrentFrame.getStackAddendum = function () {
+      var stack = ''; // Add an extra top frame while an element is being validated
+
+      if (currentlyValidatingElement) {
+        var name = getComponentName(currentlyValidatingElement.type);
+        var owner = currentlyValidatingElement._owner;
+        stack += describeComponentFrame(name, currentlyValidatingElement._source, owner && getComponentName(owner.type));
+      } // Delegate to the injected renderer-specific implementation
+
+
+      var impl = ReactDebugCurrentFrame.getCurrentStack;
+
+      if (impl) {
+        stack += impl() || '';
+      }
+
+      return stack;
+    };
+  }
+
+  /**
+   * Used by act() to track whether you're inside an act() scope.
+   */
+  var IsSomeRendererActing = {
+    current: false
+  };
+
+  var ReactSharedInternals = {
+    ReactCurrentDispatcher: ReactCurrentDispatcher,
+    ReactCurrentBatchConfig: ReactCurrentBatchConfig,
+    ReactCurrentOwner: ReactCurrentOwner,
+    IsSomeRendererActing: IsSomeRendererActing,
+    // Used by renderers to avoid bundling object-assign twice in UMD bundles:
+    assign: objectAssign
+  };
+
+  {
+    objectAssign(ReactSharedInternals, {
+      // These should not be included in production.
+      ReactDebugCurrentFrame: ReactDebugCurrentFrame,
+      // Shim for React DOM 16.0.0 which still destructured (but not used) this.
+      // TODO: remove in React 17.0.
+      ReactComponentTreeHook: {}
+    });
+  }
+
+  // by calls to these methods by a Babel plugin.
+  //
+  // In PROD (or in packages without access to React internals),
+  // they are left as they are instead.
+
+  function warn(format) {
+    {
+      for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
+        args[_key - 1] = arguments[_key];
+      }
+
+      printWarning('warn', format, args);
+    }
+  }
+  function error(format) {
+    {
+      for (var _len2 = arguments.length, args = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {
+        args[_key2 - 1] = arguments[_key2];
+      }
+
+      printWarning('error', format, args);
+    }
+  }
+
+  function printWarning(level, format, args) {
+    // When changing this logic, you might want to also
+    // update consoleWithStackDev.www.js as well.
+    {
+      var hasExistingStack = args.length > 0 && typeof args[args.length - 1] === 'string' && args[args.length - 1].indexOf('\n    in') === 0;
+
+      if (!hasExistingStack) {
+        var ReactDebugCurrentFrame = ReactSharedInternals.ReactDebugCurrentFrame;
+        var stack = ReactDebugCurrentFrame.getStackAddendum();
+
+        if (stack !== '') {
+          format += '%s';
+          args = args.concat([stack]);
+        }
+      }
+
+      var argsWithFormat = args.map(function (item) {
+        return '' + item;
+      }); // Careful: RN currently depends on this prefix
+
+      argsWithFormat.unshift('Warning: ' + format); // We intentionally don't use spread (or .apply) directly because it
+      // breaks IE9: https://github.com/facebook/react/issues/13610
+      // eslint-disable-next-line react-internal/no-production-logging
+
+      Function.prototype.apply.call(console[level], console, argsWithFormat);
+
+      try {
+        // --- Welcome to debugging React ---
+        // This error was thrown as a convenience so that you can use this stack
+        // to find the callsite that caused this warning to fire.
+        var argIndex = 0;
+        var message = 'Warning: ' + format.replace(/%s/g, function () {
+          return args[argIndex++];
+        });
+        throw new Error(message);
+      } catch (x) {}
+    }
+  }
+
+  var didWarnStateUpdateForUnmountedComponent = {};
+
+  function warnNoop(publicInstance, callerName) {
+    {
+      var _constructor = publicInstance.constructor;
+      var componentName = _constructor && (_constructor.displayName || _constructor.name) || 'ReactClass';
+      var warningKey = componentName + "." + callerName;
+
+      if (didWarnStateUpdateForUnmountedComponent[warningKey]) {
+        return;
+      }
+
+      error("Can't call %s on a component that is not yet mounted. " + 'This is a no-op, but it might indicate a bug in your application. ' + 'Instead, assign to `this.state` directly or define a `state = {};` ' + 'class property with the desired state in the %s component.', callerName, componentName);
+
+      didWarnStateUpdateForUnmountedComponent[warningKey] = true;
+    }
+  }
+  /**
+   * This is the abstract API for an update queue.
+   */
+
+
+  var ReactNoopUpdateQueue = {
+    /**
+     * Checks whether or not this composite component is mounted.
+     * @param {ReactClass} publicInstance The instance we want to test.
+     * @return {boolean} True if mounted, false otherwise.
+     * @protected
+     * @final
+     */
+    isMounted: function (publicInstance) {
+      return false;
+    },
+
+    /**
+     * Forces an update. This should only be invoked when it is known with
+     * certainty that we are **not** in a DOM transaction.
+     *
+     * You may want to call this when you know that some deeper aspect of the
+     * component's state has changed but `setState` was not called.
+     *
+     * This will not invoke `shouldComponentUpdate`, but it will invoke
+     * `componentWillUpdate` and `componentDidUpdate`.
+     *
+     * @param {ReactClass} publicInstance The instance that should rerender.
+     * @param {?function} callback Called after component is updated.
+     * @param {?string} callerName name of the calling function in the public API.
+     * @internal
+     */
+    enqueueForceUpdate: function (publicInstance, callback, callerName) {
+      warnNoop(publicInstance, 'forceUpdate');
+    },
+
+    /**
+     * Replaces all of the state. Always use this or `setState` to mutate state.
+     * You should treat `this.state` as immutable.
+     *
+     * There is no guarantee that `this.state` will be immediately updated, so
+     * accessing `this.state` after calling this method may return the old value.
+     *
+     * @param {ReactClass} publicInstance The instance that should rerender.
+     * @param {object} completeState Next state.
+     * @param {?function} callback Called after component is updated.
+     * @param {?string} callerName name of the calling function in the public API.
+     * @internal
+     */
+    enqueueReplaceState: function (publicInstance, completeState, callback, callerName) {
+      warnNoop(publicInstance, 'replaceState');
+    },
+
+    /**
+     * Sets a subset of the state. This only exists because _pendingState is
+     * internal. This provides a merging strategy that is not available to deep
+     * properties which is confusing. TODO: Expose pendingState or don't use it
+     * during the merge.
+     *
+     * @param {ReactClass} publicInstance The instance that should rerender.
+     * @param {object} partialState Next partial state to be merged with state.
+     * @param {?function} callback Called after component is updated.
+     * @param {?string} Name of the calling function in the public API.
+     * @internal
+     */
+    enqueueSetState: function (publicInstance, partialState, callback, callerName) {
+      warnNoop(publicInstance, 'setState');
+    }
+  };
+
+  var emptyObject = {};
+
+  {
+    Object.freeze(emptyObject);
+  }
+  /**
+   * Base class helpers for the updating state of a component.
+   */
+
+
+  function Component(props, context, updater) {
+    this.props = props;
+    this.context = context; // If a component has string refs, we will assign a different object later.
+
+    this.refs = emptyObject; // We initialize the default updater but the real one gets injected by the
+    // renderer.
+
+    this.updater = updater || ReactNoopUpdateQueue;
+  }
+
+  Component.prototype.isReactComponent = {};
+  /**
+   * Sets a subset of the state. Always use this to mutate
+   * state. You should treat `this.state` as immutable.
+   *
+   * There is no guarantee that `this.state` will be immediately updated, so
+   * accessing `this.state` after calling this method may return the old value.
+   *
+   * There is no guarantee that calls to `setState` will run synchronously,
+   * as they may eventually be batched together.  You can provide an optional
+   * callback that will be executed when the call to setState is actually
+   * completed.
+   *
+   * When a function is provided to setState, it will be called at some point in
+   * the future (not synchronously). It will be called with the up to date
+   * component arguments (state, props, context). These values can be different
+   * from this.* because your function may be called after receiveProps but before
+   * shouldComponentUpdate, and this new state, props, and context will not yet be
+   * assigned to this.
+   *
+   * @param {object|function} partialState Next partial state or function to
+   *        produce next partial state to be merged with current state.
+   * @param {?function} callback Called after state is updated.
+   * @final
+   * @protected
+   */
+
+  Component.prototype.setState = function (partialState, callback) {
+    if (!(typeof partialState === 'object' || typeof partialState === 'function' || partialState == null)) {
+      {
+        throw Error( "setState(...): takes an object of state variables to update or a function which returns an object of state variables." );
+      }
+    }
+
+    this.updater.enqueueSetState(this, partialState, callback, 'setState');
+  };
+  /**
+   * Forces an update. This should only be invoked when it is known with
+   * certainty that we are **not** in a DOM transaction.
+   *
+   * You may want to call this when you know that some deeper aspect of the
+   * component's state has changed but `setState` was not called.
+   *
+   * This will not invoke `shouldComponentUpdate`, but it will invoke
+   * `componentWillUpdate` and `componentDidUpdate`.
+   *
+   * @param {?function} callback Called after update is complete.
+   * @final
+   * @protected
+   */
+
+
+  Component.prototype.forceUpdate = function (callback) {
+    this.updater.enqueueForceUpdate(this, callback, 'forceUpdate');
+  };
+  /**
+   * Deprecated APIs. These APIs used to exist on classic React classes but since
+   * we would like to deprecate them, we're not going to move them over to this
+   * modern base class. Instead, we define a getter that warns if it's accessed.
+   */
+
+
+  {
+    var deprecatedAPIs = {
+      isMounted: ['isMounted', 'Instead, make sure to clean up subscriptions and pending requests in ' + 'componentWillUnmount to prevent memory leaks.'],
+      replaceState: ['replaceState', 'Refactor your code to use setState instead (see ' + 'https://github.com/facebook/react/issues/3236).']
+    };
+
+    var defineDeprecationWarning = function (methodName, info) {
+      Object.defineProperty(Component.prototype, methodName, {
+        get: function () {
+          warn('%s(...) is deprecated in plain JavaScript React classes. %s', info[0], info[1]);
+
+          return undefined;
+        }
+      });
+    };
+
+    for (var fnName in deprecatedAPIs) {
+      if (deprecatedAPIs.hasOwnProperty(fnName)) {
+        defineDeprecationWarning(fnName, deprecatedAPIs[fnName]);
+      }
+    }
+  }
+
+  function ComponentDummy() {}
+
+  ComponentDummy.prototype = Component.prototype;
+  /**
+   * Convenience component with default shallow equality check for sCU.
+   */
+
+  function PureComponent(props, context, updater) {
+    this.props = props;
+    this.context = context; // If a component has string refs, we will assign a different object later.
+
+    this.refs = emptyObject;
+    this.updater = updater || ReactNoopUpdateQueue;
+  }
+
+  var pureComponentPrototype = PureComponent.prototype = new ComponentDummy();
+  pureComponentPrototype.constructor = PureComponent; // Avoid an extra prototype jump for these methods.
+
+  objectAssign(pureComponentPrototype, Component.prototype);
+
+  pureComponentPrototype.isPureReactComponent = true;
+
+  // an immutable object with a single mutable value
+  function createRef() {
+    var refObject = {
+      current: null
+    };
+
+    {
+      Object.seal(refObject);
+    }
+
+    return refObject;
+  }
+
+  var hasOwnProperty$1 = Object.prototype.hasOwnProperty;
+  var RESERVED_PROPS = {
+    key: true,
+    ref: true,
+    __self: true,
+    __source: true
+  };
+  var specialPropKeyWarningShown, specialPropRefWarningShown, didWarnAboutStringRefs;
+
+  {
+    didWarnAboutStringRefs = {};
+  }
+
+  function hasValidRef(config) {
+    {
+      if (hasOwnProperty$1.call(config, 'ref')) {
+        var getter = Object.getOwnPropertyDescriptor(config, 'ref').get;
+
+        if (getter && getter.isReactWarning) {
+          return false;
+        }
+      }
+    }
+
+    return config.ref !== undefined;
+  }
+
+  function hasValidKey(config) {
+    {
+      if (hasOwnProperty$1.call(config, 'key')) {
+        var getter = Object.getOwnPropertyDescriptor(config, 'key').get;
+
+        if (getter && getter.isReactWarning) {
+          return false;
+        }
+      }
+    }
+
+    return config.key !== undefined;
+  }
+
+  function defineKeyPropWarningGetter(props, displayName) {
+    var warnAboutAccessingKey = function () {
+      {
+        if (!specialPropKeyWarningShown) {
+          specialPropKeyWarningShown = true;
+
+          error('%s: `key` is not a prop. Trying to access it will result ' + 'in `undefined` being returned. If you need to access the same ' + 'value within the child component, you should pass it as a different ' + 'prop. (https://fb.me/react-special-props)', displayName);
+        }
+      }
+    };
+
+    warnAboutAccessingKey.isReactWarning = true;
+    Object.defineProperty(props, 'key', {
+      get: warnAboutAccessingKey,
+      configurable: true
+    });
+  }
+
+  function defineRefPropWarningGetter(props, displayName) {
+    var warnAboutAccessingRef = function () {
+      {
+        if (!specialPropRefWarningShown) {
+          specialPropRefWarningShown = true;
+
+          error('%s: `ref` is not a prop. Trying to access it will result ' + 'in `undefined` being returned. If you need to access the same ' + 'value within the child component, you should pass it as a different ' + 'prop. (https://fb.me/react-special-props)', displayName);
+        }
+      }
+    };
+
+    warnAboutAccessingRef.isReactWarning = true;
+    Object.defineProperty(props, 'ref', {
+      get: warnAboutAccessingRef,
+      configurable: true
+    });
+  }
+
+  function warnIfStringRefCannotBeAutoConverted(config) {
+    {
+      if (typeof config.ref === 'string' && ReactCurrentOwner.current && config.__self && ReactCurrentOwner.current.stateNode !== config.__self) {
+        var componentName = getComponentName(ReactCurrentOwner.current.type);
+
+        if (!didWarnAboutStringRefs[componentName]) {
+          error('Component "%s" contains the string ref "%s". ' + 'Support for string refs will be removed in a future major release. ' + 'This case cannot be automatically converted to an arrow function. ' + 'We ask you to manually fix this case by using useRef() or createRef() instead. ' + 'Learn more about using refs safely here: ' + 'https://fb.me/react-strict-mode-string-ref', getComponentName(ReactCurrentOwner.current.type), config.ref);
+
+          didWarnAboutStringRefs[componentName] = true;
+        }
+      }
+    }
+  }
+  /**
+   * Factory method to create a new React element. This no longer adheres to
+   * the class pattern, so do not use new to call it. Also, instanceof check
+   * will not work. Instead test $$typeof field against Symbol.for('react.element') to check
+   * if something is a React Element.
+   *
+   * @param {*} type
+   * @param {*} props
+   * @param {*} key
+   * @param {string|object} ref
+   * @param {*} owner
+   * @param {*} self A *temporary* helper to detect places where `this` is
+   * different from the `owner` when React.createElement is called, so that we
+   * can warn. We want to get rid of owner and replace string `ref`s with arrow
+   * functions, and as long as `this` and owner are the same, there will be no
+   * change in behavior.
+   * @param {*} source An annotation object (added by a transpiler or otherwise)
+   * indicating filename, line number, and/or other information.
+   * @internal
+   */
+
+
+  var ReactElement = function (type, key, ref, self, source, owner, props) {
+    var element = {
+      // This tag allows us to uniquely identify this as a React Element
+      $$typeof: REACT_ELEMENT_TYPE,
+      // Built-in properties that belong on the element
+      type: type,
+      key: key,
+      ref: ref,
+      props: props,
+      // Record the component responsible for creating this element.
+      _owner: owner
+    };
+
+    {
+      // The validation flag is currently mutative. We put it on
+      // an external backing store so that we can freeze the whole object.
+      // This can be replaced with a WeakMap once they are implemented in
+      // commonly used development environments.
+      element._store = {}; // To make comparing ReactElements easier for testing purposes, we make
+      // the validation flag non-enumerable (where possible, which should
+      // include every environment we run tests in), so the test framework
+      // ignores it.
+
+      Object.defineProperty(element._store, 'validated', {
+        configurable: false,
+        enumerable: false,
+        writable: true,
+        value: false
+      }); // self and source are DEV only properties.
+
+      Object.defineProperty(element, '_self', {
+        configurable: false,
+        enumerable: false,
+        writable: false,
+        value: self
+      }); // Two elements created in two different places should be considered
+      // equal for testing purposes and therefore we hide it from enumeration.
+
+      Object.defineProperty(element, '_source', {
+        configurable: false,
+        enumerable: false,
+        writable: false,
+        value: source
+      });
+
+      if (Object.freeze) {
+        Object.freeze(element.props);
+        Object.freeze(element);
+      }
+    }
+
+    return element;
+  };
+  /**
+   * Create and return a new ReactElement of the given type.
+   * See https://reactjs.org/docs/react-api.html#createelement
+   */
+
+  function createElement(type, config, children) {
+    var propName; // Reserved names are extracted
+
+    var props = {};
+    var key = null;
+    var ref = null;
+    var self = null;
+    var source = null;
+
+    if (config != null) {
+      if (hasValidRef(config)) {
+        ref = config.ref;
+
+        {
+          warnIfStringRefCannotBeAutoConverted(config);
+        }
+      }
+
+      if (hasValidKey(config)) {
+        key = '' + config.key;
+      }
+
+      self = config.__self === undefined ? null : config.__self;
+      source = config.__source === undefined ? null : config.__source; // Remaining properties are added to a new props object
+
+      for (propName in config) {
+        if (hasOwnProperty$1.call(config, propName) && !RESERVED_PROPS.hasOwnProperty(propName)) {
+          props[propName] = config[propName];
+        }
+      }
+    } // Children can be more than one argument, and those are transferred onto
+    // the newly allocated props object.
+
+
+    var childrenLength = arguments.length - 2;
+
+    if (childrenLength === 1) {
+      props.children = children;
+    } else if (childrenLength > 1) {
+      var childArray = Array(childrenLength);
+
+      for (var i = 0; i < childrenLength; i++) {
+        childArray[i] = arguments[i + 2];
+      }
+
+      {
+        if (Object.freeze) {
+          Object.freeze(childArray);
+        }
+      }
+
+      props.children = childArray;
+    } // Resolve default props
+
+
+    if (type && type.defaultProps) {
+      var defaultProps = type.defaultProps;
+
+      for (propName in defaultProps) {
+        if (props[propName] === undefined) {
+          props[propName] = defaultProps[propName];
+        }
+      }
+    }
+
+    {
+      if (key || ref) {
+        var displayName = typeof type === 'function' ? type.displayName || type.name || 'Unknown' : type;
+
+        if (key) {
+          defineKeyPropWarningGetter(props, displayName);
+        }
+
+        if (ref) {
+          defineRefPropWarningGetter(props, displayName);
+        }
+      }
+    }
+
+    return ReactElement(type, key, ref, self, source, ReactCurrentOwner.current, props);
+  }
+  function cloneAndReplaceKey(oldElement, newKey) {
+    var newElement = ReactElement(oldElement.type, newKey, oldElement.ref, oldElement._self, oldElement._source, oldElement._owner, oldElement.props);
+    return newElement;
+  }
+  /**
+   * Clone and return a new ReactElement using element as the starting point.
+   * See https://reactjs.org/docs/react-api.html#cloneelement
+   */
+
+  function cloneElement(element, config, children) {
+    if (!!(element === null || element === undefined)) {
+      {
+        throw Error( "React.cloneElement(...): The argument must be a React element, but you passed " + element + "." );
+      }
+    }
+
+    var propName; // Original props are copied
+
+    var props = objectAssign({}, element.props); // Reserved names are extracted
+
+
+    var key = element.key;
+    var ref = element.ref; // Self is preserved since the owner is preserved.
+
+    var self = element._self; // Source is preserved since cloneElement is unlikely to be targeted by a
+    // transpiler, and the original source is probably a better indicator of the
+    // true owner.
+
+    var source = element._source; // Owner will be preserved, unless ref is overridden
+
+    var owner = element._owner;
+
+    if (config != null) {
+      if (hasValidRef(config)) {
+        // Silently steal the ref from the parent.
+        ref = config.ref;
+        owner = ReactCurrentOwner.current;
+      }
+
+      if (hasValidKey(config)) {
+        key = '' + config.key;
+      } // Remaining properties override existing props
+
+
+      var defaultProps;
+
+      if (element.type && element.type.defaultProps) {
+        defaultProps = element.type.defaultProps;
+      }
+
+      for (propName in config) {
+        if (hasOwnProperty$1.call(config, propName) && !RESERVED_PROPS.hasOwnProperty(propName)) {
+          if (config[propName] === undefined && defaultProps !== undefined) {
+            // Resolve default props
+            props[propName] = defaultProps[propName];
+          } else {
+            props[propName] = config[propName];
+          }
+        }
+      }
+    } // Children can be more than one argument, and those are transferred onto
+    // the newly allocated props object.
+
+
+    var childrenLength = arguments.length - 2;
+
+    if (childrenLength === 1) {
+      props.children = children;
+    } else if (childrenLength > 1) {
+      var childArray = Array(childrenLength);
+
+      for (var i = 0; i < childrenLength; i++) {
+        childArray[i] = arguments[i + 2];
+      }
+
+      props.children = childArray;
+    }
+
+    return ReactElement(element.type, key, ref, self, source, owner, props);
+  }
+  /**
+   * Verifies the object is a ReactElement.
+   * See https://reactjs.org/docs/react-api.html#isvalidelement
+   * @param {?object} object
+   * @return {boolean} True if `object` is a ReactElement.
+   * @final
+   */
+
+  function isValidElement(object) {
+    return typeof object === 'object' && object !== null && object.$$typeof === REACT_ELEMENT_TYPE;
+  }
+
+  var SEPARATOR = '.';
+  var SUBSEPARATOR = ':';
+  /**
+   * Escape and wrap key so it is safe to use as a reactid
+   *
+   * @param {string} key to be escaped.
+   * @return {string} the escaped key.
+   */
+
+  function escape(key) {
+    var escapeRegex = /[=:]/g;
+    var escaperLookup = {
+      '=': '=0',
+      ':': '=2'
+    };
+    var escapedString = ('' + key).replace(escapeRegex, function (match) {
+      return escaperLookup[match];
+    });
+    return '$' + escapedString;
+  }
+  /**
+   * TODO: Test that a single child and an array with one item have the same key
+   * pattern.
+   */
+
+
+  var didWarnAboutMaps = false;
+  var userProvidedKeyEscapeRegex = /\/+/g;
+
+  function escapeUserProvidedKey(text) {
+    return ('' + text).replace(userProvidedKeyEscapeRegex, '$&/');
+  }
+
+  var POOL_SIZE = 10;
+  var traverseContextPool = [];
+
+  function getPooledTraverseContext(mapResult, keyPrefix, mapFunction, mapContext) {
+    if (traverseContextPool.length) {
+      var traverseContext = traverseContextPool.pop();
+      traverseContext.result = mapResult;
+      traverseContext.keyPrefix = keyPrefix;
+      traverseContext.func = mapFunction;
+      traverseContext.context = mapContext;
+      traverseContext.count = 0;
+      return traverseContext;
+    } else {
+      return {
+        result: mapResult,
+        keyPrefix: keyPrefix,
+        func: mapFunction,
+        context: mapContext,
+        count: 0
+      };
+    }
+  }
+
+  function releaseTraverseContext(traverseContext) {
+    traverseContext.result = null;
+    traverseContext.keyPrefix = null;
+    traverseContext.func = null;
+    traverseContext.context = null;
+    traverseContext.count = 0;
+
+    if (traverseContextPool.length < POOL_SIZE) {
+      traverseContextPool.push(traverseContext);
+    }
+  }
+  /**
+   * @param {?*} children Children tree container.
+   * @param {!string} nameSoFar Name of the key path so far.
+   * @param {!function} callback Callback to invoke with each child found.
+   * @param {?*} traverseContext Used to pass information throughout the traversal
+   * process.
+   * @return {!number} The number of children in this subtree.
+   */
+
+
+  function traverseAllChildrenImpl(children, nameSoFar, callback, traverseContext) {
+    var type = typeof children;
+
+    if (type === 'undefined' || type === 'boolean') {
+      // All of the above are perceived as null.
+      children = null;
+    }
+
+    var invokeCallback = false;
+
+    if (children === null) {
+      invokeCallback = true;
+    } else {
+      switch (type) {
+        case 'string':
+        case 'number':
+          invokeCallback = true;
+          break;
+
+        case 'object':
+          switch (children.$$typeof) {
+            case REACT_ELEMENT_TYPE:
+            case REACT_PORTAL_TYPE:
+              invokeCallback = true;
+          }
+
+      }
+    }
+
+    if (invokeCallback) {
+      callback(traverseContext, children, // If it's the only child, treat the name as if it was wrapped in an array
+      // so that it's consistent if the number of children grows.
+      nameSoFar === '' ? SEPARATOR + getComponentKey(children, 0) : nameSoFar);
+      return 1;
+    }
+
+    var child;
+    var nextName;
+    var subtreeCount = 0; // Count of children found in the current subtree.
+
+    var nextNamePrefix = nameSoFar === '' ? SEPARATOR : nameSoFar + SUBSEPARATOR;
+
+    if (Array.isArray(children)) {
+      for (var i = 0; i < children.length; i++) {
+        child = children[i];
+        nextName = nextNamePrefix + getComponentKey(child, i);
+        subtreeCount += traverseAllChildrenImpl(child, nextName, callback, traverseContext);
+      }
+    } else {
+      var iteratorFn = getIteratorFn(children);
+
+      if (typeof iteratorFn === 'function') {
+
+        {
+          // Warn about using Maps as children
+          if (iteratorFn === children.entries) {
+            if (!didWarnAboutMaps) {
+              warn('Using Maps as children is deprecated and will be removed in ' + 'a future major release. Consider converting children to ' + 'an array of keyed ReactElements instead.');
+            }
+
+            didWarnAboutMaps = true;
+          }
+        }
+
+        var iterator = iteratorFn.call(children);
+        var step;
+        var ii = 0;
+
+        while (!(step = iterator.next()).done) {
+          child = step.value;
+          nextName = nextNamePrefix + getComponentKey(child, ii++);
+          subtreeCount += traverseAllChildrenImpl(child, nextName, callback, traverseContext);
+        }
+      } else if (type === 'object') {
+        var addendum = '';
+
+        {
+          addendum = ' If you meant to render a collection of children, use an array ' + 'instead.' + ReactDebugCurrentFrame.getStackAddendum();
+        }
+
+        var childrenString = '' + children;
+
+        {
+          {
+            throw Error( "Objects are not valid as a React child (found: " + (childrenString === '[object Object]' ? 'object with keys {' + Object.keys(children).join(', ') + '}' : childrenString) + ")." + addendum );
+          }
+        }
+      }
+    }
+
+    return subtreeCount;
+  }
+  /**
+   * Traverses children that are typically specified as `props.children`, but
+   * might also be specified through attributes:
+   *
+   * - `traverseAllChildren(this.props.children, ...)`
+   * - `traverseAllChildren(this.props.leftPanelChildren, ...)`
+   *
+   * The `traverseContext` is an optional argument that is passed through the
+   * entire traversal. It can be used to store accumulations or anything else that
+   * the callback might find relevant.
+   *
+   * @param {?*} children Children tree object.
+   * @param {!function} callback To invoke upon traversing each child.
+   * @param {?*} traverseContext Context for traversal.
+   * @return {!number} The number of children in this subtree.
+   */
+
+
+  function traverseAllChildren(children, callback, traverseContext) {
+    if (children == null) {
+      return 0;
+    }
+
+    return traverseAllChildrenImpl(children, '', callback, traverseContext);
+  }
+  /**
+   * Generate a key string that identifies a component within a set.
+   *
+   * @param {*} component A component that could contain a manual key.
+   * @param {number} index Index that is used if a manual key is not provided.
+   * @return {string}
+   */
+
+
+  function getComponentKey(component, index) {
+    // Do some typechecking here since we call this blindly. We want to ensure
+    // that we don't block potential future ES APIs.
+    if (typeof component === 'object' && component !== null && component.key != null) {
+      // Explicit key
+      return escape(component.key);
+    } // Implicit key determined by the index in the set
+
+
+    return index.toString(36);
+  }
+
+  function forEachSingleChild(bookKeeping, child, name) {
+    var func = bookKeeping.func,
+        context = bookKeeping.context;
+    func.call(context, child, bookKeeping.count++);
+  }
+  /**
+   * Iterates through children that are typically specified as `props.children`.
+   *
+   * See https://reactjs.org/docs/react-api.html#reactchildrenforeach
+   *
+   * The provided forEachFunc(child, index) will be called for each
+   * leaf child.
+   *
+   * @param {?*} children Children tree container.
+   * @param {function(*, int)} forEachFunc
+   * @param {*} forEachContext Context for forEachContext.
+   */
+
+
+  function forEachChildren(children, forEachFunc, forEachContext) {
+    if (children == null) {
+      return children;
+    }
+
+    var traverseContext = getPooledTraverseContext(null, null, forEachFunc, forEachContext);
+    traverseAllChildren(children, forEachSingleChild, traverseContext);
+    releaseTraverseContext(traverseContext);
+  }
+
+  function mapSingleChildIntoContext(bookKeeping, child, childKey) {
+    var result = bookKeeping.result,
+        keyPrefix = bookKeeping.keyPrefix,
+        func = bookKeeping.func,
+        context = bookKeeping.context;
+    var mappedChild = func.call(context, child, bookKeeping.count++);
+
+    if (Array.isArray(mappedChild)) {
+      mapIntoWithKeyPrefixInternal(mappedChild, result, childKey, function (c) {
+        return c;
+      });
+    } else if (mappedChild != null) {
+      if (isValidElement(mappedChild)) {
+        mappedChild = cloneAndReplaceKey(mappedChild, // Keep both the (mapped) and old keys if they differ, just as
+        // traverseAllChildren used to do for objects as children
+        keyPrefix + (mappedChild.key && (!child || child.key !== mappedChild.key) ? escapeUserProvidedKey(mappedChild.key) + '/' : '') + childKey);
+      }
+
+      result.push(mappedChild);
+    }
+  }
+
+  function mapIntoWithKeyPrefixInternal(children, array, prefix, func, context) {
+    var escapedPrefix = '';
+
+    if (prefix != null) {
+      escapedPrefix = escapeUserProvidedKey(prefix) + '/';
+    }
+
+    var traverseContext = getPooledTraverseContext(array, escapedPrefix, func, context);
+    traverseAllChildren(children, mapSingleChildIntoContext, traverseContext);
+    releaseTraverseContext(traverseContext);
+  }
+  /**
+   * Maps children that are typically specified as `props.children`.
+   *
+   * See https://reactjs.org/docs/react-api.html#reactchildrenmap
+   *
+   * The provided mapFunction(child, key, index) will be called for each
+   * leaf child.
+   *
+   * @param {?*} children Children tree container.
+   * @param {function(*, int)} func The map function.
+   * @param {*} context Context for mapFunction.
+   * @return {object} Object containing the ordered map of results.
+   */
+
+
+  function mapChildren(children, func, context) {
+    if (children == null) {
+      return children;
+    }
+
+    var result = [];
+    mapIntoWithKeyPrefixInternal(children, result, null, func, context);
+    return result;
+  }
+  /**
+   * Count the number of children that are typically specified as
+   * `props.children`.
+   *
+   * See https://reactjs.org/docs/react-api.html#reactchildrencount
+   *
+   * @param {?*} children Children tree container.
+   * @return {number} The number of children.
+   */
+
+
+  function countChildren(children) {
+    return traverseAllChildren(children, function () {
+      return null;
+    }, null);
+  }
+  /**
+   * Flatten a children object (typically specified as `props.children`) and
+   * return an array with appropriately re-keyed children.
+   *
+   * See https://reactjs.org/docs/react-api.html#reactchildrentoarray
+   */
+
+
+  function toArray(children) {
+    var result = [];
+    mapIntoWithKeyPrefixInternal(children, result, null, function (child) {
+      return child;
+    });
+    return result;
+  }
+  /**
+   * Returns the first child in a collection of children and verifies that there
+   * is only one child in the collection.
+   *
+   * See https://reactjs.org/docs/react-api.html#reactchildrenonly
+   *
+   * The current implementation of this function assumes that a single child gets
+   * passed without a wrapper, but the purpose of this helper function is to
+   * abstract away the particular structure of children.
+   *
+   * @param {?object} children Child collection structure.
+   * @return {ReactElement} The first and only `ReactElement` contained in the
+   * structure.
+   */
+
+
+  function onlyChild(children) {
+    if (!isValidElement(children)) {
+      {
+        throw Error( "React.Children.only expected to receive a single React element child." );
+      }
+    }
+
+    return children;
+  }
+
+  function createContext(defaultValue, calculateChangedBits) {
+    if (calculateChangedBits === undefined) {
+      calculateChangedBits = null;
+    } else {
+      {
+        if (calculateChangedBits !== null && typeof calculateChangedBits !== 'function') {
+          error('createContext: Expected the optional second argument to be a ' + 'function. Instead received: %s', calculateChangedBits);
+        }
+      }
+    }
+
+    var context = {
+      $$typeof: REACT_CONTEXT_TYPE,
+      _calculateChangedBits: calculateChangedBits,
+      // As a workaround to support multiple concurrent renderers, we categorize
+      // some renderers as primary and others as secondary. We only expect
+      // there to be two concurrent renderers at most: React Native (primary) and
+      // Fabric (secondary); React DOM (primary) and React ART (secondary).
+      // Secondary renderers store their context values on separate fields.
+      _currentValue: defaultValue,
+      _currentValue2: defaultValue,
+      // Used to track how many concurrent renderers this context currently
+      // supports within in a single renderer. Such as parallel server rendering.
+      _threadCount: 0,
+      // These are circular
+      Provider: null,
+      Consumer: null
+    };
+    context.Provider = {
+      $$typeof: REACT_PROVIDER_TYPE,
+      _context: context
+    };
+    var hasWarnedAboutUsingNestedContextConsumers = false;
+    var hasWarnedAboutUsingConsumerProvider = false;
+
+    {
+      // A separate object, but proxies back to the original context object for
+      // backwards compatibility. It has a different $$typeof, so we can properly
+      // warn for the incorrect usage of Context as a Consumer.
+      var Consumer = {
+        $$typeof: REACT_CONTEXT_TYPE,
+        _context: context,
+        _calculateChangedBits: context._calculateChangedBits
+      }; // $FlowFixMe: Flow complains about not setting a value, which is intentional here
+
+      Object.defineProperties(Consumer, {
+        Provider: {
+          get: function () {
+            if (!hasWarnedAboutUsingConsumerProvider) {
+              hasWarnedAboutUsingConsumerProvider = true;
+
+              error('Rendering <Context.Consumer.Provider> is not supported and will be removed in ' + 'a future major release. Did you mean to render <Context.Provider> instead?');
+            }
+
+            return context.Provider;
+          },
+          set: function (_Provider) {
+            context.Provider = _Provider;
+          }
+        },
+        _currentValue: {
+          get: function () {
+            return context._currentValue;
+          },
+          set: function (_currentValue) {
+            context._currentValue = _currentValue;
+          }
+        },
+        _currentValue2: {
+          get: function () {
+            return context._currentValue2;
+          },
+          set: function (_currentValue2) {
+            context._currentValue2 = _currentValue2;
+          }
+        },
+        _threadCount: {
+          get: function () {
+            return context._threadCount;
+          },
+          set: function (_threadCount) {
+            context._threadCount = _threadCount;
+          }
+        },
+        Consumer: {
+          get: function () {
+            if (!hasWarnedAboutUsingNestedContextConsumers) {
+              hasWarnedAboutUsingNestedContextConsumers = true;
+
+              error('Rendering <Context.Consumer.Consumer> is not supported and will be removed in ' + 'a future major release. Did you mean to render <Context.Consumer> instead?');
+            }
+
+            return context.Consumer;
+          }
+        }
+      }); // $FlowFixMe: Flow complains about missing properties because it doesn't understand defineProperty
+
+      context.Consumer = Consumer;
+    }
+
+    {
+      context._currentRenderer = null;
+      context._currentRenderer2 = null;
+    }
+
+    return context;
+  }
+
+  function lazy(ctor) {
+    var lazyType = {
+      $$typeof: REACT_LAZY_TYPE,
+      _ctor: ctor,
+      // React uses these fields to store the result.
+      _status: -1,
+      _result: null
+    };
+
+    {
+      // In production, this would just set it on the object.
+      var defaultProps;
+      var propTypes;
+      Object.defineProperties(lazyType, {
+        defaultProps: {
+          configurable: true,
+          get: function () {
+            return defaultProps;
+          },
+          set: function (newDefaultProps) {
+            error('React.lazy(...): It is not supported to assign `defaultProps` to ' + 'a lazy component import. Either specify them where the component ' + 'is defined, or create a wrapping component around it.');
+
+            defaultProps = newDefaultProps; // Match production behavior more closely:
+
+            Object.defineProperty(lazyType, 'defaultProps', {
+              enumerable: true
+            });
+          }
+        },
+        propTypes: {
+          configurable: true,
+          get: function () {
+            return propTypes;
+          },
+          set: function (newPropTypes) {
+            error('React.lazy(...): It is not supported to assign `propTypes` to ' + 'a lazy component import. Either specify them where the component ' + 'is defined, or create a wrapping component around it.');
+
+            propTypes = newPropTypes; // Match production behavior more closely:
+
+            Object.defineProperty(lazyType, 'propTypes', {
+              enumerable: true
+            });
+          }
+        }
+      });
+    }
+
+    return lazyType;
+  }
+
+  function forwardRef(render) {
+    {
+      if (render != null && render.$$typeof === REACT_MEMO_TYPE) {
+        error('forwardRef requires a render function but received a `memo` ' + 'component. Instead of forwardRef(memo(...)), use ' + 'memo(forwardRef(...)).');
+      } else if (typeof render !== 'function') {
+        error('forwardRef requires a render function but was given %s.', render === null ? 'null' : typeof render);
+      } else {
+        if (render.length !== 0 && render.length !== 2) {
+          error('forwardRef render functions accept exactly two parameters: props and ref. %s', render.length === 1 ? 'Did you forget to use the ref parameter?' : 'Any additional parameter will be undefined.');
+        }
+      }
+
+      if (render != null) {
+        if (render.defaultProps != null || render.propTypes != null) {
+          error('forwardRef render functions do not support propTypes or defaultProps. ' + 'Did you accidentally pass a React component?');
+        }
+      }
+    }
+
+    return {
+      $$typeof: REACT_FORWARD_REF_TYPE,
+      render: render
+    };
+  }
+
+  function isValidElementType(type) {
+    return typeof type === 'string' || typeof type === 'function' || // Note: its typeof might be other than 'symbol' or 'number' if it's a polyfill.
+    type === REACT_FRAGMENT_TYPE || type === REACT_CONCURRENT_MODE_TYPE || type === REACT_PROFILER_TYPE || type === REACT_STRICT_MODE_TYPE || type === REACT_SUSPENSE_TYPE || type === REACT_SUSPENSE_LIST_TYPE || typeof type === 'object' && type !== null && (type.$$typeof === REACT_LAZY_TYPE || type.$$typeof === REACT_MEMO_TYPE || type.$$typeof === REACT_PROVIDER_TYPE || type.$$typeof === REACT_CONTEXT_TYPE || type.$$typeof === REACT_FORWARD_REF_TYPE || type.$$typeof === REACT_FUNDAMENTAL_TYPE || type.$$typeof === REACT_RESPONDER_TYPE || type.$$typeof === REACT_SCOPE_TYPE || type.$$typeof === REACT_BLOCK_TYPE);
+  }
+
+  function memo(type, compare) {
+    {
+      if (!isValidElementType(type)) {
+        error('memo: The first argument must be a component. Instead ' + 'received: %s', type === null ? 'null' : typeof type);
+      }
+    }
+
+    return {
+      $$typeof: REACT_MEMO_TYPE,
+      type: type,
+      compare: compare === undefined ? null : compare
+    };
+  }
+
+  function resolveDispatcher() {
+    var dispatcher = ReactCurrentDispatcher.current;
+
+    if (!(dispatcher !== null)) {
+      {
+        throw Error( "Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:\n1. You might have mismatching versions of React and the renderer (such as React DOM)\n2. You might be breaking the Rules of Hooks\n3. You might have more than one copy of React in the same app\nSee https://fb.me/react-invalid-hook-call for tips about how to debug and fix this problem." );
+      }
+    }
+
+    return dispatcher;
+  }
+
+  function useContext(Context, unstable_observedBits) {
+    var dispatcher = resolveDispatcher();
+
+    {
+      if (unstable_observedBits !== undefined) {
+        error('useContext() second argument is reserved for future ' + 'use in React. Passing it is not supported. ' + 'You passed: %s.%s', unstable_observedBits, typeof unstable_observedBits === 'number' && Array.isArray(arguments[2]) ? '\n\nDid you call array.map(useContext)? ' + 'Calling Hooks inside a loop is not supported. ' + 'Learn more at https://fb.me/rules-of-hooks' : '');
+      } // TODO: add a more generic warning for invalid values.
+
+
+      if (Context._context !== undefined) {
+        var realContext = Context._context; // Don't deduplicate because this legitimately causes bugs
+        // and nobody should be using this in existing code.
+
+        if (realContext.Consumer === Context) {
+          error('Calling useContext(Context.Consumer) is not supported, may cause bugs, and will be ' + 'removed in a future major release. Did you mean to call useContext(Context) instead?');
+        } else if (realContext.Provider === Context) {
+          error('Calling useContext(Context.Provider) is not supported. ' + 'Did you mean to call useContext(Context) instead?');
+        }
+      }
+    }
+
+    return dispatcher.useContext(Context, unstable_observedBits);
+  }
+  function useState(initialState) {
+    var dispatcher = resolveDispatcher();
+    return dispatcher.useState(initialState);
+  }
+  function useReducer(reducer, initialArg, init) {
+    var dispatcher = resolveDispatcher();
+    return dispatcher.useReducer(reducer, initialArg, init);
+  }
+  function useRef(initialValue) {
+    var dispatcher = resolveDispatcher();
+    return dispatcher.useRef(initialValue);
+  }
+  function useEffect(create, deps) {
+    var dispatcher = resolveDispatcher();
+    return dispatcher.useEffect(create, deps);
+  }
+  function useLayoutEffect(create, deps) {
+    var dispatcher = resolveDispatcher();
+    return dispatcher.useLayoutEffect(create, deps);
+  }
+  function useCallback(callback, deps) {
+    var dispatcher = resolveDispatcher();
+    return dispatcher.useCallback(callback, deps);
+  }
+  function useMemo(create, deps) {
+    var dispatcher = resolveDispatcher();
+    return dispatcher.useMemo(create, deps);
+  }
+  function useImperativeHandle(ref, create, deps) {
+    var dispatcher = resolveDispatcher();
+    return dispatcher.useImperativeHandle(ref, create, deps);
+  }
+  function useDebugValue(value, formatterFn) {
+    {
+      var dispatcher = resolveDispatcher();
+      return dispatcher.useDebugValue(value, formatterFn);
+    }
+  }
+
+  /**
+   * Copyright (c) 2013-present, Facebook, Inc.
+   *
+   * This source code is licensed under the MIT license found in the
+   * LICENSE file in the root directory of this source tree.
+   */
+
+  var ReactPropTypesSecret = 'SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED';
+
+  var ReactPropTypesSecret_1 = ReactPropTypesSecret;
+
+  var printWarning$1 = function() {};
+
+  {
+    var ReactPropTypesSecret$1 = ReactPropTypesSecret_1;
+    var loggedTypeFailures = {};
+    var has = Function.call.bind(Object.prototype.hasOwnProperty);
+
+    printWarning$1 = function(text) {
+      var message = 'Warning: ' + text;
+      if (typeof console !== 'undefined') {
+        console.error(message);
+      }
+      try {
+        // --- Welcome to debugging React ---
+        // This error was thrown as a convenience so that you can use this stack
+        // to find the callsite that caused this warning to fire.
+        throw new Error(message);
+      } catch (x) {}
+    };
+  }
+
+  /**
+   * Assert that the values match with the type specs.
+   * Error messages are memorized and will only be shown once.
+   *
+   * @param {object} typeSpecs Map of name to a ReactPropType
+   * @param {object} values Runtime values that need to be type-checked
+   * @param {string} location e.g. "prop", "context", "child context"
+   * @param {string} componentName Name of the component for error messages.
+   * @param {?Function} getStack Returns the component stack.
+   * @private
+   */
+  function checkPropTypes(typeSpecs, values, location, componentName, getStack) {
+    {
+      for (var typeSpecName in typeSpecs) {
+        if (has(typeSpecs, typeSpecName)) {
+          var error;
+          // Prop type validation may throw. In case they do, we don't want to
+          // fail the render phase where it didn't fail before. So we log it.
+          // After these have been cleaned up, we'll let them throw.
+          try {
+            // This is intentionally an invariant that gets caught. It's the same
+            // behavior as without this statement except with a better message.
+            if (typeof typeSpecs[typeSpecName] !== 'function') {
+              var err = Error(
+                (componentName || 'React class') + ': ' + location + ' type `' + typeSpecName + '` is invalid; ' +
+                'it must be a function, usually from the `prop-types` package, but received `' + typeof typeSpecs[typeSpecName] + '`.'
+              );
+              err.name = 'Invariant Violation';
+              throw err;
+            }
+            error = typeSpecs[typeSpecName](values, typeSpecName, componentName, location, null, ReactPropTypesSecret$1);
+          } catch (ex) {
+            error = ex;
+          }
+          if (error && !(error instanceof Error)) {
+            printWarning$1(
+              (componentName || 'React class') + ': type specification of ' +
+              location + ' `' + typeSpecName + '` is invalid; the type checker ' +
+              'function must return `null` or an `Error` but returned a ' + typeof error + '. ' +
+              'You may have forgotten to pass an argument to the type checker ' +
+              'creator (arrayOf, instanceOf, objectOf, oneOf, oneOfType, and ' +
+              'shape all require an argument).'
+            );
+          }
+          if (error instanceof Error && !(error.message in loggedTypeFailures)) {
+            // Only monitor this failure once because there tends to be a lot of the
+            // same error.
+            loggedTypeFailures[error.message] = true;
+
+            var stack = getStack ? getStack() : '';
+
+            printWarning$1(
+              'Failed ' + location + ' type: ' + error.message + (stack != null ? stack : '')
+            );
+          }
+        }
+      }
+    }
+  }
+
+  /**
+   * Resets warning cache when testing.
+   *
+   * @private
+   */
+  checkPropTypes.resetWarningCache = function() {
+    {
+      loggedTypeFailures = {};
+    }
+  };
+
+  var checkPropTypes_1 = checkPropTypes;
+
+  var propTypesMisspellWarningShown;
+
+  {
+    propTypesMisspellWarningShown = false;
+  }
+
+  function getDeclarationErrorAddendum() {
+    if (ReactCurrentOwner.current) {
+      var name = getComponentName(ReactCurrentOwner.current.type);
+
+      if (name) {
+        return '\n\nCheck the render method of `' + name + '`.';
+      }
+    }
+
+    return '';
+  }
+
+  function getSourceInfoErrorAddendum(source) {
+    if (source !== undefined) {
+      var fileName = source.fileName.replace(/^.*[\\\/]/, '');
+      var lineNumber = source.lineNumber;
+      return '\n\nCheck your code at ' + fileName + ':' + lineNumber + '.';
+    }
+
+    return '';
+  }
+
+  function getSourceInfoErrorAddendumForProps(elementProps) {
+    if (elementProps !== null && elementProps !== undefined) {
+      return getSourceInfoErrorAddendum(elementProps.__source);
+    }
+
+    return '';
+  }
+  /**
+   * Warn if there's no key explicitly set on dynamic arrays of children or
+   * object keys are not valid. This allows us to keep track of children between
+   * updates.
+   */
+
+
+  var ownerHasKeyUseWarning = {};
+
+  function getCurrentComponentErrorInfo(parentType) {
+    var info = getDeclarationErrorAddendum();
+
+    if (!info) {
+      var parentName = typeof parentType === 'string' ? parentType : parentType.displayName || parentType.name;
+
+      if (parentName) {
+        info = "\n\nCheck the top-level render call using <" + parentName + ">.";
+      }
+    }
+
+    return info;
+  }
+  /**
+   * Warn if the element doesn't have an explicit key assigned to it.
+   * This element is in an array. The array could grow and shrink or be
+   * reordered. All children that haven't already been validated are required to
+   * have a "key" property assigned to it. Error statuses are cached so a warning
+   * will only be shown once.
+   *
+   * @internal
+   * @param {ReactElement} element Element that requires a key.
+   * @param {*} parentType element's parent's type.
+   */
+
+
+  function validateExplicitKey(element, parentType) {
+    if (!element._store || element._store.validated || element.key != null) {
+      return;
+    }
+
+    element._store.validated = true;
+    var currentComponentErrorInfo = getCurrentComponentErrorInfo(parentType);
+
+    if (ownerHasKeyUseWarning[currentComponentErrorInfo]) {
+      return;
+    }
+
+    ownerHasKeyUseWarning[currentComponentErrorInfo] = true; // Usually the current owner is the offender, but if it accepts children as a
+    // property, it may be the creator of the child that's responsible for
+    // assigning it a key.
+
+    var childOwner = '';
+
+    if (element && element._owner && element._owner !== ReactCurrentOwner.current) {
+      // Give the component that originally created this child.
+      childOwner = " It was passed a child from " + getComponentName(element._owner.type) + ".";
+    }
+
+    setCurrentlyValidatingElement(element);
+
+    {
+      error('Each child in a list should have a unique "key" prop.' + '%s%s See https://fb.me/react-warning-keys for more information.', currentComponentErrorInfo, childOwner);
+    }
+
+    setCurrentlyValidatingElement(null);
+  }
+  /**
+   * Ensure that every element either is passed in a static location, in an
+   * array with an explicit keys property defined, or in an object literal
+   * with valid key property.
+   *
+   * @internal
+   * @param {ReactNode} node Statically passed child of any type.
+   * @param {*} parentType node's parent's type.
+   */
+
+
+  function validateChildKeys(node, parentType) {
+    if (typeof node !== 'object') {
+      return;
+    }
+
+    if (Array.isArray(node)) {
+      for (var i = 0; i < node.length; i++) {
+        var child = node[i];
+
+        if (isValidElement(child)) {
+          validateExplicitKey(child, parentType);
+        }
+      }
+    } else if (isValidElement(node)) {
+      // This element was passed in a valid location.
+      if (node._store) {
+        node._store.validated = true;
+      }
+    } else if (node) {
+      var iteratorFn = getIteratorFn(node);
+
+      if (typeof iteratorFn === 'function') {
+        // Entry iterators used to provide implicit keys,
+        // but now we print a separate warning for them later.
+        if (iteratorFn !== node.entries) {
+          var iterator = iteratorFn.call(node);
+          var step;
+
+          while (!(step = iterator.next()).done) {
+            if (isValidElement(step.value)) {
+              validateExplicitKey(step.value, parentType);
+            }
+          }
+        }
+      }
+    }
+  }
+  /**
+   * Given an element, validate that its props follow the propTypes definition,
+   * provided by the type.
+   *
+   * @param {ReactElement} element
+   */
+
+
+  function validatePropTypes(element) {
+    {
+      var type = element.type;
+
+      if (type === null || type === undefined || typeof type === 'string') {
+        return;
+      }
+
+      var name = getComponentName(type);
+      var propTypes;
+
+      if (typeof type === 'function') {
+        propTypes = type.propTypes;
+      } else if (typeof type === 'object' && (type.$$typeof === REACT_FORWARD_REF_TYPE || // Note: Memo only checks outer props here.
+      // Inner props are checked in the reconciler.
+      type.$$typeof === REACT_MEMO_TYPE)) {
+        propTypes = type.propTypes;
+      } else {
+        return;
+      }
+
+      if (propTypes) {
+        setCurrentlyValidatingElement(element);
+        checkPropTypes_1(propTypes, element.props, 'prop', name, ReactDebugCurrentFrame.getStackAddendum);
+        setCurrentlyValidatingElement(null);
+      } else if (type.PropTypes !== undefined && !propTypesMisspellWarningShown) {
+        propTypesMisspellWarningShown = true;
+
+        error('Component %s declared `PropTypes` instead of `propTypes`. Did you misspell the property assignment?', name || 'Unknown');
+      }
+
+      if (typeof type.getDefaultProps === 'function' && !type.getDefaultProps.isReactClassApproved) {
+        error('getDefaultProps is only used on classic React.createClass ' + 'definitions. Use a static property named `defaultProps` instead.');
+      }
+    }
+  }
+  /**
+   * Given a fragment, validate that it can only be provided with fragment props
+   * @param {ReactElement} fragment
+   */
+
+
+  function validateFragmentProps(fragment) {
+    {
+      setCurrentlyValidatingElement(fragment);
+      var keys = Object.keys(fragment.props);
+
+      for (var i = 0; i < keys.length; i++) {
+        var key = keys[i];
+
+        if (key !== 'children' && key !== 'key') {
+          error('Invalid prop `%s` supplied to `React.Fragment`. ' + 'React.Fragment can only have `key` and `children` props.', key);
+
+          break;
+        }
+      }
+
+      if (fragment.ref !== null) {
+        error('Invalid attribute `ref` supplied to `React.Fragment`.');
+      }
+
+      setCurrentlyValidatingElement(null);
+    }
+  }
+  function createElementWithValidation(type, props, children) {
+    var validType = isValidElementType(type); // We warn in this case but don't throw. We expect the element creation to
+    // succeed and there will likely be errors in render.
+
+    if (!validType) {
+      var info = '';
+
+      if (type === undefined || typeof type === 'object' && type !== null && Object.keys(type).length === 0) {
+        info += ' You likely forgot to export your component from the file ' + "it's defined in, or you might have mixed up default and named imports.";
+      }
+
+      var sourceInfo = getSourceInfoErrorAddendumForProps(props);
+
+      if (sourceInfo) {
+        info += sourceInfo;
+      } else {
+        info += getDeclarationErrorAddendum();
+      }
+
+      var typeString;
+
+      if (type === null) {
+        typeString = 'null';
+      } else if (Array.isArray(type)) {
+        typeString = 'array';
+      } else if (type !== undefined && type.$$typeof === REACT_ELEMENT_TYPE) {
+        typeString = "<" + (getComponentName(type.type) || 'Unknown') + " />";
+        info = ' Did you accidentally export a JSX literal instead of a component?';
+      } else {
+        typeString = typeof type;
+      }
+
+      {
+        error('React.createElement: type is invalid -- expected a string (for ' + 'built-in components) or a class/function (for composite ' + 'components) but got: %s.%s', typeString, info);
+      }
+    }
+
+    var element = createElement.apply(this, arguments); // The result can be nullish if a mock or a custom function is used.
+    // TODO: Drop this when these are no longer allowed as the type argument.
+
+    if (element == null) {
+      return element;
+    } // Skip key warning if the type isn't valid since our key validation logic
+    // doesn't expect a non-string/function type and can throw confusing errors.
+    // We don't want exception behavior to differ between dev and prod.
+    // (Rendering will throw with a helpful message and as soon as the type is
+    // fixed, the key warnings will appear.)
+
+
+    if (validType) {
+      for (var i = 2; i < arguments.length; i++) {
+        validateChildKeys(arguments[i], type);
+      }
+    }
+
+    if (type === REACT_FRAGMENT_TYPE) {
+      validateFragmentProps(element);
+    } else {
+      validatePropTypes(element);
+    }
+
+    return element;
+  }
+  var didWarnAboutDeprecatedCreateFactory = false;
+  function createFactoryWithValidation(type) {
+    var validatedFactory = createElementWithValidation.bind(null, type);
+    validatedFactory.type = type;
+
+    {
+      if (!didWarnAboutDeprecatedCreateFactory) {
+        didWarnAboutDeprecatedCreateFactory = true;
+
+        warn('React.createFactory() is deprecated and will be removed in ' + 'a future major release. Consider using JSX ' + 'or use React.createElement() directly instead.');
+      } // Legacy hook: remove it
+
+
+      Object.defineProperty(validatedFactory, 'type', {
+        enumerable: false,
+        get: function () {
+          warn('Factory.type is deprecated. Access the class directly ' + 'before passing it to createFactory.');
+
+          Object.defineProperty(this, 'type', {
+            value: type
+          });
+          return type;
+        }
+      });
+    }
+
+    return validatedFactory;
+  }
+  function cloneElementWithValidation(element, props, children) {
+    var newElement = cloneElement.apply(this, arguments);
+
+    for (var i = 2; i < arguments.length; i++) {
+      validateChildKeys(arguments[i], newElement.type);
+    }
+
+    validatePropTypes(newElement);
+    return newElement;
+  }
+
+  var enableSchedulerDebugging = false;
+  var enableProfiling = true;
+
+  var requestHostCallback;
+  var requestHostTimeout;
+  var cancelHostTimeout;
+  var shouldYieldToHost;
+  var requestPaint;
+  var getCurrentTime;
+  var forceFrameRate;
+
+  if ( // If Scheduler runs in a non-DOM environment, it falls back to a naive
+  // implementation using setTimeout.
+  typeof window === 'undefined' || // Check if MessageChannel is supported, too.
+  typeof MessageChannel !== 'function') {
+    // If this accidentally gets imported in a non-browser environment, e.g. JavaScriptCore,
+    // fallback to a naive implementation.
+    var _callback = null;
+    var _timeoutID = null;
+
+    var _flushCallback = function () {
+      if (_callback !== null) {
+        try {
+          var currentTime = getCurrentTime();
+          var hasRemainingTime = true;
+
+          _callback(hasRemainingTime, currentTime);
+
+          _callback = null;
+        } catch (e) {
+          setTimeout(_flushCallback, 0);
+          throw e;
+        }
+      }
+    };
+
+    var initialTime = Date.now();
+
+    getCurrentTime = function () {
+      return Date.now() - initialTime;
+    };
+
+    requestHostCallback = function (cb) {
+      if (_callback !== null) {
+        // Protect against re-entrancy.
+        setTimeout(requestHostCallback, 0, cb);
+      } else {
+        _callback = cb;
+        setTimeout(_flushCallback, 0);
+      }
+    };
+
+    requestHostTimeout = function (cb, ms) {
+      _timeoutID = setTimeout(cb, ms);
+    };
+
+    cancelHostTimeout = function () {
+      clearTimeout(_timeoutID);
+    };
+
+    shouldYieldToHost = function () {
+      return false;
+    };
+
+    requestPaint = forceFrameRate = function () {};
+  } else {
+    // Capture local references to native APIs, in case a polyfill overrides them.
+    var performance = window.performance;
+    var _Date = window.Date;
+    var _setTimeout = window.setTimeout;
+    var _clearTimeout = window.clearTimeout;
+
+    if (typeof console !== 'undefined') {
+      // TODO: Scheduler no longer requires these methods to be polyfilled. But
+      // maybe we want to continue warning if they don't exist, to preserve the
+      // option to rely on it in the future?
+      var requestAnimationFrame = window.requestAnimationFrame;
+      var cancelAnimationFrame = window.cancelAnimationFrame; // TODO: Remove fb.me link
+
+      if (typeof requestAnimationFrame !== 'function') {
+        // Using console['error'] to evade Babel and ESLint
+        console['error']("This browser doesn't support requestAnimationFrame. " + 'Make sure that you load a ' + 'polyfill in older browsers. https://fb.me/react-polyfills');
+      }
+
+      if (typeof cancelAnimationFrame !== 'function') {
+        // Using console['error'] to evade Babel and ESLint
+        console['error']("This browser doesn't support cancelAnimationFrame. " + 'Make sure that you load a ' + 'polyfill in older browsers. https://fb.me/react-polyfills');
+      }
+    }
+
+    if (typeof performance === 'object' && typeof performance.now === 'function') {
+      getCurrentTime = function () {
+        return performance.now();
+      };
+    } else {
+      var _initialTime = _Date.now();
+
+      getCurrentTime = function () {
+        return _Date.now() - _initialTime;
+      };
+    }
+
+    var isMessageLoopRunning = false;
+    var scheduledHostCallback = null;
+    var taskTimeoutID = -1; // Scheduler periodically yields in case there is other work on the main
+    // thread, like user events. By default, it yields multiple times per frame.
+    // It does not attempt to align with frame boundaries, since most tasks don't
+    // need to be frame aligned; for those that do, use requestAnimationFrame.
+
+    var yieldInterval = 5;
+    var deadline = 0; // TODO: Make this configurable
+
+    {
+      // `isInputPending` is not available. Since we have no way of knowing if
+      // there's pending input, always yield at the end of the frame.
+      shouldYieldToHost = function () {
+        return getCurrentTime() >= deadline;
+      }; // Since we yield every frame regardless, `requestPaint` has no effect.
+
+
+      requestPaint = function () {};
+    }
+
+    forceFrameRate = function (fps) {
+      if (fps < 0 || fps > 125) {
+        // Using console['error'] to evade Babel and ESLint
+        console['error']('forceFrameRate takes a positive int between 0 and 125, ' + 'forcing framerates higher than 125 fps is not unsupported');
+        return;
+      }
+
+      if (fps > 0) {
+        yieldInterval = Math.floor(1000 / fps);
+      } else {
+        // reset the framerate
+        yieldInterval = 5;
+      }
+    };
+
+    var performWorkUntilDeadline = function () {
+      if (scheduledHostCallback !== null) {
+        var currentTime = getCurrentTime(); // Yield after `yieldInterval` ms, regardless of where we are in the vsync
+        // cycle. This means there's always time remaining at the beginning of
+        // the message event.
+
+        deadline = currentTime + yieldInterval;
+        var hasTimeRemaining = true;
+
+        try {
+          var hasMoreWork = scheduledHostCallback(hasTimeRemaining, currentTime);
+
+          if (!hasMoreWork) {
+            isMessageLoopRunning = false;
+            scheduledHostCallback = null;
+          } else {
+            // If there's more work, schedule the next message event at the end
+            // of the preceding one.
+            port.postMessage(null);
+          }
+        } catch (error) {
+          // If a scheduler task throws, exit the current browser task so the
+          // error can be observed.
+          port.postMessage(null);
+          throw error;
+        }
+      } else {
+        isMessageLoopRunning = false;
+      } // Yielding to the browser will give it a chance to paint, so we can
+    };
+
+    var channel = new MessageChannel();
+    var port = channel.port2;
+    channel.port1.onmessage = performWorkUntilDeadline;
+
+    requestHostCallback = function (callback) {
+      scheduledHostCallback = callback;
+
+      if (!isMessageLoopRunning) {
+        isMessageLoopRunning = true;
+        port.postMessage(null);
+      }
+    };
+
+    requestHostTimeout = function (callback, ms) {
+      taskTimeoutID = _setTimeout(function () {
+        callback(getCurrentTime());
+      }, ms);
+    };
+
+    cancelHostTimeout = function () {
+      _clearTimeout(taskTimeoutID);
+
+      taskTimeoutID = -1;
+    };
+  }
+
+  function push(heap, node) {
+    var index = heap.length;
+    heap.push(node);
+    siftUp(heap, node, index);
+  }
+  function peek(heap) {
+    var first = heap[0];
+    return first === undefined ? null : first;
+  }
+  function pop(heap) {
+    var first = heap[0];
+
+    if (first !== undefined) {
+      var last = heap.pop();
+
+      if (last !== first) {
+        heap[0] = last;
+        siftDown(heap, last, 0);
+      }
+
+      return first;
+    } else {
+      return null;
+    }
+  }
+
+  function siftUp(heap, node, i) {
+    var index = i;
+
+    while (true) {
+      var parentIndex = index - 1 >>> 1;
+      var parent = heap[parentIndex];
+
+      if (parent !== undefined && compare(parent, node) > 0) {
+        // The parent is larger. Swap positions.
+        heap[parentIndex] = node;
+        heap[index] = parent;
+        index = parentIndex;
+      } else {
+        // The parent is smaller. Exit.
+        return;
+      }
+    }
+  }
+
+  function siftDown(heap, node, i) {
+    var index = i;
+    var length = heap.length;
+
+    while (index < length) {
+      var leftIndex = (index + 1) * 2 - 1;
+      var left = heap[leftIndex];
+      var rightIndex = leftIndex + 1;
+      var right = heap[rightIndex]; // If the left or right node is smaller, swap with the smaller of those.
+
+      if (left !== undefined && compare(left, node) < 0) {
+        if (right !== undefined && compare(right, left) < 0) {
+          heap[index] = right;
+          heap[rightIndex] = node;
+          index = rightIndex;
+        } else {
+          heap[index] = left;
+          heap[leftIndex] = node;
+          index = leftIndex;
+        }
+      } else if (right !== undefined && compare(right, node) < 0) {
+        heap[index] = right;
+        heap[rightIndex] = node;
+        index = rightIndex;
+      } else {
+        // Neither child is smaller. Exit.
+        return;
+      }
+    }
+  }
+
+  function compare(a, b) {
+    // Compare sort index first, then task id.
+    var diff = a.sortIndex - b.sortIndex;
+    return diff !== 0 ? diff : a.id - b.id;
+  }
+
+  // TODO: Use symbols?
+  var NoPriority = 0;
+  var ImmediatePriority = 1;
+  var UserBlockingPriority = 2;
+  var NormalPriority = 3;
+  var LowPriority = 4;
+  var IdlePriority = 5;
+
+  var runIdCounter = 0;
+  var mainThreadIdCounter = 0;
+  var profilingStateSize = 4;
+  var sharedProfilingBuffer =  // $FlowFixMe Flow doesn't know about SharedArrayBuffer
+  typeof SharedArrayBuffer === 'function' ? new SharedArrayBuffer(profilingStateSize * Int32Array.BYTES_PER_ELEMENT) : // $FlowFixMe Flow doesn't know about ArrayBuffer
+  typeof ArrayBuffer === 'function' ? new ArrayBuffer(profilingStateSize * Int32Array.BYTES_PER_ELEMENT) : null // Don't crash the init path on IE9
+  ;
+  var profilingState =  sharedProfilingBuffer !== null ? new Int32Array(sharedProfilingBuffer) : []; // We can't read this but it helps save bytes for null checks
+
+  var PRIORITY = 0;
+  var CURRENT_TASK_ID = 1;
+  var CURRENT_RUN_ID = 2;
+  var QUEUE_SIZE = 3;
+
+  {
+    profilingState[PRIORITY] = NoPriority; // This is maintained with a counter, because the size of the priority queue
+    // array might include canceled tasks.
+
+    profilingState[QUEUE_SIZE] = 0;
+    profilingState[CURRENT_TASK_ID] = 0;
+  } // Bytes per element is 4
+
+
+  var INITIAL_EVENT_LOG_SIZE = 131072;
+  var MAX_EVENT_LOG_SIZE = 524288; // Equivalent to 2 megabytes
+
+  var eventLogSize = 0;
+  var eventLogBuffer = null;
+  var eventLog = null;
+  var eventLogIndex = 0;
+  var TaskStartEvent = 1;
+  var TaskCompleteEvent = 2;
+  var TaskErrorEvent = 3;
+  var TaskCancelEvent = 4;
+  var TaskRunEvent = 5;
+  var TaskYieldEvent = 6;
+  var SchedulerSuspendEvent = 7;
+  var SchedulerResumeEvent = 8;
+
+  function logEvent(entries) {
+    if (eventLog !== null) {
+      var offset = eventLogIndex;
+      eventLogIndex += entries.length;
+
+      if (eventLogIndex + 1 > eventLogSize) {
+        eventLogSize *= 2;
+
+        if (eventLogSize > MAX_EVENT_LOG_SIZE) {
+          // Using console['error'] to evade Babel and ESLint
+          console['error']("Scheduler Profiling: Event log exceeded maximum size. Don't " + 'forget to call `stopLoggingProfilingEvents()`.');
+          stopLoggingProfilingEvents();
+          return;
+        }
+
+        var newEventLog = new Int32Array(eventLogSize * 4);
+        newEventLog.set(eventLog);
+        eventLogBuffer = newEventLog.buffer;
+        eventLog = newEventLog;
+      }
+
+      eventLog.set(entries, offset);
+    }
+  }
+
+  function startLoggingProfilingEvents() {
+    eventLogSize = INITIAL_EVENT_LOG_SIZE;
+    eventLogBuffer = new ArrayBuffer(eventLogSize * 4);
+    eventLog = new Int32Array(eventLogBuffer);
+    eventLogIndex = 0;
+  }
+  function stopLoggingProfilingEvents() {
+    var buffer = eventLogBuffer;
+    eventLogSize = 0;
+    eventLogBuffer = null;
+    eventLog = null;
+    eventLogIndex = 0;
+    return buffer;
+  }
+  function markTaskStart(task, ms) {
+    {
+      profilingState[QUEUE_SIZE]++;
+
+      if (eventLog !== null) {
+        // performance.now returns a float, representing milliseconds. When the
+        // event is logged, it's coerced to an int. Convert to microseconds to
+        // maintain extra degrees of precision.
+        logEvent([TaskStartEvent, ms * 1000, task.id, task.priorityLevel]);
+      }
+    }
+  }
+  function markTaskCompleted(task, ms) {
+    {
+      profilingState[PRIORITY] = NoPriority;
+      profilingState[CURRENT_TASK_ID] = 0;
+      profilingState[QUEUE_SIZE]--;
+
+      if (eventLog !== null) {
+        logEvent([TaskCompleteEvent, ms * 1000, task.id]);
+      }
+    }
+  }
+  function markTaskCanceled(task, ms) {
+    {
+      profilingState[QUEUE_SIZE]--;
+
+      if (eventLog !== null) {
+        logEvent([TaskCancelEvent, ms * 1000, task.id]);
+      }
+    }
+  }
+  function markTaskErrored(task, ms) {
+    {
+      profilingState[PRIORITY] = NoPriority;
+      profilingState[CURRENT_TASK_ID] = 0;
+      profilingState[QUEUE_SIZE]--;
+
+      if (eventLog !== null) {
+        logEvent([TaskErrorEvent, ms * 1000, task.id]);
+      }
+    }
+  }
+  function markTaskRun(task, ms) {
+    {
+      runIdCounter++;
+      profilingState[PRIORITY] = task.priorityLevel;
+      profilingState[CURRENT_TASK_ID] = task.id;
+      profilingState[CURRENT_RUN_ID] = runIdCounter;
+
+      if (eventLog !== null) {
+        logEvent([TaskRunEvent, ms * 1000, task.id, runIdCounter]);
+      }
+    }
+  }
+  function markTaskYield(task, ms) {
+    {
+      profilingState[PRIORITY] = NoPriority;
+      profilingState[CURRENT_TASK_ID] = 0;
+      profilingState[CURRENT_RUN_ID] = 0;
+
+      if (eventLog !== null) {
+        logEvent([TaskYieldEvent, ms * 1000, task.id, runIdCounter]);
+      }
+    }
+  }
+  function markSchedulerSuspended(ms) {
+    {
+      mainThreadIdCounter++;
+
+      if (eventLog !== null) {
+        logEvent([SchedulerSuspendEvent, ms * 1000, mainThreadIdCounter]);
+      }
+    }
+  }
+  function markSchedulerUnsuspended(ms) {
+    {
+      if (eventLog !== null) {
+        logEvent([SchedulerResumeEvent, ms * 1000, mainThreadIdCounter]);
+      }
+    }
+  }
+
+  /* eslint-disable no-var */
+  // Math.pow(2, 30) - 1
+  // 0b111111111111111111111111111111
+
+  var maxSigned31BitInt = 1073741823; // Times out immediately
+
+  var IMMEDIATE_PRIORITY_TIMEOUT = -1; // Eventually times out
+
+  var USER_BLOCKING_PRIORITY = 250;
+  var NORMAL_PRIORITY_TIMEOUT = 5000;
+  var LOW_PRIORITY_TIMEOUT = 10000; // Never times out
+
+  var IDLE_PRIORITY = maxSigned31BitInt; // Tasks are stored on a min heap
+
+  var taskQueue = [];
+  var timerQueue = []; // Incrementing id counter. Used to maintain insertion order.
+
+  var taskIdCounter = 1; // Pausing the scheduler is useful for debugging.
+  var currentTask = null;
+  var currentPriorityLevel = NormalPriority; // This is set while performing work, to prevent re-entrancy.
+
+  var isPerformingWork = false;
+  var isHostCallbackScheduled = false;
+  var isHostTimeoutScheduled = false;
+
+  function advanceTimers(currentTime) {
+    // Check for tasks that are no longer delayed and add them to the queue.
+    var timer = peek(timerQueue);
+
+    while (timer !== null) {
+      if (timer.callback === null) {
+        // Timer was cancelled.
+        pop(timerQueue);
+      } else if (timer.startTime <= currentTime) {
+        // Timer fired. Transfer to the task queue.
+        pop(timerQueue);
+        timer.sortIndex = timer.expirationTime;
+        push(taskQueue, timer);
+
+        {
+          markTaskStart(timer, currentTime);
+          timer.isQueued = true;
+        }
+      } else {
+        // Remaining timers are pending.
+        return;
+      }
+
+      timer = peek(timerQueue);
+    }
+  }
+
+  function handleTimeout(currentTime) {
+    isHostTimeoutScheduled = false;
+    advanceTimers(currentTime);
+
+    if (!isHostCallbackScheduled) {
+      if (peek(taskQueue) !== null) {
+        isHostCallbackScheduled = true;
+        requestHostCallback(flushWork);
+      } else {
+        var firstTimer = peek(timerQueue);
+
+        if (firstTimer !== null) {
+          requestHostTimeout(handleTimeout, firstTimer.startTime - currentTime);
+        }
+      }
+    }
+  }
+
+  function flushWork(hasTimeRemaining, initialTime) {
+    {
+      markSchedulerUnsuspended(initialTime);
+    } // We'll need a host callback the next time work is scheduled.
+
+
+    isHostCallbackScheduled = false;
+
+    if (isHostTimeoutScheduled) {
+      // We scheduled a timeout but it's no longer needed. Cancel it.
+      isHostTimeoutScheduled = false;
+      cancelHostTimeout();
+    }
+
+    isPerformingWork = true;
+    var previousPriorityLevel = currentPriorityLevel;
+
+    try {
+      if (enableProfiling) {
+        try {
+          return workLoop(hasTimeRemaining, initialTime);
+        } catch (error) {
+          if (currentTask !== null) {
+            var currentTime = getCurrentTime();
+            markTaskErrored(currentTask, currentTime);
+            currentTask.isQueued = false;
+          }
+
+          throw error;
+        }
+      } else {
+        // No catch in prod codepath.
+        return workLoop(hasTimeRemaining, initialTime);
+      }
+    } finally {
+      currentTask = null;
+      currentPriorityLevel = previousPriorityLevel;
+      isPerformingWork = false;
+
+      {
+        var _currentTime = getCurrentTime();
+
+        markSchedulerSuspended(_currentTime);
+      }
+    }
+  }
+
+  function workLoop(hasTimeRemaining, initialTime) {
+    var currentTime = initialTime;
+    advanceTimers(currentTime);
+    currentTask = peek(taskQueue);
+
+    while (currentTask !== null && !(enableSchedulerDebugging )) {
+      if (currentTask.expirationTime > currentTime && (!hasTimeRemaining || shouldYieldToHost())) {
+        // This currentTask hasn't expired, and we've reached the deadline.
+        break;
+      }
+
+      var callback = currentTask.callback;
+
+      if (callback !== null) {
+        currentTask.callback = null;
+        currentPriorityLevel = currentTask.priorityLevel;
+        var didUserCallbackTimeout = currentTask.expirationTime <= currentTime;
+        markTaskRun(currentTask, currentTime);
+        var continuationCallback = callback(didUserCallbackTimeout);
+        currentTime = getCurrentTime();
+
+        if (typeof continuationCallback === 'function') {
+          currentTask.callback = continuationCallback;
+          markTaskYield(currentTask, currentTime);
+        } else {
+          {
+            markTaskCompleted(currentTask, currentTime);
+            currentTask.isQueued = false;
+          }
+
+          if (currentTask === peek(taskQueue)) {
+            pop(taskQueue);
+          }
+        }
+
+        advanceTimers(currentTime);
+      } else {
+        pop(taskQueue);
+      }
+
+      currentTask = peek(taskQueue);
+    } // Return whether there's additional work
+
+
+    if (currentTask !== null) {
+      return true;
+    } else {
+      var firstTimer = peek(timerQueue);
+
+      if (firstTimer !== null) {
+        requestHostTimeout(handleTimeout, firstTimer.startTime - currentTime);
+      }
+
+      return false;
+    }
+  }
+
+  function unstable_runWithPriority(priorityLevel, eventHandler) {
+    switch (priorityLevel) {
+      case ImmediatePriority:
+      case UserBlockingPriority:
+      case NormalPriority:
+      case LowPriority:
+      case IdlePriority:
+        break;
+
+      default:
+        priorityLevel = NormalPriority;
+    }
+
+    var previousPriorityLevel = currentPriorityLevel;
+    currentPriorityLevel = priorityLevel;
+
+    try {
+      return eventHandler();
+    } finally {
+      currentPriorityLevel = previousPriorityLevel;
+    }
+  }
+
+  function unstable_next(eventHandler) {
+    var priorityLevel;
+
+    switch (currentPriorityLevel) {
+      case ImmediatePriority:
+      case UserBlockingPriority:
+      case NormalPriority:
+        // Shift down to normal priority
+        priorityLevel = NormalPriority;
+        break;
+
+      default:
+        // Anything lower than normal priority should remain at the current level.
+        priorityLevel = currentPriorityLevel;
+        break;
+    }
+
+    var previousPriorityLevel = currentPriorityLevel;
+    currentPriorityLevel = priorityLevel;
+
+    try {
+      return eventHandler();
+    } finally {
+      currentPriorityLevel = previousPriorityLevel;
+    }
+  }
+
+  function unstable_wrapCallback(callback) {
+    var parentPriorityLevel = currentPriorityLevel;
+    return function () {
+      // This is a fork of runWithPriority, inlined for performance.
+      var previousPriorityLevel = currentPriorityLevel;
+      currentPriorityLevel = parentPriorityLevel;
+
+      try {
+        return callback.apply(this, arguments);
+      } finally {
+        currentPriorityLevel = previousPriorityLevel;
+      }
+    };
+  }
+
+  function timeoutForPriorityLevel(priorityLevel) {
+    switch (priorityLevel) {
+      case ImmediatePriority:
+        return IMMEDIATE_PRIORITY_TIMEOUT;
+
+      case UserBlockingPriority:
+        return USER_BLOCKING_PRIORITY;
+
+      case IdlePriority:
+        return IDLE_PRIORITY;
+
+      case LowPriority:
+        return LOW_PRIORITY_TIMEOUT;
+
+      case NormalPriority:
+      default:
+        return NORMAL_PRIORITY_TIMEOUT;
+    }
+  }
+
+  function unstable_scheduleCallback(priorityLevel, callback, options) {
+    var currentTime = getCurrentTime();
+    var startTime;
+    var timeout;
+
+    if (typeof options === 'object' && options !== null) {
+      var delay = options.delay;
+
+      if (typeof delay === 'number' && delay > 0) {
+        startTime = currentTime + delay;
+      } else {
+        startTime = currentTime;
+      }
+
+      timeout = typeof options.timeout === 'number' ? options.timeout : timeoutForPriorityLevel(priorityLevel);
+    } else {
+      timeout = timeoutForPriorityLevel(priorityLevel);
+      startTime = currentTime;
+    }
+
+    var expirationTime = startTime + timeout;
+    var newTask = {
+      id: taskIdCounter++,
+      callback: callback,
+      priorityLevel: priorityLevel,
+      startTime: startTime,
+      expirationTime: expirationTime,
+      sortIndex: -1
+    };
+
+    {
+      newTask.isQueued = false;
+    }
+
+    if (startTime > currentTime) {
+      // This is a delayed task.
+      newTask.sortIndex = startTime;
+      push(timerQueue, newTask);
+
+      if (peek(taskQueue) === null && newTask === peek(timerQueue)) {
+        // All tasks are delayed, and this is the task with the earliest delay.
+        if (isHostTimeoutScheduled) {
+          // Cancel an existing timeout.
+          cancelHostTimeout();
+        } else {
+          isHostTimeoutScheduled = true;
+        } // Schedule a timeout.
+
+
+        requestHostTimeout(handleTimeout, startTime - currentTime);
+      }
+    } else {
+      newTask.sortIndex = expirationTime;
+      push(taskQueue, newTask);
+
+      {
+        markTaskStart(newTask, currentTime);
+        newTask.isQueued = true;
+      } // Schedule a host callback, if needed. If we're already performing work,
+      // wait until the next time we yield.
+
+
+      if (!isHostCallbackScheduled && !isPerformingWork) {
+        isHostCallbackScheduled = true;
+        requestHostCallback(flushWork);
+      }
+    }
+
+    return newTask;
+  }
+
+  function unstable_pauseExecution() {
+  }
+
+  function unstable_continueExecution() {
+
+    if (!isHostCallbackScheduled && !isPerformingWork) {
+      isHostCallbackScheduled = true;
+      requestHostCallback(flushWork);
+    }
+  }
+
+  function unstable_getFirstCallbackNode() {
+    return peek(taskQueue);
+  }
+
+  function unstable_cancelCallback(task) {
+    {
+      if (task.isQueued) {
+        var currentTime = getCurrentTime();
+        markTaskCanceled(task, currentTime);
+        task.isQueued = false;
+      }
+    } // Null out the callback to indicate the task has been canceled. (Can't
+    // remove from the queue because you can't remove arbitrary nodes from an
+    // array based heap, only the first one.)
+
+
+    task.callback = null;
+  }
+
+  function unstable_getCurrentPriorityLevel() {
+    return currentPriorityLevel;
+  }
+
+  function unstable_shouldYield() {
+    var currentTime = getCurrentTime();
+    advanceTimers(currentTime);
+    var firstTask = peek(taskQueue);
+    return firstTask !== currentTask && currentTask !== null && firstTask !== null && firstTask.callback !== null && firstTask.startTime <= currentTime && firstTask.expirationTime < currentTask.expirationTime || shouldYieldToHost();
+  }
+
+  var unstable_requestPaint = requestPaint;
+  var unstable_Profiling =  {
+    startLoggingProfilingEvents: startLoggingProfilingEvents,
+    stopLoggingProfilingEvents: stopLoggingProfilingEvents,
+    sharedProfilingBuffer: sharedProfilingBuffer
+  } ;
+
+
+
+  var Scheduler = /*#__PURE__*/Object.freeze({
+    __proto__: null,
+    unstable_ImmediatePriority: ImmediatePriority,
+    unstable_UserBlockingPriority: UserBlockingPriority,
+    unstable_NormalPriority: NormalPriority,
+    unstable_IdlePriority: IdlePriority,
+    unstable_LowPriority: LowPriority,
+    unstable_runWithPriority: unstable_runWithPriority,
+    unstable_next: unstable_next,
+    unstable_scheduleCallback: unstable_scheduleCallback,
+    unstable_cancelCallback: unstable_cancelCallback,
+    unstable_wrapCallback: unstable_wrapCallback,
+    unstable_getCurrentPriorityLevel: unstable_getCurrentPriorityLevel,
+    unstable_shouldYield: unstable_shouldYield,
+    unstable_requestPaint: unstable_requestPaint,
+    unstable_continueExecution: unstable_continueExecution,
+    unstable_pauseExecution: unstable_pauseExecution,
+    unstable_getFirstCallbackNode: unstable_getFirstCallbackNode,
+    get unstable_now () { return getCurrentTime; },
+    get unstable_forceFrameRate () { return forceFrameRate; },
+    unstable_Profiling: unstable_Profiling
+  });
+
+  var DEFAULT_THREAD_ID = 0; // Counters used to generate unique IDs.
+
+  var interactionIDCounter = 0;
+  var threadIDCounter = 0; // Set of currently traced interactions.
+  // Interactions "stack"–
+  // Meaning that newly traced interactions are appended to the previously active set.
+  // When an interaction goes out of scope, the previous set (if any) is restored.
+
+  var interactionsRef = null; // Listener(s) to notify when interactions begin and end.
+
+  var subscriberRef = null;
+
+  {
+    interactionsRef = {
+      current: new Set()
+    };
+    subscriberRef = {
+      current: null
+    };
+  }
+  function unstable_clear(callback) {
+
+    var prevInteractions = interactionsRef.current;
+    interactionsRef.current = new Set();
+
+    try {
+      return callback();
+    } finally {
+      interactionsRef.current = prevInteractions;
+    }
+  }
+  function unstable_getCurrent() {
+    {
+      return interactionsRef.current;
+    }
+  }
+  function unstable_getThreadID() {
+    return ++threadIDCounter;
+  }
+  function unstable_trace(name, timestamp, callback) {
+    var threadID = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : DEFAULT_THREAD_ID;
+
+    var interaction = {
+      __count: 1,
+      id: interactionIDCounter++,
+      name: name,
+      timestamp: timestamp
+    };
+    var prevInteractions = interactionsRef.current; // Traced interactions should stack/accumulate.
+    // To do that, clone the current interactions.
+    // The previous set will be restored upon completion.
+
+    var interactions = new Set(prevInteractions);
+    interactions.add(interaction);
+    interactionsRef.current = interactions;
+    var subscriber = subscriberRef.current;
+    var returnValue;
+
+    try {
+      if (subscriber !== null) {
+        subscriber.onInteractionTraced(interaction);
+      }
+    } finally {
+      try {
+        if (subscriber !== null) {
+          subscriber.onWorkStarted(interactions, threadID);
+        }
+      } finally {
+        try {
+          returnValue = callback();
+        } finally {
+          interactionsRef.current = prevInteractions;
+
+          try {
+            if (subscriber !== null) {
+              subscriber.onWorkStopped(interactions, threadID);
+            }
+          } finally {
+            interaction.__count--; // If no async work was scheduled for this interaction,
+            // Notify subscribers that it's completed.
+
+            if (subscriber !== null && interaction.__count === 0) {
+              subscriber.onInteractionScheduledWorkCompleted(interaction);
+            }
+          }
+        }
+      }
+    }
+
+    return returnValue;
+  }
+  function unstable_wrap(callback) {
+    var threadID = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : DEFAULT_THREAD_ID;
+
+    var wrappedInteractions = interactionsRef.current;
+    var subscriber = subscriberRef.current;
+
+    if (subscriber !== null) {
+      subscriber.onWorkScheduled(wrappedInteractions, threadID);
+    } // Update the pending async work count for the current interactions.
+    // Update after calling subscribers in case of error.
+
+
+    wrappedInteractions.forEach(function (interaction) {
+      interaction.__count++;
+    });
+    var hasRun = false;
+
+    function wrapped() {
+      var prevInteractions = interactionsRef.current;
+      interactionsRef.current = wrappedInteractions;
+      subscriber = subscriberRef.current;
+
+      try {
+        var returnValue;
+
+        try {
+          if (subscriber !== null) {
+            subscriber.onWorkStarted(wrappedInteractions, threadID);
+          }
+        } finally {
+          try {
+            returnValue = callback.apply(undefined, arguments);
+          } finally {
+            interactionsRef.current = prevInteractions;
+
+            if (subscriber !== null) {
+              subscriber.onWorkStopped(wrappedInteractions, threadID);
+            }
+          }
+        }
+
+        return returnValue;
+      } finally {
+        if (!hasRun) {
+          // We only expect a wrapped function to be executed once,
+          // But in the event that it's executed more than once–
+          // Only decrement the outstanding interaction counts once.
+          hasRun = true; // Update pending async counts for all wrapped interactions.
+          // If this was the last scheduled async work for any of them,
+          // Mark them as completed.
+
+          wrappedInteractions.forEach(function (interaction) {
+            interaction.__count--;
+
+            if (subscriber !== null && interaction.__count === 0) {
+              subscriber.onInteractionScheduledWorkCompleted(interaction);
+            }
+          });
+        }
+      }
+    }
+
+    wrapped.cancel = function cancel() {
+      subscriber = subscriberRef.current;
+
+      try {
+        if (subscriber !== null) {
+          subscriber.onWorkCanceled(wrappedInteractions, threadID);
+        }
+      } finally {
+        // Update pending async counts for all wrapped interactions.
+        // If this was the last scheduled async work for any of them,
+        // Mark them as completed.
+        wrappedInteractions.forEach(function (interaction) {
+          interaction.__count--;
+
+          if (subscriber && interaction.__count === 0) {
+            subscriber.onInteractionScheduledWorkCompleted(interaction);
+          }
+        });
+      }
+    };
+
+    return wrapped;
+  }
+
+  var subscribers = null;
+
+  {
+    subscribers = new Set();
+  }
+
+  function unstable_subscribe(subscriber) {
+    {
+      subscribers.add(subscriber);
+
+      if (subscribers.size === 1) {
+        subscriberRef.current = {
+          onInteractionScheduledWorkCompleted: onInteractionScheduledWorkCompleted,
+          onInteractionTraced: onInteractionTraced,
+          onWorkCanceled: onWorkCanceled,
+          onWorkScheduled: onWorkScheduled,
+          onWorkStarted: onWorkStarted,
+          onWorkStopped: onWorkStopped
+        };
+      }
+    }
+  }
+  function unstable_unsubscribe(subscriber) {
+    {
+      subscribers.delete(subscriber);
+
+      if (subscribers.size === 0) {
+        subscriberRef.current = null;
+      }
+    }
+  }
+
+  function onInteractionTraced(interaction) {
+    var didCatchError = false;
+    var caughtError = null;
+    subscribers.forEach(function (subscriber) {
+      try {
+        subscriber.onInteractionTraced(interaction);
+      } catch (error) {
+        if (!didCatchError) {
+          didCatchError = true;
+          caughtError = error;
+        }
+      }
+    });
+
+    if (didCatchError) {
+      throw caughtError;
+    }
+  }
+
+  function onInteractionScheduledWorkCompleted(interaction) {
+    var didCatchError = false;
+    var caughtError = null;
+    subscribers.forEach(function (subscriber) {
+      try {
+        subscriber.onInteractionScheduledWorkCompleted(interaction);
+      } catch (error) {
+        if (!didCatchError) {
+          didCatchError = true;
+          caughtError = error;
+        }
+      }
+    });
+
+    if (didCatchError) {
+      throw caughtError;
+    }
+  }
+
+  function onWorkScheduled(interactions, threadID) {
+    var didCatchError = false;
+    var caughtError = null;
+    subscribers.forEach(function (subscriber) {
+      try {
+        subscriber.onWorkScheduled(interactions, threadID);
+      } catch (error) {
+        if (!didCatchError) {
+          didCatchError = true;
+          caughtError = error;
+        }
+      }
+    });
+
+    if (didCatchError) {
+      throw caughtError;
+    }
+  }
+
+  function onWorkStarted(interactions, threadID) {
+    var didCatchError = false;
+    var caughtError = null;
+    subscribers.forEach(function (subscriber) {
+      try {
+        subscriber.onWorkStarted(interactions, threadID);
+      } catch (error) {
+        if (!didCatchError) {
+          didCatchError = true;
+          caughtError = error;
+        }
+      }
+    });
+
+    if (didCatchError) {
+      throw caughtError;
+    }
+  }
+
+  function onWorkStopped(interactions, threadID) {
+    var didCatchError = false;
+    var caughtError = null;
+    subscribers.forEach(function (subscriber) {
+      try {
+        subscriber.onWorkStopped(interactions, threadID);
+      } catch (error) {
+        if (!didCatchError) {
+          didCatchError = true;
+          caughtError = error;
+        }
+      }
+    });
+
+    if (didCatchError) {
+      throw caughtError;
+    }
+  }
+
+  function onWorkCanceled(interactions, threadID) {
+    var didCatchError = false;
+    var caughtError = null;
+    subscribers.forEach(function (subscriber) {
+      try {
+        subscriber.onWorkCanceled(interactions, threadID);
+      } catch (error) {
+        if (!didCatchError) {
+          didCatchError = true;
+          caughtError = error;
+        }
+      }
+    });
+
+    if (didCatchError) {
+      throw caughtError;
+    }
+  }
+
+
+
+  var SchedulerTracing = /*#__PURE__*/Object.freeze({
+    __proto__: null,
+    get __interactionsRef () { return interactionsRef; },
+    get __subscriberRef () { return subscriberRef; },
+    unstable_clear: unstable_clear,
+    unstable_getCurrent: unstable_getCurrent,
+    unstable_getThreadID: unstable_getThreadID,
+    unstable_trace: unstable_trace,
+    unstable_wrap: unstable_wrap,
+    unstable_subscribe: unstable_subscribe,
+    unstable_unsubscribe: unstable_unsubscribe
+  });
+
+  var ReactSharedInternals$1 = {
+    ReactCurrentDispatcher: ReactCurrentDispatcher,
+    ReactCurrentOwner: ReactCurrentOwner,
+    IsSomeRendererActing: IsSomeRendererActing,
+    // Used by renderers to avoid bundling object-assign twice in UMD bundles:
+    assign: objectAssign
+  };
+
+  {
+    objectAssign(ReactSharedInternals$1, {
+      // These should not be included in production.
+      ReactDebugCurrentFrame: ReactDebugCurrentFrame,
+      // Shim for React DOM 16.0.0 which still destructured (but not used) this.
+      // TODO: remove in React 17.0.
+      ReactComponentTreeHook: {}
+    });
+  } // Re-export the schedule API(s) for UMD bundles.
+  // This avoids introducing a dependency on a new UMD global in a minor update,
+  // Since that would be a breaking change (e.g. for all existing CodeSandboxes).
+  // This re-export is only required for UMD bundles;
+  // CJS bundles use the shared NPM package.
+
+
+  objectAssign(ReactSharedInternals$1, {
+    Scheduler: Scheduler,
+    SchedulerTracing: SchedulerTracing
+  });
+
+  {
+
+    try {
+      var frozenObject = Object.freeze({});
+      var testMap = new Map([[frozenObject, null]]);
+      var testSet = new Set([frozenObject]); // This is necessary for Rollup to not consider these unused.
+      // https://github.com/rollup/rollup/issues/1771
+      // TODO: we can remove these if Rollup fixes the bug.
+
+      testMap.set(0, 0);
+      testSet.add(0);
+    } catch (e) {
+    }
+  }
+
+  var createElement$1 =  createElementWithValidation ;
+  var cloneElement$1 =  cloneElementWithValidation ;
+  var createFactory =  createFactoryWithValidation ;
+  var Children = {
+    map: mapChildren,
+    forEach: forEachChildren,
+    count: countChildren,
+    toArray: toArray,
+    only: onlyChild
+  };
+
+  exports.Children = Children;
+  exports.Component = Component;
+  exports.Fragment = REACT_FRAGMENT_TYPE;
+  exports.Profiler = REACT_PROFILER_TYPE;
+  exports.PureComponent = PureComponent;
+  exports.StrictMode = REACT_STRICT_MODE_TYPE;
+  exports.Suspense = REACT_SUSPENSE_TYPE;
+  exports.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED = ReactSharedInternals$1;
+  exports.cloneElement = cloneElement$1;
+  exports.createContext = createContext;
+  exports.createElement = createElement$1;
+  exports.createFactory = createFactory;
+  exports.createRef = createRef;
+  exports.forwardRef = forwardRef;
+  exports.isValidElement = isValidElement;
+  exports.lazy = lazy;
+  exports.memo = memo;
+  exports.useCallback = useCallback;
+  exports.useContext = useContext;
+  exports.useDebugValue = useDebugValue;
+  exports.useEffect = useEffect;
+  exports.useImperativeHandle = useImperativeHandle;
+  exports.useLayoutEffect = useLayoutEffect;
+  exports.useMemo = useMemo;
+  exports.useReducer = useReducer;
+  exports.useRef = useRef;
+  exports.useState = useState;
+  exports.version = ReactVersion;
+
+})));
Index: node_modules/react/umd/react.production.min.js
===================================================================
--- node_modules/react/umd/react.production.min.js	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
+++ node_modules/react/umd/react.production.min.js	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
@@ -0,0 +1,32 @@
+/** @license React v16.14.0
+ * react.production.min.js
+ *
+ * Copyright (c) Facebook, Inc. and its affiliates.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+'use strict';(function(d,r){"object"===typeof exports&&"undefined"!==typeof module?r(exports):"function"===typeof define&&define.amd?define(["exports"],r):(d=d||self,r(d.React={}))})(this,function(d){function r(a){for(var b="https://reactjs.org/docs/error-decoder.html?invariant="+a,c=1;c<arguments.length;c++)b+="&args[]="+encodeURIComponent(arguments[c]);return"Minified React error #"+a+"; visit "+b+" for the full message or use the non-minified dev environment for full errors and additional helpful warnings."}
+function w(a,b,c){this.props=a;this.context=b;this.refs=ba;this.updater=c||ca}function da(){}function L(a,b,c){this.props=a;this.context=b;this.refs=ba;this.updater=c||ca}function ea(a,b,c){var g,e={},fa=null,d=null;if(null!=b)for(g in void 0!==b.ref&&(d=b.ref),void 0!==b.key&&(fa=""+b.key),b)ha.call(b,g)&&!ia.hasOwnProperty(g)&&(e[g]=b[g]);var h=arguments.length-2;if(1===h)e.children=c;else if(1<h){for(var k=Array(h),f=0;f<h;f++)k[f]=arguments[f+2];e.children=k}if(a&&a.defaultProps)for(g in h=a.defaultProps,
+h)void 0===e[g]&&(e[g]=h[g]);return{$$typeof:x,type:a,key:fa,ref:d,props:e,_owner:M.current}}function va(a,b){return{$$typeof:x,type:a.type,key:b,ref:a.ref,props:a.props,_owner:a._owner}}function N(a){return"object"===typeof a&&null!==a&&a.$$typeof===x}function wa(a){var b={"=":"=0",":":"=2"};return"$"+(""+a).replace(/[=:]/g,function(a){return b[a]})}function ja(a,b,c,g){if(C.length){var e=C.pop();e.result=a;e.keyPrefix=b;e.func=c;e.context=g;e.count=0;return e}return{result:a,keyPrefix:b,func:c,
+context:g,count:0}}function ka(a){a.result=null;a.keyPrefix=null;a.func=null;a.context=null;a.count=0;10>C.length&&C.push(a)}function O(a,b,c,g){var e=typeof a;if("undefined"===e||"boolean"===e)a=null;var d=!1;if(null===a)d=!0;else switch(e){case "string":case "number":d=!0;break;case "object":switch(a.$$typeof){case x:case xa:d=!0}}if(d)return c(g,a,""===b?"."+P(a,0):b),1;d=0;b=""===b?".":b+":";if(Array.isArray(a))for(var f=0;f<a.length;f++){e=a[f];var h=b+P(e,f);d+=O(e,h,c,g)}else if(null===a||
+"object"!==typeof a?h=null:(h=la&&a[la]||a["@@iterator"],h="function"===typeof h?h:null),"function"===typeof h)for(a=h.call(a),f=0;!(e=a.next()).done;)e=e.value,h=b+P(e,f++),d+=O(e,h,c,g);else if("object"===e)throw c=""+a,Error(r(31,"[object Object]"===c?"object with keys {"+Object.keys(a).join(", ")+"}":c,""));return d}function Q(a,b,c){return null==a?0:O(a,"",b,c)}function P(a,b){return"object"===typeof a&&null!==a&&null!=a.key?wa(a.key):b.toString(36)}function ya(a,b,c){a.func.call(a.context,b,
+a.count++)}function za(a,b,c){var g=a.result,e=a.keyPrefix;a=a.func.call(a.context,b,a.count++);Array.isArray(a)?R(a,g,c,function(a){return a}):null!=a&&(N(a)&&(a=va(a,e+(!a.key||b&&b.key===a.key?"":(""+a.key).replace(ma,"$&/")+"/")+c)),g.push(a))}function R(a,b,c,g,e){var d="";null!=c&&(d=(""+c).replace(ma,"$&/")+"/");b=ja(b,d,g,e);Q(a,za,b);ka(b)}function t(){var a=na.current;if(null===a)throw Error(r(321));return a}function S(a,b){var c=a.length;a.push(b);a:for(;;){var g=c-1>>>1,e=a[g];if(void 0!==
+e&&0<D(e,b))a[g]=b,a[c]=e,c=g;else break a}}function n(a){a=a[0];return void 0===a?null:a}function E(a){var b=a[0];if(void 0!==b){var c=a.pop();if(c!==b){a[0]=c;a:for(var g=0,e=a.length;g<e;){var d=2*(g+1)-1,f=a[d],h=d+1,k=a[h];if(void 0!==f&&0>D(f,c))void 0!==k&&0>D(k,f)?(a[g]=k,a[h]=c,g=h):(a[g]=f,a[d]=c,g=d);else if(void 0!==k&&0>D(k,c))a[g]=k,a[h]=c,g=h;else break a}}return b}return null}function D(a,b){var c=a.sortIndex-b.sortIndex;return 0!==c?c:a.id-b.id}function F(a){for(var b=n(u);null!==
+b;){if(null===b.callback)E(u);else if(b.startTime<=a)E(u),b.sortIndex=b.expirationTime,S(p,b);else break;b=n(u)}}function T(a){y=!1;F(a);if(!v)if(null!==n(p))v=!0,z(U);else{var b=n(u);null!==b&&G(T,b.startTime-a)}}function U(a,b){v=!1;y&&(y=!1,V());H=!0;var c=m;try{F(b);for(l=n(p);null!==l&&(!(l.expirationTime>b)||a&&!W());){var g=l.callback;if(null!==g){l.callback=null;m=l.priorityLevel;var e=g(l.expirationTime<=b);b=q();"function"===typeof e?l.callback=e:l===n(p)&&E(p);F(b)}else E(p);l=n(p)}if(null!==
+l)var d=!0;else{var f=n(u);null!==f&&G(T,f.startTime-b);d=!1}return d}finally{l=null,m=c,H=!1}}function oa(a){switch(a){case 1:return-1;case 2:return 250;case 5:return 1073741823;case 4:return 1E4;default:return 5E3}}var f="function"===typeof Symbol&&Symbol.for,x=f?Symbol.for("react.element"):60103,xa=f?Symbol.for("react.portal"):60106,Aa=f?Symbol.for("react.fragment"):60107,Ba=f?Symbol.for("react.strict_mode"):60108,Ca=f?Symbol.for("react.profiler"):60114,Da=f?Symbol.for("react.provider"):60109,
+Ea=f?Symbol.for("react.context"):60110,Fa=f?Symbol.for("react.forward_ref"):60112,Ga=f?Symbol.for("react.suspense"):60113,Ha=f?Symbol.for("react.memo"):60115,Ia=f?Symbol.for("react.lazy"):60116,la="function"===typeof Symbol&&Symbol.iterator,pa=Object.getOwnPropertySymbols,Ja=Object.prototype.hasOwnProperty,Ka=Object.prototype.propertyIsEnumerable,I=function(){try{if(!Object.assign)return!1;var a=new String("abc");a[5]="de";if("5"===Object.getOwnPropertyNames(a)[0])return!1;var b={};for(a=0;10>a;a++)b["_"+
+String.fromCharCode(a)]=a;if("0123456789"!==Object.getOwnPropertyNames(b).map(function(a){return b[a]}).join(""))return!1;var c={};"abcdefghijklmnopqrst".split("").forEach(function(a){c[a]=a});return"abcdefghijklmnopqrst"!==Object.keys(Object.assign({},c)).join("")?!1:!0}catch(g){return!1}}()?Object.assign:function(a,b){if(null===a||void 0===a)throw new TypeError("Object.assign cannot be called with null or undefined");var c=Object(a);for(var g,e=1;e<arguments.length;e++){var d=Object(arguments[e]);
+for(var f in d)Ja.call(d,f)&&(c[f]=d[f]);if(pa){g=pa(d);for(var h=0;h<g.length;h++)Ka.call(d,g[h])&&(c[g[h]]=d[g[h]])}}return c},ca={isMounted:function(a){return!1},enqueueForceUpdate:function(a,b,c){},enqueueReplaceState:function(a,b,c,d){},enqueueSetState:function(a,b,c,d){}},ba={};w.prototype.isReactComponent={};w.prototype.setState=function(a,b){if("object"!==typeof a&&"function"!==typeof a&&null!=a)throw Error(r(85));this.updater.enqueueSetState(this,a,b,"setState")};w.prototype.forceUpdate=
+function(a){this.updater.enqueueForceUpdate(this,a,"forceUpdate")};da.prototype=w.prototype;f=L.prototype=new da;f.constructor=L;I(f,w.prototype);f.isPureReactComponent=!0;var M={current:null},ha=Object.prototype.hasOwnProperty,ia={key:!0,ref:!0,__self:!0,__source:!0},ma=/\/+/g,C=[],na={current:null},X;if("undefined"===typeof window||"function"!==typeof MessageChannel){var A=null,qa=null,ra=function(){if(null!==A)try{var a=q();A(!0,a);A=null}catch(b){throw setTimeout(ra,0),b;}},La=Date.now();var q=
+function(){return Date.now()-La};var z=function(a){null!==A?setTimeout(z,0,a):(A=a,setTimeout(ra,0))};var G=function(a,b){qa=setTimeout(a,b)};var V=function(){clearTimeout(qa)};var W=function(){return!1};f=X=function(){}}else{var Y=window.performance,sa=window.Date,Ma=window.setTimeout,Na=window.clearTimeout;"undefined"!==typeof console&&(f=window.cancelAnimationFrame,"function"!==typeof window.requestAnimationFrame&&console.error("This browser doesn't support requestAnimationFrame. Make sure that you load a polyfill in older browsers. https://fb.me/react-polyfills"),
+"function"!==typeof f&&console.error("This browser doesn't support cancelAnimationFrame. Make sure that you load a polyfill in older browsers. https://fb.me/react-polyfills"));if("object"===typeof Y&&"function"===typeof Y.now)q=function(){return Y.now()};else{var Oa=sa.now();q=function(){return sa.now()-Oa}}var J=!1,K=null,Z=-1,ta=5,ua=0;W=function(){return q()>=ua};f=function(){};X=function(a){0>a||125<a?console.error("forceFrameRate takes a positive int between 0 and 125, forcing framerates higher than 125 fps is not unsupported"):
+ta=0<a?Math.floor(1E3/a):5};var B=new MessageChannel,aa=B.port2;B.port1.onmessage=function(){if(null!==K){var a=q();ua=a+ta;try{K(!0,a)?aa.postMessage(null):(J=!1,K=null)}catch(b){throw aa.postMessage(null),b;}}else J=!1};z=function(a){K=a;J||(J=!0,aa.postMessage(null))};G=function(a,b){Z=Ma(function(){a(q())},b)};V=function(){Na(Z);Z=-1}}var p=[],u=[],Pa=1,l=null,m=3,H=!1,v=!1,y=!1,Qa=0;B={ReactCurrentDispatcher:na,ReactCurrentOwner:M,IsSomeRendererActing:{current:!1},assign:I};I(B,{Scheduler:{__proto__:null,
+unstable_ImmediatePriority:1,unstable_UserBlockingPriority:2,unstable_NormalPriority:3,unstable_IdlePriority:5,unstable_LowPriority:4,unstable_runWithPriority:function(a,b){switch(a){case 1:case 2:case 3:case 4:case 5:break;default:a=3}var c=m;m=a;try{return b()}finally{m=c}},unstable_next:function(a){switch(m){case 1:case 2:case 3:var b=3;break;default:b=m}var c=m;m=b;try{return a()}finally{m=c}},unstable_scheduleCallback:function(a,b,c){var d=q();if("object"===typeof c&&null!==c){var e=c.delay;
+e="number"===typeof e&&0<e?d+e:d;c="number"===typeof c.timeout?c.timeout:oa(a)}else c=oa(a),e=d;c=e+c;a={id:Pa++,callback:b,priorityLevel:a,startTime:e,expirationTime:c,sortIndex:-1};e>d?(a.sortIndex=e,S(u,a),null===n(p)&&a===n(u)&&(y?V():y=!0,G(T,e-d))):(a.sortIndex=c,S(p,a),v||H||(v=!0,z(U)));return a},unstable_cancelCallback:function(a){a.callback=null},unstable_wrapCallback:function(a){var b=m;return function(){var c=m;m=b;try{return a.apply(this,arguments)}finally{m=c}}},unstable_getCurrentPriorityLevel:function(){return m},
+unstable_shouldYield:function(){var a=q();F(a);var b=n(p);return b!==l&&null!==l&&null!==b&&null!==b.callback&&b.startTime<=a&&b.expirationTime<l.expirationTime||W()},unstable_requestPaint:f,unstable_continueExecution:function(){v||H||(v=!0,z(U))},unstable_pauseExecution:function(){},unstable_getFirstCallbackNode:function(){return n(p)},get unstable_now(){return q},get unstable_forceFrameRate(){return X},unstable_Profiling:null},SchedulerTracing:{__proto__:null,__interactionsRef:null,__subscriberRef:null,
+unstable_clear:function(a){return a()},unstable_getCurrent:function(){return null},unstable_getThreadID:function(){return++Qa},unstable_trace:function(a,b,c){return c()},unstable_wrap:function(a){return a},unstable_subscribe:function(a){},unstable_unsubscribe:function(a){}}});d.Children={map:function(a,b,c){if(null==a)return a;var d=[];R(a,d,null,b,c);return d},forEach:function(a,b,c){if(null==a)return a;b=ja(null,null,b,c);Q(a,ya,b);ka(b)},count:function(a){return Q(a,function(){return null},null)},
+toArray:function(a){var b=[];R(a,b,null,function(a){return a});return b},only:function(a){if(!N(a))throw Error(r(143));return a}};d.Component=w;d.Fragment=Aa;d.Profiler=Ca;d.PureComponent=L;d.StrictMode=Ba;d.Suspense=Ga;d.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED=B;d.cloneElement=function(a,b,c){if(null===a||void 0===a)throw Error(r(267,a));var d=I({},a.props),e=a.key,f=a.ref,m=a._owner;if(null!=b){void 0!==b.ref&&(f=b.ref,m=M.current);void 0!==b.key&&(e=""+b.key);if(a.type&&a.type.defaultProps)var h=
+a.type.defaultProps;for(k in b)ha.call(b,k)&&!ia.hasOwnProperty(k)&&(d[k]=void 0===b[k]&&void 0!==h?h[k]:b[k])}var k=arguments.length-2;if(1===k)d.children=c;else if(1<k){h=Array(k);for(var l=0;l<k;l++)h[l]=arguments[l+2];d.children=h}return{$$typeof:x,type:a.type,key:e,ref:f,props:d,_owner:m}};d.createContext=function(a,b){void 0===b&&(b=null);a={$$typeof:Ea,_calculateChangedBits:b,_currentValue:a,_currentValue2:a,_threadCount:0,Provider:null,Consumer:null};a.Provider={$$typeof:Da,_context:a};return a.Consumer=
+a};d.createElement=ea;d.createFactory=function(a){var b=ea.bind(null,a);b.type=a;return b};d.createRef=function(){return{current:null}};d.forwardRef=function(a){return{$$typeof:Fa,render:a}};d.isValidElement=N;d.lazy=function(a){return{$$typeof:Ia,_ctor:a,_status:-1,_result:null}};d.memo=function(a,b){return{$$typeof:Ha,type:a,compare:void 0===b?null:b}};d.useCallback=function(a,b){return t().useCallback(a,b)};d.useContext=function(a,b){return t().useContext(a,b)};d.useDebugValue=function(a,b){};
+d.useEffect=function(a,b){return t().useEffect(a,b)};d.useImperativeHandle=function(a,b,c){return t().useImperativeHandle(a,b,c)};d.useLayoutEffect=function(a,b){return t().useLayoutEffect(a,b)};d.useMemo=function(a,b){return t().useMemo(a,b)};d.useReducer=function(a,b,c){return t().useReducer(a,b,c)};d.useRef=function(a){return t().useRef(a)};d.useState=function(a){return t().useState(a)};d.version="16.14.0"});
Index: node_modules/react/umd/react.profiling.min.js
===================================================================
--- node_modules/react/umd/react.profiling.min.js	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
+++ node_modules/react/umd/react.profiling.min.js	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
@@ -0,0 +1,39 @@
+/** @license React v16.14.0
+ * react.profiling.min.js
+ *
+ * Copyright (c) Facebook, Inc. and its affiliates.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+'use strict';(function(f,x){"object"===typeof exports&&"undefined"!==typeof module?x(exports):"function"===typeof define&&define.amd?define(["exports"],x):(f=f||self,x(f.React={}))})(this,function(f){function x(a){for(var b="https://reactjs.org/docs/error-decoder.html?invariant="+a,c=1;c<arguments.length;c++)b+="&args[]="+encodeURIComponent(arguments[c]);return"Minified React error #"+a+"; visit "+b+" for the full message or use the non-minified dev environment for full errors and additional helpful warnings."}
+function E(a,b,c){this.props=a;this.context=b;this.refs=pa;this.updater=c||qa}function ra(){}function V(a,b,c){this.props=a;this.context=b;this.refs=pa;this.updater=c||qa}function sa(a,b,c){var d,e={},h=null,n=null;if(null!=b)for(d in void 0!==b.ref&&(n=b.ref),void 0!==b.key&&(h=""+b.key),b)ta.call(b,d)&&!ua.hasOwnProperty(d)&&(e[d]=b[d]);var g=arguments.length-2;if(1===g)e.children=c;else if(1<g){for(var f=Array(g),k=0;k<g;k++)f[k]=arguments[k+2];e.children=f}if(a&&a.defaultProps)for(d in g=a.defaultProps,
+g)void 0===e[d]&&(e[d]=g[d]);return{$$typeof:F,type:a,key:h,ref:n,props:e,_owner:W.current}}function Na(a,b){return{$$typeof:F,type:a.type,key:b,ref:a.ref,props:a.props,_owner:a._owner}}function X(a){return"object"===typeof a&&null!==a&&a.$$typeof===F}function Oa(a){var b={"=":"=0",":":"=2"};return"$"+(""+a).replace(/[=:]/g,function(a){return b[a]})}function wa(a,b,c,d){if(L.length){var e=L.pop();e.result=a;e.keyPrefix=b;e.func=c;e.context=d;e.count=0;return e}return{result:a,keyPrefix:b,func:c,context:d,
+count:0}}function xa(a){a.result=null;a.keyPrefix=null;a.func=null;a.context=null;a.count=0;10>L.length&&L.push(a)}function Y(a,b,c,d){var e=typeof a;if("undefined"===e||"boolean"===e)a=null;var h=!1;if(null===a)h=!0;else switch(e){case "string":case "number":h=!0;break;case "object":switch(a.$$typeof){case F:case Pa:h=!0}}if(h)return c(d,a,""===b?"."+Z(a,0):b),1;h=0;b=""===b?".":b+":";if(Array.isArray(a))for(var n=0;n<a.length;n++){e=a[n];var g=b+Z(e,n);h+=Y(e,g,c,d)}else if(null===a||"object"!==
+typeof a?g=null:(g=ya&&a[ya]||a["@@iterator"],g="function"===typeof g?g:null),"function"===typeof g)for(a=g.call(a),n=0;!(e=a.next()).done;)e=e.value,g=b+Z(e,n++),h+=Y(e,g,c,d);else if("object"===e)throw c=""+a,Error(x(31,"[object Object]"===c?"object with keys {"+Object.keys(a).join(", ")+"}":c,""));return h}function aa(a,b,c){return null==a?0:Y(a,"",b,c)}function Z(a,b){return"object"===typeof a&&null!==a&&null!=a.key?Oa(a.key):b.toString(36)}function Qa(a,b,c){a.func.call(a.context,b,a.count++)}
+function Ra(a,b,c){var d=a.result,e=a.keyPrefix;a=a.func.call(a.context,b,a.count++);Array.isArray(a)?ba(a,d,c,function(a){return a}):null!=a&&(X(a)&&(a=Na(a,e+(!a.key||b&&b.key===a.key?"":(""+a.key).replace(za,"$&/")+"/")+c)),d.push(a))}function ba(a,b,c,d,e){var h="";null!=c&&(h=(""+c).replace(za,"$&/")+"/");b=wa(b,h,d,e);aa(a,Ra,b);xa(b)}function y(){var a=Aa.current;if(null===a)throw Error(x(321));return a}function ca(a,b){var c=a.length;a.push(b);a:for(;;){var d=c-1>>>1,e=a[d];if(void 0!==e&&
+0<M(e,b))a[d]=b,a[c]=e,c=d;else break a}}function u(a){a=a[0];return void 0===a?null:a}function N(a){var b=a[0];if(void 0!==b){var c=a.pop();if(c!==b){a[0]=c;a:for(var d=0,e=a.length;d<e;){var h=2*(d+1)-1,n=a[h],g=h+1,f=a[g];if(void 0!==n&&0>M(n,c))void 0!==f&&0>M(f,n)?(a[d]=f,a[g]=c,d=g):(a[d]=n,a[h]=c,d=h);else if(void 0!==f&&0>M(f,c))a[d]=f,a[g]=c,d=g;else break a}}return b}return null}function M(a,b){var c=a.sortIndex-b.sortIndex;return 0!==c?c:a.id-b.id}function z(a){if(null!==q){var b=G;G+=
+a.length;if(G+1>C){C*=2;if(524288<C){console.error("Scheduler Profiling: Event log exceeded maximum size. Don't forget to call `stopLoggingProfilingEvents()`.");Ba();return}var c=new Int32Array(4*C);c.set(q);H=c.buffer;q=c}q.set(a,b)}}function Ba(){var a=H;C=0;q=H=null;G=0;return a}function Ca(a,b){l[3]++;null!==q&&z([1,1E3*b,a.id,a.priorityLevel])}function O(a){for(var b=u(A);null!==b;){if(null===b.callback)N(A);else if(b.startTime<=a)N(A),b.sortIndex=b.expirationTime,ca(v,b),Ca(b,a),b.isQueued=
+!0;else break;b=u(A)}}function da(a){I=!1;O(a);if(!D)if(null!==u(v))D=!0,J(ea);else{var b=u(A);null!==b&&P(da,b.startTime-a)}}function ea(a,b){null!==q&&z([8,1E3*b,fa]);D=!1;I&&(I=!1,ha());Q=!0;var c=m;try{try{O(b);for(k=u(v);null!==k&&(!(k.expirationTime>b)||a&&!ia());){var d=k.callback;if(null!==d){k.callback=null;m=k.priorityLevel;var e=k.expirationTime<=b,h=k,f=b;R++;l[0]=h.priorityLevel;l[1]=h.id;l[2]=R;null!==q&&z([5,1E3*f,h.id,R]);var g=d(e);b=r();"function"===typeof g?(k.callback=g,h=k,f=
+b,l[0]=0,l[1]=0,l[2]=0,null!==q&&z([6,1E3*f,h.id,R])):(h=k,f=b,l[0]=0,l[1]=0,l[3]--,null!==q&&z([2,1E3*f,h.id]),k.isQueued=!1,k===u(v)&&N(v));O(b)}else N(v);k=u(v)}if(null!==k)var va=!0;else{var p=u(A);null!==p&&P(da,p.startTime-b);va=!1}return va}catch(Sa){if(null!==k){var t=r();a=k;l[0]=0;l[1]=0;l[3]--;null!==q&&z([3,1E3*t,a.id]);k.isQueued=!1}throw Sa;}}finally{k=null,m=c,Q=!1,c=r(),fa++,null!==q&&z([7,1E3*c,fa])}}function Da(a){switch(a){case 1:return-1;case 2:return 250;case 5:return 1073741823;
+case 4:return 1E4;default:return 5E3}}function Ta(a){var b=!1,c=null;t.forEach(function(d){try{d.onInteractionTraced(a)}catch(e){b||(b=!0,c=e)}});if(b)throw c;}function Ua(a){var b=!1,c=null;t.forEach(function(d){try{d.onInteractionScheduledWorkCompleted(a)}catch(e){b||(b=!0,c=e)}});if(b)throw c;}function Va(a,b){var c=!1,d=null;t.forEach(function(e){try{e.onWorkScheduled(a,b)}catch(h){c||(c=!0,d=h)}});if(c)throw d;}function Wa(a,b){var c=!1,d=null;t.forEach(function(e){try{e.onWorkStarted(a,b)}catch(h){c||
+(c=!0,d=h)}});if(c)throw d;}function Xa(a,b){var c=!1,d=null;t.forEach(function(e){try{e.onWorkStopped(a,b)}catch(h){c||(c=!0,d=h)}});if(c)throw d;}function Ya(a,b){var c=!1,d=null;t.forEach(function(e){try{e.onWorkCanceled(a,b)}catch(h){c||(c=!0,d=h)}});if(c)throw d;}var w="function"===typeof Symbol&&Symbol.for,F=w?Symbol.for("react.element"):60103,Pa=w?Symbol.for("react.portal"):60106,Za=w?Symbol.for("react.fragment"):60107,$a=w?Symbol.for("react.strict_mode"):60108,ab=w?Symbol.for("react.profiler"):
+60114,bb=w?Symbol.for("react.provider"):60109,cb=w?Symbol.for("react.context"):60110,db=w?Symbol.for("react.forward_ref"):60112,eb=w?Symbol.for("react.suspense"):60113,fb=w?Symbol.for("react.memo"):60115,gb=w?Symbol.for("react.lazy"):60116,ya="function"===typeof Symbol&&Symbol.iterator,Ea=Object.getOwnPropertySymbols,hb=Object.prototype.hasOwnProperty,ib=Object.prototype.propertyIsEnumerable,S=function(){try{if(!Object.assign)return!1;var a=new String("abc");a[5]="de";if("5"===Object.getOwnPropertyNames(a)[0])return!1;
+var b={};for(a=0;10>a;a++)b["_"+String.fromCharCode(a)]=a;if("0123456789"!==Object.getOwnPropertyNames(b).map(function(a){return b[a]}).join(""))return!1;var c={};"abcdefghijklmnopqrst".split("").forEach(function(a){c[a]=a});return"abcdefghijklmnopqrst"!==Object.keys(Object.assign({},c)).join("")?!1:!0}catch(d){return!1}}()?Object.assign:function(a,b){if(null===a||void 0===a)throw new TypeError("Object.assign cannot be called with null or undefined");var c=Object(a);for(var d,e=1;e<arguments.length;e++){var h=
+Object(arguments[e]);for(var f in h)hb.call(h,f)&&(c[f]=h[f]);if(Ea){d=Ea(h);for(var g=0;g<d.length;g++)ib.call(h,d[g])&&(c[d[g]]=h[d[g]])}}return c},qa={isMounted:function(a){return!1},enqueueForceUpdate:function(a,b,c){},enqueueReplaceState:function(a,b,c,d){},enqueueSetState:function(a,b,c,d){}},pa={};E.prototype.isReactComponent={};E.prototype.setState=function(a,b){if("object"!==typeof a&&"function"!==typeof a&&null!=a)throw Error(x(85));this.updater.enqueueSetState(this,a,b,"setState")};E.prototype.forceUpdate=
+function(a){this.updater.enqueueForceUpdate(this,a,"forceUpdate")};ra.prototype=E.prototype;var ja=V.prototype=new ra;ja.constructor=V;S(ja,E.prototype);ja.isPureReactComponent=!0;var W={current:null},ta=Object.prototype.hasOwnProperty,ua={key:!0,ref:!0,__self:!0,__source:!0},za=/\/+/g,L=[],Aa={current:null},ka;if("undefined"===typeof window||"function"!==typeof MessageChannel){var K=null,Fa=null,Ga=function(){if(null!==K)try{var a=r();K(!0,a);K=null}catch(b){throw setTimeout(Ga,0),b;}},jb=Date.now();
+var r=function(){return Date.now()-jb};var J=function(a){null!==K?setTimeout(J,0,a):(K=a,setTimeout(Ga,0))};var P=function(a,b){Fa=setTimeout(a,b)};var ha=function(){clearTimeout(Fa)};var ia=function(){return!1};var Ha=ka=function(){}}else{var la=window.performance,Ia=window.Date,kb=window.setTimeout,lb=window.clearTimeout;if("undefined"!==typeof console){var mb=window.cancelAnimationFrame;"function"!==typeof window.requestAnimationFrame&&console.error("This browser doesn't support requestAnimationFrame. Make sure that you load a polyfill in older browsers. https://fb.me/react-polyfills");
+"function"!==typeof mb&&console.error("This browser doesn't support cancelAnimationFrame. Make sure that you load a polyfill in older browsers. https://fb.me/react-polyfills")}if("object"===typeof la&&"function"===typeof la.now)r=function(){return la.now()};else{var nb=Ia.now();r=function(){return Ia.now()-nb}}var T=!1,U=null,ma=-1,Ja=5,Ka=0;ia=function(){return r()>=Ka};Ha=function(){};ka=function(a){0>a||125<a?console.error("forceFrameRate takes a positive int between 0 and 125, forcing framerates higher than 125 fps is not unsupported"):
+Ja=0<a?Math.floor(1E3/a):5};var La=new MessageChannel,na=La.port2;La.port1.onmessage=function(){if(null!==U){var a=r();Ka=a+Ja;try{U(!0,a)?na.postMessage(null):(T=!1,U=null)}catch(b){throw na.postMessage(null),b;}}else T=!1};J=function(a){U=a;T||(T=!0,na.postMessage(null))};P=function(a,b){ma=kb(function(){a(r())},b)};ha=function(){lb(ma);ma=-1}}var R=0,fa=0,oa="function"===typeof SharedArrayBuffer?new SharedArrayBuffer(4*Int32Array.BYTES_PER_ELEMENT):"function"===typeof ArrayBuffer?new ArrayBuffer(4*
+Int32Array.BYTES_PER_ELEMENT):null,l=null!==oa?new Int32Array(oa):[];l[0]=0;l[3]=0;var C=l[1]=0,H=null,q=null,G=0,v=[],A=[],ob=1,k=null,m=3,Q=!1,D=!1,I=!1,pb={__proto__:null,unstable_ImmediatePriority:1,unstable_UserBlockingPriority:2,unstable_NormalPriority:3,unstable_IdlePriority:5,unstable_LowPriority:4,unstable_runWithPriority:function(a,b){switch(a){case 1:case 2:case 3:case 4:case 5:break;default:a=3}var c=m;m=a;try{return b()}finally{m=c}},unstable_next:function(a){switch(m){case 1:case 2:case 3:var b=
+3;break;default:b=m}var c=m;m=b;try{return a()}finally{m=c}},unstable_scheduleCallback:function(a,b,c){var d=r();if("object"===typeof c&&null!==c){var e=c.delay;e="number"===typeof e&&0<e?d+e:d;c="number"===typeof c.timeout?c.timeout:Da(a)}else c=Da(a),e=d;c=e+c;a={id:ob++,callback:b,priorityLevel:a,startTime:e,expirationTime:c,sortIndex:-1,isQueued:!1};e>d?(a.sortIndex=e,ca(A,a),null===u(v)&&a===u(A)&&(I?ha():I=!0,P(da,e-d))):(a.sortIndex=c,ca(v,a),Ca(a,d),a.isQueued=!0,D||Q||(D=!0,J(ea)));return a},
+unstable_cancelCallback:function(a){if(a.isQueued){var b=r();l[3]--;null!==q&&z([4,1E3*b,a.id]);a.isQueued=!1}a.callback=null},unstable_wrapCallback:function(a){var b=m;return function(){var c=m;m=b;try{return a.apply(this,arguments)}finally{m=c}}},unstable_getCurrentPriorityLevel:function(){return m},unstable_shouldYield:function(){var a=r();O(a);var b=u(v);return b!==k&&null!==k&&null!==b&&null!==b.callback&&b.startTime<=a&&b.expirationTime<k.expirationTime||ia()},unstable_requestPaint:Ha,unstable_continueExecution:function(){D||
+Q||(D=!0,J(ea))},unstable_pauseExecution:function(){},unstable_getFirstCallbackNode:function(){return u(v)},get unstable_now(){return r},get unstable_forceFrameRate(){return ka},unstable_Profiling:{startLoggingProfilingEvents:function(){C=131072;H=new ArrayBuffer(4*C);q=new Int32Array(H);G=0},stopLoggingProfilingEvents:Ba,sharedProfilingBuffer:oa}},qb=0,rb=0,p=null,B=null;p={current:new Set};B={current:null};var t=null;t=new Set;var Ma={ReactCurrentDispatcher:Aa,ReactCurrentOwner:W,IsSomeRendererActing:{current:!1},
+assign:S};S(Ma,{Scheduler:pb,SchedulerTracing:{__proto__:null,get __interactionsRef(){return p},get __subscriberRef(){return B},unstable_clear:function(a){var b=p.current;p.current=new Set;try{return a()}finally{p.current=b}},unstable_getCurrent:function(){return p.current},unstable_getThreadID:function(){return++rb},unstable_trace:function(a,b,c){var d=3<arguments.length&&void 0!==arguments[3]?arguments[3]:0,e={__count:1,id:qb++,name:a,timestamp:b},f=p.current,n=new Set(f);n.add(e);p.current=n;var g=
+B.current;try{if(null!==g)g.onInteractionTraced(e)}finally{try{if(null!==g)g.onWorkStarted(n,d)}finally{try{var k=c()}finally{p.current=f;try{if(null!==g)g.onWorkStopped(n,d)}finally{if(e.__count--,null!==g&&0===e.__count)g.onInteractionScheduledWorkCompleted(e)}}}}return k},unstable_wrap:function(a){function b(){var b=p.current;p.current=d;e=B.current;try{try{if(null!==e)e.onWorkStarted(d,c)}finally{try{var g=a.apply(void 0,arguments)}finally{if(p.current=b,null!==e)e.onWorkStopped(d,c)}}return g}finally{f||
+(f=!0,d.forEach(function(a){a.__count--;if(null!==e&&0===a.__count)e.onInteractionScheduledWorkCompleted(a)}))}}var c=1<arguments.length&&void 0!==arguments[1]?arguments[1]:0,d=p.current,e=B.current;if(null!==e)e.onWorkScheduled(d,c);d.forEach(function(a){a.__count++});var f=!1;b.cancel=function(){e=B.current;try{if(null!==e)e.onWorkCanceled(d,c)}finally{d.forEach(function(a){a.__count--;if(e&&0===a.__count)e.onInteractionScheduledWorkCompleted(a)})}};return b},unstable_subscribe:function(a){t.add(a);
+1===t.size&&(B.current={onInteractionScheduledWorkCompleted:Ua,onInteractionTraced:Ta,onWorkCanceled:Ya,onWorkScheduled:Va,onWorkStarted:Wa,onWorkStopped:Xa})},unstable_unsubscribe:function(a){t.delete(a);0===t.size&&(B.current=null)}}});f.Children={map:function(a,b,c){if(null==a)return a;var d=[];ba(a,d,null,b,c);return d},forEach:function(a,b,c){if(null==a)return a;b=wa(null,null,b,c);aa(a,Qa,b);xa(b)},count:function(a){return aa(a,function(){return null},null)},toArray:function(a){var b=[];ba(a,
+b,null,function(a){return a});return b},only:function(a){if(!X(a))throw Error(x(143));return a}};f.Component=E;f.Fragment=Za;f.Profiler=ab;f.PureComponent=V;f.StrictMode=$a;f.Suspense=eb;f.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED=Ma;f.cloneElement=function(a,b,c){if(null===a||void 0===a)throw Error(x(267,a));var d=S({},a.props),e=a.key,f=a.ref,k=a._owner;if(null!=b){void 0!==b.ref&&(f=b.ref,k=W.current);void 0!==b.key&&(e=""+b.key);if(a.type&&a.type.defaultProps)var g=a.type.defaultProps;
+for(l in b)ta.call(b,l)&&!ua.hasOwnProperty(l)&&(d[l]=void 0===b[l]&&void 0!==g?g[l]:b[l])}var l=arguments.length-2;if(1===l)d.children=c;else if(1<l){g=Array(l);for(var m=0;m<l;m++)g[m]=arguments[m+2];d.children=g}return{$$typeof:F,type:a.type,key:e,ref:f,props:d,_owner:k}};f.createContext=function(a,b){void 0===b&&(b=null);a={$$typeof:cb,_calculateChangedBits:b,_currentValue:a,_currentValue2:a,_threadCount:0,Provider:null,Consumer:null};a.Provider={$$typeof:bb,_context:a};return a.Consumer=a};f.createElement=
+sa;f.createFactory=function(a){var b=sa.bind(null,a);b.type=a;return b};f.createRef=function(){return{current:null}};f.forwardRef=function(a){return{$$typeof:db,render:a}};f.isValidElement=X;f.lazy=function(a){return{$$typeof:gb,_ctor:a,_status:-1,_result:null}};f.memo=function(a,b){return{$$typeof:fb,type:a,compare:void 0===b?null:b}};f.useCallback=function(a,b){return y().useCallback(a,b)};f.useContext=function(a,b){return y().useContext(a,b)};f.useDebugValue=function(a,b){};f.useEffect=function(a,
+b){return y().useEffect(a,b)};f.useImperativeHandle=function(a,b,c){return y().useImperativeHandle(a,b,c)};f.useLayoutEffect=function(a,b){return y().useLayoutEffect(a,b)};f.useMemo=function(a,b){return y().useMemo(a,b)};f.useReducer=function(a,b,c){return y().useReducer(a,b,c)};f.useRef=function(a){return y().useRef(a)};f.useState=function(a){return y().useState(a)};f.version="16.14.0"});
Index: package-lock.json
===================================================================
--- package-lock.json	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
+++ package-lock.json	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
@@ -0,0 +1,135 @@
+{
+  "name": "Phonelux",
+  "lockfileVersion": 2,
+  "requires": true,
+  "packages": {
+    "": {
+      "dependencies": {
+        "react-facebook-login": "^4.1.1"
+      }
+    },
+    "node_modules/js-tokens": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
+      "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
+      "peer": true
+    },
+    "node_modules/loose-envify": {
+      "version": "1.4.0",
+      "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
+      "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
+      "peer": true,
+      "dependencies": {
+        "js-tokens": "^3.0.0 || ^4.0.0"
+      },
+      "bin": {
+        "loose-envify": "cli.js"
+      }
+    },
+    "node_modules/object-assign": {
+      "version": "4.1.1",
+      "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
+      "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
+      "peer": true,
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/prop-types": {
+      "version": "15.8.1",
+      "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
+      "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
+      "peer": true,
+      "dependencies": {
+        "loose-envify": "^1.4.0",
+        "object-assign": "^4.1.1",
+        "react-is": "^16.13.1"
+      }
+    },
+    "node_modules/react": {
+      "version": "16.14.0",
+      "resolved": "https://registry.npmjs.org/react/-/react-16.14.0.tgz",
+      "integrity": "sha512-0X2CImDkJGApiAlcf0ODKIneSwBPhqJawOa5wCtKbu7ZECrmS26NvtSILynQ66cgkT/RJ4LidJOc3bUESwmU8g==",
+      "peer": true,
+      "dependencies": {
+        "loose-envify": "^1.1.0",
+        "object-assign": "^4.1.1",
+        "prop-types": "^15.6.2"
+      },
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/react-facebook-login": {
+      "version": "4.1.1",
+      "resolved": "https://registry.npmjs.org/react-facebook-login/-/react-facebook-login-4.1.1.tgz",
+      "integrity": "sha512-COnHEHlYGTKipz4963safFAK9PaNTcCiXfPXMS/yxo8El+/AJL5ye8kMJf23lKSSGGPgqFQuInskIHVqGqTvSw==",
+      "peerDependencies": {
+        "react": "^16.0.0"
+      }
+    },
+    "node_modules/react-is": {
+      "version": "16.13.1",
+      "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
+      "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
+      "peer": true
+    }
+  },
+  "dependencies": {
+    "js-tokens": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
+      "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
+      "peer": true
+    },
+    "loose-envify": {
+      "version": "1.4.0",
+      "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
+      "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
+      "peer": true,
+      "requires": {
+        "js-tokens": "^3.0.0 || ^4.0.0"
+      }
+    },
+    "object-assign": {
+      "version": "4.1.1",
+      "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
+      "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
+      "peer": true
+    },
+    "prop-types": {
+      "version": "15.8.1",
+      "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
+      "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
+      "peer": true,
+      "requires": {
+        "loose-envify": "^1.4.0",
+        "object-assign": "^4.1.1",
+        "react-is": "^16.13.1"
+      }
+    },
+    "react": {
+      "version": "16.14.0",
+      "resolved": "https://registry.npmjs.org/react/-/react-16.14.0.tgz",
+      "integrity": "sha512-0X2CImDkJGApiAlcf0ODKIneSwBPhqJawOa5wCtKbu7ZECrmS26NvtSILynQ66cgkT/RJ4LidJOc3bUESwmU8g==",
+      "peer": true,
+      "requires": {
+        "loose-envify": "^1.1.0",
+        "object-assign": "^4.1.1",
+        "prop-types": "^15.6.2"
+      }
+    },
+    "react-facebook-login": {
+      "version": "4.1.1",
+      "resolved": "https://registry.npmjs.org/react-facebook-login/-/react-facebook-login-4.1.1.tgz",
+      "integrity": "sha512-COnHEHlYGTKipz4963safFAK9PaNTcCiXfPXMS/yxo8El+/AJL5ye8kMJf23lKSSGGPgqFQuInskIHVqGqTvSw==",
+      "requires": {}
+    },
+    "react-is": {
+      "version": "16.13.1",
+      "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
+      "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
+      "peer": true
+    }
+  }
+}
Index: package.json
===================================================================
--- package.json	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
+++ package.json	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
@@ -0,0 +1,5 @@
+{
+  "dependencies": {
+    "react-facebook-login": "^4.1.1"
+  }
+}
Index: phonelux-backend/pom.xml
===================================================================
--- phonelux-backend/pom.xml	(revision ffd50db1e5e2b9839ba7546d8ca44b600150bd71)
+++ phonelux-backend/pom.xml	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
@@ -69,4 +69,9 @@
 		</dependency>
 
+		<dependency>
+			<groupId>org.springframework.boot</groupId>
+			<artifactId>spring-boot-starter-oauth2-client</artifactId>
+		</dependency>
+
 	</dependencies>
 
Index: phonelux-backend/src/main/java/finki/it/phoneluxbackend/controllers/OfferReportController.java
===================================================================
--- phonelux-backend/src/main/java/finki/it/phoneluxbackend/controllers/OfferReportController.java	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
+++ phonelux-backend/src/main/java/finki/it/phoneluxbackend/controllers/OfferReportController.java	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
@@ -0,0 +1,45 @@
+package finki.it.phoneluxbackend.controllers;
+
+import finki.it.phoneluxbackend.entities.OfferReport;
+import finki.it.phoneluxbackend.services.OfferReportService;
+import lombok.AllArgsConstructor;
+import org.apache.coyote.Response;
+import org.springframework.http.ResponseEntity;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+@AllArgsConstructor
+@RestController
+@RequestMapping(path = "/offerreport")
+public class OfferReportController {
+    private final OfferReportService offerReportService;
+
+    @GetMapping(path = "/allreports")
+    public List<OfferReport> getAllOfferReports(){
+        return offerReportService.getAllOfferReports();
+    }
+
+    @PostMapping(path = "/{offerId}/{userId}")
+    public ResponseEntity<Object> reportOffer(@PathVariable("offerId") Long offerId,
+                                              @PathVariable("userId") Long userId){
+
+        return offerReportService.reportOffer(offerId, userId);
+    }
+
+    @DeleteMapping(path = "/remove/{offerReportId}")
+    public ResponseEntity<Object> removeOfferReport(@PathVariable("offerReportId") Long offerReportId){
+
+        return offerReportService.removeOfferReport(offerReportId);
+    }
+
+    @DeleteMapping(path = "/removeall")
+    public ResponseEntity<Object> removeAllOfferReports(){
+
+        return offerReportService.removeAllOfferReports();
+    }
+
+
+
+}
Index: phonelux-backend/src/main/java/finki/it/phoneluxbackend/controllers/ScrapperInfoController.java
===================================================================
--- phonelux-backend/src/main/java/finki/it/phoneluxbackend/controllers/ScrapperInfoController.java	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
+++ phonelux-backend/src/main/java/finki/it/phoneluxbackend/controllers/ScrapperInfoController.java	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
@@ -0,0 +1,23 @@
+package finki.it.phoneluxbackend.controllers;
+
+import finki.it.phoneluxbackend.entities.ScrapperInfo;
+import finki.it.phoneluxbackend.services.ScrapperInfoService;
+import lombok.AllArgsConstructor;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.List;
+
+@AllArgsConstructor
+@RestController
+@RequestMapping(path = "/scrapperinfo")
+public class ScrapperInfoController{
+    private final ScrapperInfoService scrapperInfoService;
+
+    @GetMapping
+    public List<ScrapperInfo> getAllScrapperInfos(){
+        return scrapperInfoService.getAllScrapperInfos();
+    }
+
+}
Index: phonelux-backend/src/main/java/finki/it/phoneluxbackend/entities/OfferReport.java
===================================================================
--- phonelux-backend/src/main/java/finki/it/phoneluxbackend/entities/OfferReport.java	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
+++ phonelux-backend/src/main/java/finki/it/phoneluxbackend/entities/OfferReport.java	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
@@ -0,0 +1,45 @@
+package finki.it.phoneluxbackend.entities;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import lombok.*;
+
+import javax.persistence.*;
+import java.time.LocalDateTime;
+
+@AllArgsConstructor
+@NoArgsConstructor
+@Getter
+@Setter
+@ToString
+@Entity
+public class OfferReport {
+    @SequenceGenerator(
+            name = "offer_report_sequence",
+            sequenceName = "offer_report_sequence",
+            allocationSize = 1
+    )
+    @Id
+    @GeneratedValue(
+            strategy = GenerationType.SEQUENCE,
+            generator = "offer_report_sequence"
+    )
+    private Long id;
+
+    @ManyToOne(fetch = FetchType.EAGER)
+    @JoinColumn(name = "offer_id", referencedColumnName = "offer_id")
+    private PhoneOffer phoneOffer;
+
+    private Integer times_reported;
+
+    private LocalDateTime reportedAt;
+
+    private String reportedBy;
+
+
+    public OfferReport(PhoneOffer phoneOffer, Integer times_reported, LocalDateTime reportedAt, String reportedBy) {
+        this.phoneOffer = phoneOffer;
+        this.times_reported = times_reported;
+        this.reportedAt = reportedAt;
+        this.reportedBy = reportedBy;
+    }
+}
Index: phonelux-backend/src/main/java/finki/it/phoneluxbackend/entities/ScrapperInfo.java
===================================================================
--- phonelux-backend/src/main/java/finki/it/phoneluxbackend/entities/ScrapperInfo.java	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
+++ phonelux-backend/src/main/java/finki/it/phoneluxbackend/entities/ScrapperInfo.java	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
@@ -0,0 +1,35 @@
+package finki.it.phoneluxbackend.entities;
+
+import lombok.*;
+
+import javax.persistence.*;
+import java.time.LocalDateTime;
+
+
+@AllArgsConstructor
+@NoArgsConstructor
+@Getter
+@Setter
+@ToString
+@Entity(name = "ScrapperInfo")
+@Table(name = "scrapper_info")
+public class ScrapperInfo {
+
+    @Id
+    @Column(name = "id")
+    @GeneratedValue(strategy=GenerationType.IDENTITY)
+    private Long id;
+    @Column(name = "store")
+    private String store;
+    @Column(name = "status")
+    private String status;
+    @Column(name = "recieved_at")
+    private LocalDateTime recievedAt;
+
+    public ScrapperInfo(String store, String status, LocalDateTime recievedAt) {
+        this.store = store;
+        this.status = status;
+        this.recievedAt = recievedAt;
+    }
+
+}
Index: phonelux-backend/src/main/java/finki/it/phoneluxbackend/entities/User.java
===================================================================
--- phonelux-backend/src/main/java/finki/it/phoneluxbackend/entities/User.java	(revision ffd50db1e5e2b9839ba7546d8ca44b600150bd71)
+++ phonelux-backend/src/main/java/finki/it/phoneluxbackend/entities/User.java	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
@@ -78,4 +78,11 @@
     }
 
+    public User(String firstName, String lastName, String email, UserRole userRole) {
+        this.firstName = firstName;
+        this.lastName = lastName;
+        this.email = email;
+        this.userRole = userRole;
+    }
+
     @Override
     public Collection<? extends GrantedAuthority> getAuthorities() {
Index: phonelux-backend/src/main/java/finki/it/phoneluxbackend/repositories/OfferReportRepository.java
===================================================================
--- phonelux-backend/src/main/java/finki/it/phoneluxbackend/repositories/OfferReportRepository.java	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
+++ phonelux-backend/src/main/java/finki/it/phoneluxbackend/repositories/OfferReportRepository.java	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
@@ -0,0 +1,13 @@
+package finki.it.phoneluxbackend.repositories;
+
+import finki.it.phoneluxbackend.entities.OfferReport;
+import finki.it.phoneluxbackend.entities.PhoneOffer;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+
+import java.util.Optional;
+
+@Repository
+public interface OfferReportRepository extends JpaRepository<OfferReport,Long> {
+    Optional<OfferReport> findOfferReportByPhoneOffer(PhoneOffer phoneOffer);
+}
Index: phonelux-backend/src/main/java/finki/it/phoneluxbackend/repositories/ScrapperInfoRepository.java
===================================================================
--- phonelux-backend/src/main/java/finki/it/phoneluxbackend/repositories/ScrapperInfoRepository.java	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
+++ phonelux-backend/src/main/java/finki/it/phoneluxbackend/repositories/ScrapperInfoRepository.java	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
@@ -0,0 +1,9 @@
+package finki.it.phoneluxbackend.repositories;
+
+import finki.it.phoneluxbackend.entities.ScrapperInfo;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public interface ScrapperInfoRepository extends JpaRepository<ScrapperInfo, Long> {
+}
Index: phonelux-backend/src/main/java/finki/it/phoneluxbackend/security/configs/WebSecurityConfig.java
===================================================================
--- phonelux-backend/src/main/java/finki/it/phoneluxbackend/security/configs/WebSecurityConfig.java	(revision ffd50db1e5e2b9839ba7546d8ca44b600150bd71)
+++ phonelux-backend/src/main/java/finki/it/phoneluxbackend/security/configs/WebSecurityConfig.java	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
@@ -5,4 +5,5 @@
 import finki.it.phoneluxbackend.services.UserService;
 import lombok.AllArgsConstructor;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
@@ -17,6 +18,4 @@
 import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
 
-import static org.springframework.http.HttpMethod.GET;
-
 @Configuration
 @AllArgsConstructor
@@ -26,5 +25,4 @@
     private final UserService userService;
     private final BCryptPasswordEncoder bCryptPasswordEncoder;
-
     @Override
     protected void configure(HttpSecurity http) throws Exception {
@@ -47,6 +45,15 @@
                 .antMatchers("/admin/**")
                 .hasAnyAuthority("ADMIN","SUPERADMIN")
+                .and()
+                .authorizeRequests()
+                .antMatchers("/offerreport/**")
+                .hasAnyAuthority("USER", "ADMIN", "SUPERADMIN")
+                .and()
+                .authorizeRequests()
+                .antMatchers("/scrapperinfo/**")
+                .hasAnyAuthority("SUPERADMIN")
+                .and()
+                .authorizeRequests()
                 .anyRequest().permitAll();
-
 
 
@@ -55,4 +62,5 @@
 
     }
+
 
     @Override
Index: phonelux-backend/src/main/java/finki/it/phoneluxbackend/services/OfferReportService.java
===================================================================
--- phonelux-backend/src/main/java/finki/it/phoneluxbackend/services/OfferReportService.java	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
+++ phonelux-backend/src/main/java/finki/it/phoneluxbackend/services/OfferReportService.java	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
@@ -0,0 +1,78 @@
+package finki.it.phoneluxbackend.services;
+
+import finki.it.phoneluxbackend.entities.OfferReport;
+import finki.it.phoneluxbackend.entities.PhoneOffer;
+import finki.it.phoneluxbackend.entities.User;
+import finki.it.phoneluxbackend.repositories.OfferReportRepository;
+import finki.it.phoneluxbackend.repositories.PhoneOfferRepository;
+import finki.it.phoneluxbackend.repositories.UserRepository;
+import lombok.AllArgsConstructor;
+import org.springframework.http.ResponseEntity;
+import org.springframework.stereotype.Service;
+
+import java.time.LocalDateTime;
+import java.util.List;
+import java.util.stream.Collectors;
+
+@AllArgsConstructor
+@Service
+public class OfferReportService {
+    private final OfferReportRepository offerReportRepository;
+    private final PhoneOfferRepository phoneOfferRepository;
+    private final UserRepository userRepository;
+
+    public ResponseEntity<Object> reportOffer(Long offerId, Long userId) {
+        boolean exists = phoneOfferRepository.findById(offerId).isPresent();
+
+        if(!exists){
+            return ResponseEntity.badRequest().body("Понудата не постои");
+        }
+
+        exists = userRepository.findById(userId).isPresent();
+
+        if(!exists){
+            return ResponseEntity.badRequest().body("Корисникот не постои");
+        }
+
+        User user = userRepository.findById(userId).get();
+        PhoneOffer offer = phoneOfferRepository.findById(offerId).get();
+
+        exists = offerReportRepository.findOfferReportByPhoneOffer(offer).isPresent();
+        OfferReport offerReport;
+        if(exists)
+        {
+            offerReport = offerReportRepository.findOfferReportByPhoneOffer(offer).get();
+            offerReport.setTimes_reported(offerReport.getTimes_reported()+1);
+            offerReport.setReportedAt(LocalDateTime.now());
+            offerReport.setReportedBy(user.getEmail());
+        }
+        else{
+            offerReport = new OfferReport(offer, 1, LocalDateTime.now(), user.getEmail());
+        }
+
+        offerReportRepository.save(offerReport);
+
+        return ResponseEntity.ok().build();
+    }
+
+    public List<OfferReport> getAllOfferReports() {
+        return offerReportRepository.findAll();
+    }
+
+    public ResponseEntity<Object> removeOfferReport(Long offerReportId) {
+        boolean exists = offerReportRepository.findById(offerReportId).isPresent();
+
+        if(!exists){
+            return ResponseEntity.badRequest().body("Пријавата не постои");
+        }
+
+        offerReportRepository.deleteById(offerReportId);
+
+        return ResponseEntity.ok().build();
+    }
+
+    public ResponseEntity<Object> removeAllOfferReports() {
+        offerReportRepository.deleteAll();
+        return ResponseEntity.ok().build();
+    }
+}
Index: phonelux-backend/src/main/java/finki/it/phoneluxbackend/services/RegistrationService.java
===================================================================
--- phonelux-backend/src/main/java/finki/it/phoneluxbackend/services/RegistrationService.java	(revision ffd50db1e5e2b9839ba7546d8ca44b600150bd71)
+++ phonelux-backend/src/main/java/finki/it/phoneluxbackend/services/RegistrationService.java	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
@@ -1,8 +1,4 @@
 package finki.it.phoneluxbackend.services;
 
-import com.fasterxml.jackson.core.JsonParser;
-import com.fasterxml.jackson.core.io.JsonStringEncoder;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.databind.util.JSONPObject;
 import finki.it.phoneluxbackend.data.RegistrationRequest;
 import finki.it.phoneluxbackend.data.UserRole;
@@ -12,6 +8,4 @@
 import finki.it.phoneluxbackend.security.email.EmailValidator;
 import lombok.AllArgsConstructor;
-import org.apache.coyote.Response;
-import org.apache.tomcat.util.json.JSONParser;
 import org.springframework.http.HttpStatus;
 import org.springframework.http.ResponseEntity;
@@ -20,5 +14,4 @@
 
 import java.time.LocalDateTime;
-import java.util.HashMap;
 
 @Service
Index: phonelux-backend/src/main/java/finki/it/phoneluxbackend/services/ScrapperInfoService.java
===================================================================
--- phonelux-backend/src/main/java/finki/it/phoneluxbackend/services/ScrapperInfoService.java	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
+++ phonelux-backend/src/main/java/finki/it/phoneluxbackend/services/ScrapperInfoService.java	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
@@ -0,0 +1,18 @@
+package finki.it.phoneluxbackend.services;
+
+import finki.it.phoneluxbackend.entities.ScrapperInfo;
+import finki.it.phoneluxbackend.repositories.ScrapperInfoRepository;
+import lombok.AllArgsConstructor;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+@AllArgsConstructor
+@Service
+public class ScrapperInfoService {
+    private final ScrapperInfoRepository scrapperInfoRepository;
+
+    public List<ScrapperInfo> getAllScrapperInfos() {
+        return scrapperInfoRepository.findAll();
+    }
+}
Index: phonelux-backend/src/main/java/finki/it/phoneluxbackend/services/UserService.java
===================================================================
--- phonelux-backend/src/main/java/finki/it/phoneluxbackend/services/UserService.java	(revision ffd50db1e5e2b9839ba7546d8ca44b600150bd71)
+++ phonelux-backend/src/main/java/finki/it/phoneluxbackend/services/UserService.java	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
@@ -41,4 +41,6 @@
     }
 
+
+
     public ResponseEntity<Object> signUpUser(User user)
     {
Index: phonelux-frontend/package-lock.json
===================================================================
--- phonelux-frontend/package-lock.json	(revision ffd50db1e5e2b9839ba7546d8ca44b600150bd71)
+++ phonelux-frontend/package-lock.json	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
@@ -21,4 +21,5 @@
         "@testing-library/user-event": "^13.5.0",
         "@tippyjs/react": "^4.2.6",
+        "antd": "^4.23.6",
         "axios": "^0.27.2",
         "jwt-decode": "^3.1.2",
@@ -47,4 +48,51 @@
       "engines": {
         "node": ">=6.0.0"
+      }
+    },
+    "node_modules/@ant-design/colors": {
+      "version": "6.0.0",
+      "resolved": "https://registry.npmjs.org/@ant-design/colors/-/colors-6.0.0.tgz",
+      "integrity": "sha512-qAZRvPzfdWHtfameEGP2Qvuf838NhergR35o+EuVyB5XvSA98xod5r4utvi4TJ3ywmevm290g9nsCG5MryrdWQ==",
+      "dependencies": {
+        "@ctrl/tinycolor": "^3.4.0"
+      }
+    },
+    "node_modules/@ant-design/icons": {
+      "version": "4.7.0",
+      "resolved": "https://registry.npmjs.org/@ant-design/icons/-/icons-4.7.0.tgz",
+      "integrity": "sha512-aoB4Z7JA431rt6d4u+8xcNPPCrdufSRMUOpxa1ab6mz1JCQZOEVolj2WVs/tDFmN62zzK30mNelEsprLYsSF3g==",
+      "dependencies": {
+        "@ant-design/colors": "^6.0.0",
+        "@ant-design/icons-svg": "^4.2.1",
+        "@babel/runtime": "^7.11.2",
+        "classnames": "^2.2.6",
+        "rc-util": "^5.9.4"
+      },
+      "engines": {
+        "node": ">=8"
+      },
+      "peerDependencies": {
+        "react": ">=16.0.0",
+        "react-dom": ">=16.0.0"
+      }
+    },
+    "node_modules/@ant-design/icons-svg": {
+      "version": "4.2.1",
+      "resolved": "https://registry.npmjs.org/@ant-design/icons-svg/-/icons-svg-4.2.1.tgz",
+      "integrity": "sha512-EB0iwlKDGpG93hW8f85CTJTs4SvMX7tt5ceupvhALp1IF44SeUFOMhKUOYqpsoYWQKAOuTRDMqn75rEaKDp0Xw=="
+    },
+    "node_modules/@ant-design/react-slick": {
+      "version": "0.29.2",
+      "resolved": "https://registry.npmjs.org/@ant-design/react-slick/-/react-slick-0.29.2.tgz",
+      "integrity": "sha512-kgjtKmkGHa19FW21lHnAfyyH9AAoh35pBdcJ53rHmQ3O+cfFHGHnUbj/HFrRNJ5vIts09FKJVAD8RpaC+RaWfA==",
+      "dependencies": {
+        "@babel/runtime": "^7.10.4",
+        "classnames": "^2.2.5",
+        "json2mq": "^0.2.0",
+        "lodash": "^4.17.21",
+        "resize-observer-polyfill": "^1.5.1"
+      },
+      "peerDependencies": {
+        "react": ">=16.9.0"
       }
     },
@@ -2169,4 +2217,12 @@
       }
     },
+    "node_modules/@ctrl/tinycolor": {
+      "version": "3.4.1",
+      "resolved": "https://registry.npmjs.org/@ctrl/tinycolor/-/tinycolor-3.4.1.tgz",
+      "integrity": "sha512-ej5oVy6lykXsvieQtqZxCOaLT+xD4+QNarq78cIYISHmZXshCvROLudpQN3lfL8G0NL7plMSSK+zlyvCaIJ4Iw==",
+      "engines": {
+        "node": ">=10"
+      }
+    },
     "node_modules/@emotion/babel-plugin": {
       "version": "11.10.2",
@@ -5253,4 +5309,63 @@
       }
     },
+    "node_modules/antd": {
+      "version": "4.23.6",
+      "resolved": "https://registry.npmjs.org/antd/-/antd-4.23.6.tgz",
+      "integrity": "sha512-AYH57cWBDe1ChtbnvG8i9dpKG4WnjE3AG0zIKpXByFNnxsr4saV6/19ihE8/ImSGpohN4E2zTXmo7R5/MyVRKQ==",
+      "dependencies": {
+        "@ant-design/colors": "^6.0.0",
+        "@ant-design/icons": "^4.7.0",
+        "@ant-design/react-slick": "~0.29.1",
+        "@babel/runtime": "^7.18.3",
+        "@ctrl/tinycolor": "^3.4.0",
+        "classnames": "^2.2.6",
+        "copy-to-clipboard": "^3.2.0",
+        "lodash": "^4.17.21",
+        "memoize-one": "^6.0.0",
+        "moment": "^2.29.2",
+        "rc-cascader": "~3.7.0",
+        "rc-checkbox": "~2.3.0",
+        "rc-collapse": "~3.3.0",
+        "rc-dialog": "~8.9.0",
+        "rc-drawer": "~5.1.0",
+        "rc-dropdown": "~4.0.0",
+        "rc-field-form": "~1.27.0",
+        "rc-image": "~5.7.0",
+        "rc-input": "~0.1.2",
+        "rc-input-number": "~7.3.9",
+        "rc-mentions": "~1.10.0",
+        "rc-menu": "~9.6.3",
+        "rc-motion": "^2.6.1",
+        "rc-notification": "~4.6.0",
+        "rc-pagination": "~3.1.17",
+        "rc-picker": "~2.6.11",
+        "rc-progress": "~3.3.2",
+        "rc-rate": "~2.9.0",
+        "rc-resize-observer": "^1.2.0",
+        "rc-segmented": "~2.1.0",
+        "rc-select": "~14.1.13",
+        "rc-slider": "~10.0.0",
+        "rc-steps": "~4.1.0",
+        "rc-switch": "~3.2.0",
+        "rc-table": "~7.26.0",
+        "rc-tabs": "~12.2.0",
+        "rc-textarea": "~0.4.5",
+        "rc-tooltip": "~5.2.0",
+        "rc-tree": "~5.7.0",
+        "rc-tree-select": "~5.5.0",
+        "rc-trigger": "^5.2.10",
+        "rc-upload": "~4.3.0",
+        "rc-util": "^5.22.5",
+        "scroll-into-view-if-needed": "^2.2.25"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/ant-design"
+      },
+      "peerDependencies": {
+        "react": ">=16.9.0",
+        "react-dom": ">=16.9.0"
+      }
+    },
     "node_modules/anymatch": {
       "version": "3.1.2",
@@ -5313,4 +5428,9 @@
       }
     },
+    "node_modules/array-tree-filter": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/array-tree-filter/-/array-tree-filter-2.1.0.tgz",
+      "integrity": "sha512-4ROwICNlNw/Hqa9v+rk5h22KjmzB1JGTMVKP2AKJBOCgb0yL0ASf0+YvCcLNNwquOHNX48jkeZIJ3a+oOQqKcw=="
+    },
     "node_modules/array-union": {
       "version": "2.1.0",
@@ -5387,4 +5507,9 @@
       "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz",
       "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ=="
+    },
+    "node_modules/async-validator": {
+      "version": "4.2.5",
+      "resolved": "https://registry.npmjs.org/async-validator/-/async-validator-4.2.5.tgz",
+      "integrity": "sha512-7HhHjtERjqlNbZtqNqy2rckN/SpOOlmDliet+lP7k+eKZEjPk3DgyeU9lIXLdeLz0uBbbVp+9Qdow9wJWgwwfg=="
     },
     "node_modules/asynckit": {
@@ -6119,4 +6244,9 @@
       "integrity": "sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA=="
     },
+    "node_modules/classnames": {
+      "version": "2.3.2",
+      "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.3.2.tgz",
+      "integrity": "sha512-CSbhY4cFEJRe6/GQzIk5qXZ4Jeg5pcsP7b5peFSDpffpe1cqjASH/n9UTjBwOp6XpMSTwQ8Za2K5V02ueA7Tmw=="
+    },
     "node_modules/clean-css": {
       "version": "5.3.1",
@@ -6283,4 +6413,9 @@
       "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
       "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
+    },
+    "node_modules/compute-scroll-into-view": {
+      "version": "1.0.17",
+      "resolved": "https://registry.npmjs.org/compute-scroll-into-view/-/compute-scroll-into-view-1.0.17.tgz",
+      "integrity": "sha512-j4dx+Fb0URmzbwwMUrhqWM2BEWHdFGx+qZ9qqASHRPqvTYdqvWnHg0H1hIbcyLnvgnoNAVMlwkepyqM3DaIFUg=="
     },
     "node_modules/concat-map": {
@@ -6360,4 +6495,12 @@
       "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
       "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ=="
+    },
+    "node_modules/copy-to-clipboard": {
+      "version": "3.3.2",
+      "resolved": "https://registry.npmjs.org/copy-to-clipboard/-/copy-to-clipboard-3.3.2.tgz",
+      "integrity": "sha512-Vme1Z6RUDzrb6xAI7EZlVZ5uvOk2F//GaxKUxajDqm9LhOVM1inxNAD2vy+UZDYsd0uyA9s7b3/FVZPSxqrCfg==",
+      "dependencies": {
+        "toggle-selection": "^1.0.6"
+      }
     },
     "node_modules/core-js": {
@@ -6850,4 +6993,21 @@
       }
     },
+    "node_modules/date-fns": {
+      "version": "2.29.3",
+      "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.29.3.tgz",
+      "integrity": "sha512-dDCnyH2WnnKusqvZZ6+jA1O51Ibt8ZMRNkDZdyAyK4YfbDwa/cEmuztzG5pk6hqlp9aSBPYcjOlktquahGwGeA==",
+      "engines": {
+        "node": ">=0.11"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/date-fns"
+      }
+    },
+    "node_modules/dayjs": {
+      "version": "1.11.6",
+      "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.6.tgz",
+      "integrity": "sha512-zZbY5giJAinCG+7AGaw0wIhNZ6J8AhWuSXKvuc1KAyMiRsvGQWqh4L+MomvhdAYjN+lqvVCMq1I41e3YHvXkyQ=="
+    },
     "node_modules/debug": {
       "version": "4.3.4",
@@ -7071,4 +7231,9 @@
       "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.14.tgz",
       "integrity": "sha512-NMt+m9zFMPZe0JcY9gN224Qvk6qLIdqex29clBvc/y75ZBX9YA9wNK3frsYvu2DI1xcCIwxwnX+TlsJ2DSOADg=="
+    },
+    "node_modules/dom-align": {
+      "version": "1.12.3",
+      "resolved": "https://registry.npmjs.org/dom-align/-/dom-align-1.12.3.tgz",
+      "integrity": "sha512-Gj9hZN3a07cbR6zviMUBOMPdWxYhbMI+x+WS0NAIu2zFZmbK8ys9R79g+iG9qLnlCwpFoaB+fKy8Pdv470GsPA=="
     },
     "node_modules/dom-converter": {
@@ -11891,4 +12056,12 @@
       "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw=="
     },
+    "node_modules/json2mq": {
+      "version": "0.2.0",
+      "resolved": "https://registry.npmjs.org/json2mq/-/json2mq-0.2.0.tgz",
+      "integrity": "sha512-SzoRg7ux5DWTII9J2qkrZrqV1gt+rTaoufMxEzXbS26Uid0NwaJd123HcoB80TgubEppxxIGdNxCx50fEoEWQA==",
+      "dependencies": {
+        "string-convert": "^0.2.0"
+      }
+    },
     "node_modules/json5": {
       "version": "2.2.1",
@@ -12173,4 +12346,9 @@
       }
     },
+    "node_modules/memoize-one": {
+      "version": "6.0.0",
+      "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-6.0.0.tgz",
+      "integrity": "sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw=="
+    },
     "node_modules/merge-descriptors": {
       "version": "1.0.1",
@@ -12354,4 +12532,12 @@
       "bin": {
         "mkdirp": "bin/cmd.js"
+      }
+    },
+    "node_modules/moment": {
+      "version": "2.29.4",
+      "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz",
+      "integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==",
+      "engines": {
+        "node": "*"
       }
     },
@@ -14400,4 +14586,594 @@
       }
     },
+    "node_modules/rc-align": {
+      "version": "4.0.12",
+      "resolved": "https://registry.npmjs.org/rc-align/-/rc-align-4.0.12.tgz",
+      "integrity": "sha512-3DuwSJp8iC/dgHzwreOQl52soj40LchlfUHtgACOUtwGuoFIOVh6n/sCpfqCU8kO5+iz6qR0YKvjgB8iPdE3aQ==",
+      "dependencies": {
+        "@babel/runtime": "^7.10.1",
+        "classnames": "2.x",
+        "dom-align": "^1.7.0",
+        "lodash": "^4.17.21",
+        "rc-util": "^5.3.0",
+        "resize-observer-polyfill": "^1.5.1"
+      },
+      "peerDependencies": {
+        "react": ">=16.9.0",
+        "react-dom": ">=16.9.0"
+      }
+    },
+    "node_modules/rc-cascader": {
+      "version": "3.7.0",
+      "resolved": "https://registry.npmjs.org/rc-cascader/-/rc-cascader-3.7.0.tgz",
+      "integrity": "sha512-SFtGpwmYN7RaWEAGTS4Rkc62ZV/qmQGg/tajr/7mfIkleuu8ro9Hlk6J+aA0x1YS4zlaZBtTcSaXM01QMiEV/A==",
+      "dependencies": {
+        "@babel/runtime": "^7.12.5",
+        "array-tree-filter": "^2.1.0",
+        "classnames": "^2.3.1",
+        "rc-select": "~14.1.0",
+        "rc-tree": "~5.7.0",
+        "rc-util": "^5.6.1"
+      },
+      "peerDependencies": {
+        "react": ">=16.9.0",
+        "react-dom": ">=16.9.0"
+      }
+    },
+    "node_modules/rc-checkbox": {
+      "version": "2.3.2",
+      "resolved": "https://registry.npmjs.org/rc-checkbox/-/rc-checkbox-2.3.2.tgz",
+      "integrity": "sha512-afVi1FYiGv1U0JlpNH/UaEXdh6WUJjcWokj/nUN2TgG80bfG+MDdbfHKlLcNNba94mbjy2/SXJ1HDgrOkXGAjg==",
+      "dependencies": {
+        "@babel/runtime": "^7.10.1",
+        "classnames": "^2.2.1"
+      },
+      "peerDependencies": {
+        "react": ">=16.9.0",
+        "react-dom": ">=16.9.0"
+      }
+    },
+    "node_modules/rc-collapse": {
+      "version": "3.3.1",
+      "resolved": "https://registry.npmjs.org/rc-collapse/-/rc-collapse-3.3.1.tgz",
+      "integrity": "sha512-cOJfcSe3R8vocrF8T+PgaHDrgeA1tX+lwfhwSj60NX9QVRidsILIbRNDLD6nAzmcvVC5PWiIRiR4S1OobxdhCg==",
+      "dependencies": {
+        "@babel/runtime": "^7.10.1",
+        "classnames": "2.x",
+        "rc-motion": "^2.3.4",
+        "rc-util": "^5.2.1",
+        "shallowequal": "^1.1.0"
+      },
+      "peerDependencies": {
+        "react": ">=16.9.0",
+        "react-dom": ">=16.9.0"
+      }
+    },
+    "node_modules/rc-dialog": {
+      "version": "8.9.0",
+      "resolved": "https://registry.npmjs.org/rc-dialog/-/rc-dialog-8.9.0.tgz",
+      "integrity": "sha512-Cp0tbJnrvPchJfnwIvOMWmJ4yjX3HWFatO6oBFD1jx8QkgsQCR0p8nUWAKdd3seLJhEC39/v56kZaEjwp9muoQ==",
+      "dependencies": {
+        "@babel/runtime": "^7.10.1",
+        "classnames": "^2.2.6",
+        "rc-motion": "^2.3.0",
+        "rc-util": "^5.21.0"
+      },
+      "peerDependencies": {
+        "react": ">=16.9.0",
+        "react-dom": ">=16.9.0"
+      }
+    },
+    "node_modules/rc-drawer": {
+      "version": "5.1.0",
+      "resolved": "https://registry.npmjs.org/rc-drawer/-/rc-drawer-5.1.0.tgz",
+      "integrity": "sha512-pU3Tsn99pxGdYowXehzZbdDVE+4lDXSGb7p8vA9mSmr569oc2Izh4Zw5vLKSe/Xxn2p5MSNbLVqD4tz+pK6SOw==",
+      "dependencies": {
+        "@babel/runtime": "^7.10.1",
+        "classnames": "^2.2.6",
+        "rc-motion": "^2.6.1",
+        "rc-util": "^5.21.2"
+      },
+      "peerDependencies": {
+        "react": ">=16.9.0",
+        "react-dom": ">=16.9.0"
+      }
+    },
+    "node_modules/rc-dropdown": {
+      "version": "4.0.1",
+      "resolved": "https://registry.npmjs.org/rc-dropdown/-/rc-dropdown-4.0.1.tgz",
+      "integrity": "sha512-OdpXuOcme1rm45cR0Jzgfl1otzmU4vuBVb+etXM8vcaULGokAKVpKlw8p6xzspG7jGd/XxShvq+N3VNEfk/l5g==",
+      "dependencies": {
+        "@babel/runtime": "^7.18.3",
+        "classnames": "^2.2.6",
+        "rc-trigger": "^5.3.1",
+        "rc-util": "^5.17.0"
+      },
+      "peerDependencies": {
+        "react": ">=16.11.0",
+        "react-dom": ">=16.11.0"
+      }
+    },
+    "node_modules/rc-field-form": {
+      "version": "1.27.2",
+      "resolved": "https://registry.npmjs.org/rc-field-form/-/rc-field-form-1.27.2.tgz",
+      "integrity": "sha512-NaTjkSB8JsHRgm52wkDorsDzFf2HH6GmCQ2AqkwO8zo+zIqybw8K1lkzDBMDJI8nw1pFuD46U5QsYZv4blYvdw==",
+      "dependencies": {
+        "@babel/runtime": "^7.18.0",
+        "async-validator": "^4.1.0",
+        "rc-util": "^5.8.0"
+      },
+      "engines": {
+        "node": ">=8.x"
+      },
+      "peerDependencies": {
+        "react": ">=16.9.0",
+        "react-dom": ">=16.9.0"
+      }
+    },
+    "node_modules/rc-image": {
+      "version": "5.7.1",
+      "resolved": "https://registry.npmjs.org/rc-image/-/rc-image-5.7.1.tgz",
+      "integrity": "sha512-QyMfdhoUfb5W14plqXSisaYwpdstcLYnB0MjX5ccIK2rydQM9sDPuekQWu500DDGR2dBaIF5vx9XbWkNFK17Fg==",
+      "dependencies": {
+        "@babel/runtime": "^7.11.2",
+        "classnames": "^2.2.6",
+        "rc-dialog": "~8.9.0",
+        "rc-util": "^5.0.6"
+      },
+      "peerDependencies": {
+        "react": ">=16.9.0",
+        "react-dom": ">=16.9.0"
+      }
+    },
+    "node_modules/rc-input": {
+      "version": "0.1.2",
+      "resolved": "https://registry.npmjs.org/rc-input/-/rc-input-0.1.2.tgz",
+      "integrity": "sha512-ZPmwcFspgfYpUfbSx3KnLk9gImBcLOrlQCr4oTJ4jBoIXgJLTfm26yelzRgBJewhkvD8uJbgX0sQ/yOzuOHnJg==",
+      "dependencies": {
+        "@babel/runtime": "^7.11.1",
+        "classnames": "^2.2.1",
+        "rc-util": "^5.18.1"
+      },
+      "peerDependencies": {
+        "react": ">=16.0.0",
+        "react-dom": ">=16.0.0"
+      }
+    },
+    "node_modules/rc-input-number": {
+      "version": "7.3.9",
+      "resolved": "https://registry.npmjs.org/rc-input-number/-/rc-input-number-7.3.9.tgz",
+      "integrity": "sha512-u0+miS+SATdb6DtssYei2JJ1WuZME+nXaG6XGtR8maNyW5uGDytfDu60OTWLQEb0Anv/AcCzehldV8CKmKyQfA==",
+      "dependencies": {
+        "@babel/runtime": "^7.10.1",
+        "classnames": "^2.2.5",
+        "rc-util": "^5.23.0"
+      },
+      "peerDependencies": {
+        "react": ">=16.9.0",
+        "react-dom": ">=16.9.0"
+      }
+    },
+    "node_modules/rc-mentions": {
+      "version": "1.10.0",
+      "resolved": "https://registry.npmjs.org/rc-mentions/-/rc-mentions-1.10.0.tgz",
+      "integrity": "sha512-oMlYWnwXSxP2NQVlgxOTzuG/u9BUc3ySY78K3/t7MNhJWpZzXTao+/Bic6tyZLuNCO89//hVQJBdaR2rnFQl6Q==",
+      "dependencies": {
+        "@babel/runtime": "^7.10.1",
+        "classnames": "^2.2.6",
+        "rc-menu": "~9.6.0",
+        "rc-textarea": "^0.4.0",
+        "rc-trigger": "^5.0.4",
+        "rc-util": "^5.22.5"
+      },
+      "peerDependencies": {
+        "react": ">=16.9.0",
+        "react-dom": ">=16.9.0"
+      }
+    },
+    "node_modules/rc-menu": {
+      "version": "9.6.4",
+      "resolved": "https://registry.npmjs.org/rc-menu/-/rc-menu-9.6.4.tgz",
+      "integrity": "sha512-6DiNAjxjVIPLZXHffXxxcyE15d4isRL7iQ1ru4MqYDH2Cqc5bW96wZOdMydFtGLyDdnmEQ9jVvdCE9yliGvzkw==",
+      "dependencies": {
+        "@babel/runtime": "^7.10.1",
+        "classnames": "2.x",
+        "rc-motion": "^2.4.3",
+        "rc-overflow": "^1.2.0",
+        "rc-trigger": "^5.1.2",
+        "rc-util": "^5.12.0",
+        "shallowequal": "^1.1.0"
+      },
+      "peerDependencies": {
+        "react": ">=16.9.0",
+        "react-dom": ">=16.9.0"
+      }
+    },
+    "node_modules/rc-motion": {
+      "version": "2.6.2",
+      "resolved": "https://registry.npmjs.org/rc-motion/-/rc-motion-2.6.2.tgz",
+      "integrity": "sha512-4w1FaX3dtV749P8GwfS4fYnFG4Rb9pxvCYPc/b2fw1cmlHJWNNgOFIz7ysiD+eOrzJSvnLJWlNQQncpNMXwwpg==",
+      "dependencies": {
+        "@babel/runtime": "^7.11.1",
+        "classnames": "^2.2.1",
+        "rc-util": "^5.21.0"
+      },
+      "peerDependencies": {
+        "react": ">=16.9.0",
+        "react-dom": ">=16.9.0"
+      }
+    },
+    "node_modules/rc-notification": {
+      "version": "4.6.0",
+      "resolved": "https://registry.npmjs.org/rc-notification/-/rc-notification-4.6.0.tgz",
+      "integrity": "sha512-xF3MKgIoynzjQAO4lqsoraiFo3UXNYlBfpHs0VWvwF+4pimen9/H1DYLN2mfRWhHovW6gRpla73m2nmyIqAMZQ==",
+      "dependencies": {
+        "@babel/runtime": "^7.10.1",
+        "classnames": "2.x",
+        "rc-motion": "^2.2.0",
+        "rc-util": "^5.20.1"
+      },
+      "engines": {
+        "node": ">=8.x"
+      },
+      "peerDependencies": {
+        "react": ">=16.9.0",
+        "react-dom": ">=16.9.0"
+      }
+    },
+    "node_modules/rc-overflow": {
+      "version": "1.2.8",
+      "resolved": "https://registry.npmjs.org/rc-overflow/-/rc-overflow-1.2.8.tgz",
+      "integrity": "sha512-QJ0UItckWPQ37ZL1dMEBAdY1dhfTXFL9k6oTTcyydVwoUNMnMqCGqnRNA98axSr/OeDKqR6DVFyi8eA5RQI/uQ==",
+      "dependencies": {
+        "@babel/runtime": "^7.11.1",
+        "classnames": "^2.2.1",
+        "rc-resize-observer": "^1.0.0",
+        "rc-util": "^5.19.2"
+      },
+      "peerDependencies": {
+        "react": ">=16.9.0",
+        "react-dom": ">=16.9.0"
+      }
+    },
+    "node_modules/rc-pagination": {
+      "version": "3.1.17",
+      "resolved": "https://registry.npmjs.org/rc-pagination/-/rc-pagination-3.1.17.tgz",
+      "integrity": "sha512-/BQ5UxcBnW28vFAcP2hfh+Xg15W0QZn8TWYwdCApchMH1H0CxiaUUcULP8uXcFM1TygcdKWdt3JqsL9cTAfdkQ==",
+      "dependencies": {
+        "@babel/runtime": "^7.10.1",
+        "classnames": "^2.2.1"
+      },
+      "peerDependencies": {
+        "react": ">=16.9.0",
+        "react-dom": ">=16.9.0"
+      }
+    },
+    "node_modules/rc-picker": {
+      "version": "2.6.11",
+      "resolved": "https://registry.npmjs.org/rc-picker/-/rc-picker-2.6.11.tgz",
+      "integrity": "sha512-INJ7ULu+Kj4UgqbcqE8Q+QpMw55xFf9kkyLBHJFk0ihjJpAV4glialRfqHE7k4KX2BWYPQfpILwhwR14x2EiRQ==",
+      "dependencies": {
+        "@babel/runtime": "^7.10.1",
+        "classnames": "^2.2.1",
+        "date-fns": "2.x",
+        "dayjs": "1.x",
+        "moment": "^2.24.0",
+        "rc-trigger": "^5.0.4",
+        "rc-util": "^5.4.0",
+        "shallowequal": "^1.1.0"
+      },
+      "engines": {
+        "node": ">=8.x"
+      },
+      "peerDependencies": {
+        "react": ">=16.9.0",
+        "react-dom": ">=16.9.0"
+      }
+    },
+    "node_modules/rc-progress": {
+      "version": "3.3.3",
+      "resolved": "https://registry.npmjs.org/rc-progress/-/rc-progress-3.3.3.tgz",
+      "integrity": "sha512-MDVNVHzGanYtRy2KKraEaWeZLri2ZHWIRyaE1a9MQ2MuJ09m+Wxj5cfcaoaR6z5iRpHpA59YeUxAlpML8N4PJw==",
+      "dependencies": {
+        "@babel/runtime": "^7.10.1",
+        "classnames": "^2.2.6",
+        "rc-util": "^5.16.1"
+      },
+      "peerDependencies": {
+        "react": ">=16.9.0",
+        "react-dom": ">=16.9.0"
+      }
+    },
+    "node_modules/rc-rate": {
+      "version": "2.9.2",
+      "resolved": "https://registry.npmjs.org/rc-rate/-/rc-rate-2.9.2.tgz",
+      "integrity": "sha512-SaiZFyN8pe0Fgphv8t3+kidlej+cq/EALkAJAc3A0w0XcPaH2L1aggM8bhe1u6GAGuQNAoFvTLjw4qLPGRKV5g==",
+      "dependencies": {
+        "@babel/runtime": "^7.10.1",
+        "classnames": "^2.2.5",
+        "rc-util": "^5.0.1"
+      },
+      "engines": {
+        "node": ">=8.x"
+      },
+      "peerDependencies": {
+        "react": ">=16.9.0",
+        "react-dom": ">=16.9.0"
+      }
+    },
+    "node_modules/rc-resize-observer": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/rc-resize-observer/-/rc-resize-observer-1.2.0.tgz",
+      "integrity": "sha512-6W+UzT3PyDM0wVCEHfoW3qTHPTvbdSgiA43buiy8PzmeMnfgnDeb9NjdimMXMl3/TcrvvWl5RRVdp+NqcR47pQ==",
+      "dependencies": {
+        "@babel/runtime": "^7.10.1",
+        "classnames": "^2.2.1",
+        "rc-util": "^5.15.0",
+        "resize-observer-polyfill": "^1.5.1"
+      },
+      "peerDependencies": {
+        "react": ">=16.9.0",
+        "react-dom": ">=16.9.0"
+      }
+    },
+    "node_modules/rc-segmented": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/rc-segmented/-/rc-segmented-2.1.0.tgz",
+      "integrity": "sha512-hUlonro+pYoZcwrH6Vm56B2ftLfQh046hrwif/VwLIw1j3zGt52p5mREBwmeVzXnSwgnagpOpfafspzs1asjGw==",
+      "dependencies": {
+        "@babel/runtime": "^7.11.1",
+        "classnames": "^2.2.1",
+        "rc-motion": "^2.4.4",
+        "rc-util": "^5.17.0"
+      },
+      "peerDependencies": {
+        "react": ">=16.0.0",
+        "react-dom": ">=16.0.0"
+      }
+    },
+    "node_modules/rc-select": {
+      "version": "14.1.13",
+      "resolved": "https://registry.npmjs.org/rc-select/-/rc-select-14.1.13.tgz",
+      "integrity": "sha512-WMEsC3gTwA1dbzWOdVIXDmWyidYNLq68AwvvUlRROw790uGUly0/vmqDozXrIr0QvN/A3CEULx12o+WtLCAefg==",
+      "dependencies": {
+        "@babel/runtime": "^7.10.1",
+        "classnames": "2.x",
+        "rc-motion": "^2.0.1",
+        "rc-overflow": "^1.0.0",
+        "rc-trigger": "^5.0.4",
+        "rc-util": "^5.16.1",
+        "rc-virtual-list": "^3.2.0"
+      },
+      "engines": {
+        "node": ">=8.x"
+      },
+      "peerDependencies": {
+        "react": "*",
+        "react-dom": "*"
+      }
+    },
+    "node_modules/rc-slider": {
+      "version": "10.0.1",
+      "resolved": "https://registry.npmjs.org/rc-slider/-/rc-slider-10.0.1.tgz",
+      "integrity": "sha512-igTKF3zBet7oS/3yNiIlmU8KnZ45npmrmHlUUio8PNbIhzMcsh+oE/r2UD42Y6YD2D/s+kzCQkzQrPD6RY435Q==",
+      "dependencies": {
+        "@babel/runtime": "^7.10.1",
+        "classnames": "^2.2.5",
+        "rc-util": "^5.18.1",
+        "shallowequal": "^1.1.0"
+      },
+      "engines": {
+        "node": ">=8.x"
+      },
+      "peerDependencies": {
+        "react": ">=16.9.0",
+        "react-dom": ">=16.9.0"
+      }
+    },
+    "node_modules/rc-steps": {
+      "version": "4.1.4",
+      "resolved": "https://registry.npmjs.org/rc-steps/-/rc-steps-4.1.4.tgz",
+      "integrity": "sha512-qoCqKZWSpkh/b03ASGx1WhpKnuZcRWmvuW+ZUu4mvMdfvFzVxblTwUM+9aBd0mlEUFmt6GW8FXhMpHkK3Uzp3w==",
+      "dependencies": {
+        "@babel/runtime": "^7.10.2",
+        "classnames": "^2.2.3",
+        "rc-util": "^5.0.1"
+      },
+      "engines": {
+        "node": ">=8.x"
+      },
+      "peerDependencies": {
+        "react": ">=16.9.0",
+        "react-dom": ">=16.9.0"
+      }
+    },
+    "node_modules/rc-switch": {
+      "version": "3.2.2",
+      "resolved": "https://registry.npmjs.org/rc-switch/-/rc-switch-3.2.2.tgz",
+      "integrity": "sha512-+gUJClsZZzvAHGy1vZfnwySxj+MjLlGRyXKXScrtCTcmiYNPzxDFOxdQ/3pK1Kt/0POvwJ/6ALOR8gwdXGhs+A==",
+      "dependencies": {
+        "@babel/runtime": "^7.10.1",
+        "classnames": "^2.2.1",
+        "rc-util": "^5.0.1"
+      },
+      "peerDependencies": {
+        "react": ">=16.9.0",
+        "react-dom": ">=16.9.0"
+      }
+    },
+    "node_modules/rc-table": {
+      "version": "7.26.0",
+      "resolved": "https://registry.npmjs.org/rc-table/-/rc-table-7.26.0.tgz",
+      "integrity": "sha512-0cD8e6S+DTGAt5nBZQIPFYEaIukn17sfa5uFL98faHlH/whZzD8ii3dbFL4wmUDEL4BLybhYop+QUfZJ4CPvNQ==",
+      "dependencies": {
+        "@babel/runtime": "^7.10.1",
+        "classnames": "^2.2.5",
+        "rc-resize-observer": "^1.1.0",
+        "rc-util": "^5.22.5",
+        "shallowequal": "^1.1.0"
+      },
+      "engines": {
+        "node": ">=8.x"
+      },
+      "peerDependencies": {
+        "react": ">=16.9.0",
+        "react-dom": ">=16.9.0"
+      }
+    },
+    "node_modules/rc-tabs": {
+      "version": "12.2.1",
+      "resolved": "https://registry.npmjs.org/rc-tabs/-/rc-tabs-12.2.1.tgz",
+      "integrity": "sha512-09pVv4kN8VFqp6THceEmxOW8PAShQC08hrroeVYP4Y8YBFaP1PIWdyFL01czcbyz5YZFj9flZ7aljMaAl0jLVg==",
+      "dependencies": {
+        "@babel/runtime": "^7.11.2",
+        "classnames": "2.x",
+        "rc-dropdown": "~4.0.0",
+        "rc-menu": "~9.6.0",
+        "rc-motion": "^2.6.2",
+        "rc-resize-observer": "^1.0.0",
+        "rc-util": "^5.5.0"
+      },
+      "engines": {
+        "node": ">=8.x"
+      },
+      "peerDependencies": {
+        "react": ">=16.9.0",
+        "react-dom": ">=16.9.0"
+      }
+    },
+    "node_modules/rc-textarea": {
+      "version": "0.4.5",
+      "resolved": "https://registry.npmjs.org/rc-textarea/-/rc-textarea-0.4.5.tgz",
+      "integrity": "sha512-WHeJRgUlloNyVgTsItMrIXwMhU6P3NmrUDkxX+JRwEpJjECsKtZNlNcXe9pHNLCaYQ3Z1cVCfsClhgDDgJ2kFQ==",
+      "dependencies": {
+        "@babel/runtime": "^7.10.1",
+        "classnames": "^2.2.1",
+        "rc-resize-observer": "^1.0.0",
+        "rc-util": "^5.7.0",
+        "shallowequal": "^1.1.0"
+      },
+      "peerDependencies": {
+        "react": ">=16.9.0",
+        "react-dom": ">=16.9.0"
+      }
+    },
+    "node_modules/rc-tooltip": {
+      "version": "5.2.2",
+      "resolved": "https://registry.npmjs.org/rc-tooltip/-/rc-tooltip-5.2.2.tgz",
+      "integrity": "sha512-jtQzU/18S6EI3lhSGoDYhPqNpWajMtS5VV/ld1LwyfrDByQpYmw/LW6U7oFXXLukjfDHQ7Ju705A82PRNFWYhg==",
+      "dependencies": {
+        "@babel/runtime": "^7.11.2",
+        "classnames": "^2.3.1",
+        "rc-trigger": "^5.0.0"
+      },
+      "peerDependencies": {
+        "react": ">=16.9.0",
+        "react-dom": ">=16.9.0"
+      }
+    },
+    "node_modules/rc-tree": {
+      "version": "5.7.0",
+      "resolved": "https://registry.npmjs.org/rc-tree/-/rc-tree-5.7.0.tgz",
+      "integrity": "sha512-F+Ewkv/UcutshnVBMISP+lPdHDlcsL+YH/MQDVWbk+QdkfID7vXiwrHMEZn31+2Rbbm21z/HPceGS8PXGMmnQg==",
+      "dependencies": {
+        "@babel/runtime": "^7.10.1",
+        "classnames": "2.x",
+        "rc-motion": "^2.0.1",
+        "rc-util": "^5.16.1",
+        "rc-virtual-list": "^3.4.8"
+      },
+      "engines": {
+        "node": ">=10.x"
+      },
+      "peerDependencies": {
+        "react": "*",
+        "react-dom": "*"
+      }
+    },
+    "node_modules/rc-tree-select": {
+      "version": "5.5.2",
+      "resolved": "https://registry.npmjs.org/rc-tree-select/-/rc-tree-select-5.5.2.tgz",
+      "integrity": "sha512-toxkzVhkWQ2wvInOhHwmyEpCCi9osnoRQmN0trKvdvyzLattCw63F2T+V/dS2d/xUkrw6Zr1Y2J0/xP57x/jYQ==",
+      "dependencies": {
+        "@babel/runtime": "^7.10.1",
+        "classnames": "2.x",
+        "rc-select": "~14.1.0",
+        "rc-tree": "~5.7.0",
+        "rc-util": "^5.16.1"
+      },
+      "peerDependencies": {
+        "react": "*",
+        "react-dom": "*"
+      }
+    },
+    "node_modules/rc-trigger": {
+      "version": "5.3.1",
+      "resolved": "https://registry.npmjs.org/rc-trigger/-/rc-trigger-5.3.1.tgz",
+      "integrity": "sha512-5gaFbDkYSefZ14j2AdzucXzlWgU2ri5uEjkHvsf1ynRhdJbKxNOnw4PBZ9+FVULNGFiDzzlVF8RJnR9P/xrnKQ==",
+      "dependencies": {
+        "@babel/runtime": "^7.18.3",
+        "classnames": "^2.2.6",
+        "rc-align": "^4.0.0",
+        "rc-motion": "^2.0.0",
+        "rc-util": "^5.19.2"
+      },
+      "engines": {
+        "node": ">=8.x"
+      },
+      "peerDependencies": {
+        "react": ">=16.9.0",
+        "react-dom": ">=16.9.0"
+      }
+    },
+    "node_modules/rc-upload": {
+      "version": "4.3.4",
+      "resolved": "https://registry.npmjs.org/rc-upload/-/rc-upload-4.3.4.tgz",
+      "integrity": "sha512-uVbtHFGNjHG/RyAfm9fluXB6pvArAGyAx8z7XzXXyorEgVIWj6mOlriuDm0XowDHYz4ycNK0nE0oP3cbFnzxiQ==",
+      "dependencies": {
+        "@babel/runtime": "^7.18.3",
+        "classnames": "^2.2.5",
+        "rc-util": "^5.2.0"
+      },
+      "peerDependencies": {
+        "react": ">=16.9.0",
+        "react-dom": ">=16.9.0"
+      }
+    },
+    "node_modules/rc-util": {
+      "version": "5.24.4",
+      "resolved": "https://registry.npmjs.org/rc-util/-/rc-util-5.24.4.tgz",
+      "integrity": "sha512-2a4RQnycV9eV7lVZPEJ7QwJRPlZNc06J7CwcwZo4vIHr3PfUqtYgl1EkUV9ETAc6VRRi8XZOMFhYG63whlIC9Q==",
+      "dependencies": {
+        "@babel/runtime": "^7.18.3",
+        "react-is": "^16.12.0",
+        "shallowequal": "^1.1.0"
+      },
+      "peerDependencies": {
+        "react": ">=16.9.0",
+        "react-dom": ">=16.9.0"
+      }
+    },
+    "node_modules/rc-util/node_modules/react-is": {
+      "version": "16.13.1",
+      "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
+      "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
+    },
+    "node_modules/rc-virtual-list": {
+      "version": "3.4.10",
+      "resolved": "https://registry.npmjs.org/rc-virtual-list/-/rc-virtual-list-3.4.10.tgz",
+      "integrity": "sha512-Jv0cgJxJ+8F/YViW8WGs/jQF2rmT8RUcJ5uDJs5MOFLTYLAvCpM/xU+Zu6EpCun50fmovhXiItQctcfE2UY3Aw==",
+      "dependencies": {
+        "classnames": "^2.2.6",
+        "rc-resize-observer": "^1.0.0",
+        "rc-util": "^5.15.0"
+      },
+      "engines": {
+        "node": ">=8.x"
+      },
+      "peerDependencies": {
+        "react": "*",
+        "react-dom": "*"
+      }
+    },
     "node_modules/react": {
       "version": "18.2.0",
@@ -14895,4 +15671,9 @@
       "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ=="
     },
+    "node_modules/resize-observer-polyfill": {
+      "version": "1.5.1",
+      "resolved": "https://registry.npmjs.org/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz",
+      "integrity": "sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg=="
+    },
     "node_modules/resolve": {
       "version": "1.22.1",
@@ -15206,4 +15987,12 @@
         "type": "opencollective",
         "url": "https://opencollective.com/webpack"
+      }
+    },
+    "node_modules/scroll-into-view-if-needed": {
+      "version": "2.2.29",
+      "resolved": "https://registry.npmjs.org/scroll-into-view-if-needed/-/scroll-into-view-if-needed-2.2.29.tgz",
+      "integrity": "sha512-hxpAR6AN+Gh53AdAimHM6C8oTN1ppwVZITihix+WqalywBeFcQ6LdQP5ABNl26nX8GTEL7VT+b8lKpdqq65wXg==",
+      "dependencies": {
+        "compute-scroll-into-view": "^1.0.17"
       }
     },
@@ -15376,4 +16165,9 @@
       "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw=="
     },
+    "node_modules/shallowequal": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/shallowequal/-/shallowequal-1.1.0.tgz",
+      "integrity": "sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ=="
+    },
     "node_modules/shebang-command": {
       "version": "2.0.0",
@@ -15601,4 +16395,9 @@
         }
       ]
+    },
+    "node_modules/string-convert": {
+      "version": "0.2.1",
+      "resolved": "https://registry.npmjs.org/string-convert/-/string-convert-0.2.1.tgz",
+      "integrity": "sha512-u/1tdPl4yQnPBjnVrmdLo9gtuLvELKsAoRapekWggdiQNvvvum+jYF329d84NAa660KQw7pB2n36KrIKVoXa3A=="
     },
     "node_modules/string-length": {
@@ -16146,4 +16945,9 @@
         "node": ">=8.0"
       }
+    },
+    "node_modules/toggle-selection": {
+      "version": "1.0.6",
+      "resolved": "https://registry.npmjs.org/toggle-selection/-/toggle-selection-1.0.6.tgz",
+      "integrity": "sha512-BiZS+C1OS8g/q2RRbJmy59xpyghNBqrr6k5L/uKBGRsTfxmu3ffiRnd8mlGPUVayg8pvfi5urfnu8TU7DVOkLQ=="
     },
     "node_modules/toidentifier": {
@@ -17442,4 +18246,41 @@
         "@jridgewell/gen-mapping": "^0.1.0",
         "@jridgewell/trace-mapping": "^0.3.9"
+      }
+    },
+    "@ant-design/colors": {
+      "version": "6.0.0",
+      "resolved": "https://registry.npmjs.org/@ant-design/colors/-/colors-6.0.0.tgz",
+      "integrity": "sha512-qAZRvPzfdWHtfameEGP2Qvuf838NhergR35o+EuVyB5XvSA98xod5r4utvi4TJ3ywmevm290g9nsCG5MryrdWQ==",
+      "requires": {
+        "@ctrl/tinycolor": "^3.4.0"
+      }
+    },
+    "@ant-design/icons": {
+      "version": "4.7.0",
+      "resolved": "https://registry.npmjs.org/@ant-design/icons/-/icons-4.7.0.tgz",
+      "integrity": "sha512-aoB4Z7JA431rt6d4u+8xcNPPCrdufSRMUOpxa1ab6mz1JCQZOEVolj2WVs/tDFmN62zzK30mNelEsprLYsSF3g==",
+      "requires": {
+        "@ant-design/colors": "^6.0.0",
+        "@ant-design/icons-svg": "^4.2.1",
+        "@babel/runtime": "^7.11.2",
+        "classnames": "^2.2.6",
+        "rc-util": "^5.9.4"
+      }
+    },
+    "@ant-design/icons-svg": {
+      "version": "4.2.1",
+      "resolved": "https://registry.npmjs.org/@ant-design/icons-svg/-/icons-svg-4.2.1.tgz",
+      "integrity": "sha512-EB0iwlKDGpG93hW8f85CTJTs4SvMX7tt5ceupvhALp1IF44SeUFOMhKUOYqpsoYWQKAOuTRDMqn75rEaKDp0Xw=="
+    },
+    "@ant-design/react-slick": {
+      "version": "0.29.2",
+      "resolved": "https://registry.npmjs.org/@ant-design/react-slick/-/react-slick-0.29.2.tgz",
+      "integrity": "sha512-kgjtKmkGHa19FW21lHnAfyyH9AAoh35pBdcJ53rHmQ3O+cfFHGHnUbj/HFrRNJ5vIts09FKJVAD8RpaC+RaWfA==",
+      "requires": {
+        "@babel/runtime": "^7.10.4",
+        "classnames": "^2.2.5",
+        "json2mq": "^0.2.0",
+        "lodash": "^4.17.21",
+        "resize-observer-polyfill": "^1.5.1"
       }
     },
@@ -18813,4 +19654,9 @@
       "requires": {}
     },
+    "@ctrl/tinycolor": {
+      "version": "3.4.1",
+      "resolved": "https://registry.npmjs.org/@ctrl/tinycolor/-/tinycolor-3.4.1.tgz",
+      "integrity": "sha512-ej5oVy6lykXsvieQtqZxCOaLT+xD4+QNarq78cIYISHmZXshCvROLudpQN3lfL8G0NL7plMSSK+zlyvCaIJ4Iw=="
+    },
     "@emotion/babel-plugin": {
       "version": "11.10.2",
@@ -21032,4 +21878,55 @@
       }
     },
+    "antd": {
+      "version": "4.23.6",
+      "resolved": "https://registry.npmjs.org/antd/-/antd-4.23.6.tgz",
+      "integrity": "sha512-AYH57cWBDe1ChtbnvG8i9dpKG4WnjE3AG0zIKpXByFNnxsr4saV6/19ihE8/ImSGpohN4E2zTXmo7R5/MyVRKQ==",
+      "requires": {
+        "@ant-design/colors": "^6.0.0",
+        "@ant-design/icons": "^4.7.0",
+        "@ant-design/react-slick": "~0.29.1",
+        "@babel/runtime": "^7.18.3",
+        "@ctrl/tinycolor": "^3.4.0",
+        "classnames": "^2.2.6",
+        "copy-to-clipboard": "^3.2.0",
+        "lodash": "^4.17.21",
+        "memoize-one": "^6.0.0",
+        "moment": "^2.29.2",
+        "rc-cascader": "~3.7.0",
+        "rc-checkbox": "~2.3.0",
+        "rc-collapse": "~3.3.0",
+        "rc-dialog": "~8.9.0",
+        "rc-drawer": "~5.1.0",
+        "rc-dropdown": "~4.0.0",
+        "rc-field-form": "~1.27.0",
+        "rc-image": "~5.7.0",
+        "rc-input": "~0.1.2",
+        "rc-input-number": "~7.3.9",
+        "rc-mentions": "~1.10.0",
+        "rc-menu": "~9.6.3",
+        "rc-motion": "^2.6.1",
+        "rc-notification": "~4.6.0",
+        "rc-pagination": "~3.1.17",
+        "rc-picker": "~2.6.11",
+        "rc-progress": "~3.3.2",
+        "rc-rate": "~2.9.0",
+        "rc-resize-observer": "^1.2.0",
+        "rc-segmented": "~2.1.0",
+        "rc-select": "~14.1.13",
+        "rc-slider": "~10.0.0",
+        "rc-steps": "~4.1.0",
+        "rc-switch": "~3.2.0",
+        "rc-table": "~7.26.0",
+        "rc-tabs": "~12.2.0",
+        "rc-textarea": "~0.4.5",
+        "rc-tooltip": "~5.2.0",
+        "rc-tree": "~5.7.0",
+        "rc-tree-select": "~5.5.0",
+        "rc-trigger": "^5.2.10",
+        "rc-upload": "~4.3.0",
+        "rc-util": "^5.22.5",
+        "scroll-into-view-if-needed": "^2.2.25"
+      }
+    },
     "anymatch": {
       "version": "3.1.2",
@@ -21080,4 +21977,9 @@
       }
     },
+    "array-tree-filter": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/array-tree-filter/-/array-tree-filter-2.1.0.tgz",
+      "integrity": "sha512-4ROwICNlNw/Hqa9v+rk5h22KjmzB1JGTMVKP2AKJBOCgb0yL0ASf0+YvCcLNNwquOHNX48jkeZIJ3a+oOQqKcw=="
+    },
     "array-union": {
       "version": "2.1.0",
@@ -21133,4 +22035,9 @@
       "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz",
       "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ=="
+    },
+    "async-validator": {
+      "version": "4.2.5",
+      "resolved": "https://registry.npmjs.org/async-validator/-/async-validator-4.2.5.tgz",
+      "integrity": "sha512-7HhHjtERjqlNbZtqNqy2rckN/SpOOlmDliet+lP7k+eKZEjPk3DgyeU9lIXLdeLz0uBbbVp+9Qdow9wJWgwwfg=="
     },
     "asynckit": {
@@ -21677,4 +22584,9 @@
       "integrity": "sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA=="
     },
+    "classnames": {
+      "version": "2.3.2",
+      "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.3.2.tgz",
+      "integrity": "sha512-CSbhY4cFEJRe6/GQzIk5qXZ4Jeg5pcsP7b5peFSDpffpe1cqjASH/n9UTjBwOp6XpMSTwQ8Za2K5V02ueA7Tmw=="
+    },
     "clean-css": {
       "version": "5.3.1",
@@ -21815,4 +22727,9 @@
       }
     },
+    "compute-scroll-into-view": {
+      "version": "1.0.17",
+      "resolved": "https://registry.npmjs.org/compute-scroll-into-view/-/compute-scroll-into-view-1.0.17.tgz",
+      "integrity": "sha512-j4dx+Fb0URmzbwwMUrhqWM2BEWHdFGx+qZ9qqASHRPqvTYdqvWnHg0H1hIbcyLnvgnoNAVMlwkepyqM3DaIFUg=="
+    },
     "concat-map": {
       "version": "0.0.1",
@@ -21867,4 +22784,12 @@
       "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
       "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ=="
+    },
+    "copy-to-clipboard": {
+      "version": "3.3.2",
+      "resolved": "https://registry.npmjs.org/copy-to-clipboard/-/copy-to-clipboard-3.3.2.tgz",
+      "integrity": "sha512-Vme1Z6RUDzrb6xAI7EZlVZ5uvOk2F//GaxKUxajDqm9LhOVM1inxNAD2vy+UZDYsd0uyA9s7b3/FVZPSxqrCfg==",
+      "requires": {
+        "toggle-selection": "^1.0.6"
+      }
     },
     "core-js": {
@@ -22198,4 +23123,14 @@
       }
     },
+    "date-fns": {
+      "version": "2.29.3",
+      "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.29.3.tgz",
+      "integrity": "sha512-dDCnyH2WnnKusqvZZ6+jA1O51Ibt8ZMRNkDZdyAyK4YfbDwa/cEmuztzG5pk6hqlp9aSBPYcjOlktquahGwGeA=="
+    },
+    "dayjs": {
+      "version": "1.11.6",
+      "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.6.tgz",
+      "integrity": "sha512-zZbY5giJAinCG+7AGaw0wIhNZ6J8AhWuSXKvuc1KAyMiRsvGQWqh4L+MomvhdAYjN+lqvVCMq1I41e3YHvXkyQ=="
+    },
     "debug": {
       "version": "4.3.4",
@@ -22360,4 +23295,9 @@
       "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.14.tgz",
       "integrity": "sha512-NMt+m9zFMPZe0JcY9gN224Qvk6qLIdqex29clBvc/y75ZBX9YA9wNK3frsYvu2DI1xcCIwxwnX+TlsJ2DSOADg=="
+    },
+    "dom-align": {
+      "version": "1.12.3",
+      "resolved": "https://registry.npmjs.org/dom-align/-/dom-align-1.12.3.tgz",
+      "integrity": "sha512-Gj9hZN3a07cbR6zviMUBOMPdWxYhbMI+x+WS0NAIu2zFZmbK8ys9R79g+iG9qLnlCwpFoaB+fKy8Pdv470GsPA=="
     },
     "dom-converter": {
@@ -25851,4 +26791,12 @@
       "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw=="
     },
+    "json2mq": {
+      "version": "0.2.0",
+      "resolved": "https://registry.npmjs.org/json2mq/-/json2mq-0.2.0.tgz",
+      "integrity": "sha512-SzoRg7ux5DWTII9J2qkrZrqV1gt+rTaoufMxEzXbS26Uid0NwaJd123HcoB80TgubEppxxIGdNxCx50fEoEWQA==",
+      "requires": {
+        "string-convert": "^0.2.0"
+      }
+    },
     "json5": {
       "version": "2.2.1",
@@ -26066,4 +27014,9 @@
         "fs-monkey": "^1.0.3"
       }
+    },
+    "memoize-one": {
+      "version": "6.0.0",
+      "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-6.0.0.tgz",
+      "integrity": "sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw=="
     },
     "merge-descriptors": {
@@ -26194,4 +27147,9 @@
         "minimist": "^1.2.6"
       }
+    },
+    "moment": {
+      "version": "2.29.4",
+      "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz",
+      "integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w=="
     },
     "ms": {
@@ -27479,4 +28437,416 @@
       }
     },
+    "rc-align": {
+      "version": "4.0.12",
+      "resolved": "https://registry.npmjs.org/rc-align/-/rc-align-4.0.12.tgz",
+      "integrity": "sha512-3DuwSJp8iC/dgHzwreOQl52soj40LchlfUHtgACOUtwGuoFIOVh6n/sCpfqCU8kO5+iz6qR0YKvjgB8iPdE3aQ==",
+      "requires": {
+        "@babel/runtime": "^7.10.1",
+        "classnames": "2.x",
+        "dom-align": "^1.7.0",
+        "lodash": "^4.17.21",
+        "rc-util": "^5.3.0",
+        "resize-observer-polyfill": "^1.5.1"
+      }
+    },
+    "rc-cascader": {
+      "version": "3.7.0",
+      "resolved": "https://registry.npmjs.org/rc-cascader/-/rc-cascader-3.7.0.tgz",
+      "integrity": "sha512-SFtGpwmYN7RaWEAGTS4Rkc62ZV/qmQGg/tajr/7mfIkleuu8ro9Hlk6J+aA0x1YS4zlaZBtTcSaXM01QMiEV/A==",
+      "requires": {
+        "@babel/runtime": "^7.12.5",
+        "array-tree-filter": "^2.1.0",
+        "classnames": "^2.3.1",
+        "rc-select": "~14.1.0",
+        "rc-tree": "~5.7.0",
+        "rc-util": "^5.6.1"
+      }
+    },
+    "rc-checkbox": {
+      "version": "2.3.2",
+      "resolved": "https://registry.npmjs.org/rc-checkbox/-/rc-checkbox-2.3.2.tgz",
+      "integrity": "sha512-afVi1FYiGv1U0JlpNH/UaEXdh6WUJjcWokj/nUN2TgG80bfG+MDdbfHKlLcNNba94mbjy2/SXJ1HDgrOkXGAjg==",
+      "requires": {
+        "@babel/runtime": "^7.10.1",
+        "classnames": "^2.2.1"
+      }
+    },
+    "rc-collapse": {
+      "version": "3.3.1",
+      "resolved": "https://registry.npmjs.org/rc-collapse/-/rc-collapse-3.3.1.tgz",
+      "integrity": "sha512-cOJfcSe3R8vocrF8T+PgaHDrgeA1tX+lwfhwSj60NX9QVRidsILIbRNDLD6nAzmcvVC5PWiIRiR4S1OobxdhCg==",
+      "requires": {
+        "@babel/runtime": "^7.10.1",
+        "classnames": "2.x",
+        "rc-motion": "^2.3.4",
+        "rc-util": "^5.2.1",
+        "shallowequal": "^1.1.0"
+      }
+    },
+    "rc-dialog": {
+      "version": "8.9.0",
+      "resolved": "https://registry.npmjs.org/rc-dialog/-/rc-dialog-8.9.0.tgz",
+      "integrity": "sha512-Cp0tbJnrvPchJfnwIvOMWmJ4yjX3HWFatO6oBFD1jx8QkgsQCR0p8nUWAKdd3seLJhEC39/v56kZaEjwp9muoQ==",
+      "requires": {
+        "@babel/runtime": "^7.10.1",
+        "classnames": "^2.2.6",
+        "rc-motion": "^2.3.0",
+        "rc-util": "^5.21.0"
+      }
+    },
+    "rc-drawer": {
+      "version": "5.1.0",
+      "resolved": "https://registry.npmjs.org/rc-drawer/-/rc-drawer-5.1.0.tgz",
+      "integrity": "sha512-pU3Tsn99pxGdYowXehzZbdDVE+4lDXSGb7p8vA9mSmr569oc2Izh4Zw5vLKSe/Xxn2p5MSNbLVqD4tz+pK6SOw==",
+      "requires": {
+        "@babel/runtime": "^7.10.1",
+        "classnames": "^2.2.6",
+        "rc-motion": "^2.6.1",
+        "rc-util": "^5.21.2"
+      }
+    },
+    "rc-dropdown": {
+      "version": "4.0.1",
+      "resolved": "https://registry.npmjs.org/rc-dropdown/-/rc-dropdown-4.0.1.tgz",
+      "integrity": "sha512-OdpXuOcme1rm45cR0Jzgfl1otzmU4vuBVb+etXM8vcaULGokAKVpKlw8p6xzspG7jGd/XxShvq+N3VNEfk/l5g==",
+      "requires": {
+        "@babel/runtime": "^7.18.3",
+        "classnames": "^2.2.6",
+        "rc-trigger": "^5.3.1",
+        "rc-util": "^5.17.0"
+      }
+    },
+    "rc-field-form": {
+      "version": "1.27.2",
+      "resolved": "https://registry.npmjs.org/rc-field-form/-/rc-field-form-1.27.2.tgz",
+      "integrity": "sha512-NaTjkSB8JsHRgm52wkDorsDzFf2HH6GmCQ2AqkwO8zo+zIqybw8K1lkzDBMDJI8nw1pFuD46U5QsYZv4blYvdw==",
+      "requires": {
+        "@babel/runtime": "^7.18.0",
+        "async-validator": "^4.1.0",
+        "rc-util": "^5.8.0"
+      }
+    },
+    "rc-image": {
+      "version": "5.7.1",
+      "resolved": "https://registry.npmjs.org/rc-image/-/rc-image-5.7.1.tgz",
+      "integrity": "sha512-QyMfdhoUfb5W14plqXSisaYwpdstcLYnB0MjX5ccIK2rydQM9sDPuekQWu500DDGR2dBaIF5vx9XbWkNFK17Fg==",
+      "requires": {
+        "@babel/runtime": "^7.11.2",
+        "classnames": "^2.2.6",
+        "rc-dialog": "~8.9.0",
+        "rc-util": "^5.0.6"
+      }
+    },
+    "rc-input": {
+      "version": "0.1.2",
+      "resolved": "https://registry.npmjs.org/rc-input/-/rc-input-0.1.2.tgz",
+      "integrity": "sha512-ZPmwcFspgfYpUfbSx3KnLk9gImBcLOrlQCr4oTJ4jBoIXgJLTfm26yelzRgBJewhkvD8uJbgX0sQ/yOzuOHnJg==",
+      "requires": {
+        "@babel/runtime": "^7.11.1",
+        "classnames": "^2.2.1",
+        "rc-util": "^5.18.1"
+      }
+    },
+    "rc-input-number": {
+      "version": "7.3.9",
+      "resolved": "https://registry.npmjs.org/rc-input-number/-/rc-input-number-7.3.9.tgz",
+      "integrity": "sha512-u0+miS+SATdb6DtssYei2JJ1WuZME+nXaG6XGtR8maNyW5uGDytfDu60OTWLQEb0Anv/AcCzehldV8CKmKyQfA==",
+      "requires": {
+        "@babel/runtime": "^7.10.1",
+        "classnames": "^2.2.5",
+        "rc-util": "^5.23.0"
+      }
+    },
+    "rc-mentions": {
+      "version": "1.10.0",
+      "resolved": "https://registry.npmjs.org/rc-mentions/-/rc-mentions-1.10.0.tgz",
+      "integrity": "sha512-oMlYWnwXSxP2NQVlgxOTzuG/u9BUc3ySY78K3/t7MNhJWpZzXTao+/Bic6tyZLuNCO89//hVQJBdaR2rnFQl6Q==",
+      "requires": {
+        "@babel/runtime": "^7.10.1",
+        "classnames": "^2.2.6",
+        "rc-menu": "~9.6.0",
+        "rc-textarea": "^0.4.0",
+        "rc-trigger": "^5.0.4",
+        "rc-util": "^5.22.5"
+      }
+    },
+    "rc-menu": {
+      "version": "9.6.4",
+      "resolved": "https://registry.npmjs.org/rc-menu/-/rc-menu-9.6.4.tgz",
+      "integrity": "sha512-6DiNAjxjVIPLZXHffXxxcyE15d4isRL7iQ1ru4MqYDH2Cqc5bW96wZOdMydFtGLyDdnmEQ9jVvdCE9yliGvzkw==",
+      "requires": {
+        "@babel/runtime": "^7.10.1",
+        "classnames": "2.x",
+        "rc-motion": "^2.4.3",
+        "rc-overflow": "^1.2.0",
+        "rc-trigger": "^5.1.2",
+        "rc-util": "^5.12.0",
+        "shallowequal": "^1.1.0"
+      }
+    },
+    "rc-motion": {
+      "version": "2.6.2",
+      "resolved": "https://registry.npmjs.org/rc-motion/-/rc-motion-2.6.2.tgz",
+      "integrity": "sha512-4w1FaX3dtV749P8GwfS4fYnFG4Rb9pxvCYPc/b2fw1cmlHJWNNgOFIz7ysiD+eOrzJSvnLJWlNQQncpNMXwwpg==",
+      "requires": {
+        "@babel/runtime": "^7.11.1",
+        "classnames": "^2.2.1",
+        "rc-util": "^5.21.0"
+      }
+    },
+    "rc-notification": {
+      "version": "4.6.0",
+      "resolved": "https://registry.npmjs.org/rc-notification/-/rc-notification-4.6.0.tgz",
+      "integrity": "sha512-xF3MKgIoynzjQAO4lqsoraiFo3UXNYlBfpHs0VWvwF+4pimen9/H1DYLN2mfRWhHovW6gRpla73m2nmyIqAMZQ==",
+      "requires": {
+        "@babel/runtime": "^7.10.1",
+        "classnames": "2.x",
+        "rc-motion": "^2.2.0",
+        "rc-util": "^5.20.1"
+      }
+    },
+    "rc-overflow": {
+      "version": "1.2.8",
+      "resolved": "https://registry.npmjs.org/rc-overflow/-/rc-overflow-1.2.8.tgz",
+      "integrity": "sha512-QJ0UItckWPQ37ZL1dMEBAdY1dhfTXFL9k6oTTcyydVwoUNMnMqCGqnRNA98axSr/OeDKqR6DVFyi8eA5RQI/uQ==",
+      "requires": {
+        "@babel/runtime": "^7.11.1",
+        "classnames": "^2.2.1",
+        "rc-resize-observer": "^1.0.0",
+        "rc-util": "^5.19.2"
+      }
+    },
+    "rc-pagination": {
+      "version": "3.1.17",
+      "resolved": "https://registry.npmjs.org/rc-pagination/-/rc-pagination-3.1.17.tgz",
+      "integrity": "sha512-/BQ5UxcBnW28vFAcP2hfh+Xg15W0QZn8TWYwdCApchMH1H0CxiaUUcULP8uXcFM1TygcdKWdt3JqsL9cTAfdkQ==",
+      "requires": {
+        "@babel/runtime": "^7.10.1",
+        "classnames": "^2.2.1"
+      }
+    },
+    "rc-picker": {
+      "version": "2.6.11",
+      "resolved": "https://registry.npmjs.org/rc-picker/-/rc-picker-2.6.11.tgz",
+      "integrity": "sha512-INJ7ULu+Kj4UgqbcqE8Q+QpMw55xFf9kkyLBHJFk0ihjJpAV4glialRfqHE7k4KX2BWYPQfpILwhwR14x2EiRQ==",
+      "requires": {
+        "@babel/runtime": "^7.10.1",
+        "classnames": "^2.2.1",
+        "date-fns": "2.x",
+        "dayjs": "1.x",
+        "moment": "^2.24.0",
+        "rc-trigger": "^5.0.4",
+        "rc-util": "^5.4.0",
+        "shallowequal": "^1.1.0"
+      }
+    },
+    "rc-progress": {
+      "version": "3.3.3",
+      "resolved": "https://registry.npmjs.org/rc-progress/-/rc-progress-3.3.3.tgz",
+      "integrity": "sha512-MDVNVHzGanYtRy2KKraEaWeZLri2ZHWIRyaE1a9MQ2MuJ09m+Wxj5cfcaoaR6z5iRpHpA59YeUxAlpML8N4PJw==",
+      "requires": {
+        "@babel/runtime": "^7.10.1",
+        "classnames": "^2.2.6",
+        "rc-util": "^5.16.1"
+      }
+    },
+    "rc-rate": {
+      "version": "2.9.2",
+      "resolved": "https://registry.npmjs.org/rc-rate/-/rc-rate-2.9.2.tgz",
+      "integrity": "sha512-SaiZFyN8pe0Fgphv8t3+kidlej+cq/EALkAJAc3A0w0XcPaH2L1aggM8bhe1u6GAGuQNAoFvTLjw4qLPGRKV5g==",
+      "requires": {
+        "@babel/runtime": "^7.10.1",
+        "classnames": "^2.2.5",
+        "rc-util": "^5.0.1"
+      }
+    },
+    "rc-resize-observer": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/rc-resize-observer/-/rc-resize-observer-1.2.0.tgz",
+      "integrity": "sha512-6W+UzT3PyDM0wVCEHfoW3qTHPTvbdSgiA43buiy8PzmeMnfgnDeb9NjdimMXMl3/TcrvvWl5RRVdp+NqcR47pQ==",
+      "requires": {
+        "@babel/runtime": "^7.10.1",
+        "classnames": "^2.2.1",
+        "rc-util": "^5.15.0",
+        "resize-observer-polyfill": "^1.5.1"
+      }
+    },
+    "rc-segmented": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/rc-segmented/-/rc-segmented-2.1.0.tgz",
+      "integrity": "sha512-hUlonro+pYoZcwrH6Vm56B2ftLfQh046hrwif/VwLIw1j3zGt52p5mREBwmeVzXnSwgnagpOpfafspzs1asjGw==",
+      "requires": {
+        "@babel/runtime": "^7.11.1",
+        "classnames": "^2.2.1",
+        "rc-motion": "^2.4.4",
+        "rc-util": "^5.17.0"
+      }
+    },
+    "rc-select": {
+      "version": "14.1.13",
+      "resolved": "https://registry.npmjs.org/rc-select/-/rc-select-14.1.13.tgz",
+      "integrity": "sha512-WMEsC3gTwA1dbzWOdVIXDmWyidYNLq68AwvvUlRROw790uGUly0/vmqDozXrIr0QvN/A3CEULx12o+WtLCAefg==",
+      "requires": {
+        "@babel/runtime": "^7.10.1",
+        "classnames": "2.x",
+        "rc-motion": "^2.0.1",
+        "rc-overflow": "^1.0.0",
+        "rc-trigger": "^5.0.4",
+        "rc-util": "^5.16.1",
+        "rc-virtual-list": "^3.2.0"
+      }
+    },
+    "rc-slider": {
+      "version": "10.0.1",
+      "resolved": "https://registry.npmjs.org/rc-slider/-/rc-slider-10.0.1.tgz",
+      "integrity": "sha512-igTKF3zBet7oS/3yNiIlmU8KnZ45npmrmHlUUio8PNbIhzMcsh+oE/r2UD42Y6YD2D/s+kzCQkzQrPD6RY435Q==",
+      "requires": {
+        "@babel/runtime": "^7.10.1",
+        "classnames": "^2.2.5",
+        "rc-util": "^5.18.1",
+        "shallowequal": "^1.1.0"
+      }
+    },
+    "rc-steps": {
+      "version": "4.1.4",
+      "resolved": "https://registry.npmjs.org/rc-steps/-/rc-steps-4.1.4.tgz",
+      "integrity": "sha512-qoCqKZWSpkh/b03ASGx1WhpKnuZcRWmvuW+ZUu4mvMdfvFzVxblTwUM+9aBd0mlEUFmt6GW8FXhMpHkK3Uzp3w==",
+      "requires": {
+        "@babel/runtime": "^7.10.2",
+        "classnames": "^2.2.3",
+        "rc-util": "^5.0.1"
+      }
+    },
+    "rc-switch": {
+      "version": "3.2.2",
+      "resolved": "https://registry.npmjs.org/rc-switch/-/rc-switch-3.2.2.tgz",
+      "integrity": "sha512-+gUJClsZZzvAHGy1vZfnwySxj+MjLlGRyXKXScrtCTcmiYNPzxDFOxdQ/3pK1Kt/0POvwJ/6ALOR8gwdXGhs+A==",
+      "requires": {
+        "@babel/runtime": "^7.10.1",
+        "classnames": "^2.2.1",
+        "rc-util": "^5.0.1"
+      }
+    },
+    "rc-table": {
+      "version": "7.26.0",
+      "resolved": "https://registry.npmjs.org/rc-table/-/rc-table-7.26.0.tgz",
+      "integrity": "sha512-0cD8e6S+DTGAt5nBZQIPFYEaIukn17sfa5uFL98faHlH/whZzD8ii3dbFL4wmUDEL4BLybhYop+QUfZJ4CPvNQ==",
+      "requires": {
+        "@babel/runtime": "^7.10.1",
+        "classnames": "^2.2.5",
+        "rc-resize-observer": "^1.1.0",
+        "rc-util": "^5.22.5",
+        "shallowequal": "^1.1.0"
+      }
+    },
+    "rc-tabs": {
+      "version": "12.2.1",
+      "resolved": "https://registry.npmjs.org/rc-tabs/-/rc-tabs-12.2.1.tgz",
+      "integrity": "sha512-09pVv4kN8VFqp6THceEmxOW8PAShQC08hrroeVYP4Y8YBFaP1PIWdyFL01czcbyz5YZFj9flZ7aljMaAl0jLVg==",
+      "requires": {
+        "@babel/runtime": "^7.11.2",
+        "classnames": "2.x",
+        "rc-dropdown": "~4.0.0",
+        "rc-menu": "~9.6.0",
+        "rc-motion": "^2.6.2",
+        "rc-resize-observer": "^1.0.0",
+        "rc-util": "^5.5.0"
+      }
+    },
+    "rc-textarea": {
+      "version": "0.4.5",
+      "resolved": "https://registry.npmjs.org/rc-textarea/-/rc-textarea-0.4.5.tgz",
+      "integrity": "sha512-WHeJRgUlloNyVgTsItMrIXwMhU6P3NmrUDkxX+JRwEpJjECsKtZNlNcXe9pHNLCaYQ3Z1cVCfsClhgDDgJ2kFQ==",
+      "requires": {
+        "@babel/runtime": "^7.10.1",
+        "classnames": "^2.2.1",
+        "rc-resize-observer": "^1.0.0",
+        "rc-util": "^5.7.0",
+        "shallowequal": "^1.1.0"
+      }
+    },
+    "rc-tooltip": {
+      "version": "5.2.2",
+      "resolved": "https://registry.npmjs.org/rc-tooltip/-/rc-tooltip-5.2.2.tgz",
+      "integrity": "sha512-jtQzU/18S6EI3lhSGoDYhPqNpWajMtS5VV/ld1LwyfrDByQpYmw/LW6U7oFXXLukjfDHQ7Ju705A82PRNFWYhg==",
+      "requires": {
+        "@babel/runtime": "^7.11.2",
+        "classnames": "^2.3.1",
+        "rc-trigger": "^5.0.0"
+      }
+    },
+    "rc-tree": {
+      "version": "5.7.0",
+      "resolved": "https://registry.npmjs.org/rc-tree/-/rc-tree-5.7.0.tgz",
+      "integrity": "sha512-F+Ewkv/UcutshnVBMISP+lPdHDlcsL+YH/MQDVWbk+QdkfID7vXiwrHMEZn31+2Rbbm21z/HPceGS8PXGMmnQg==",
+      "requires": {
+        "@babel/runtime": "^7.10.1",
+        "classnames": "2.x",
+        "rc-motion": "^2.0.1",
+        "rc-util": "^5.16.1",
+        "rc-virtual-list": "^3.4.8"
+      }
+    },
+    "rc-tree-select": {
+      "version": "5.5.2",
+      "resolved": "https://registry.npmjs.org/rc-tree-select/-/rc-tree-select-5.5.2.tgz",
+      "integrity": "sha512-toxkzVhkWQ2wvInOhHwmyEpCCi9osnoRQmN0trKvdvyzLattCw63F2T+V/dS2d/xUkrw6Zr1Y2J0/xP57x/jYQ==",
+      "requires": {
+        "@babel/runtime": "^7.10.1",
+        "classnames": "2.x",
+        "rc-select": "~14.1.0",
+        "rc-tree": "~5.7.0",
+        "rc-util": "^5.16.1"
+      }
+    },
+    "rc-trigger": {
+      "version": "5.3.1",
+      "resolved": "https://registry.npmjs.org/rc-trigger/-/rc-trigger-5.3.1.tgz",
+      "integrity": "sha512-5gaFbDkYSefZ14j2AdzucXzlWgU2ri5uEjkHvsf1ynRhdJbKxNOnw4PBZ9+FVULNGFiDzzlVF8RJnR9P/xrnKQ==",
+      "requires": {
+        "@babel/runtime": "^7.18.3",
+        "classnames": "^2.2.6",
+        "rc-align": "^4.0.0",
+        "rc-motion": "^2.0.0",
+        "rc-util": "^5.19.2"
+      }
+    },
+    "rc-upload": {
+      "version": "4.3.4",
+      "resolved": "https://registry.npmjs.org/rc-upload/-/rc-upload-4.3.4.tgz",
+      "integrity": "sha512-uVbtHFGNjHG/RyAfm9fluXB6pvArAGyAx8z7XzXXyorEgVIWj6mOlriuDm0XowDHYz4ycNK0nE0oP3cbFnzxiQ==",
+      "requires": {
+        "@babel/runtime": "^7.18.3",
+        "classnames": "^2.2.5",
+        "rc-util": "^5.2.0"
+      }
+    },
+    "rc-util": {
+      "version": "5.24.4",
+      "resolved": "https://registry.npmjs.org/rc-util/-/rc-util-5.24.4.tgz",
+      "integrity": "sha512-2a4RQnycV9eV7lVZPEJ7QwJRPlZNc06J7CwcwZo4vIHr3PfUqtYgl1EkUV9ETAc6VRRi8XZOMFhYG63whlIC9Q==",
+      "requires": {
+        "@babel/runtime": "^7.18.3",
+        "react-is": "^16.12.0",
+        "shallowequal": "^1.1.0"
+      },
+      "dependencies": {
+        "react-is": {
+          "version": "16.13.1",
+          "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
+          "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
+        }
+      }
+    },
+    "rc-virtual-list": {
+      "version": "3.4.10",
+      "resolved": "https://registry.npmjs.org/rc-virtual-list/-/rc-virtual-list-3.4.10.tgz",
+      "integrity": "sha512-Jv0cgJxJ+8F/YViW8WGs/jQF2rmT8RUcJ5uDJs5MOFLTYLAvCpM/xU+Zu6EpCun50fmovhXiItQctcfE2UY3Aw==",
+      "requires": {
+        "classnames": "^2.2.6",
+        "rc-resize-observer": "^1.0.0",
+        "rc-util": "^5.15.0"
+      }
+    },
     "react": {
       "version": "18.2.0",
@@ -27859,4 +29229,9 @@
       "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ=="
     },
+    "resize-observer-polyfill": {
+      "version": "1.5.1",
+      "resolved": "https://registry.npmjs.org/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz",
+      "integrity": "sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg=="
+    },
     "resolve": {
       "version": "1.22.1",
@@ -28051,4 +29426,12 @@
         "ajv": "^6.12.5",
         "ajv-keywords": "^3.5.2"
+      }
+    },
+    "scroll-into-view-if-needed": {
+      "version": "2.2.29",
+      "resolved": "https://registry.npmjs.org/scroll-into-view-if-needed/-/scroll-into-view-if-needed-2.2.29.tgz",
+      "integrity": "sha512-hxpAR6AN+Gh53AdAimHM6C8oTN1ppwVZITihix+WqalywBeFcQ6LdQP5ABNl26nX8GTEL7VT+b8lKpdqq65wXg==",
+      "requires": {
+        "compute-scroll-into-view": "^1.0.17"
       }
     },
@@ -28200,4 +29583,9 @@
       "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw=="
     },
+    "shallowequal": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/shallowequal/-/shallowequal-1.1.0.tgz",
+      "integrity": "sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ=="
+    },
     "shebang-command": {
       "version": "2.0.0",
@@ -28373,4 +29761,9 @@
         }
       }
+    },
+    "string-convert": {
+      "version": "0.2.1",
+      "resolved": "https://registry.npmjs.org/string-convert/-/string-convert-0.2.1.tgz",
+      "integrity": "sha512-u/1tdPl4yQnPBjnVrmdLo9gtuLvELKsAoRapekWggdiQNvvvum+jYF329d84NAa660KQw7pB2n36KrIKVoXa3A=="
     },
     "string-length": {
@@ -28777,4 +30170,9 @@
         "is-number": "^7.0.0"
       }
+    },
+    "toggle-selection": {
+      "version": "1.0.6",
+      "resolved": "https://registry.npmjs.org/toggle-selection/-/toggle-selection-1.0.6.tgz",
+      "integrity": "sha512-BiZS+C1OS8g/q2RRbJmy59xpyghNBqrr6k5L/uKBGRsTfxmu3ffiRnd8mlGPUVayg8pvfi5urfnu8TU7DVOkLQ=="
     },
     "toidentifier": {
Index: phonelux-frontend/package.json
===================================================================
--- phonelux-frontend/package.json	(revision ffd50db1e5e2b9839ba7546d8ca44b600150bd71)
+++ phonelux-frontend/package.json	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
@@ -16,4 +16,5 @@
     "@testing-library/user-event": "^13.5.0",
     "@tippyjs/react": "^4.2.6",
+    "antd": "^4.23.6",
     "axios": "^0.27.2",
     "jwt-decode": "^3.1.2",
Index: phonelux-frontend/src/App.js
===================================================================
--- phonelux-frontend/src/App.js	(revision ffd50db1e5e2b9839ba7546d8ca44b600150bd71)
+++ phonelux-frontend/src/App.js	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
@@ -12,4 +12,6 @@
 import CompareOffersComponent from "./components/CompareOffersComponent/CompareOffersComponent";
 import SpecificationsFilterComponent from "./components/FiltersComponents/SpecificationsFilterComponent";
+import OfferReportsComponent from "./components/OfferReportsComponent/OfferReportsComponent";
+import ScrappersComponent from "./components/ScrappersComponent/ScrappersComponent";
 
 
@@ -29,4 +31,6 @@
         <Route path="/admin/editoffer/:offerId" element={<EditOfferComponent/>}/>
         <Route path="/compareoffers" element={<CompareOffersComponent/>}/>
+        <Route path="/offerreport/reports" element={<OfferReportsComponent/>}/>
+        <Route path="/scrapperinfo" element={<ScrappersComponent/>}/>
       </Routes>
     </BrowserRouter>
Index: phonelux-frontend/src/components/EditOfferComponent/EditOfferComponent.js
===================================================================
--- phonelux-frontend/src/components/EditOfferComponent/EditOfferComponent.js	(revision ffd50db1e5e2b9839ba7546d8ca44b600150bd71)
+++ phonelux-frontend/src/components/EditOfferComponent/EditOfferComponent.js	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
@@ -17,14 +17,4 @@
 
     componentDidMount(){
-        // if(!localStorage.getItem('token'))
-        // {
-        //     window.location.href = "/"
-        // }
-
-        // if(this.context.role != 'ADMIN' && this.context.role != 'SUPERADMIN')
-        // {
-        //     window.location.href = "/"
-        // }
-
         var config = {
             method: 'get',
Index: phonelux-frontend/src/components/HomepageComponent.js
===================================================================
--- phonelux-frontend/src/components/HomepageComponent.js	(revision ffd50db1e5e2b9839ba7546d8ca44b600150bd71)
+++ phonelux-frontend/src/components/HomepageComponent.js	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
@@ -220,5 +220,5 @@
   render() {
     // console.log(this.context)
-    // console.log(localStorage.getItem('token'))
+    console.log(localStorage.getItem('token'))
     // console.log(this.state)
     return (
Index: phonelux-frontend/src/components/LoginRegisterComponents/LoginFormComponent.css
===================================================================
--- phonelux-frontend/src/components/LoginRegisterComponents/LoginFormComponent.css	(revision ffd50db1e5e2b9839ba7546d8ca44b600150bd71)
+++ phonelux-frontend/src/components/LoginRegisterComponents/LoginFormComponent.css	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
@@ -162,2 +162,15 @@
   background-color: rgb(251, 224, 224);
  }
+
+ .login-with-facebook-image{
+  width: 40%;
+ }
+
+.login-with-facebook-image:hover{
+  cursor: pointer;
+}
+
+ .login-with-facebook-wrapper{
+  display: flex;
+  justify-content: center;
+ }
Index: phonelux-frontend/src/components/LoginRegisterComponents/LoginFormComponent.js
===================================================================
--- phonelux-frontend/src/components/LoginRegisterComponents/LoginFormComponent.js	(revision ffd50db1e5e2b9839ba7546d8ca44b600150bd71)
+++ phonelux-frontend/src/components/LoginRegisterComponents/LoginFormComponent.js	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
@@ -6,4 +6,5 @@
 import { Link } from 'react-router-dom';
 import axios from 'axios';
+import FacebookLogin from 'react-facebook-login'
 
 export class LoginFormComponent extends Component {
@@ -18,8 +19,5 @@
     }
   }
-  
-  changeHandler = (e) =>{
-      this.setState({[e.target.name] : e.target.value})
-  }
+
 
   submitHandler = (e) => {
Index: phonelux-frontend/src/components/NavbarComponent/NavbarComponent.js
===================================================================
--- phonelux-frontend/src/components/NavbarComponent/NavbarComponent.js	(revision ffd50db1e5e2b9839ba7546d8ca44b600150bd71)
+++ phonelux-frontend/src/components/NavbarComponent/NavbarComponent.js	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
@@ -12,4 +12,7 @@
 import SupervisorAccountIcon from '@mui/icons-material/SupervisorAccount';
 import CompareIcon from '@mui/icons-material/Compare';
+import BugReportIcon from '@mui/icons-material/BugReport';
+import ReportIcon from '@mui/icons-material/Report';
+import UpdateIcon from '@mui/icons-material/Update';
 
 export class NavbarComponent extends Component {
@@ -36,4 +39,20 @@
             <Link style={{color: 'black'}} to={"/management/users"}>
               <SupervisorAccountIcon style={{fontSize: '40px', marginTop: '10px', marginRight: '10px' }} className='navbar-superadmin-icon'/>
+            </Link>
+          </Tippy> : <></>
+        }
+         {
+          localStorage.getItem('token') && this.context.role == 'SUPERADMIN' ? 
+          <Tippy placement='bottom' content='Преземање на содржина'>
+            <Link style={{color: 'black'}} to={"/scrapperinfo"}>
+              <UpdateIcon style={{fontSize: '40px', marginTop: '10px', marginRight: '10px' }} className='navbar-superadmin-icon'/>
+            </Link>
+          </Tippy> : <></>
+        }
+         {
+          localStorage.getItem('token') && (this.context.role == 'SUPERADMIN' || this.context.role == 'ADMIN') ? 
+          <Tippy placement='bottom' content='Пријавени понуди'>
+            <Link style={{color: 'black'}} to={"/offerreport/reports"}>
+              <BugReportIcon style={{fontSize: '40px', marginTop: '10px', marginRight: '10px' }} className='navbar-offerreports-icon'/>
             </Link>
           </Tippy> : <></>
Index: phonelux-frontend/src/components/OfferReportsComponent/OfferReportsComponent.css
===================================================================
--- phonelux-frontend/src/components/OfferReportsComponent/OfferReportsComponent.css	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
+++ phonelux-frontend/src/components/OfferReportsComponent/OfferReportsComponent.css	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
@@ -0,0 +1,82 @@
+.offerreports-section-header{
+    background-color: #B6E2C8;
+    justify-content: center;
+    align-content: center;
+    margin-top: -30px;
+    width: 100%;
+    display: flex;
+    font-size: 18px;
+}
+.offerreports-section-header-text{
+    width: fit-content;
+}
+
+.offerreports-section-table-row:nth-of-type(even){
+    background-color: #eef2f0;
+}
+
+.offerreports-section-table{
+    border-collapse: collapse;
+    width: 100%;
+    table-layout: fixed;
+}
+
+.offerreports-section-table-row{
+    border: 1px solid gainsboro;
+    padding: 20px ;
+    font-size: 18px;
+}
+
+.offerreports-section-table td{
+    text-align: center;
+    word-wrap: break-word;
+}
+
+.offerreports-section-table-head{
+    background-color: #a6c9ab;
+    font-size: 22px;
+}
+
+.offerreports-section-table-head th{
+    word-wrap: break-word;
+    width: 100%;
+}
+
+.reportoffer-removeall-button{    
+    font-weight: bold;
+    font-size: 15px;
+    width: 80%;
+    border-radius: 20px;
+    border: 2px solid red;
+    background-color: rgb(243, 203, 203);
+}
+
+.reportoffer-removeall-button:hover{
+    cursor: pointer;
+    background-color: rgb(228, 179, 179);
+    box-shadow: 0 12px 16px 0 rgba(0,0,0,0.24), 0 17px 50px 0 rgba(0,0,0,0.19);
+    transition: box-shadow 0.5s, background-color 0.5s ;
+}
+
+.no-offerreports-message{
+    text-align: center;
+    background-color: #a6c9ab;
+    padding: 10px;
+    border-radius: 50px;
+    border: 1px solid black;
+    width: fit-content;
+}
+
+.no-offerreports-wrapper{
+    margin-top: 100px;
+    display: flex;
+    justify-content: center;
+    width: 100%;
+}
+
+.offerreports-pagination-wrapper{
+    margin-top: 40px;
+    display: flex;
+    justify-content: center;
+    margin-bottom: 30px;
+}
Index: phonelux-frontend/src/components/OfferReportsComponent/OfferReportsComponent.js
===================================================================
--- phonelux-frontend/src/components/OfferReportsComponent/OfferReportsComponent.js	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
+++ phonelux-frontend/src/components/OfferReportsComponent/OfferReportsComponent.js	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
@@ -0,0 +1,149 @@
+import { Pagination } from '@mui/material'
+import axios from 'axios'
+import React, { Component } from 'react'
+import HeaderComponent from '../HeaderComponent/HeaderComponent'
+import './OfferReportsComponent.css'
+import SingleReportComponent from './SingleReportComponent'
+
+export class OfferReportsComponent extends Component {
+
+    constructor(props) {
+      super(props)
+    
+      this.state = {
+         offerReports: [],
+         currentReports: [],
+         reportsPerPage:10,
+         numberOfPages: 0,
+         currentPage: 1,
+      }
+    }
+
+    componentDidMount(){
+       this.getOfferReports()
+    }
+
+    removeOfferReport = (id) => {
+        var config = {
+            method: 'delete',
+            url: '/offerreport/remove/'+id,
+            headers: { 
+              'Authorization': 'Bearer '+localStorage.getItem('token')
+            }
+          };
+          
+          axios(config)
+          .then(response => {
+            this.getOfferReports()
+          })
+          .catch(error => {
+            console.log(error);
+          });
+          
+    }
+
+    removeAllOfferReports = () => {
+        var config = {
+            method: 'delete',
+            url: '/offerreport/removeall',
+            headers: { 
+              'Authorization': 'Bearer '+localStorage.getItem('token')
+            }
+          };
+          
+          axios(config)
+          .then(response => {
+            this.getOfferReports()
+          })
+          .catch(error => {
+            console.log(error);
+          });
+    }
+
+    getOfferReports = () => {
+        var config = {
+            method: 'get',
+            url: '/offerreport/allreports',
+            headers: { 
+                'Authorization': 'Bearer '+localStorage.getItem('token')
+            }
+            };
+    
+            axios(config)
+            .then(response => {
+            this.setState({
+                offerReports: response.data,
+                numberOfPages: Math.ceil(response.data.length / this.state.reportsPerPage)
+            },(e) => this.setNewPage(e,this.state.currentPage))
+            })
+            .catch(error => {
+            console.log(error);
+            });
+    }
+
+    setNewPage = (event,page) => {
+
+        const indexOfLastReport = parseInt(page) * this.state.reportsPerPage;
+        const indexOfFirstReport = indexOfLastReport - this.state.reportsPerPage;
+    
+        const currReports = this.state.offerReports.slice(indexOfFirstReport, indexOfLastReport)
+    
+        this.setState({
+          currentPage: parseInt(page),
+          currentReports: currReports
+        })
+    }
+    
+  render() {
+    console.log(this.state)
+    return (
+        <div className='offerreports-section-main'>
+        <HeaderComponent/>
+        <div className='offerreports-section-header'>
+          <h1 className='offerreports-section-header-text'>
+            Пријавени невалидни понуди
+          </h1>
+        </div>
+
+        {
+            this.state.offerReports.length > 0 ? 
+            <>
+              <div className='offerreports-section'>
+                <table cellPadding={20} className='offerreports-section-table'>
+                <thead className='offerreports-section-table-head'>
+                    <tr>
+                    <th>Име на понуда</th>
+                    <th>Време на пријавување</th>
+                    <th>Последно пријавена од</th>
+                    <th>Вкупно пријави</th>
+                    <th>
+                    <button className='reportoffer-removeall-button' onClick={this.removeAllOfferReports}>Отстрани ги сите пријави</button>
+                    </th>
+                    </tr>
+                </thead>
+                <tbody>
+                    {
+                    this.state.currentReports.map((offer,idx) => <SingleReportComponent key={idx} id={offer.id} 
+                    times_reported={offer.times_reported} reportedAt={offer.reportedAt} phoneOffer={offer.phoneOffer} 
+                    reportedBy={offer.reportedBy} removeOfferReport={this.removeOfferReport}/>)
+                    }
+                </tbody>
+                </table>
+
+                </div>
+                <div className='offerreports-pagination-wrapper'>
+                <Pagination className='offerreports-pagination' onChange={this.setNewPage} page={this.state.currentPage}
+                count={this.state.numberOfPages} color="primary" />
+                </div>      
+            </>
+            :
+            <div className='no-offerreports-wrapper'>
+                <h1 className='no-offerreports-message'>Нема пријавено понуди</h1>
+            </div>
+        }
+      </div>
+    )
+  }
+}
+
+export default OfferReportsComponent
Index: phonelux-frontend/src/components/OfferReportsComponent/SingleReportComponent.css
===================================================================
--- phonelux-frontend/src/components/OfferReportsComponent/SingleReportComponent.css	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
+++ phonelux-frontend/src/components/OfferReportsComponent/SingleReportComponent.css	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
@@ -0,0 +1,4 @@
+.offerreport-remove-icon{
+    cursor: pointer;
+}
+
Index: phonelux-frontend/src/components/OfferReportsComponent/SingleReportComponent.js
===================================================================
--- phonelux-frontend/src/components/OfferReportsComponent/SingleReportComponent.js	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
+++ phonelux-frontend/src/components/OfferReportsComponent/SingleReportComponent.js	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
@@ -0,0 +1,35 @@
+import React, { Component } from 'react'
+import { Link } from 'react-router-dom'
+import './SingleReportComponent.css'
+import DeleteIcon from '@mui/icons-material/Delete';
+import Tippy from '@tippyjs/react';
+import { Delete } from '@mui/icons-material';
+
+export class SingleReportComponent extends Component {
+    constructor(props) {
+      super(props)
+    
+      this.state = {
+         
+      }
+    }
+    
+  render() {
+    return (
+        <tr className='offerreports-section-table-row'>
+          <td><Link to={"/phoneoffer/"+this.props.phoneOffer.id}>{this.props.phoneOffer.offer_name}</Link></td>
+          <td>{this.props.reportedAt.split('T')[0]}</td>
+          <td>{this.props.reportedBy}</td>
+          <td>{this.props.times_reported}</td>
+          <td>{
+           <Tippy placement='bottom' content='Отстрани пријава'>
+           <Delete className='offerreport-remove-icon' onClick={() => this.props.removeOfferReport(this.props.id)}
+            style={{fontSize: '45px'}}/>
+        </Tippy>
+        }</td>
+        </tr>
+      )
+  }
+}
+
+export default SingleReportComponent
Index: phonelux-frontend/src/components/PhoneOfferDetailsComponent/PhoneOfferDetailsComponent.css
===================================================================
--- phonelux-frontend/src/components/PhoneOfferDetailsComponent/PhoneOfferDetailsComponent.css	(revision ffd50db1e5e2b9839ba7546d8ca44b600150bd71)
+++ phonelux-frontend/src/components/PhoneOfferDetailsComponent/PhoneOfferDetailsComponent.css	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
@@ -140,4 +140,8 @@
 }
 
+.offerdetails-report-icon{
+    cursor: pointer;
+}
 
 
+
Index: phonelux-frontend/src/components/PhoneOfferDetailsComponent/PhoneOfferDetailsComponent.js
===================================================================
--- phonelux-frontend/src/components/PhoneOfferDetailsComponent/PhoneOfferDetailsComponent.js	(revision ffd50db1e5e2b9839ba7546d8ca44b600150bd71)
+++ phonelux-frontend/src/components/PhoneOfferDetailsComponent/PhoneOfferDetailsComponent.js	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
@@ -9,4 +9,5 @@
 import VisibilityIcon from '@mui/icons-material/Visibility';
 import VisibilityOffIcon from '@mui/icons-material/VisibilityOff';
+import ReportIcon from '@mui/icons-material/Report';
 
 
@@ -61,4 +62,23 @@
   }
 
+    reportOffer = () =>{
+      alert('Пратена е пријава до администратор за невалидност на спецификациите на понудата!')
+      var config = {
+        method: 'post',
+        url: '/offerreport/'+this.state.offerId+'/'+this.context.userId,
+        headers: { 
+          'Authorization': 'Bearer '+localStorage.getItem('token')
+        }
+      };
+      
+      axios(config)
+      .then(function (response) {
+        console.log(JSON.stringify(response.data));
+      })
+      .catch(function (error) {
+        console.log(error);
+      });
+    }
+
   render() {
     console.log(this.state)
@@ -71,4 +91,10 @@
           {
             localStorage.getItem('token') ? 
+            <Tippy placement='bottom' content='Пријави понуда за неточни спецификации'>
+            <ReportIcon onClick={this.reportOffer} className='offerdetails-report-icon' style={{fontSize: '45px'}}/>
+         </Tippy> : <></>
+          }
+          {
+            localStorage.getItem('token') ? 
             this.state.showAllSpecs ? 
               <Tippy placement='bottom' content='Прикажи ги избраните спецификации'>
@@ -103,4 +129,5 @@
 
           })()}
+
         </div>
         <div className='phone-offer-details-last-updated-wrapper'></div>
@@ -109,5 +136,7 @@
         <table className='phone-offer-details-table'>
           <thead>
-          <tr><th colSpan={2}>Детали за понудата</th></tr>
+          <tr><th colSpan={2}>
+            Детали за понудата
+          </th></tr>
           </thead>
           <tbody>
Index: phonelux-frontend/src/components/ScrappersComponent/ScrapperInfoComponent.js
===================================================================
--- phonelux-frontend/src/components/ScrappersComponent/ScrapperInfoComponent.js	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
+++ phonelux-frontend/src/components/ScrappersComponent/ScrapperInfoComponent.js	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
@@ -0,0 +1,25 @@
+import React, { Component } from 'react'
+
+export class ScrapperInfoComponent extends Component {
+    constructor(props) {
+      super(props)
+    
+      this.state = {
+         
+      }
+    }
+    
+  render() {
+    return (
+        <tr className='scrappers-section-table-row'>
+        <td>{this.props.store}</td>
+        <td>{this.props.status == 'success' ? <span className='scrapper-info-success'>Успешно</span> 
+        : 
+        <span className='scrapper-info-failed'>Неуспешно</span>}</td>
+        <td>{this.props.recievedAt.split('T')[0]}</td>
+      </tr>
+    )
+  }
+}
+
+export default ScrapperInfoComponent
Index: phonelux-frontend/src/components/ScrappersComponent/ScrappersComponent.css
===================================================================
--- phonelux-frontend/src/components/ScrappersComponent/ScrappersComponent.css	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
+++ phonelux-frontend/src/components/ScrappersComponent/ScrappersComponent.css	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
@@ -0,0 +1,52 @@
+.scrappers-section-header{
+    background-color: #B6E2C8;
+    justify-content: center;
+    align-content: center;
+    margin-top: -30px;
+    width: 100%;
+    display: flex;
+    font-size: 18px;
+}
+.scrappers-section-header-text{
+    width: fit-content;
+}
+
+
+.scrappers-section-table{
+    border-collapse: collapse;
+    width: 100%;
+    table-layout: fixed;
+}
+
+.scrappers-section-table-row{
+    border: 1px solid gainsboro;
+    padding: 20px ;
+    font-size: 18px;
+}
+
+.scrappers-section-table td{
+    text-align: center;
+    word-wrap: break-word;
+}
+
+.scrappers-section-table-head{
+    background-color: #a6c9ab;
+    font-size: 22px;
+}
+
+.scrappers-section-table-head th{
+    word-wrap: break-word;
+    width: 100%;
+}
+
+.scrapper-info-failed{
+    color: red;
+}
+
+.scrapper-info-success{
+    color: #58ad7b;
+}
+
+.scrappers-section-table-row{
+    font-weight: bold;
+}
Index: phonelux-frontend/src/components/ScrappersComponent/ScrappersComponent.js
===================================================================
--- phonelux-frontend/src/components/ScrappersComponent/ScrappersComponent.js	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
+++ phonelux-frontend/src/components/ScrappersComponent/ScrappersComponent.js	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
@@ -0,0 +1,69 @@
+import axios from 'axios'
+import React, { Component } from 'react'
+import HeaderComponent from '../HeaderComponent/HeaderComponent'
+import ScrapperInfoComponent from './ScrapperInfoComponent'
+import "./ScrappersComponent.css"
+
+export class ScrappersComponent extends Component {
+    constructor(props) {
+      super(props)
+    
+      this.state = {
+        scrapperinfos: []
+      }
+
+    }
+
+    componentDidMount(){
+        var config = {
+            method: 'get',
+            url: '/scrapperinfo',
+            headers: { 
+              'Authorization': 'Bearer '+localStorage.getItem('token')
+            }
+          };
+          
+          axios(config)
+          .then(response => {
+            this.setState({
+                scrapperinfos: response.data
+            })
+          })
+          .catch(error => {
+            console.log(error);
+          });
+    }
+    
+  render() {
+    return (
+        <div className='scrappers-section-main'>
+            <HeaderComponent/>
+            <div className='scrappers-section-header'>
+            <h1 className='scrappers-section-header-text'>
+                Преземање на содржина
+            </h1>
+            </div>
+
+            <div className='scrappers-info-section'>
+                <table cellPadding={20} className='scrappers-section-table'>
+                    <thead className='scrappers-section-table-head'>
+                    <tr>
+                    <th>Продавница</th>
+                    <th>Статус</th>
+                    <th>Датум</th>
+                    </tr>
+                    </thead>
+                    <tbody>
+                    {
+                        this.state.scrapperinfos.map((info,idx) => <ScrapperInfoComponent key={idx} id={info.id} store={info.store} 
+                        status={info.status} recievedAt={info.recievedAt}/>) 
+                    }
+                    </tbody>
+                </table>
+            </div>
+        </div>
+    )
+  }
+}
+
+export default ScrappersComponent
Index: phonelux-frontend/src/components/SuperAdminComponent/SuperAdminComponent.js
===================================================================
--- phonelux-frontend/src/components/SuperAdminComponent/SuperAdminComponent.js	(revision ffd50db1e5e2b9839ba7546d8ca44b600150bd71)
+++ phonelux-frontend/src/components/SuperAdminComponent/SuperAdminComponent.js	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
@@ -69,13 +69,4 @@
 
     componentDidMount(){
-      // if(!localStorage.getItem('token'))
-      // {
-      //     window.location.href = "/"
-      // }
-
-      // if(this.context.role != 'SUPERADMIN')
-      // {
-      //     window.location.href = "/"
-      // }
       this.getUsers()
     }
Index: phonelux_scrappers/.idea/misc.xml
===================================================================
--- phonelux_scrappers/.idea/misc.xml	(revision ffd50db1e5e2b9839ba7546d8ca44b600150bd71)
+++ phonelux_scrappers/.idea/misc.xml	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
@@ -1,4 +1,4 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <project version="4">
-  <component name="ProjectRootManager" version="2" project-jdk-name="Python 3.8 (phonelux_scrappers) (2)" project-jdk-type="Python SDK" />
+  <component name="ProjectRootManager" version="2" project-jdk-name="Python 3.9 (phonelux_scrappers)" project-jdk-type="Python SDK" />
 </project>
Index: phonelux_scrappers/.idea/phonelux_scrappers.iml
===================================================================
--- phonelux_scrappers/.idea/phonelux_scrappers.iml	(revision ffd50db1e5e2b9839ba7546d8ca44b600150bd71)
+++ phonelux_scrappers/.idea/phonelux_scrappers.iml	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
@@ -5,5 +5,5 @@
       <excludeFolder url="file://$MODULE_DIR$/venv" />
     </content>
-    <orderEntry type="inheritedJdk" />
+    <orderEntry type="jdk" jdkName="Python 3.9 (phonelux_scrappers)" jdkType="Python SDK" />
     <orderEntry type="sourceFolder" forTests="false" />
   </component>
Index: phonelux_scrappers/outputfile.txt
===================================================================
--- phonelux_scrappers/outputfile.txt	(revision ffd50db1e5e2b9839ba7546d8ca44b600150bd71)
+++ phonelux_scrappers/outputfile.txt	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
@@ -1,588 +1,0 @@
-Samsung Galaxy A13
-9990
-Apple iPhone 13
-47499
-Apple iPhone 13 Pro
-62690
-Apple iPhone 12
-32690
-Samsung Galaxy S22 Ultra 5G
-60000
-Apple iPhone 11
-23490
-Samsung Galaxy S22 5G
-43000
-Samsung Galaxy S21 FE
-33800
-Samsung Galaxy A33 5G
-17490
-Apple iPhone 13 Pro Max
-68890
-Samsung Galaxy A32
-13900
-Samsung Galaxy S22+ 5G
-50150
-Apple iPhone 14 Pro
-71890
-Xiaomi 12
-28999
-Samsung Galaxy A53 5G
-20290
-Xiaomi Redmi Note 11
-11990
-Xiaomi Redmi 9A
-6490
-Huawei Nova 9
-22900
-Samsung Galaxy A12
-9500
-Samsung Galaxy Z Flip 4
-58400
-Apple iPhone 14
-1
-Apple iPhone 13 Mini
-42990
-Samsung Galaxy A52s
-18500
-Xiaomi Redmi 10C
-9990
-Apple iPhone SE
-24600
-Samsung Galaxy A03s
-6790
-Samsung Galaxy A22 5G
-11700
-Xiaomi Mi 11 Lite
-18500
-Samsung Galaxy A23
-11790
-Apple iPhone 14 Pro Max
-99999
-Samsung Galaxy Z Fold 4
-98400
-Samsung Galaxy A03
-8490
-Huawei nova Y70
-13699
-Samsung Galaxy Z Flip3 5G
-38990
-Huawei Nova 8i
-19999
-Samsung Galaxy Z Fold 3 5G
-69990
-Xiaomi 11 Lite 5G NE
-24999
-Xiaomi Redmi Note 11 Pro
-16590
-Xiaomi Mi 11T 5G
-23400
-Huawei Nova 9 SE
-22999
-Xiaomi Redmi 9
-9399
-Huawei nova Y90
-15999
-Apple iPhone SE (2022)
-28290
-Xiaomi Poco X3
-13999
-OnePlus Nord N10 5G
-18999
-Samsung Galaxy A52
-18190
-Xiaomi Redmi Note 10
-13999
-Blackview A70 Pro
-7399
-Realme C11
-6999
-Honor 50 Lite
-11990
-Xiaomi Poco F3
-21500
-Huawei P50 Pro
-58400
-Xiaomi Redmi 9C
-6990
-Xiaomi 12X
-29900
-Blackview A55
-5999
-OnePlus Nord CE
-26999
-Vivo Y72 5G
-18999
-Xiaomi Mi 11T Pro 5G
-33800
-Xiaomi Poco M3
-12290
-Vivo V21 5G
-24999
-Vivo Y33s
-15999
-Samsung Galaxy A02s
-8890
-Motorola Moto G31
-12899
-Xiaomi Mi 11 Lite 5G NE
-25999
-Alcatel 2019G
-2290
-Samsung Galaxy S21+ 5G
-41790
-Xiaomi Redmi Note 10 5G
-13490
-Xiaomi 11T
-31999
-Alcatel 1SE
-6290
-Alcatel 1066D
-1299
-Xiaomi Redmi Note 9
-9990
-Xiaomi Redmi Note 11 Pro+ 5G
-27999
-Blackview A80
-6499
-Motorola Moto G22
-11299
-Xiaomi Poco M3 Pro 5G
-12999
-Xiaomi Redmi Note 9S
-11900
-Blackview A70
-7299
-Xiaomi Redmi 9AT
-6999
-Doogee X95
-5999
-Xiaomi Redmi Note 10 Pro
-15990
-Motorola Edge 20
-30999
-Motorola Moto G60
-16999
-Honor 50
-23400
-Apple iPhone 12 Pro Max
-66500
-Apple iPhone 11 Pro Max
-32690
-Nokia 105 (2017)
-1490
-Samsung Galaxy S21 Ultra 5G
-52290
-Motorola Moto E7 Power
-8999
-Apple iPhone 11 Pro
-27790
-Alcatel 1
-5499
-Xiaomi Poco X3 Pro
-15400
-Xiaomi Redmi Note 9 Pro
-15499
-Blackview A60 Pro
-6299
-Blackview Oscal C20
-5249
-Realme C21Y
-7999
-Vivo Y21
-11899
-Samsung Galaxy A20e
-9699
-Vivo Y21s
-13999
-Nokia 3310
-3399
-Xiaomi Mi 10 Lite 5G
-15990
-Xiaomi Mi Note 10 Lite
-19700
-Samsung Galaxy S21 5G
-38999
-Xiaomi Mi 11 Ultra
-53490
-Motorola Moto G10
-10299
-Alcatel 3026X
-4499
-Samsung Galaxy S20 FE
-22690
-Xiaomi Redmi Note 11S
-19999
-Doogee X96
-7699
-Alcatel 2053D
-2999
-Alcatel 3025X
-3999
-Doogee X93
-5999
-Vivo Y20s
-12499
-Infinix Hot 11
-10499
-Infinix Smart 6
-7999
-Panasonic KX-TU160
-3999
-Xiaomi 12 Pro
-54150
-Xiaomi Mi 10T Pro 5G
-29900
-Xiaomi Poco X4 Pro 5G
-17200
-Apple iPhone 12 Pro
-61590
-Google Pixel 6 Pro
-61500
-Samsung Galaxy Note 20
-36900
-Xiaomi Poco M4 Pro 5G
-15999
-OnePlus 10 Pro 5G
-52290
-Wiko View
-5990
-Samsung Galaxy A72
-23300
-Alcatel 2003D
-2199
-Xiaomi Redmi Note 10 Pro Max
-16490
-Trevi Max 10
-1599
-Honor X8
-16499
-Nokia 6310
-5490
-Xiaomi 11T Pro
-47999
-Samsung Galaxy A02
-8000
-Samsung Galaxy A40
-11999
-Motorola Moto G71
-18999
-Samsung Galaxy Note 20 Ultra 5G
-50390
-Samsung Galaxy A73 5G
-27000
-Xiaomi Redmi Note 10S
-14999
-Blackview A60
-4999
-Blackview A80 Plus
-8999
-Realme C21
-8999
-Motorola Moto G51
-14999
-Xiaomi Mi 10T Lite 5G
-15390
-OnePlus 9 Pro
-46200
-Cubot P30
-9999
-Cubot Note 20
-8999
-Motorola Moto G30
-13999
-Asus ROG Phone 5
-46100
-Tesla Smartphone 3.4
-4999
-Oppo F11 Pro
-16600
-Honor View 20
-36800
-Honor 70
-32999
-Realme 8i
-15999
-OnePlus 9
-30800
-Samsung Galaxy M12
-9500
-Samsung Galaxy A31
-16999
-Xiaomi Redmi 9i
-8890
-OnePlus 7T Pro McLaren Edition
-36900
-OnePlus 7T
-27700
-Oppo A9
-16600
-Nokia 8110 4G
-4300
-Blackberry Porsche Design P9981
-19000
-Asus ROG Phone 2
-32000
-Xiaomi Redmi Note 9T 5G
-12290
-Motorola Edge 20 Pro
-44999
-Xiaomi Poco X3 GT
-17200
-Nokia 105 (2019)
-1999
-Apple iPhone 12 Mini
-34999
-Samsung Galaxy Z Fold 2
-141499
-Samsung Galaxy M32
-14100
-Alcatel 1S
-6390
-Doogee X95 Pro
-7399
-Doogee S58 Pro
-12499
-Motorola Moto G100
-30999
-Motorola Moto G200
-30999
-Realme 9i
-16699
-Realme 9 Pro+
-27999
-Realme GT Master
-20300
-Alcatel 1C
-4499
-Trevi Flex 50 GT
-2199
-Huawei Honor 8X Max
-12300
-Huawei Honor 9X Lite
-11000
-Oppo A94 5G
-15390
-MeanIT Veteran I
-1599
-MeanIT Senior Flip XL
-3399
-Denver B242
-2999
-Asus ROG Phone 3
-36900
-Huawei Y Max
-12300
-Apple iPhone X
-15990
-Xiaomi Redmi Note 11T 5G
-18500
-Motorola G60
-17999
-OnePlus 8 Pro
-40000
-Samsung Galaxy M52 5G
-21500
-Xiaomi Mi 12 Pro 5G
-54100
-Alcatel 1066G
-1190
-Google Pixel 6
-40000
-Wiko View Max
-7990
-Xiaomi Black Shark 4
-29990
-Tcl 20L+
-15999
-Xiaomi Poco F4 GT
-47999
-Samsung Galaxy A51
-18999
-Samsung Galaxy A50
-18999
-Xiaomi Mi A2 Lite
-8999
-Xiaomi Mi Play
-9999
-Xiaomi Mi 6
-9999
-Xiaomi Mi Max 2
-6999
-Xiaomi Mi A3
-8999
-Samsung Galaxy A30s
-13999
-Samsung Galaxy A41
-16999
-Alcatel Pixi 4 Power Plus
-5999
-Honor X7
-13999
-Energizer Energy E20
-1999
-Energizer Energy E241S
-2299
-Energizer Hardcase H240S
-3999
-Energizer Power Max P550S
-4999
-Huawei Mate 10 Lite
-9999
-Samsung Galaxy M02s
-9500
-Xiaomi Mi 10T 5G
-24500
-Xiaomi Redmi 8A
-7400
-Huawei P30 Pro
-29500
-Huawei P40 Lite E
-9200
-Apple iPhone XS
-17890
-Apple iPhone XS Max
-21590
-Nokia C21
-8999
-Alcatel 1S (2021)
-8999
-Huawei P50 Pocket
-76900
-CAT B26
-5999
-Cubot J9
-5299
-Samsung Galaxy A21s
-11199
-Xiaomi Mi A2
-13799
-Alcatel 1V
-4399
-Trevi Phablet 5Q2
-4599
-Energizer Energy E10
-1299
-Huawei P20
-24999
-Honor 9 Lite
-7999
-Huawei Honor 8X
-16999
-Honor 10 Lite
-8499
-Wiko Power U20
-8999
-Wiko Y62
-6999
-Vivax Pro M1
-4499
-Vivax Fun S10
-3999
-Vivax Fun S20
-4999
-Vivax Point X2
-5999
-Vivax Fly 5 Lite
-7499
-Vivax Fly V1
-8999
-Vivax Point X502
-4499
-Vivax Point X1
-6999
-Vivax Fun S1
-2999
-Oppo A15s
-8999
-Oppo Reno4 Z 5G
-18999
-Oppo Reno5 5G
-24999
-Oppo Reno4 Lite
-15999
-Oppo Find X5 Lite
-24590
-Denver B183
-1499
-Noa N2
-7499
-Noa Sprint 4G
-5499
-Samsung Galaxy J7
-8999
-Manta MS1701
-1099
-Huawei P10 Lite
-11999
-Xiaomi Redmi Note 10T 5G
-12300
-Nokia 6300 4G
-4000
-Tcl 306
-9999
-Oppo Find X3 Lite
-16000
-Wiko Lenny 5
-4290
-Doro 2404
-4499
-AllCall Smooth 4G
-5499
-Realme C25Y
-10999
-Motorola Moto G41
-16999
-Honor Magic4 Lite
-21999
-Huawei Honor 7A
-5999
-Honor 20 Lite
-11299
-Panasonic KX-TU155
-4699
-Vivax Fly 6
-5999
-Tesla Feature 3
-1599
-Noa Fresh 4G
-2999
-Samsung Galaxy F12
-9200
-Nokia 106
-1999
-OnePlus Nord
-22999
-Infinix Hot 12i
-9999
-Doro 1370
-4999
-Apple iPhone XR
-17290
-Doogee X96 Pro
-8799
-Samsung Galaxy F62
-18400
-OnePlus 9R
-27700
-Alcatel 3080G
-4499
-Motorola Moto E20
-8999
-AllCall Brother 4G
-5499
-Realme 8
-14999
-Huawei Honor 7S
-7599
-Motorola Moto G50
-16999
-Nokia 110
-2299
-Motorola Edge 30
-31999
-Realme 9 Pro
-22499
-Nokia 8
-14999
-OnePlus Nord N100
-10499
Index: phonelux_scrappers/phones_image_setter.py
===================================================================
--- phonelux_scrappers/phones_image_setter.py	(revision ffd50db1e5e2b9839ba7546d8ca44b600150bd71)
+++ phonelux_scrappers/phones_image_setter.py	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
@@ -13,10 +13,19 @@
     offers = list(json.loads(requests.get('http://localhost:8080/phones/offers/' + phone_id).text))
 
-    offers = list(filter(lambda offer: offer['image_url'] is not None, offers))
+# remove mobitech condition
+    offers = list(filter(lambda offer: offer['image_url'] is not None and 'mobitech' not in offer['image_url']
+                         , offers))
 
     image_url = None
 
+    if len(offers) > 1:
+        image_url = offers[1]['image_url']
+
     if len(offers) > 0:
         image_url = offers[0]['image_url']
+
+    # print('phone :'+str(phone))
+    # print(image_url)
+    # print('------------------------------')
 
     phone['image_url'] = image_url
Index: phonelux_scrappers/phones_model_setter.py
===================================================================
--- phonelux_scrappers/phones_model_setter.py	(revision ffd50db1e5e2b9839ba7546d8ca44b600150bd71)
+++ phonelux_scrappers/phones_model_setter.py	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
@@ -23,4 +23,3 @@
             break
     if not flag:
-        # requests.delete('http://localhost:8080/phoneoffer/deleteoffer/' + str(offer['id']))
-        print('delete offer id '+str(offer['id']))
+        requests.delete('http://localhost:8080/phoneoffer/deleteoffer/' + str(offer['id']))
Index: phonelux_scrappers/scrappers/a1_scrapper.py
===================================================================
--- phonelux_scrappers/scrappers/a1_scrapper.py	(revision ffd50db1e5e2b9839ba7546d8ca44b600150bd71)
+++ phonelux_scrappers/scrappers/a1_scrapper.py	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
@@ -1,2 +1,3 @@
+import traceback
 import unicodedata
 from datetime import datetime
@@ -18,144 +19,174 @@
 is_validated = False
 
-# A1 phone offers that are already in database
+# Call to read the configuration file and connect to database
+cinfo = config_read.get_databaseconfig("../postgresdb.config")
+db_connection = psycopg2.connect(
+    database=cinfo[0],
+    host=cinfo[1],
+    user=cinfo[2],
+    password=cinfo[3]
+)
+cur = db_connection.cursor()
 
-offers = json.loads(unicodedata.normalize('NFKD', requests.get('http://localhost:8080/phoneoffer/shop/a1').text))
+try:
+    # A1 phone offers that are already in database
+    offers = json.loads(unicodedata.normalize('NFKD', requests.get('http://localhost:8080/phoneoffer/shop/a1').text))
 
-database_offers = []
+    database_offers = []
 
-for offer in offers:
-    phoneOffer = PhoneOffer(offer['id'], offer['offer_shop'], offer['offer_name'], offer['price'],
-                            offer['ram_memory'],
-                            offer['rom_memory'], offer['color'], offer['front_camera'], offer['back_camera'],
-                            offer['chipset'], offer['battery'], offer['operating_system'], offer['cpu'],
-                            offer['image_url'],
-                            offer['offer_url'], offer['last_updated'], offer['is_validated'],
-                            offer['offer_description'],
-                            offer['offer_shop_code'])
-    database_offers.append(phoneOffer)
+    for offer in offers:
+        phoneOffer = PhoneOffer(offer['id'], offer['offer_shop'], offer['offer_name'], offer['price'],
+                                offer['ram_memory'],
+                                offer['rom_memory'], offer['color'], offer['front_camera'], offer['back_camera'],
+                                offer['chipset'], offer['battery'], offer['operating_system'], offer['cpu'],
+                                offer['image_url'],
+                                offer['offer_url'], offer['last_updated'], offer['is_validated'],
+                                offer['offer_description'],
+                                offer['offer_shop_code'])
+        database_offers.append(phoneOffer)
 
-a1_url = 'https://www.a1.mk/webshop/mk/phones'
+    a1_url = 'https://www.a1.mk/webshop/mk/phones'
 
-response1 = requests.get(a1_url)
-soup1 = BeautifulSoup(response1.content, 'html.parser')
+    response1 = requests.get(a1_url)
+    soup1 = BeautifulSoup(response1.content, 'html.parser')
 
-phones = soup1.find('main', {'class', 'gsm-advisor-grid phones'}).find('div', {'class', 'd-flex'}) \
-    .find_all('div', {'class', 'dvc-idtfr by4'})
+    phones = soup1.find('main', {'class', 'gsm-advisor-grid phones'}).find('div', {'class', 'd-flex'}) \
+        .find_all('div', {'class', 'dvc-idtfr by4'})
 
-new_offers = []
+    new_offers = []
 
-for phone in phones:
-    brand = phone.get('data-brand').strip()
-    offer_name = brand + " " + phone.get('data-model').strip()
+    for phone in phones:
+        brand = phone.get('data-brand').strip()
+        offer_name = brand + " " + phone.get('data-model').strip()
 
-    # if brand not in offer_name:
-    #     offer_name = brand+" "+offer_name
+        # if brand not in offer_name:
+        #     offer_name = brand+" "+offer_name
 
-    offer_shop_code = phone.get('data-productid').strip()
-    offer_url = phone.find('a', {'class', 'device-link'}).get('href')
-    image_url = phone.get('data-image')
+        offer_shop_code = phone.get('data-productid').strip()
+        offer_url = phone.find('a', {'class', 'device-link'}).get('href')
+        image_url = phone.get('data-image')
 
-    response2 = requests.get(offer_url)
-    soup2 = BeautifulSoup(response2.content, 'html.parser')
+        response2 = requests.get(offer_url)
+        soup2 = BeautifulSoup(response2.content, 'html.parser')
 
-    temp_prices = soup2.find('div', {'class': 'ured-tabs-content'}) \
-        .find('div', {'class': 'cenovnik-secondary d-flex justify-content-between'}).find_all('div')
+        temp_prices = soup2.find('div', {'class': 'ured-tabs-content'}) \
+            .find('div', {'class': 'cenovnik-secondary d-flex justify-content-between'}).find_all('div')
 
-    # offer price
-    price = None
-    for temp_price in temp_prices:
-        if 'Цена само за уред' in temp_price.get_text().strip():
-            price = int(temp_price.get_text().replace('Цена само за уред', '')
-                        .replace('Одбери', '').replace('денари', '').replace('.', '').strip())
+        # offer price
+        price = None
+        for temp_price in temp_prices:
+            if 'Цена само за уред' in temp_price.get_text().strip():
+                price = int(temp_price.get_text().replace('Цена само за уред', '')
+                            .replace('Одбери', '').replace('денари', '').replace('.', '').strip())
 
-    colors_section = soup2.find('div', {'id': 'hero'}).find('div', {'class': 'widget'}).find_all('label')
+        colors_section = soup2.find('div', {'id': 'hero'}).find('div', {'class': 'widget'}).find_all('label')
 
-    temp_colors = []
-    for color_section in colors_section:
-        temp_colors.append(color_section.get('data-content'))
+        temp_colors = []
+        for color_section in colors_section:
+            temp_colors.append(color_section.get('data-content'))
 
-    color = ','.join(temp_colors)  # colors available for the offer
+        color = ','.join(temp_colors)  # colors available for the offer
 
-    phone_description = soup2.find('div', {'class': 'desc section'}).find('p').get_text().strip()
+        phone_description = soup2.find('div', {'class': 'desc section'}).find('p').get_text().strip()
 
-    table_rows = soup2.find('table', {'class': 'table karakteristiki'}).find_all('tr')
+        table_rows = soup2.find('table', {'class': 'table karakteristiki'}).find_all('tr')
 
-    back_camera = None
-    operating_system = None
-    cpu = None
-    rom_memory = None
-    ram_memory = None
-    battery = None
-    front_camera = None
-    chipset = None
-    offer_description = None
+        back_camera = None
+        operating_system = None
+        cpu = None
+        rom_memory = None
+        ram_memory = None
+        battery = None
+        front_camera = None
+        chipset = None
+        offer_description = None
 
-    for row in table_rows:
-        if 'Камера' in row.get_text().strip():
-            back_camera = row.get_text().replace('Камера', '').strip()
+        for row in table_rows:
+            if 'Камера' in row.get_text().strip():
+                back_camera = row.get_text().replace('Камера', '').strip()
 
-        if 'Оперативен систем' in row.get_text().strip():
-            operating_system = row.get_text().replace('Оперативен систем', '').strip()
+            if 'Оперативен систем' in row.get_text().strip():
+                operating_system = row.get_text().replace('Оперативен систем', '').strip()
 
-        if 'CPU' in row.get_text().strip():
-            cpu = row.get_text().replace('CPU', '').strip()
+            if 'CPU' in row.get_text().strip():
+                cpu = row.get_text().replace('CPU', '').strip()
 
-        if 'Вградена меморија' in row.get_text().strip():
-            rom_memory = row.get_text().replace('Вградена меморија', '').strip()
+            if 'Вградена меморија' in row.get_text().strip():
+                rom_memory = row.get_text().replace('Вградена меморија', '').strip()
 
-        if 'RAM меморија' in row.get_text().strip():
-            ram_memory = row.get_text().replace('RAM меморија', '').strip()
+            if 'RAM меморија' in row.get_text().strip():
+                ram_memory = row.get_text().replace('RAM меморија', '').strip()
 
-        if 'Батерија' in row.get_text().strip():
-            battery = row.get_text().replace('Батерија', '').strip()
+            if 'Батерија' in row.get_text().strip():
+                battery = row.get_text().replace('Батерија', '').strip()
 
-        if 'Предна камера' in row.get_text().strip():
-            front_camera = row.get_text().replace('Предна камера', '').strip()
+            if 'Предна камера' in row.get_text().strip():
+                front_camera = row.get_text().replace('Предна камера', '').strip()
 
-    new_offers.append(PhoneOffer(offer_shop, offer_name, price, ram_memory, rom_memory,
-                                 color, front_camera, back_camera, chipset, battery, operating_system, cpu, image_url,
-                                 offer_url, last_updated, is_validated, offer_description, offer_shop_code))
+        new_offers.append(PhoneOffer(offer_shop, offer_name, price, ram_memory, rom_memory,
+                                     color, front_camera, back_camera, chipset, battery, operating_system, cpu,
+                                     image_url,
+                                     offer_url, last_updated, is_validated, offer_description, offer_shop_code))
 
-for new_offer in new_offers:
-    flag = False
-    flag_price = False
-    offer_id = None
+    for new_offer in new_offers:
+        flag = False
+        flag_price = False
+        offer_id = None
+
+        for old_offer in database_offers:
+
+            if new_offer.offer_shop_code == old_offer.offer_shop_code:
+                flag = True
+                if new_offer.price != old_offer.price:
+                    flag_price = True
+                    offer_id = old_offer.offer_id
+
+        if flag:
+            # print('ALREADY IN DATABASE')
+            # print(new_offer)
+            # if it's already in database, check PRICE and if it's changed, change it !!!!!!
+            if flag_price:
+                print('PRICE CHANGED!')  # CHANGE PRICE
+                print('offer id: ' + str(offer_id))
+                headers = {'Content-type': 'application/json'}
+                requests.put(
+                    'http://localhost:8080/phoneoffer/' + str(offer_id) + '/changeprice/' + str(new_offer.price),
+                    headers=headers)
+        else:
+            print('ADDED')  # ADD OFFER
+            print(new_offer)
+            headers = {'Content-type': 'application/json'}
+            requests.post('http://localhost:8080/phoneoffer/addoffer', headers=headers,
+                          data=json.dumps(new_offer.__dict__,
+                                          default=str))
+
+    print('------------------------------------')
 
     for old_offer in database_offers:
+        flag = False
+        for new_offer in new_offers:
+            if old_offer.offer_shop_code == new_offer.offer_shop_code:
+                flag = True
 
-        if new_offer.offer_shop_code == old_offer.offer_shop_code:
-            flag = True
-            if new_offer.price != old_offer.price:
-                flag_price = True
-                offer_id = old_offer.offer_id
-
-    if flag:
-        # print('ALREADY IN DATABASE')
-        # print(new_offer)
-        # if it's already in database, check PRICE and if it's changed, change it !!!!!!
-        if flag_price:
-            print('PRICE CHANGED!')  # CHANGE PRICE
-            print('offer id: ' + str(offer_id))
-            headers = {'Content-type': 'application/json'}
-            requests.put('http://localhost:8080/phoneoffer/' + str(offer_id) + '/changeprice/' + str(new_offer.price),
-                         headers=headers)
-    else:
-        print('ADDED')  # ADD OFFER
-        print(new_offer)
-        headers = {'Content-type': 'application/json'}
-        requests.post('http://localhost:8080/phoneoffer/addoffer', headers=headers, data=json.dumps(new_offer.__dict__,
-                                                                                                    default=str))
-
-print('------------------------------------')
-
-for old_offer in database_offers:
-    flag = False
-    for new_offer in new_offers:
-        if old_offer.offer_shop_code == new_offer.offer_shop_code:
-            flag = True
-
-    if not flag:
-        print('OFFER DELETED')
-        print(old_offer)
-        # DELETE OFFER
-        requests.delete('http://localhost:8080/phoneoffer/deleteoffer/' + str(old_offer.offer_id))
+        if not flag:
+            print('OFFER DELETED')
+            print(old_offer)
+            # DELETE OFFER
+            requests.delete('http://localhost:8080/phoneoffer/deleteoffer/' + str(old_offer.offer_id))
+except Exception:
+    traceback.print_exc()
+    insert_script = 'INSERT INTO scrapper_info (store, recieved_at, status)' \
+                    ' VALUES (%s, %s, %s);'
+    insert_value = (offer_shop, last_updated, 'failed')
+    cur.execute(insert_script, insert_value)
+    db_connection.commit()
+    cur.close()
+    db_connection.close()
+else:
+    insert_script = 'INSERT INTO scrapper_info (store, recieved_at, status)' \
+                    ' VALUES (%s, %s, %s);'
+    insert_value = (offer_shop, last_updated, 'success')
+    cur.execute(insert_script, insert_value)
+    db_connection.commit()
+    cur.close()
+    db_connection.close()
Index: phonelux_scrappers/scrappers/akcija_scrapper.py
===================================================================
--- phonelux_scrappers/scrappers/akcija_scrapper.py	(revision ffd50db1e5e2b9839ba7546d8ca44b600150bd71)
+++ phonelux_scrappers/scrappers/akcija_scrapper.py	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
@@ -1,3 +1,4 @@
 import json
+import traceback
 from datetime import datetime
 
@@ -18,118 +19,146 @@
 is_validated = False
 
-# Akcija phone offers that are already in database
+# Call to read the configuration file and connect to database
+cinfo = config_read.get_databaseconfig("../postgresdb.config")
+db_connection = psycopg2.connect(
+    database=cinfo[0],
+    host=cinfo[1],
+    user=cinfo[2],
+    password=cinfo[3]
+)
+cur = db_connection.cursor()
 
-offers = json.loads(unicodedata.normalize('NFKD', requests.get('http://localhost:8080/phoneoffer/shop/akcija').text))
+try:
+    # Akcija phone offers that are already in database
+    offers = json.loads(unicodedata.normalize('NFKD', requests.get('http://localhost:8080/phoneoffer/shop/akcija').text))
 
-database_offers = []
+    database_offers = []
 
-for offer in offers:
-    phoneOffer = PhoneOffer(offer['id'], offer['offer_shop'], offer['offer_name'], offer['price'],
-                            offer['ram_memory'],
-                            offer['rom_memory'], offer['color'], offer['front_camera'], offer['back_camera'],
-                            offer['chipset'], offer['battery'], offer['operating_system'], offer['cpu'],
-                            offer['image_url'],
-                            offer['offer_url'], offer['last_updated'], offer['is_validated'],
-                            offer['offer_description'],
-                            offer['offer_shop_code'])
-    database_offers.append(phoneOffer)
+    for offer in offers:
+        phoneOffer = PhoneOffer(offer['id'], offer['offer_shop'], offer['offer_name'], offer['price'],
+                                offer['ram_memory'],
+                                offer['rom_memory'], offer['color'], offer['front_camera'], offer['back_camera'],
+                                offer['chipset'], offer['battery'], offer['operating_system'], offer['cpu'],
+                                offer['image_url'],
+                                offer['offer_url'], offer['last_updated'], offer['is_validated'],
+                                offer['offer_description'],
+                                offer['offer_shop_code'])
+        database_offers.append(phoneOffer)
 
-new_offers = []
+    new_offers = []
 
-i = 0
-while i <= 20:
-    akcija_url = "https://akcija.com.mk/listing/" + str(i) + "?category=mobilnitelefoni"
-    response1 = requests.get(akcija_url)
-    response1.encoding = 'utf-8'
-    soup1 = BeautifulSoup(response1.text, 'html.parser')
+    i = 0
+    while i <= 20:
+        akcija_url = "https://akcija.com.mk/listing/" + str(i) + "?category=mobilnitelefoni"
+        response1 = requests.get(akcija_url)
+        response1.encoding = 'utf-8'
+        soup1 = BeautifulSoup(response1.text, 'html.parser')
 
-    phones = soup1.find_all('div', {'class', 'product-item__body pb-xl-2'})
+        phones = soup1.find_all('div', {'class', 'product-item__body pb-xl-2'})
 
-    for phone in phones:
-        offer_name = phone.find('h5', {'class': 'mb-1 product-item__title'}).find('a') \
-            .get_text().replace('Паметен телефон', '').strip()
-        brand = offer_name.split(' ')[0]
+        for phone in phones:
+            offer_name = phone.find('h5', {'class': 'mb-1 product-item__title'}).find('a') \
+                .get_text().replace('Паметен телефон', '').strip()
+            brand = offer_name.split(' ')[0]
 
-        if brand not in offer_name:
-            offer_name = brand + " " + offer_name
+            if brand not in offer_name:
+                offer_name = brand + " " + offer_name
 
-        offer_url = phone.find('h5', {'class': 'mb-1 product-item__title'}).find('a').get('href')
-        image_url = phone.find('div', {'class', 'mb-2'}).find('img').get('src')
-        price = int(phone.find('div', {'class', 'flex-center-between mb-1 pt-xl-2'}) \
-                    .find('ins').get_text().split(' ')[0].strip())
+            offer_url = phone.find('h5', {'class': 'mb-1 product-item__title'}).find('a').get('href')
+            image_url = phone.find('div', {'class', 'mb-2'}).find('img').get('src')
+            price = int(phone.find('div', {'class', 'flex-center-between mb-1 pt-xl-2'}) \
+                        .find('ins').get_text().split(' ')[0].strip())
 
-        response2 = requests.get(offer_url)
-        response2.encoding = 'utf-8'
-        soup2 = BeautifulSoup(response2.text, 'html.parser')
+            response2 = requests.get(offer_url)
+            response2.encoding = 'utf-8'
+            soup2 = BeautifulSoup(response2.text, 'html.parser')
 
-        back_camera = None
-        operating_system = None
-        chipset = None
-        battery = None
-        ram_memory = None
-        rom_memory = None
-        cpu = None
-        front_camera = None
-        color = None
-        offer_shop_code = None
+            back_camera = None
+            operating_system = None
+            chipset = None
+            battery = None
+            ram_memory = None
+            rom_memory = None
+            cpu = None
+            front_camera = None
+            color = None
+            offer_shop_code = None
 
-        specifications = soup2.find('main', {'id': 'content'}) \
-            .find_all('div', {'class', 'container'})[1].find('div', {'class', 'mb-14'}) \
-            .find('div', {'class', 'col-md-6 col-lg-4 col-xl-4 mb-md-6 mb-lg-0'}).find_all('p')
+            specifications = soup2.find('main', {'id': 'content'}) \
+                .find_all('div', {'class', 'container'})[1].find('div', {'class', 'mb-14'}) \
+                .find('div', {'class', 'col-md-6 col-lg-4 col-xl-4 mb-md-6 mb-lg-0'}).find_all('p')
 
-        offer_description = ''
-        for specification in specifications:
-            if 'Код за нарачка' in str(specification.get_text(separator='\n').replace('NBSP', '').strip()):
-                continue
-            offer_description += unicodedata.normalize('NFKD',
-                                                       str(specification.get_text(separator='\n').strip())) + "\n"
+            offer_description = ''
+            for specification in specifications:
+                if 'Код за нарачка' in str(specification.get_text(separator='\n').replace('NBSP', '').strip()):
+                    continue
+                offer_description += unicodedata.normalize('NFKD',
+                                                           str(specification.get_text(separator='\n').strip())) + "\n"
 
-        new_offers.append(PhoneOffer(offer_shop, offer_name, price, ram_memory, rom_memory,
-                                     color, front_camera, back_camera, chipset, battery, operating_system, cpu,
-                                     image_url,
-                                     offer_url, last_updated, is_validated, offer_description, offer_shop_code))
-    i += 20
+            new_offers.append(PhoneOffer(offer_shop, offer_name, price, ram_memory, rom_memory,
+                                         color, front_camera, back_camera, chipset, battery, operating_system, cpu,
+                                         image_url,
+                                         offer_url, last_updated, is_validated, offer_description, offer_shop_code))
+        i += 20
 
-for new_offer in new_offers:
-    flag = False
-    flag_price = False
-    offer_id = None
+    for new_offer in new_offers:
+        flag = False
+        flag_price = False
+        offer_id = None
+
+        for old_offer in database_offers:
+
+            if new_offer.offer_name == old_offer.offer_name:
+                flag = True
+                if new_offer.price != old_offer.price:
+                    flag_price = True
+                    offer_id = old_offer.offer_id
+
+        if flag:
+            # print('ALREADY IN DATABASE')
+            # print(new_offer)
+            # if it's already in database, check PRICE and if it's changed, change it !!!!!!
+            if flag_price:
+                print('PRICE CHANGED!')  # CHANGE PRICE
+                print('offer id: ' + str(offer_id))
+                headers = {'Content-type': 'application/json'}
+                requests.put('http://localhost:8080/phoneoffer/' + str(offer_id) + '/changeprice/' + str(new_offer.price),
+                             headers=headers)
+        else:
+            print('ADDED')  # ADD OFFER
+            print(new_offer)
+            headers = {'Content-type': 'application/json'}
+            requests.post('http://localhost:8080/phoneoffer/addoffer',
+                          headers=headers, data=json.dumps(new_offer.__dict__, default=str))
+
+    print('------------------------------------')
 
     for old_offer in database_offers:
+        flag = False
+        for new_offer in new_offers:
+            if old_offer.offer_name == new_offer.offer_name:
+                flag = True
 
-        if new_offer.offer_name == old_offer.offer_name:
-            flag = True
-            if new_offer.price != old_offer.price:
-                flag_price = True
-                offer_id = old_offer.offer_id
+        if not flag:
+            print('OFFER DELETED')
+            print(old_offer)
+            # DELETE OFFER
+            requests.delete('http://localhost:8080/phoneoffer/deleteoffer/' + str(old_offer.offer_id))
+except Exception:
+    traceback.print_exc()
+    insert_script = 'INSERT INTO scrapper_info (store, recieved_at, status)' \
+                    ' VALUES (%s, %s, %s);'
+    insert_value = (offer_shop, last_updated, 'failed')
+    cur.execute(insert_script, insert_value)
+    db_connection.commit()
+    cur.close()
+    db_connection.close()
+else:
+    insert_script = 'INSERT INTO scrapper_info (store, recieved_at, status)' \
+                    ' VALUES (%s, %s, %s);'
+    insert_value = (offer_shop, last_updated, 'success')
+    cur.execute(insert_script, insert_value)
+    db_connection.commit()
+    cur.close()
+    db_connection.close()
 
-    if flag:
-        # print('ALREADY IN DATABASE')
-        # print(new_offer)
-        # if it's already in database, check PRICE and if it's changed, change it !!!!!!
-        if flag_price:
-            print('PRICE CHANGED!')  # CHANGE PRICE
-            print('offer id: ' + str(offer_id))
-            headers = {'Content-type': 'application/json'}
-            requests.put('http://localhost:8080/phoneoffer/' + str(offer_id) + '/changeprice/' + str(new_offer.price),
-                         headers=headers)
-    else:
-        print('ADDED')  # ADD OFFER
-        print(new_offer)
-        headers = {'Content-type': 'application/json'}
-        requests.post('http://localhost:8080/phoneoffer/addoffer',
-                      headers=headers, data=json.dumps(new_offer.__dict__, default=str))
-
-print('------------------------------------')
-
-for old_offer in database_offers:
-    flag = False
-    for new_offer in new_offers:
-        if old_offer.offer_name == new_offer.offer_name:
-            flag = True
-
-    if not flag:
-        print('OFFER DELETED')
-        print(old_offer)
-        # DELETE OFFER
-        requests.delete('http://localhost:8080/phoneoffer/deleteoffer/' + str(old_offer.offer_id))
Index: phonelux_scrappers/scrappers/handy_scrapper.py
===================================================================
--- phonelux_scrappers/scrappers/handy_scrapper.py	(revision ffd50db1e5e2b9839ba7546d8ca44b600150bd71)
+++ phonelux_scrappers/scrappers/handy_scrapper.py	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
@@ -1,3 +1,4 @@
 import json
+import traceback
 import unicodedata
 from datetime import datetime
@@ -20,121 +21,150 @@
 is_validated = False
 
-# Handy phone offers that are already in database
-offers = json.loads(unicodedata.normalize('NFKD', requests.get('http://localhost:8080/phoneoffer/shop/handy').text))
+# Call to read the configuration file and connect to database
+cinfo = config_read.get_databaseconfig("../postgresdb.config")
+db_connection = psycopg2.connect(
+    database=cinfo[0],
+    host=cinfo[1],
+    user=cinfo[2],
+    password=cinfo[3]
+)
+cur = db_connection.cursor()
 
-database_offers = []
+try:
+    # Handy phone offers that are already in database
+    offers = json.loads(unicodedata.normalize('NFKD', requests.get('http://localhost:8080/phoneoffer/shop/handy').text))
 
-for offer in offers:
-    phoneOffer = PhoneOffer(offer['id'], offer['offer_shop'], offer['offer_name'], offer['price'],
-                            offer['ram_memory'],
-                            offer['rom_memory'], offer['color'], offer['front_camera'], offer['back_camera'],
-                            offer['chipset'], offer['battery'], offer['operating_system'], offer['cpu'],
-                            offer['image_url'],
-                            offer['offer_url'], offer['last_updated'], offer['is_validated'],
-                            offer['offer_description'],
-                            offer['offer_shop_code'])
-    database_offers.append(phoneOffer)
+    database_offers = []
 
-new_offers = []
+    for offer in offers:
+        phoneOffer = PhoneOffer(offer['id'], offer['offer_shop'], offer['offer_name'], offer['price'],
+                                offer['ram_memory'],
+                                offer['rom_memory'], offer['color'], offer['front_camera'], offer['back_camera'],
+                                offer['chipset'], offer['battery'], offer['operating_system'], offer['cpu'],
+                                offer['image_url'],
+                                offer['offer_url'], offer['last_updated'], offer['is_validated'],
+                                offer['offer_description'],
+                                offer['offer_shop_code'])
+        database_offers.append(phoneOffer)
 
-handy_url = 'https://www.handy.mk/telefoni?page=6'
+    new_offers = []
 
-response1 = requests.get(handy_url)
-soup1 = BeautifulSoup(response1.content, 'html.parser')
+    handy_url = 'https://www.handy.mk/telefoni?page=6'
 
-phones = soup1.find_all('li', {'data-hook': 'product-list-grid-item'})
+    response1 = requests.get(handy_url)
+    soup1 = BeautifulSoup(response1.content, 'html.parser')
 
-for phone in phones:
-    offer_url = phone.find('a').get('href')
-    offer_name = phone.find('div', {'data-hook': 'not-image-container'})\
-        .find('h3', {'data-hook': 'product-item-name'}).get_text().strip()
-    brand = offer_name.split(' ')[0].capitalize()
-    price = int(float(phone.find('div', {'data-hook': 'not-image-container'}).find('div', {'data-hook': "product-item-product-details"})\
-        .find('span', {'data-hook': 'product-item-price-to-pay'}).get_text().strip().replace('ден', '').replace('.', '').replace(',', '.')))
+    phones = soup1.find_all('li', {'data-hook': 'product-list-grid-item'})
 
-    response2 = requests.get(offer_url)
-    soup2 = BeautifulSoup(response2.text, 'html.parser')
+    for phone in phones:
+        offer_url = phone.find('a').get('href')
+        offer_name = phone.find('div', {'data-hook': 'not-image-container'})\
+            .find('h3', {'data-hook': 'product-item-name'}).get_text().strip()
+        brand = offer_name.split(' ')[0].capitalize()
+        price = int(float(phone.find('div', {'data-hook': 'not-image-container'}).find('div', {'data-hook': "product-item-product-details"})\
+            .find('span', {'data-hook': 'product-item-price-to-pay'}).get_text().strip().replace('ден', '').replace('.', '').replace(',', '.')))
 
-    back_camera = None
-    operating_system = None
-    chipset = None
-    battery = None
-    ram_memory = None
-    rom_memory = None
-    cpu = None
-    front_camera = None
-    offer_shop_code = None
-    color = None
-    image_url = None
+        response2 = requests.get(offer_url)
+        soup2 = BeautifulSoup(response2.text, 'html.parser')
 
-    color_section = soup2.find('section', {'data-hook': 'product-colors-title-section'})
-    if color_section is not None:
-        temp_colors = color_section.find('fieldset', {'class': 'ColorPickerbase3548966286__container'})\
-            .find_all('input', {'type': 'radio'})
-        colors_list = []
-        for temp_color in temp_colors:
-            colors_list.append(temp_color.get('aria-label'))
-        color = ','.join(colors_list)
+        back_camera = None
+        operating_system = None
+        chipset = None
+        battery = None
+        ram_memory = None
+        rom_memory = None
+        cpu = None
+        front_camera = None
+        offer_shop_code = None
+        color = None
+        image_url = None
 
-    rows = soup2.find('div', {'data-hook': 'info-section-description'}).find_all('li')
+        color_section = soup2.find('section', {'data-hook': 'product-colors-title-section'})
+        if color_section is not None:
+            temp_colors = color_section.find('fieldset', {'class': 'ColorPickerbase3548966286__container'})\
+                .find_all('input', {'type': 'radio'})
+            colors_list = []
+            for temp_color in temp_colors:
+                colors_list.append(temp_color.get('aria-label'))
+            color = ','.join(colors_list)
 
-    if len(rows) == 0:
-        rows = soup2.find('div', {'data-hook': 'info-section-description'}).find_all('tr')
+        rows = soup2.find('div', {'data-hook': 'info-section-description'}).find_all('li')
 
-    specifications = []
+        if len(rows) == 0:
+            rows = soup2.find('div', {'data-hook': 'info-section-description'}).find_all('tr')
 
-    for row in rows:
-        specifications.append(unicodedata.normalize('NFKD', row.get_text().strip()))
+        specifications = []
 
-    offer_description = '\n'.join(specifications)
+        for row in rows:
+            specifications.append(unicodedata.normalize('NFKD', row.get_text().strip()))
 
-    new_offers.append(PhoneOffer(offer_shop, offer_name, price, ram_memory, rom_memory,
-                                 color, front_camera, back_camera, chipset, battery, operating_system, cpu,
-                                 image_url,
-                                 offer_url, last_updated, is_validated, offer_description, offer_shop_code))
+        offer_description = '\n'.join(specifications)
 
-for new_offer in new_offers:
-    flag = False
-    flag_price = False
-    offer_id = None
+        new_offers.append(PhoneOffer(offer_shop, offer_name, price, ram_memory, rom_memory,
+                                     color, front_camera, back_camera, chipset, battery, operating_system, cpu,
+                                     image_url,
+                                     offer_url, last_updated, is_validated, offer_description, offer_shop_code))
+
+    for new_offer in new_offers:
+        flag = False
+        flag_price = False
+        offer_id = None
+
+        for old_offer in database_offers:
+
+            if new_offer.offer_name == old_offer.offer_name:
+                flag = True
+                if new_offer.price != old_offer.price:
+                    flag_price = True
+                    offer_id = old_offer.offer_id
+
+        if flag:
+            # print('ALREADY IN DATABASE')
+            # print(new_offer)
+            # if it's already in database, check PRICE and if it's changed, change it !!!!!!
+            if flag_price:
+                print('PRICE CHANGED!')  # CHANGE PRICE
+                print('offer id: ' + str(offer_id))
+                headers = {'Content-type': 'application/json'}
+                requests.put('http://localhost:8080/phoneoffer/' + str(offer_id) + '/changeprice/' + str(new_offer.price),
+                             headers=headers)
+        else:
+            print('ADDED')  # ADD OFFER
+            print(new_offer)
+            headers = {'Content-type': 'application/json'}
+            requests.post('http://localhost:8080/phoneoffer/addoffer',
+                          headers=headers, data=json.dumps(new_offer.__dict__, default=str))
+
+    print('------------------------------------')
 
     for old_offer in database_offers:
+        flag = False
+        for new_offer in new_offers:
+            if old_offer.offer_name == new_offer.offer_name:
+                flag = True
 
-        if new_offer.offer_name == old_offer.offer_name:
-            flag = True
-            if new_offer.price != old_offer.price:
-                flag_price = True
-                offer_id = old_offer.offer_id
-
-    if flag:
-        # print('ALREADY IN DATABASE')
-        # print(new_offer)
-        # if it's already in database, check PRICE and if it's changed, change it !!!!!!
-        if flag_price:
-            print('PRICE CHANGED!')  # CHANGE PRICE
-            print('offer id: ' + str(offer_id))
-            headers = {'Content-type': 'application/json'}
-            requests.put('http://localhost:8080/phoneoffer/' + str(offer_id) + '/changeprice/' + str(new_offer.price),
-                         headers=headers)
-    else:
-        print('ADDED')  # ADD OFFER
-        print(new_offer)
-        headers = {'Content-type': 'application/json'}
-        requests.post('http://localhost:8080/phoneoffer/addoffer',
-                      headers=headers, data=json.dumps(new_offer.__dict__, default=str))
-
-print('------------------------------------')
-
-for old_offer in database_offers:
-    flag = False
-    for new_offer in new_offers:
-        if old_offer.offer_name == new_offer.offer_name:
-            flag = True
-
-    if not flag:
-        print('OFFER DELETED')
-        print(old_offer)
-        # DELETE OFFER
-        requests.delete('http://localhost:8080/phoneoffer/deleteoffer/' + str(old_offer.offer_id))
+        if not flag:
+            print('OFFER DELETED')
+            print(old_offer)
+            # DELETE OFFER
+            requests.delete('http://localhost:8080/phoneoffer/deleteoffer/' + str(old_offer.offer_id))
+except Exception:
+    traceback.print_exc()
+    insert_script = 'INSERT INTO scrapper_info (store, recieved_at, status)' \
+                    ' VALUES (%s, %s, %s);'
+    insert_value = (offer_shop, last_updated, 'failed')
+    cur.execute(insert_script, insert_value)
+    db_connection.commit()
+    cur.close()
+    db_connection.close()
+else:
+    insert_script = 'INSERT INTO scrapper_info (store, recieved_at, status)' \
+                    ' VALUES (%s, %s, %s);'
+    insert_value = (offer_shop, last_updated, 'success')
+    cur.execute(insert_script, insert_value)
+    db_connection.commit()
+    cur.close()
+    db_connection.close()
 
 
+
Index: phonelux_scrappers/scrappers/ledikom_scrapper.py
===================================================================
--- phonelux_scrappers/scrappers/ledikom_scrapper.py	(revision ffd50db1e5e2b9839ba7546d8ca44b600150bd71)
+++ phonelux_scrappers/scrappers/ledikom_scrapper.py	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
@@ -1,3 +1,4 @@
 import json
+import traceback
 import unicodedata
 from datetime import datetime
@@ -19,166 +20,194 @@
 is_validated = False
 
-# Ledikom phone offers that are already in database
-
-offers = json.loads(unicodedata.normalize('NFKD', requests.get('http://localhost:8080/phoneoffer/shop/ledikom').text))
-
-database_offers = []
-
-for offer in offers:
-    phoneOffer = PhoneOffer(offer['id'], offer['offer_shop'], offer['offer_name'], offer['price'],
-                            offer['ram_memory'],
-                            offer['rom_memory'], offer['color'], offer['front_camera'], offer['back_camera'],
-                            offer['chipset'], offer['battery'], offer['operating_system'], offer['cpu'],
-                            offer['image_url'],
-                            offer['offer_url'], offer['last_updated'], offer['is_validated'],
-                            offer['offer_description'],
-                            offer['offer_shop_code'])
-    database_offers.append(phoneOffer)
-
-new_offers = []
-
-ledikom_phone_urls = [
-    'https://ledikom.mk/c/416/uredi/apple/iphone?limit=96',
-    'https://ledikom.mk/c/421/uredi/samsung/telefoni?limit=96',
-    'https://ledikom.mk/c/424/mobilni-telefoni/xiaomi/telefoni?limit=96',
-    'https://ledikom.mk/c/430/uredi/huawei/telefoni?limit=96',
-    'https://ledikom.mk/c/441/uredi/oneplus/telefoni?limit=96',
-    'https://ledikom.mk/c/413/uredi/google/telefoni?limit=96',
-    'https://ledikom.mk/c/411/uredi/honor/telefoni?limit=96',
-    'https://ledikom.mk/c/460/uredi/nokia/telefoni?limit=96',
-    'https://ledikom.mk/c/461/uredi/asus/telefoni?limit=96',
-    'https://ledikom.mk/c/488/proizvodi/oppo/telefoni?limit=96'
-]
-
-for ledikom_url in ledikom_phone_urls:
-
-    # selenium is used because of the dynamic content of the page
-    driver1 = webdriver.Safari(executable_path='/usr/bin/safaridriver')
-    driver1.get(ledikom_url)
-    ledikom_html = driver1.page_source
-
-    # closing the driver so the safari instance can pair with another webdriver session
-    driver1.close()
-
-    soup1 = BeautifulSoup(ledikom_html, 'html.parser')
-
-    phones = soup1.find('div', {'id': 'content'}) \
-        .find('div', {'class': 'container'}).find('div', {'class': 'row'}).find('div', {'class': 'item-display'}) \
-        .find_all('div', {'class': 'item-in-grid'})
-
-    if len(phones) == 0:
-        continue
-
-    for phone in phones:
-        offer_url = 'https://ledikom.mk' + phone.find('a').get('href')
-        image_url = phone.find('a').find('img').get('src')
-        temp_offer_name = phone.find('div', {'class': 'item-name'}).find('a').get_text().strip()
-        offer_name = ' '.join(temp_offer_name.split())
-        brand = offer_name.split(' ')[0]
-        price = int(phone.find('span', {'class': 'price'}).get_text().replace('ден.', '')
-                    .replace('ден', '')
-                    .replace('.', '').strip())
-
+# Call to read the configuration file and connect to database
+cinfo = config_read.get_databaseconfig("../postgresdb.config")
+db_connection = psycopg2.connect(
+    database=cinfo[0],
+    host=cinfo[1],
+    user=cinfo[2],
+    password=cinfo[3]
+)
+cur = db_connection.cursor()
+
+try:
+    # Ledikom phone offers that are already in database
+    offers = json.loads(unicodedata.normalize('NFKD', requests.get('http://localhost:8080/phoneoffer/shop/ledikom').text))
+
+    database_offers = []
+
+    for offer in offers:
+        phoneOffer = PhoneOffer(offer['id'], offer['offer_shop'], offer['offer_name'], offer['price'],
+                                offer['ram_memory'],
+                                offer['rom_memory'], offer['color'], offer['front_camera'], offer['back_camera'],
+                                offer['chipset'], offer['battery'], offer['operating_system'], offer['cpu'],
+                                offer['image_url'],
+                                offer['offer_url'], offer['last_updated'], offer['is_validated'],
+                                offer['offer_description'],
+                                offer['offer_shop_code'])
+        database_offers.append(phoneOffer)
+
+    new_offers = []
+
+    ledikom_phone_urls = [
+        'https://ledikom.mk/c/416/uredi/apple/iphone?limit=96',
+        'https://ledikom.mk/c/421/uredi/samsung/telefoni?limit=96',
+        'https://ledikom.mk/c/424/mobilni-telefoni/xiaomi/telefoni?limit=96',
+        'https://ledikom.mk/c/430/uredi/huawei/telefoni?limit=96',
+        'https://ledikom.mk/c/441/uredi/oneplus/telefoni?limit=96',
+        'https://ledikom.mk/c/413/uredi/google/telefoni?limit=96',
+        'https://ledikom.mk/c/411/uredi/honor/telefoni?limit=96',
+        'https://ledikom.mk/c/460/uredi/nokia/telefoni?limit=96',
+        'https://ledikom.mk/c/461/uredi/asus/telefoni?limit=96',
+        'https://ledikom.mk/c/488/proizvodi/oppo/telefoni?limit=96'
+    ]
+
+    for ledikom_url in ledikom_phone_urls:
+
+        # selenium is used because of the dynamic content of the page
         driver1 = webdriver.Safari(executable_path='/usr/bin/safaridriver')
-        driver1.get(offer_url)
-        # getting offer page html
-        offer_html = driver1.page_source
+        driver1.get(ledikom_url)
+        ledikom_html = driver1.page_source
+
+        # closing the driver so the safari instance can pair with another webdriver session
         driver1.close()
 
-        soup2 = BeautifulSoup(offer_html, 'html.parser')
-
-        specifications = soup2.find('div', {'id': 'content'}).find('section', {'class': 'padding-section'}) \
-            .find_all('div', {'class': 'container'})[1].find('div', {'class': 'col-md-7'}) \
-            .find_all('div', {'class': 'row'})
-
-        color = None
-        rom_memory = None
-        ram_memory = None
-        back_camera = None
-        operating_system = None
-        chipset = None
-        battery = None
-        cpu = None
-        front_camera = None
-        offer_shop_code = None
-        offer_description = None
-
-        if len(specifications) != 0:
-            colors_tags = specifications[0].find('div', {'class': 'col-md-12 col-xs-12'}).find_all('a')
-            temp_colors = []
-            for color_tag in colors_tags:
-                temp_colors.append(color_tag.get_text().strip())
-            color = ','.join(temp_colors)
-
-        if len(specifications) >= 2:
-            temp_rom = specifications[1].find('div', {'class': 'col-md-12 col-xs-12'}).find_all('a')
-            rom_list = []
-            for rom in temp_rom:
-                rom_list.append(rom.get('title'))
-            rom_memory = ','.join(rom_list)
-
-        if len(specifications) >= 3:
-            temp_ram = specifications[2].find('div', {'class': 'col-md-12 col-xs-12'}).find_all('a')
-            ram_list = []
-            for ram in temp_ram:
-                ram_list.append(ram.get('title'))
-
-            ram_memory = ','.join(ram_list)
-
-        if 'Xiaomi' in brand:
-            temp = color
-            color = rom_memory
-            rom_memory = temp
-
-            temp = ram_memory
-            ram_memory = color
-            color = temp
-
-        new_offers.append(PhoneOffer(offer_shop, offer_name, price, ram_memory, rom_memory,
-                                     color, front_camera, back_camera, chipset, battery, operating_system, cpu,
-                                     image_url,
-                                     offer_url, last_updated, is_validated, offer_description, offer_shop_code))
-
-for new_offer in new_offers:
-    flag = False
-    flag_price = False
-    offer_id = None
+        soup1 = BeautifulSoup(ledikom_html, 'html.parser')
+
+        phones = soup1.find('div', {'id': 'content'}) \
+            .find('div', {'class': 'container'}).find('div', {'class': 'row'}).find('div', {'class': 'item-display'}) \
+            .find_all('div', {'class': 'item-in-grid'})
+
+        if len(phones) == 0:
+            continue
+
+        for phone in phones:
+            offer_url = 'https://ledikom.mk' + phone.find('a').get('href')
+            image_url = phone.find('a').find('img').get('src')
+            temp_offer_name = phone.find('div', {'class': 'item-name'}).find('a').get_text().strip()
+            offer_name = ' '.join(temp_offer_name.split())
+            brand = offer_name.split(' ')[0]
+            price = int(phone.find('span', {'class': 'price'}).get_text().replace('ден.', '')
+                        .replace('ден', '')
+                        .replace('.', '').strip())
+
+            driver1 = webdriver.Safari(executable_path='/usr/bin/safaridriver')
+            driver1.get(offer_url)
+            # getting offer page html
+            offer_html = driver1.page_source
+            driver1.close()
+
+            soup2 = BeautifulSoup(offer_html, 'html.parser')
+
+            specifications = soup2.find('div', {'id': 'content'}).find('section', {'class': 'padding-section'}) \
+                .find_all('div', {'class': 'container'})[1].find('div', {'class': 'col-md-7'}) \
+                .find_all('div', {'class': 'row'})
+
+            color = None
+            rom_memory = None
+            ram_memory = None
+            back_camera = None
+            operating_system = None
+            chipset = None
+            battery = None
+            cpu = None
+            front_camera = None
+            offer_shop_code = None
+            offer_description = None
+
+            if len(specifications) != 0:
+                colors_tags = specifications[0].find('div', {'class': 'col-md-12 col-xs-12'}).find_all('a')
+                temp_colors = []
+                for color_tag in colors_tags:
+                    temp_colors.append(color_tag.get_text().strip())
+                color = ','.join(temp_colors)
+
+            if len(specifications) >= 2:
+                temp_rom = specifications[1].find('div', {'class': 'col-md-12 col-xs-12'}).find_all('a')
+                rom_list = []
+                for rom in temp_rom:
+                    rom_list.append(rom.get('title'))
+                rom_memory = ','.join(rom_list)
+
+            if len(specifications) >= 3:
+                temp_ram = specifications[2].find('div', {'class': 'col-md-12 col-xs-12'}).find_all('a')
+                ram_list = []
+                for ram in temp_ram:
+                    ram_list.append(ram.get('title'))
+
+                ram_memory = ','.join(ram_list)
+
+            if 'Xiaomi' in brand:
+                temp = color
+                color = rom_memory
+                rom_memory = temp
+
+                temp = ram_memory
+                ram_memory = color
+                color = temp
+
+            new_offers.append(PhoneOffer(offer_shop, offer_name, price, ram_memory, rom_memory,
+                                         color, front_camera, back_camera, chipset, battery, operating_system, cpu,
+                                         image_url,
+                                         offer_url, last_updated, is_validated, offer_description, offer_shop_code))
+
+    for new_offer in new_offers:
+        flag = False
+        flag_price = False
+        offer_id = None
+
+        for old_offer in database_offers:
+
+            if new_offer.offer_name == old_offer.offer_name:
+                flag = True
+                if new_offer.price != old_offer.price:
+                    flag_price = True
+                    offer_id = old_offer.offer_id
+
+        if flag:
+            # print('ALREADY IN DATABASE')
+            # print(new_offer)
+            # if it's already in database, check PRICE and if it's changed, change it !!!!!!
+            if flag_price:
+                print('PRICE CHANGED!')  # CHANGE PRICE
+                print('offer id: ' + str(offer_id))
+                headers = {'Content-type': 'application/json'}
+                requests.put('http://localhost:8080/phoneoffer/' + str(offer_id) + '/changeprice/' + str(new_offer.price),
+                             headers=headers)
+        else:
+            print('ADDED')  # ADD OFFER
+            print(new_offer)
+            headers = {'Content-type': 'application/json'}
+            requests.post('http://localhost:8080/phoneoffer/addoffer',
+                          headers=headers, data=json.dumps(new_offer.__dict__, default=str))
+
+    print('------------------------------------')
 
     for old_offer in database_offers:
-
-        if new_offer.offer_name == old_offer.offer_name:
-            flag = True
-            if new_offer.price != old_offer.price:
-                flag_price = True
-                offer_id = old_offer.offer_id
-
-    if flag:
-        # print('ALREADY IN DATABASE')
-        # print(new_offer)
-        # if it's already in database, check PRICE and if it's changed, change it !!!!!!
-        if flag_price:
-            print('PRICE CHANGED!')  # CHANGE PRICE
-            print('offer id: ' + str(offer_id))
-            headers = {'Content-type': 'application/json'}
-            requests.put('http://localhost:8080/phoneoffer/' + str(offer_id) + '/changeprice/' + str(new_offer.price),
-                         headers=headers)
-    else:
-        print('ADDED')  # ADD OFFER
-        print(new_offer)
-        headers = {'Content-type': 'application/json'}
-        requests.post('http://localhost:8080/phoneoffer/addoffer',
-                      headers=headers, data=json.dumps(new_offer.__dict__, default=str))
-
-print('------------------------------------')
-
-for old_offer in database_offers:
-    flag = False
-    for new_offer in new_offers:
-        if old_offer.offer_name == new_offer.offer_name:
-            flag = True
-
-    if not flag:
-        print('OFFER DELETED')
-        print(old_offer)
-        # DELETE OFFER
-        requests.delete('http://localhost:8080/phoneoffer/deleteoffer/' + str(old_offer.offer_id))
+        flag = False
+        for new_offer in new_offers:
+            if old_offer.offer_name == new_offer.offer_name:
+                flag = True
+
+        if not flag:
+            print('OFFER DELETED')
+            print(old_offer)
+            # DELETE OFFER
+            requests.delete('http://localhost:8080/phoneoffer/deleteoffer/' + str(old_offer.offer_id))
+except Exception:
+    traceback.print_exc()
+    insert_script = 'INSERT INTO scrapper_info (store, recieved_at, status)' \
+                    ' VALUES (%s, %s, %s);'
+    insert_value = (offer_shop, last_updated, 'failed')
+    cur.execute(insert_script, insert_value)
+    db_connection.commit()
+    cur.close()
+    db_connection.close()
+else:
+    insert_script = 'INSERT INTO scrapper_info (store, recieved_at, status)' \
+                    ' VALUES (%s, %s, %s);'
+    insert_value = (offer_shop, last_updated, 'success')
+    cur.execute(insert_script, insert_value)
+    db_connection.commit()
+    cur.close()
+    db_connection.close()
+
Index: phonelux_scrappers/scrappers/mobelix_scrapper.py
===================================================================
--- phonelux_scrappers/scrappers/mobelix_scrapper.py	(revision ffd50db1e5e2b9839ba7546d8ca44b600150bd71)
+++ phonelux_scrappers/scrappers/mobelix_scrapper.py	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
@@ -3,5 +3,5 @@
 import unicodedata
 from datetime import datetime
-
+import traceback
 import psycopg2
 import config_read
@@ -19,166 +19,194 @@
 is_validated = False
 
-# Mobelix phone offers that are already in database
-
-offers = json.loads(unicodedata.normalize('NFKD', requests.get('http://localhost:8080/phoneoffer/shop/mobelix').text))
-
-database_offers = []
-
-for offer in offers:
-    phoneOffer = PhoneOffer(offer['id'], offer['offer_shop'], offer['offer_name'], offer['price'],
-                            offer['ram_memory'],
-                            offer['rom_memory'], offer['color'], offer['front_camera'], offer['back_camera'],
-                            offer['chipset'], offer['battery'], offer['operating_system'], offer['cpu'],
-                            offer['image_url'],
-                            offer['offer_url'], offer['last_updated'], offer['is_validated'],
-                            offer['offer_description'],
-                            offer['offer_shop_code'])
-    database_offers.append(phoneOffer)
-
-new_offers = []
-
-for i in range(1, 17):
-    mobelix_url = "https://mobelix.com.mk/mk/mobilni-telefoni?page=" + str(i)
-
-    response1 = requests.get(mobelix_url)
-    soup1 = BeautifulSoup(response1.content, 'html.parser')
-
-    phones = soup1.find_all('div', {'class': 'p-2 rounded text-dark bg-white d-flex w-100'})
-
-    for phone in phones:
-        offer_url = phone.find('a').get('href')
-        image_url = phone.find_all('div', {'class': 'col-12'})[0].find('img').get('src')
-        brand = phone.find_all('div', {'class': 'col-12'})[1].find('h5', {'class': 'mb-0'}).get_text().strip()
-        offer_name = phone.find_all('div', {'class': 'col-12'})[1] \
-            .find('h3', {'class': 'h5 font-weight-normal'}).get_text().strip()
-
-        if 'Watch' in offer_name or 'Pad' in offer_name or 'Tab' in offer_name or 'Pods' in offer_name or 'Buds' in offer_name or 'HomePod' in offer_name:
-            continue
-
-        if brand not in offer_name:
-            offer_name = brand + " " + offer_name
-
-        temp_prices = phone.find_all('div', {'class': 'col-12'})[1] \
-            .find('p', {'class': 'h5 price'}).get_text(separator='/').strip()
-
-        if len(temp_prices.split('/')) > 1:
-            price = int(float(temp_prices.split('/')[1].replace(',', '').replace('ден', '').strip()))
+# Call to read the configuration file and connect to database
+cinfo = config_read.get_databaseconfig("../postgresdb.config")
+db_connection = psycopg2.connect(
+    database=cinfo[0],
+    host=cinfo[1],
+    user=cinfo[2],
+    password=cinfo[3]
+)
+cur = db_connection.cursor()
+
+try:
+    # Mobelix phone offers that are already in database
+    offers = json.loads(unicodedata.normalize('NFKD', requests.get('http://localhost:8080/phoneoffer/shop/mobelix').text))
+
+    database_offers = []
+
+    for offer in offers:
+        phoneOffer = PhoneOffer(offer['id'], offer['offer_shop'], offer['offer_name'], offer['price'],
+                                    offer['ram_memory'],
+                                    offer['rom_memory'], offer['color'], offer['front_camera'], offer['back_camera'],
+                                    offer['chipset'], offer['battery'], offer['operating_system'], offer['cpu'],
+                                    offer['image_url'],
+                                    offer['offer_url'], offer['last_updated'], offer['is_validated'],
+                                    offer['offer_description'],
+                                    offer['offer_shop_code'])
+        database_offers.append(phoneOffer)
+
+    new_offers = []
+
+    for i in range(1, 17):
+        mobelix_url = "https://mobelix.com.mk/mk/mobilni-telefoni?page=" + str(i)
+
+        response1 = requests.get(mobelix_url)
+        soup1 = BeautifulSoup(response1.content, 'html.parser')
+
+        phones = soup1.find_all('div', {'class': 'p-2 rounded text-dark bg-white d-flex w-100'})
+
+        for phone in phones:
+            offer_url = phone.find('a').get('href')
+            image_url = phone.find_all('div', {'class': 'col-12'})[0].find('img').get('src')
+            brand = phone.find_all('div', {'class': 'col-12'})[1].find('h5', {'class': 'mb-0'}).get_text().strip()
+            offer_name = phone.find_all('div', {'class': 'col-12'})[1] \
+                .find('h3', {'class': 'h5 font-weight-normal'}).get_text().strip()
+
+            if 'Watch' in offer_name or 'Pad' in offer_name or 'Tab' in offer_name or 'Pods' in offer_name or 'Buds' in offer_name or 'HomePod' in offer_name:
+                continue
+
+            if brand not in offer_name:
+                offer_name = brand + " " + offer_name
+
+            temp_prices = phone.find_all('div', {'class': 'col-12'})[1] \
+                .find('p', {'class': 'h5 price'}).get_text(separator='/').strip()
+
+            if len(temp_prices.split('/')) > 1:
+                price = int(float(temp_prices.split('/')[1].replace(',', '').replace('ден', '').strip()))
+            else:
+                price = int(float(temp_prices.split('/')[0].replace(',', '').replace('ден', '').strip()))
+
+            response2 = requests.get(offer_url)
+            soup2 = BeautifulSoup(response2.content, 'html.parser')
+
+            colors_divs = soup2.find('div', {'class': 'color-wrapper mt-2 mb-1'}) \
+                .find_all('div', {'class': 'color-box d-inline-block'})  # color div tags
+
+            temp_colors = []
+            for div in colors_divs:
+                temp_colors.append(div.get('title'))
+
+            color = ",".join(temp_colors)  # available colors for offer
+
+            tables = soup2.find('div', {'class': 'mobelix-specs table-white bordered-table'}).find_all('table')
+
+            operating_system = None
+            chipset = None
+            battery = None
+            ram_memory = None
+            rom_memory = None
+            front_camera = ''
+            back_camera = ''
+            cpu = None
+            offer_shop_code = None
+            offer_description = None
+
+            for table in tables:
+                for cell in table.find_all('td'):
+                    if cell.get('data-spec') is None:
+                        continue
+
+                    if cell.get('data-spec') == 'os':
+                        operating_system = unicodedata.normalize('NFKD', cell.get_text().strip())
+
+                    if cell.get('data-spec') == 'chipset':
+                        chipset = unicodedata.normalize('NFKD', cell.get_text().strip())
+
+                    if cell.get('data-spec') == 'cpu':
+                        cpu = unicodedata.normalize('NFKD', cell.get_text().strip())
+
+                    if cell.get('data-spec') == 'internalmemory':
+                        temp_rom = []
+                        temp_ram = []
+                        temp_internalmemory = unicodedata.normalize('NFKD', cell.get_text().strip())
+                        for internalmemory in temp_internalmemory.split(','):
+                            temp_rom.append(internalmemory.strip().split(' ')[0])
+                            if len(internalmemory.strip().split(' ')) > 1:
+                                temp_ram.append(internalmemory.strip().split(' ')[1])
+                        rom_memory = ','.join(temp_rom)
+                        ram_memory = ','.join(temp_ram)
+
+                    if cell.get('data-spec') == 'cam1modules' or cell.get('data-spec') == 'cam1features' or cell.get(
+                                'data-spec') == 'cam1video':
+                        back_camera += unicodedata.normalize('NFKD', cell.get_text().strip()) + '\n'
+
+                    if cell.get('data-spec') == 'cam2modules' or cell.get('data-spec') == 'cam2features' or cell.get(
+                                'data-spec') == 'cam2video':
+                        front_camera += unicodedata.normalize('NFKD', cell.get_text().strip()) + '\n'
+
+                    if cell.get('data-spec') == 'batdescription1':
+                        battery = unicodedata.normalize('NFKD', cell.get_text().strip())
+
+            if front_camera == 'No':
+                front_camera = None
+
+            if back_camera == 'No':
+                back_camera = None
+
+            new_offers.append(PhoneOffer(offer_shop, offer_name, price, ram_memory, rom_memory,
+                                            color, front_camera, back_camera, chipset, battery, operating_system, cpu,
+                                            image_url,
+                                            offer_url, last_updated, is_validated, offer_description, offer_shop_code))
+
+
+    for new_offer in new_offers:
+        flag = False
+        flag_price = False
+        offer_id = None
+
+        for old_offer in database_offers:
+
+            if new_offer.offer_name == old_offer.offer_name:
+                flag = True
+                if new_offer.price != old_offer.price:
+                    flag_price = True
+                    offer_id = old_offer.offer_id
+
+        if flag:
+            # print('ALREADY IN DATABASE')
+            # print(new_offer)
+            # if it's already in database, check PRICE and if it's changed, change it !!!!!!
+            if flag_price:
+                print('PRICE CHANGED!')  # CHANGE PRICE
+                print('offer id: ' + str(offer_id))
+                headers = {'Content-type': 'application/json'}
+                requests.put('http://localhost:8080/phoneoffer/' + str(offer_id) + '/changeprice/' + str(new_offer.price),
+                        headers=headers)
         else:
-            price = int(float(temp_prices.split('/')[0].replace(',', '').replace('ден', '').strip()))
-
-        response2 = requests.get(offer_url)
-        soup2 = BeautifulSoup(response2.content, 'html.parser')
-
-        colors_divs = soup2.find('div', {'class': 'color-wrapper mt-2 mb-1'}) \
-            .find_all('div', {'class': 'color-box d-inline-block'})  # color div tags
-
-        temp_colors = []
-        for div in colors_divs:
-            temp_colors.append(div.get('title'))
-
-        color = ",".join(temp_colors)  # available colors for offer
-
-        tables = soup2.find('div', {'class': 'mobelix-specs table-white bordered-table'}).find_all('table')
-
-        operating_system = None
-        chipset = None
-        battery = None
-        ram_memory = None
-        rom_memory = None
-        front_camera = ''
-        back_camera = ''
-        cpu = None
-        offer_shop_code = None
-        offer_description = None
-
-        for table in tables:
-            for cell in table.find_all('td'):
-                if cell.get('data-spec') is None:
-                    continue
-
-                if cell.get('data-spec') == 'os':
-                    operating_system = unicodedata.normalize('NFKD', cell.get_text().strip())
-
-                if cell.get('data-spec') == 'chipset':
-                    chipset = unicodedata.normalize('NFKD', cell.get_text().strip())
-
-                if cell.get('data-spec') == 'cpu':
-                    cpu = unicodedata.normalize('NFKD', cell.get_text().strip())
-
-                if cell.get('data-spec') == 'internalmemory':
-                    temp_rom = []
-                    temp_ram = []
-                    temp_internalmemory = unicodedata.normalize('NFKD', cell.get_text().strip())
-                    for internalmemory in temp_internalmemory.split(','):
-                        temp_rom.append(internalmemory.strip().split(' ')[0])
-                        if len(internalmemory.strip().split(' ')) > 1:
-                            temp_ram.append(internalmemory.strip().split(' ')[1])
-                    rom_memory = ','.join(temp_rom)
-                    ram_memory = ','.join(temp_ram)
-
-                if cell.get('data-spec') == 'cam1modules' or cell.get('data-spec') == 'cam1features' or cell.get(
-                        'data-spec') == 'cam1video':
-                    back_camera += unicodedata.normalize('NFKD', cell.get_text().strip()) + '\n'
-
-                if cell.get('data-spec') == 'cam2modules' or cell.get('data-spec') == 'cam2features' or cell.get(
-                        'data-spec') == 'cam2video':
-                    front_camera += unicodedata.normalize('NFKD', cell.get_text().strip()) + '\n'
-
-                if cell.get('data-spec') == 'batdescription1':
-                    battery = unicodedata.normalize('NFKD', cell.get_text().strip())
-
-        if front_camera == 'No':
-            front_camera = None
-
-        if back_camera == 'No':
-            back_camera = None
-
-        new_offers.append(PhoneOffer(offer_shop, offer_name, price, ram_memory, rom_memory,
-                                     color, front_camera, back_camera, chipset, battery, operating_system, cpu,
-                                     image_url,
-                                     offer_url, last_updated, is_validated, offer_description, offer_shop_code))
-
-
-for new_offer in new_offers:
-    flag = False
-    flag_price = False
-    offer_id = None
+            print('ADDED')  # ADD OFFER
+            print(new_offer)
+            headers = {'Content-type': 'application/json'}
+            requests.post('http://localhost:8080/phoneoffer/addoffer',
+                        headers=headers, data=json.dumps(new_offer.__dict__, default=str))
+
+    print('------------------------------------')
 
     for old_offer in database_offers:
-
-        if new_offer.offer_name == old_offer.offer_name:
-            flag = True
-            if new_offer.price != old_offer.price:
-                flag_price = True
-                offer_id = old_offer.offer_id
-
-    if flag:
-        # print('ALREADY IN DATABASE')
-        # print(new_offer)
-        # if it's already in database, check PRICE and if it's changed, change it !!!!!!
-        if flag_price:
-            print('PRICE CHANGED!')  # CHANGE PRICE
-            print('offer id: ' + str(offer_id))
-            headers = {'Content-type': 'application/json'}
-            requests.put('http://localhost:8080/phoneoffer/' + str(offer_id) + '/changeprice/' + str(new_offer.price),
-                         headers=headers)
-    else:
-        print('ADDED')  # ADD OFFER
-        print(new_offer)
-        headers = {'Content-type': 'application/json'}
-        requests.post('http://localhost:8080/phoneoffer/addoffer',
-                      headers=headers, data=json.dumps(new_offer.__dict__, default=str))
-
-print('------------------------------------')
-
-for old_offer in database_offers:
-    flag = False
-    for new_offer in new_offers:
-        if old_offer.offer_name == new_offer.offer_name:
-            flag = True
-
-    if not flag:
-        print('OFFER DELETED')
-        print(old_offer)
-        # DELETE OFFER
-        requests.delete('http://localhost:8080/phoneoffer/deleteoffer/' + str(old_offer.offer_id))
+        flag = False
+        for new_offer in new_offers:
+            if old_offer.offer_name == new_offer.offer_name:
+                flag = True
+
+        if not flag:
+            print('OFFER DELETED')
+            print(old_offer)
+            # DELETE OFFER
+            requests.delete('http://localhost:8080/phoneoffer/deleteoffer/' + str(old_offer.offer_id))
+except Exception:
+    traceback.print_exc()
+    insert_script = 'INSERT INTO scrapper_info (store, recieved_at, status)' \
+                    ' VALUES (%s, %s, %s);'
+    insert_value = (offer_shop, last_updated, 'failed')
+    cur.execute(insert_script, insert_value)
+    db_connection.commit()
+    cur.close()
+    db_connection.close()
+else:
+    insert_script = 'INSERT INTO scrapper_info (store, recieved_at, status)' \
+                    ' VALUES (%s, %s, %s);'
+    insert_value = (offer_shop, last_updated, 'success')
+    cur.execute(insert_script, insert_value)
+    db_connection.commit()
+    cur.close()
+    db_connection.close()
+
Index: phonelux_scrappers/scrappers/mobigo_scrapper.py
===================================================================
--- phonelux_scrappers/scrappers/mobigo_scrapper.py	(revision ffd50db1e5e2b9839ba7546d8ca44b600150bd71)
+++ phonelux_scrappers/scrappers/mobigo_scrapper.py	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
@@ -1,3 +1,4 @@
 import json
+import traceback
 import unicodedata
 from datetime import datetime
@@ -18,162 +19,189 @@
 is_validated = False
 
-# Mobi Go phone offers that are already in database
-
-offers = json.loads(unicodedata.normalize('NFKD', requests.get('http://localhost:8080/phoneoffer/shop/mobigo').text))
-
-database_offers = []
-
-for offer in offers:
-    phoneOffer = PhoneOffer(offer['id'], offer['offer_shop'], offer['offer_name'], offer['price'],
-                            offer['ram_memory'],
-                            offer['rom_memory'], offer['color'], offer['front_camera'], offer['back_camera'],
-                            offer['chipset'], offer['battery'], offer['operating_system'], offer['cpu'],
-                            offer['image_url'],
-                            offer['offer_url'], offer['last_updated'], offer['is_validated'],
-                            offer['offer_description'],
-                            offer['offer_shop_code'])
-    database_offers.append(phoneOffer)
-
-new_offers = []
-
-
-for i in range(1, 6):
-    mobigo_url = "https://mobigo.mk/page/" + str(i) + "/"
-
-    response1 = requests.get(mobigo_url)
-
-    soup1 = BeautifulSoup(response1.content, 'html.parser')
-
-    phone_sections = soup1.find_all('ul', {'class': 'recent-posts'})
-    phones = phone_sections[len(phone_sections) - 1].find_all('li')
-
-    for phone in phones:
-        offer_url = phone.find('div', {'class', 'post-thumb'}).find('a').get('href')  # offer url
-        image_url = phone.find('div', {'class', 'post-thumb'}).find('a').find('img').get('src')  # image url
-        offer_name = phone.find('div', {'class', 'post-content'}).find_all('h2')[0].get_text().strip()  # offer_name
-
-        if "Watch" in offer_name or "Tab" in offer_name:  # if the product is watch or tablet, continue
-            continue
-
-        price = int(float(phone.find('div', {'class', 'post-content'}).find_all('h2')[1] \
-                          .get_text().replace('ден.', '').replace('.', '').strip()))  # price
-
-        response2 = requests.get(offer_url)
-        soup2 = BeautifulSoup(response2.content, 'html.parser')
-
-        brand = soup2.find('a', {'rel': 'category tag'}).get_text().strip()  # brand
-
-        if brand not in offer_name:
-            offer_name = brand + " " + offer_name
-
-        specifications = soup2.find('table', {'id': 'singlet'}).find_all('tr')
-
-        ram_memory = None
-        rom_memory = None
-        battery = None
-        back_camera = None
-        front_camera = None
-        chipset = None
-        operating_system = None
-        cpu = None
-        offer_shop_code = None
-        offer_description = None
-        color = None
-
-        for specification in specifications:
-            if specification.find('td') == None:
+# Call to read the configuration file and connect to database
+cinfo = config_read.get_databaseconfig("../postgresdb.config")
+db_connection = psycopg2.connect(
+    database=cinfo[0],
+    host=cinfo[1],
+    user=cinfo[2],
+    password=cinfo[3]
+)
+cur = db_connection.cursor()
+
+try:
+    # Mobi Go phone offers that are already in database
+    offers = json.loads(unicodedata.normalize('NFKD', requests.get('http://localhost:8080/phoneoffer/shop/mobigo').text))
+
+    database_offers = []
+
+    for offer in offers:
+        phoneOffer = PhoneOffer(offer['id'], offer['offer_shop'], offer['offer_name'], offer['price'],
+                                offer['ram_memory'],
+                                offer['rom_memory'], offer['color'], offer['front_camera'], offer['back_camera'],
+                                offer['chipset'], offer['battery'], offer['operating_system'], offer['cpu'],
+                                offer['image_url'],
+                                offer['offer_url'], offer['last_updated'], offer['is_validated'],
+                                offer['offer_description'],
+                                offer['offer_shop_code'])
+        database_offers.append(phoneOffer)
+
+    new_offers = []
+
+
+    for i in range(1, 6):
+        mobigo_url = "https://mobigo.mk/page/" + str(i) + "/"
+
+        response1 = requests.get(mobigo_url)
+
+        soup1 = BeautifulSoup(response1.content, 'html.parser')
+
+        phone_sections = soup1.find_all('ul', {'class': 'recent-posts'})
+        phones = phone_sections[len(phone_sections) - 1].find_all('li')
+
+        for phone in phones:
+            offer_url = phone.find('div', {'class', 'post-thumb'}).find('a').get('href')  # offer url
+            image_url = phone.find('div', {'class', 'post-thumb'}).find('a').find('img').get('src')  # image url
+            offer_name = phone.find('div', {'class', 'post-content'}).find_all('h2')[0].get_text().strip()  # offer_name
+
+            if "Watch" in offer_name or "Tab" in offer_name:  # if the product is watch or tablet, continue
                 continue
 
-            # operating system
-            if specification.find('td').get_text() == "Платформа":
-                if specification.find('i').get_text() != "/":
-                    operating_system = specification.find('i').get_text().strip()
-                else:
-                    operating_system = None
-
-            # chipset
-            if specification.find('td').get_text() == "Chipset":
-                if specification.find('i').get_text() != "/":
-                    chipset = specification.find('i').get_text().strip()
-                else:
-                    chipset = None
-
-            # ram and rom memory
-            if specification.find('td').get_text() == "Меморија":
-                if specification.find('i').get_text() != "/":
-                    rom_memory = specification.find('i').get_text().replace(',', '').split(' ')[0].strip()
-                    ram_memory = specification.find('i').get_text().replace(',', '').split(' ')[1].strip()
-                else:
-                    rom_memory = None
-                    ram_memory = None
-
-            # back camera
-            if specification.find('td').get_text() == "Главна Камера":
-                if specification.find('i').get_text() != "/":
-                    back_camera = specification.find('i').get_text().strip()
-                else:
-                    back_camera = None
-
-            # front camera
-            if specification.find('td').get_text() == "Селфи Камера":
-                if specification.find('i').get_text() != "/":
-                    front_camera = specification.find('i').get_text().strip()
-                else:
-                    front_camera = None
-
-            # battery
-            if specification.find('td').get_text() == "Батерија":
-                if specification.find('i').get_text() != "/":
-                    battery = specification.find('i').get_text().strip()
-                else:
-                    battery = None
-
-        new_offers.append(PhoneOffer(offer_shop, offer_name, price, ram_memory, rom_memory,
-                                     color, front_camera, back_camera, chipset, battery, operating_system, cpu,
-                                     image_url,
-                                     offer_url, last_updated, is_validated, offer_description, offer_shop_code))
-
-
-for new_offer in new_offers:
-    flag = False
-    flag_price = False
-    offer_id = None
+            price = int(float(phone.find('div', {'class', 'post-content'}).find_all('h2')[1] \
+                              .get_text().replace('ден.', '').replace('.', '').strip()))  # price
+
+            response2 = requests.get(offer_url)
+            soup2 = BeautifulSoup(response2.content, 'html.parser')
+
+            brand = soup2.find('a', {'rel': 'category tag'}).get_text().strip()  # brand
+
+            if brand not in offer_name:
+                offer_name = brand + " " + offer_name
+
+            specifications = soup2.find('table', {'id': 'singlet'}).find_all('tr')
+
+            ram_memory = None
+            rom_memory = None
+            battery = None
+            back_camera = None
+            front_camera = None
+            chipset = None
+            operating_system = None
+            cpu = None
+            offer_shop_code = None
+            offer_description = None
+            color = None
+
+            for specification in specifications:
+                if specification.find('td') == None:
+                    continue
+
+                # operating system
+                if specification.find('td').get_text() == "Платформа":
+                    if specification.find('i').get_text() != "/":
+                        operating_system = specification.find('i').get_text().strip()
+                    else:
+                        operating_system = None
+
+                # chipset
+                if specification.find('td').get_text() == "Chipset":
+                    if specification.find('i').get_text() != "/":
+                        chipset = specification.find('i').get_text().strip()
+                    else:
+                        chipset = None
+
+                # ram and rom memory
+                if specification.find('td').get_text() == "Меморија":
+                    if specification.find('i').get_text() != "/":
+                        rom_memory = specification.find('i').get_text().replace(',', '').split(' ')[0].strip()
+                        ram_memory = specification.find('i').get_text().replace(',', '').split(' ')[1].strip()
+                    else:
+                        rom_memory = None
+                        ram_memory = None
+
+                # back camera
+                if specification.find('td').get_text() == "Главна Камера":
+                    if specification.find('i').get_text() != "/":
+                        back_camera = specification.find('i').get_text().strip()
+                    else:
+                        back_camera = None
+
+                # front camera
+                if specification.find('td').get_text() == "Селфи Камера":
+                    if specification.find('i').get_text() != "/":
+                        front_camera = specification.find('i').get_text().strip()
+                    else:
+                        front_camera = None
+
+                # battery
+                if specification.find('td').get_text() == "Батерија":
+                    if specification.find('i').get_text() != "/":
+                        battery = specification.find('i').get_text().strip()
+                    else:
+                        battery = None
+
+            new_offers.append(PhoneOffer(offer_shop, offer_name, price, ram_memory, rom_memory,
+                                         color, front_camera, back_camera, chipset, battery, operating_system, cpu,
+                                         image_url,
+                                         offer_url, last_updated, is_validated, offer_description, offer_shop_code))
+
+
+    for new_offer in new_offers:
+        flag = False
+        flag_price = False
+        offer_id = None
+
+        for old_offer in database_offers:
+
+            if new_offer.offer_name == old_offer.offer_name:
+                flag = True
+                if new_offer.price != old_offer.price:
+                    flag_price = True
+                    offer_id = old_offer.offer_id
+
+        if flag:
+            print('ALREADY IN DATABASE')
+            print(new_offer)
+            # if it's already in database, check PRICE and if it's changed, change it !!!!!!
+            if flag_price:
+                print('PRICE CHANGED!')  # CHANGE PRICE
+                print('offer id: ' + str(offer_id))
+                headers = {'Content-type': 'application/json'}
+                requests.put('http://localhost:8080/phoneoffer/' + str(offer_id) + '/changeprice/' + str(new_offer.price),
+                             headers=headers)
+        else:
+            print('ADDED')  # ADD OFFER
+            print(new_offer)
+            headers = {'Content-type': 'application/json'}
+            requests.post('http://localhost:8080/phoneoffer/addoffer',
+                          headers=headers, data=json.dumps(new_offer.__dict__, default=str))
+
+    print('------------------------------------')
 
     for old_offer in database_offers:
-
-        if new_offer.offer_name == old_offer.offer_name:
-            flag = True
-            if new_offer.price != old_offer.price:
-                flag_price = True
-                offer_id = old_offer.offer_id
-
-    if flag:
-        print('ALREADY IN DATABASE')
-        print(new_offer)
-        # if it's already in database, check PRICE and if it's changed, change it !!!!!!
-        if flag_price:
-            print('PRICE CHANGED!')  # CHANGE PRICE
-            print('offer id: ' + str(offer_id))
-            headers = {'Content-type': 'application/json'}
-            requests.put('http://localhost:8080/phoneoffer/' + str(offer_id) + '/changeprice/' + str(new_offer.price),
-                         headers=headers)
-    else:
-        print('ADDED')  # ADD OFFER
-        print(new_offer)
-        headers = {'Content-type': 'application/json'}
-        requests.post('http://localhost:8080/phoneoffer/addoffer',
-                      headers=headers, data=json.dumps(new_offer.__dict__, default=str))
-
-print('------------------------------------')
-
-for old_offer in database_offers:
-    flag = False
-    for new_offer in new_offers:
-        if old_offer.offer_name == new_offer.offer_name:
-            flag = True
-
-    if not flag:
-        print('OFFER DELETED')
-        print(old_offer)
-        # DELETE OFFER
-        requests.delete('http://localhost:8080/phoneoffer/deleteoffer/' + str(old_offer.offer_id))
+        flag = False
+        for new_offer in new_offers:
+            if old_offer.offer_name == new_offer.offer_name:
+                flag = True
+
+        if not flag:
+            print('OFFER DELETED')
+            print(old_offer)
+            # DELETE OFFER
+            requests.delete('http://localhost:8080/phoneoffer/deleteoffer/' + str(old_offer.offer_id))
+except Exception:
+    traceback.print_exc()
+    insert_script = 'INSERT INTO scrapper_info (store, recieved_at, status)' \
+                    ' VALUES (%s, %s, %s);'
+    insert_value = (offer_shop, last_updated, 'failed')
+    cur.execute(insert_script, insert_value)
+    db_connection.commit()
+    cur.close()
+    db_connection.close()
+else:
+    insert_script = 'INSERT INTO scrapper_info (store, recieved_at, status)' \
+                    ' VALUES (%s, %s, %s);'
+    insert_value = (offer_shop, last_updated, 'success')
+    cur.execute(insert_script, insert_value)
+    db_connection.commit()
+    cur.close()
+    db_connection.close()
Index: phonelux_scrappers/scrappers/mobilezone_scrapper.py
===================================================================
--- phonelux_scrappers/scrappers/mobilezone_scrapper.py	(revision ffd50db1e5e2b9839ba7546d8ca44b600150bd71)
+++ phonelux_scrappers/scrappers/mobilezone_scrapper.py	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
@@ -1,3 +1,4 @@
 import json
+import traceback
 import unicodedata
 from datetime import datetime
@@ -18,140 +19,167 @@
 is_validated = False
 
-# Mobile Zone phone offers that are already in database
+# Call to read the configuration file and connect to database
+cinfo = config_read.get_databaseconfig("../postgresdb.config")
+db_connection = psycopg2.connect(
+    database=cinfo[0],
+    host=cinfo[1],
+    user=cinfo[2],
+    password=cinfo[3]
+)
+cur = db_connection.cursor()
 
-offers = json.loads(unicodedata.normalize('NFKD', requests.get('http://localhost:8080/phoneoffer/shop/mobilezone').text))
+try:
+    # Mobile Zone phone offers that are already in database
+    offers = json.loads(unicodedata.normalize('NFKD', requests.get('http://localhost:8080/phoneoffer/shop/mobilezone').text))
 
-database_offers = []
+    database_offers = []
 
-for offer in offers:
-    phoneOffer = PhoneOffer(offer['id'], offer['offer_shop'], offer['offer_name'], offer['price'],
-                            offer['ram_memory'],
-                            offer['rom_memory'], offer['color'], offer['front_camera'], offer['back_camera'],
-                            offer['chipset'], offer['battery'], offer['operating_system'], offer['cpu'],
-                            offer['image_url'],
-                            offer['offer_url'], offer['last_updated'], offer['is_validated'],
-                            offer['offer_description'],
-                            offer['offer_shop_code'])
-    database_offers.append(phoneOffer)
+    for offer in offers:
+        phoneOffer = PhoneOffer(offer['id'], offer['offer_shop'], offer['offer_name'], offer['price'],
+                                offer['ram_memory'],
+                                offer['rom_memory'], offer['color'], offer['front_camera'], offer['back_camera'],
+                                offer['chipset'], offer['battery'], offer['operating_system'], offer['cpu'],
+                                offer['image_url'],
+                                offer['offer_url'], offer['last_updated'], offer['is_validated'],
+                                offer['offer_description'],
+                                offer['offer_shop_code'])
+        database_offers.append(phoneOffer)
 
-new_offers = []
+    new_offers = []
 
-for i in range(1, 3):
-    mobilezone_url = 'https://mobilezone.mk/produkt-kategorija/telefoni/novi-telefoni/page/' + str(i) + '/'
+    for i in range(1, 3):
+        mobilezone_url = 'https://mobilezone.mk/produkt-kategorija/telefoni/novi-telefoni/page/' + str(i) + '/'
 
-    response1 = requests.get(mobilezone_url)
-    soup1 = BeautifulSoup(response1.content, 'html.parser')
+        response1 = requests.get(mobilezone_url)
+        soup1 = BeautifulSoup(response1.content, 'html.parser')
 
-    phones = soup1.find('ul', {
-        'class': 'products columns-tablet-2 columns-mobile-2 --skin-proto rey-wcGap-default rey-wcGrid-default '
-                 '--paginated columns-4'}).find_all('li')
+        phones = soup1.find('ul', {
+            'class': 'products columns-tablet-2 columns-mobile-2 --skin-proto rey-wcGap-default rey-wcGrid-default '
+                     '--paginated columns-4'}).find_all('li')
 
-    for phone in phones:
-        offer_url = phone.find('a', {'class': 'woocommerce-LoopProduct-link woocommerce-loop-product__link'}).get(
-            'href')
-        image_url = phone.find('a', {'class': 'woocommerce-LoopProduct-link woocommerce-loop-product__link'}) \
-            .find('img').get('data-lazy-src')
+        for phone in phones:
+            offer_url = phone.find('a', {'class': 'woocommerce-LoopProduct-link woocommerce-loop-product__link'}).get(
+                'href')
+            image_url = phone.find('a', {'class': 'woocommerce-LoopProduct-link woocommerce-loop-product__link'}) \
+                .find('img').get('data-lazy-src')
 
-        brand_section = phone.find('div', {'class': 'rey-productInner'}).find('div', {'class': 'rey-brandLink'})
+            brand_section = phone.find('div', {'class': 'rey-productInner'}).find('div', {'class': 'rey-brandLink'})
 
-        if brand_section is not None:
-            brand = brand_section.find('a').get_text().strip()
+            if brand_section is not None:
+                brand = brand_section.find('a').get_text().strip()
+            else:
+                brand = None
+
+            offer_name = phone.find('h2', {'class': 'woocommerce-loop-product__title'}).find('a').get_text().strip()
+
+            if brand is not None and brand not in offer_name:
+                offer_name = brand + ' ' + offer_name
+
+            price_tag = phone.find('span', {'class': 'woocommerce-Price-amount amount'})
+            price = None
+
+            if price_tag is not None:
+                price = int(unicodedata.normalize('NFKD', price_tag.find('bdi').get_text()
+                                              .replace(',', '')
+                                              .replace('ден', '').strip()))
+            else:
+                continue
+
+            response2 = requests.get(offer_url)
+            soup2 = BeautifulSoup(response2.text, 'html.parser')
+
+            specifications = soup2.find('table', {'class': 'woocommerce-product-attributes shop_attributes'}).find_all('tr')
+
+            back_camera = None
+            front_camera = None
+            rom_memory = None
+            ram_memory = None
+            operating_system = None
+            cpu = None
+            chipset = None
+            offer_description = None
+            offer_shop_code = None
+            battery = None
+            color = None
+
+            for specification in specifications:
+                if 'Главна камера' in specification.find('th').get_text():
+                    back_camera = specification.find('td').get_text().strip()
+
+                if 'Селфи камера' in specification.find('th').get_text():
+                    front_camera = specification.find('td').get_text().strip()
+
+                if 'Батерија' in specification.find('th').get_text():
+                    battery = specification.find('td').get_text().strip()
+
+                if 'Меморија' in specification.find('th').get_text():
+                    rom_memory = specification.find('td').get_text().strip()
+
+                if 'Боја' in specification.find('th').get_text():
+                    color = specification.find('td').get_text().strip()
+
+            new_offers.append(PhoneOffer(offer_shop, offer_name, price, ram_memory, rom_memory,
+                                         color, front_camera, back_camera, chipset, battery, operating_system, cpu,
+                                         image_url,
+                                         offer_url, last_updated, is_validated, offer_description, offer_shop_code))
+
+    for new_offer in new_offers:
+        flag = False
+        flag_price = False
+        offer_id = None
+
+        for old_offer in database_offers:
+
+            if new_offer.offer_name == old_offer.offer_name:
+                flag = True
+                if new_offer.price != old_offer.price:
+                    flag_price = True
+                    offer_id = old_offer.offer_id
+
+        if flag:
+            # print('ALREADY IN DATABASE')
+            # print(new_offer)
+            # if it's already in database, check PRICE and if it's changed, change it !!!!!!
+            if flag_price:
+                print('PRICE CHANGED!')  # CHANGE PRICE
+                print('offer id: ' + str(offer_id))
+                headers = {'Content-type': 'application/json'}
+                requests.put('http://localhost:8080/phoneoffer/' + str(offer_id) + '/changeprice/' + str(new_offer.price),
+                             headers=headers)
         else:
-            brand = None
+            print('ADDED')  # ADD OFFER
+            print(new_offer)
+            headers = {'Content-type': 'application/json'}
+            requests.post('http://localhost:8080/phoneoffer/addoffer',
+                          headers=headers, data=json.dumps(new_offer.__dict__, default=str))
 
-        offer_name = phone.find('h2', {'class': 'woocommerce-loop-product__title'}).find('a').get_text().strip()
-
-        if brand is not None and brand not in offer_name:
-            offer_name = brand + ' ' + offer_name
-
-        price_tag = phone.find('span', {'class': 'woocommerce-Price-amount amount'})
-        price = None
-
-        if price_tag is not None:
-            price = int(unicodedata.normalize('NFKD', price_tag.find('bdi').get_text()
-                                          .replace(',', '')
-                                          .replace('ден', '').strip()))
-        else:
-            continue
-
-        response2 = requests.get(offer_url)
-        soup2 = BeautifulSoup(response2.text, 'html.parser')
-
-        specifications = soup2.find('table', {'class': 'woocommerce-product-attributes shop_attributes'}).find_all('tr')
-
-        back_camera = None
-        front_camera = None
-        rom_memory = None
-        ram_memory = None
-        operating_system = None
-        cpu = None
-        chipset = None
-        offer_description = None
-        offer_shop_code = None
-        battery = None
-        color = None
-
-        for specification in specifications:
-            if 'Главна камера' in specification.find('th').get_text():
-                back_camera = specification.find('td').get_text().strip()
-
-            if 'Селфи камера' in specification.find('th').get_text():
-                front_camera = specification.find('td').get_text().strip()
-
-            if 'Батерија' in specification.find('th').get_text():
-                battery = specification.find('td').get_text().strip()
-
-            if 'Меморија' in specification.find('th').get_text():
-                rom_memory = specification.find('td').get_text().strip()
-
-            if 'Боја' in specification.find('th').get_text():
-                color = specification.find('td').get_text().strip()
-
-        new_offers.append(PhoneOffer(offer_shop, offer_name, price, ram_memory, rom_memory,
-                                     color, front_camera, back_camera, chipset, battery, operating_system, cpu,
-                                     image_url,
-                                     offer_url, last_updated, is_validated, offer_description, offer_shop_code))
-
-for new_offer in new_offers:
-    flag = False
-    flag_price = False
-    offer_id = None
+    print('------------------------------------')
 
     for old_offer in database_offers:
+        flag = False
+        for new_offer in new_offers:
+            if old_offer.offer_name == new_offer.offer_name:
+                flag = True
 
-        if new_offer.offer_name == old_offer.offer_name:
-            flag = True
-            if new_offer.price != old_offer.price:
-                flag_price = True
-                offer_id = old_offer.offer_id
-
-    if flag:
-        # print('ALREADY IN DATABASE')
-        # print(new_offer)
-        # if it's already in database, check PRICE and if it's changed, change it !!!!!!
-        if flag_price:
-            print('PRICE CHANGED!')  # CHANGE PRICE
-            print('offer id: ' + str(offer_id))
-            headers = {'Content-type': 'application/json'}
-            requests.put('http://localhost:8080/phoneoffer/' + str(offer_id) + '/changeprice/' + str(new_offer.price),
-                         headers=headers)
-    else:
-        print('ADDED')  # ADD OFFER
-        print(new_offer)
-        headers = {'Content-type': 'application/json'}
-        requests.post('http://localhost:8080/phoneoffer/addoffer',
-                      headers=headers, data=json.dumps(new_offer.__dict__, default=str))
-
-print('------------------------------------')
-
-for old_offer in database_offers:
-    flag = False
-    for new_offer in new_offers:
-        if old_offer.offer_name == new_offer.offer_name:
-            flag = True
-
-    if not flag:
-        print('OFFER DELETED')
-        print(old_offer)
-        # DELETE OFFER
-        requests.delete('http://localhost:8080/phoneoffer/deleteoffer/' + str(old_offer.offer_id))
+        if not flag:
+            print('OFFER DELETED')
+            print(old_offer)
+            # DELETE OFFER
+            requests.delete('http://localhost:8080/phoneoffer/deleteoffer/' + str(old_offer.offer_id))
+except Exception:
+    traceback.print_exc()
+    insert_script = 'INSERT INTO scrapper_info (store, recieved_at, status)' \
+                    ' VALUES (%s, %s, %s);'
+    insert_value = (offer_shop, last_updated, 'failed')
+    cur.execute(insert_script, insert_value)
+    db_connection.commit()
+    cur.close()
+    db_connection.close()
+else:
+    insert_script = 'INSERT INTO scrapper_info (store, recieved_at, status)' \
+                    ' VALUES (%s, %s, %s);'
+    insert_value = (offer_shop, last_updated, 'success')
+    cur.execute(insert_script, insert_value)
+    db_connection.commit()
+    cur.close()
+    db_connection.close()
Index: phonelux_scrappers/scrappers/mobitech_scrapper.py
===================================================================
--- phonelux_scrappers/scrappers/mobitech_scrapper.py	(revision ffd50db1e5e2b9839ba7546d8ca44b600150bd71)
+++ phonelux_scrappers/scrappers/mobitech_scrapper.py	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
@@ -1,3 +1,4 @@
 import json
+import traceback
 import unicodedata
 from datetime import datetime
@@ -14,142 +15,168 @@
 sys.stdout = open(file_path, "w")
 
-
-mobitech_url = "https://mobitech.mk/shop/"
-
-response1 = requests.get(mobitech_url)
-
-soup1 = BeautifulSoup(response1.content, 'html.parser')
-
-phones = soup1.find_all('div', {'class': 'jet-woo-products__inner-box'})
-
 offer_shop = "Mobitech"  # offer shop
 last_updated = datetime.now().date()
 is_validated = False
 
-# Mobitech phone offers that are already in database
+# Call to read the configuration file and connect to database
+cinfo = config_read.get_databaseconfig("../postgresdb.config")
+db_connection = psycopg2.connect(
+    database=cinfo[0],
+    host=cinfo[1],
+    user=cinfo[2],
+    password=cinfo[3]
+)
+cur = db_connection.cursor()
 
-offers = json.loads(unicodedata.normalize('NFKD', requests.get('http://localhost:8080/phoneoffer/shop/mobitech').text))
+try:
+    mobitech_url = "https://mobitech.mk/shop/"
 
-database_offers = []
+    response1 = requests.get(mobitech_url)
 
-for offer in offers:
-    phoneOffer = PhoneOffer(offer['id'], offer['offer_shop'], offer['offer_name'], offer['price'],
-                            offer['ram_memory'],
-                            offer['rom_memory'], offer['color'], offer['front_camera'], offer['back_camera'],
-                            offer['chipset'], offer['battery'], offer['operating_system'], offer['cpu'],
-                            offer['image_url'],
-                            offer['offer_url'], offer['last_updated'], offer['is_validated'],
-                            offer['offer_description'],
-                            offer['offer_shop_code'])
-    database_offers.append(phoneOffer)
+    soup1 = BeautifulSoup(response1.content, 'html.parser')
 
-new_offers = []
+    phones = soup1.find_all('div', {'class': 'jet-woo-products__inner-box'})
 
-for phone in phones:
-    offer_url = phone.find('h5', {'class': 'jet-woo-product-title'}).find('a').get('href')  # url
-    image_url = phone.find('div', {'class': 'jet-woo-product-thumbnail'}).find('img').get('src')  # image
-    brand = phone.find_next('div', {'class': 'jet-woo-product-categories'}).find('a').get_text().strip()  # brand
-    offer_name = phone.find('h5', {'class': 'jet-woo-product-title'}).find('a').get_text().strip()  # offer_name
-    if brand not in offer_name:
-        offer_name = brand+" "+offer_name
-    temp_prices = phone.find('div', {'class': 'jet-woo-product-price'}).find_all('bdi')
-    price = int(float(temp_prices[len(temp_prices) - 1].get_text().replace("ден", "").replace(",", "").strip())) # price
+    # Mobitech phone offers that are already in database
+    offers = json.loads(unicodedata.normalize('NFKD', requests.get('http://localhost:8080/phoneoffer/shop/mobitech').text))
 
-    response2 = requests.get(offer_url)
-    soup2 = BeautifulSoup(response2.content, 'html.parser')
+    database_offers = []
 
-    specifications = soup2.find_all('h2', {'class': 'elementor-heading-title elementor-size-default'})
+    for offer in offers:
+        phoneOffer = PhoneOffer(offer['id'], offer['offer_shop'], offer['offer_name'], offer['price'],
+                                offer['ram_memory'],
+                                offer['rom_memory'], offer['color'], offer['front_camera'], offer['back_camera'],
+                                offer['chipset'], offer['battery'], offer['operating_system'], offer['cpu'],
+                                offer['image_url'],
+                                offer['offer_url'], offer['last_updated'], offer['is_validated'],
+                                offer['offer_description'],
+                                offer['offer_shop_code'])
+        database_offers.append(phoneOffer)
 
-    ram_memory = None
-    rom_memory = None
-    battery = None
-    back_camera = None
-    front_camera = None
-    operating_system = None
-    chipset = None
-    color = None
-    offer_shop_code = None
-    cpu = None
-    offer_description = None
+    new_offers = []
 
-    for specification in specifications:
-        # rom memory
-        if specification.get_text().startswith("Меморија:"):
-            rom_memory = specification.get_text().split("Меморија:")[1].strip()
-            if rom_memory == "Нема" or rom_memory == "/":
-                rom_memory = None
+    for phone in phones:
+        offer_url = phone.find('h5', {'class': 'jet-woo-product-title'}).find('a').get('href')  # url
+        image_url = phone.find('div', {'class': 'jet-woo-product-thumbnail'}).find('img').get('src')  # image
+        brand = phone.find_next('div', {'class': 'jet-woo-product-categories'}).find('a').get_text().strip()  # brand
+        offer_name = phone.find('h5', {'class': 'jet-woo-product-title'}).find('a').get_text().strip()  # offer_name
+        if brand not in offer_name:
+            offer_name = brand+" "+offer_name
+        temp_prices = phone.find('div', {'class': 'jet-woo-product-price'}).find_all('bdi')
+        price = int(float(temp_prices[len(temp_prices) - 1].get_text().replace("ден", "").replace(",", "").strip())) # price
 
-        # ram memory
-        if specification.get_text().startswith("РАМ Меморија:"):
-            ram_memory = specification.get_text().split("РАМ Меморија:")[1].replace('RAM', '')\
-                .replace('Ram', '').strip()
-            if ram_memory == "Нема" or ram_memory == "/":
-                ram_memory = None
+        response2 = requests.get(offer_url)
+        soup2 = BeautifulSoup(response2.content, 'html.parser')
 
-        # camera
-        if specification.get_text().startswith("Камера:"):
-            back_camera = specification.get_text().split("Камера:")[1].strip()
-            if back_camera == "Нема":
-                back_camera = None
+        specifications = soup2.find_all('h2', {'class': 'elementor-heading-title elementor-size-default'})
 
-        # operating system
-        if specification.get_text().startswith("Оперативен систем:"):
-            operating_system = specification.get_text().split("Оперативен систем:")[1].split(",")[0].strip()
-            if operating_system == "Нема":
-                operating_system = None
+        ram_memory = None
+        rom_memory = None
+        battery = None
+        back_camera = None
+        front_camera = None
+        operating_system = None
+        chipset = None
+        color = None
+        offer_shop_code = None
+        cpu = None
+        offer_description = None
 
-        # battery
-        if specification.get_text().startswith("Батерија:"):
-            battery = specification.get_text().split("Батерија:")[1].strip()
-            if battery == "Нема":
-                battery = None
+        for specification in specifications:
+            # rom memory
+            if specification.get_text().startswith("Меморија:"):
+                rom_memory = specification.get_text().split("Меморија:")[1].strip()
+                if rom_memory == "Нема" or rom_memory == "/":
+                    rom_memory = None
 
-    new_offers.append(PhoneOffer(offer_shop, offer_name, price, ram_memory, rom_memory,
-                                 color, front_camera, back_camera, chipset, battery, operating_system, cpu,
-                                 image_url,
-                                 offer_url, last_updated, is_validated, offer_description, offer_shop_code))
+            # ram memory
+            if specification.get_text().startswith("РАМ Меморија:"):
+                ram_memory = specification.get_text().split("РАМ Меморија:")[1].replace('RAM', '')\
+                    .replace('Ram', '').strip()
+                if ram_memory == "Нема" or ram_memory == "/":
+                    ram_memory = None
 
-for new_offer in new_offers:
-    flag = False
-    flag_price = False
-    offer_id = None
+            # camera
+            if specification.get_text().startswith("Камера:"):
+                back_camera = specification.get_text().split("Камера:")[1].strip()
+                if back_camera == "Нема":
+                    back_camera = None
+
+            # operating system
+            if specification.get_text().startswith("Оперативен систем:"):
+                operating_system = specification.get_text().split("Оперативен систем:")[1].split(",")[0].strip()
+                if operating_system == "Нема":
+                    operating_system = None
+
+            # battery
+            if specification.get_text().startswith("Батерија:"):
+                battery = specification.get_text().split("Батерија:")[1].strip()
+                if battery == "Нема":
+                    battery = None
+
+        new_offers.append(PhoneOffer(offer_shop, offer_name, price, ram_memory, rom_memory,
+                                     color, front_camera, back_camera, chipset, battery, operating_system, cpu,
+                                     image_url,
+                                     offer_url, last_updated, is_validated, offer_description, offer_shop_code))
+
+    for new_offer in new_offers:
+        flag = False
+        flag_price = False
+        offer_id = None
+
+        for old_offer in database_offers:
+
+            if new_offer.offer_name == old_offer.offer_name:
+                flag = True
+                if new_offer.price != old_offer.price:
+                    flag_price = True
+                    offer_id = old_offer.offer_id
+
+        if flag:
+            print('ALREADY IN DATABASE')
+            print(new_offer)
+            # if it's already in database, check PRICE and if it's changed, change it !!!!!!
+            if flag_price:
+                print('PRICE CHANGED!')  # CHANGE PRICE
+                print('offer id: ' + str(offer_id))
+                headers = {'Content-type': 'application/json'}
+                requests.put('http://localhost:8080/phoneoffer/' + str(offer_id) + '/changeprice/' + str(new_offer.price),
+                             headers=headers)
+        else:
+            print('ADDED')  # ADD OFFER
+            print(new_offer)
+            headers = {'Content-type': 'application/json'}
+            requests.post('http://localhost:8080/phoneoffer/addoffer',
+                          headers=headers, data=json.dumps(new_offer.__dict__, default=str))
+
+    print('------------------------------------')
 
     for old_offer in database_offers:
+        flag = False
+        for new_offer in new_offers:
+            if old_offer.offer_name == new_offer.offer_name:
+                flag = True
 
-        if new_offer.offer_name == old_offer.offer_name:
-            flag = True
-            if new_offer.price != old_offer.price:
-                flag_price = True
-                offer_id = old_offer.offer_id
+        if not flag:
+            print('OFFER DELETED')
+            print(old_offer)
+            # DELETE OFFER
+            requests.delete('http://localhost:8080/phoneoffer/deleteoffer/' + str(old_offer.offer_id))
+except Exception:
+    traceback.print_exc()
+    insert_script = 'INSERT INTO scrapper_info (store, recieved_at, status)' \
+                    ' VALUES (%s, %s, %s);'
+    insert_value = (offer_shop, last_updated, 'failed')
+    cur.execute(insert_script, insert_value)
+    db_connection.commit()
+    cur.close()
+    db_connection.close()
+else:
+    insert_script = 'INSERT INTO scrapper_info (store, recieved_at, status)' \
+                    ' VALUES (%s, %s, %s);'
+    insert_value = (offer_shop, last_updated, 'success')
+    cur.execute(insert_script, insert_value)
+    db_connection.commit()
+    cur.close()
+    db_connection.close()
 
-    if flag:
-        print('ALREADY IN DATABASE')
-        print(new_offer)
-        # if it's already in database, check PRICE and if it's changed, change it !!!!!!
-        if flag_price:
-            print('PRICE CHANGED!')  # CHANGE PRICE
-            print('offer id: ' + str(offer_id))
-            headers = {'Content-type': 'application/json'}
-            requests.put('http://localhost:8080/phoneoffer/' + str(offer_id) + '/changeprice/' + str(new_offer.price),
-                         headers=headers)
-    else:
-        print('ADDED')  # ADD OFFER
-        print(new_offer)
-        headers = {'Content-type': 'application/json'}
-        requests.post('http://localhost:8080/phoneoffer/addoffer',
-                      headers=headers, data=json.dumps(new_offer.__dict__, default=str))
-
-print('------------------------------------')
-
-for old_offer in database_offers:
-    flag = False
-    for new_offer in new_offers:
-        if old_offer.offer_name == new_offer.offer_name:
-            flag = True
-
-    if not flag:
-        print('OFFER DELETED')
-        print(old_offer)
-        # DELETE OFFER
-        requests.delete('http://localhost:8080/phoneoffer/deleteoffer/' + str(old_offer.offer_id))
-
Index: phonelux_scrappers/scrappers/neptun_scrapper.py
===================================================================
--- phonelux_scrappers/scrappers/neptun_scrapper.py	(revision ffd50db1e5e2b9839ba7546d8ca44b600150bd71)
+++ phonelux_scrappers/scrappers/neptun_scrapper.py	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
@@ -1,3 +1,4 @@
 import json
+import traceback
 import unicodedata
 from datetime import datetime
@@ -19,152 +20,179 @@
 is_validated = False
 
-# Neptun phone offers that are already in database
+# Call to read the configuration file and connect to database
+cinfo = config_read.get_databaseconfig("../postgresdb.config")
+db_connection = psycopg2.connect(
+    database=cinfo[0],
+    host=cinfo[1],
+    user=cinfo[2],
+    password=cinfo[3]
+)
+cur = db_connection.cursor()
 
-offers = json.loads(unicodedata.normalize('NFKD', requests.get('http://localhost:8080/phoneoffer/shop/neptun').text))
+try:
+    # Neptun phone offers that are already in database
+    offers = json.loads(unicodedata.normalize('NFKD', requests.get('http://localhost:8080/phoneoffer/shop/neptun').text))
 
-database_offers = []
+    database_offers = []
 
-for offer in offers:
-    phoneOffer = PhoneOffer(offer['id'], offer['offer_shop'], offer['offer_name'], offer['price'],
-                            offer['ram_memory'],
-                            offer['rom_memory'], offer['color'], offer['front_camera'], offer['back_camera'],
-                            offer['chipset'], offer['battery'], offer['operating_system'], offer['cpu'],
-                            offer['image_url'],
-                            offer['offer_url'], offer['last_updated'], offer['is_validated'],
-                            offer['offer_description'],
-                            offer['offer_shop_code'])
-    database_offers.append(phoneOffer)
+    for offer in offers:
+        phoneOffer = PhoneOffer(offer['id'], offer['offer_shop'], offer['offer_name'], offer['price'],
+                                offer['ram_memory'],
+                                offer['rom_memory'], offer['color'], offer['front_camera'], offer['back_camera'],
+                                offer['chipset'], offer['battery'], offer['operating_system'], offer['cpu'],
+                                offer['image_url'],
+                                offer['offer_url'], offer['last_updated'], offer['is_validated'],
+                                offer['offer_description'],
+                                offer['offer_shop_code'])
+        database_offers.append(phoneOffer)
 
-new_offers = []
+    new_offers = []
 
-for i in range(1, 11):
-    neptun_url = 'https://www.neptun.mk/mobilni_telefoni.nspx?page=' + str(i)
+    for i in range(1, 11):
+        neptun_url = 'https://www.neptun.mk/mobilni_telefoni.nspx?page=' + str(i)
 
-    # selenium is used because of the dynamic content of the page
-    driver1 = webdriver.Safari(executable_path='/usr/bin/safaridriver')
-    driver1.get(neptun_url)
-    neptun_html = driver1.page_source
+        # selenium is used because of the dynamic content of the page
+        driver1 = webdriver.Safari(executable_path='/usr/bin/safaridriver')
+        driver1.get(neptun_url)
+        neptun_html = driver1.page_source
 
-    # closing the driver so the safari instance can pair with another webdriver session
-    driver1.close()
-
-    # response1 = requests.get(neptun_url)
-    soup1 = BeautifulSoup(neptun_html, 'html.parser')
-
-    phones = soup1.find('div', {'id': 'mainContainer'}).find('div',
-                                                             {'class': 'col-lg-9 col-md-9 col-sm-8 col-fix-main'}) \
-        .find_all('div', {'class': 'ng-scope product-list-item-grid'})
-
-    for phone in phones:
-        offer_url = 'https://www.neptun.mk' + phone.find('a').get('href')
-        offer_name = phone.find('a').find('h2').get_text().replace('MOB.TEL.', '').strip()
-        brand = offer_name.split(' ')[0].strip().capitalize()
-        image_url = 'https://www.neptun.mk' + phone.find('a').find('div', {'class': 'row'}).find('img').get('src')
-        price = int(
-            phone.find('div', {'class': 'col-sm-12 static'}).find('div', {'class': 'product-list-item__prices pt35'})
-            .find('div', {'class': 'row'}).find('div', {'class': 'newPriceModel'}) \
-            .find('span', {'class': 'product-price__amount--value ng-binding'}).get_text().replace('.', ''))
-
-        driver1 = webdriver.Safari(executable_path='/usr/bin/safaridriver')
-        driver1.get(offer_url)
-        offer_html = driver1.page_source
         # closing the driver so the safari instance can pair with another webdriver session
         driver1.close()
 
-        soup2 = BeautifulSoup(offer_html, 'html.parser')
+        # response1 = requests.get(neptun_url)
+        soup1 = BeautifulSoup(neptun_html, 'html.parser')
 
-        offer_shop_code = soup2.find('div', {'ng-if': 'showProductDetails'}) \
-            .find('div', {'class': 'product-details-first-row'}).find('span', {
-            'ng-bind': 'model.CodeNumber'}).get_text().strip()
+        phones = soup1.find('div', {'id': 'mainContainer'}).find('div',
+                                                                 {'class': 'col-lg-9 col-md-9 col-sm-8 col-fix-main'}) \
+            .find_all('div', {'class': 'ng-scope product-list-item-grid'})
 
-        specifications_table = \
-            soup2.find('div', {'id': 'mainContainer'}).find('div', {'ng-if': 'showProductDetails'}).find_all('ul')[-1]
-        specifications = specifications_table.get_text(separator='\n').strip().split("\n")
+        for phone in phones:
+            offer_url = 'https://www.neptun.mk' + phone.find('a').get('href')
+            offer_name = phone.find('a').find('h2').get_text().replace('MOB.TEL.', '').strip()
+            brand = offer_name.split(' ')[0].strip().capitalize()
+            image_url = 'https://www.neptun.mk' + phone.find('a').find('div', {'class': 'row'}).find('img').get('src')
+            price = int(
+                phone.find('div', {'class': 'col-sm-12 static'}).find('div', {'class': 'product-list-item__prices pt35'})
+                .find('div', {'class': 'row'}).find('div', {'class': 'newPriceModel'}) \
+                .find('span', {'class': 'product-price__amount--value ng-binding'}).get_text().replace('.', ''))
 
-        offer_description = specifications_table.get_text(separator='\n').strip()
+            driver1 = webdriver.Safari(executable_path='/usr/bin/safaridriver')
+            driver1.get(offer_url)
+            offer_html = driver1.page_source
+            # closing the driver so the safari instance can pair with another webdriver session
+            driver1.close()
 
-        back_camera = None
-        operating_system = None
-        chipset = None
-        battery = None
-        ram_memory = None
-        rom_memory = None
-        cpu = None
-        front_camera = None
-        color = None
+            soup2 = BeautifulSoup(offer_html, 'html.parser')
 
-        for specification in specifications:
-            if 'Батерија:' in specification:
-                battery = specification.split('Батерија:')[1]
+            offer_shop_code = soup2.find('div', {'ng-if': 'showProductDetails'}) \
+                .find('div', {'class': 'product-details-first-row'}).find('span', {
+                'ng-bind': 'model.CodeNumber'}).get_text().strip()
 
-            if 'CPU:' in specification:
-                cpu = specification.split('CPU:')[1]
+            specifications_table = \
+                soup2.find('div', {'id': 'mainContainer'}).find('div', {'ng-if': 'showProductDetails'}).find_all('ul')[-1]
+            specifications = specifications_table.get_text(separator='\n').strip().split("\n")
 
-            if 'Chipset:' in specification:
-                chipset = specification.split('Chipset:')[1]
+            offer_description = specifications_table.get_text(separator='\n').strip()
 
-            if 'RAM Меморија:' in specification:
-                ram_memory = specification.split('RAM Меморија:')[1]
-                continue
+            back_camera = None
+            operating_system = None
+            chipset = None
+            battery = None
+            ram_memory = None
+            rom_memory = None
+            cpu = None
+            front_camera = None
+            color = None
 
-            if 'ROM Меморија:' in specification:
-                rom_memory = specification.split('ROM Меморија:')[1]
-                continue
+            for specification in specifications:
+                if 'Батерија:' in specification:
+                    battery = specification.split('Батерија:')[1]
 
-            if 'ROM:' in specification:
-                rom_memory = specification.split('ROM:')[1]
+                if 'CPU:' in specification:
+                    cpu = specification.split('CPU:')[1]
 
-            if 'RAM:' in specification:
-                ram_memory = specification.split('RAM:')[1]
+                if 'Chipset:' in specification:
+                    chipset = specification.split('Chipset:')[1]
 
-            if 'iOS' in specification or 'Android' in specification:
-                operating_system = specification
+                if 'RAM Меморија:' in specification:
+                    ram_memory = specification.split('RAM Меморија:')[1]
+                    continue
 
-        new_offers.append(PhoneOffer(offer_shop, offer_name, price, ram_memory, rom_memory,
-                                     color, front_camera, back_camera, chipset, battery, operating_system, cpu,
-                                     image_url,
-                                     offer_url, last_updated, is_validated, offer_description, offer_shop_code))
+                if 'ROM Меморија:' in specification:
+                    rom_memory = specification.split('ROM Меморија:')[1]
+                    continue
 
-for new_offer in new_offers:
-    flag = False
-    flag_price = False
-    offer_id = None
+                if 'ROM:' in specification:
+                    rom_memory = specification.split('ROM:')[1]
+
+                if 'RAM:' in specification:
+                    ram_memory = specification.split('RAM:')[1]
+
+                if 'iOS' in specification or 'Android' in specification:
+                    operating_system = specification
+
+            new_offers.append(PhoneOffer(offer_shop, offer_name, price, ram_memory, rom_memory,
+                                         color, front_camera, back_camera, chipset, battery, operating_system, cpu,
+                                         image_url,
+                                         offer_url, last_updated, is_validated, offer_description, offer_shop_code))
+
+    for new_offer in new_offers:
+        flag = False
+        flag_price = False
+        offer_id = None
+
+        for old_offer in database_offers:
+
+            if new_offer.offer_shop_code == old_offer.offer_shop_code:
+                flag = True
+                if new_offer.price != old_offer.price:
+                    flag_price = True
+                    offer_id = old_offer.offer_id
+
+        if flag:
+            # print('ALREADY IN DATABASE')
+            # print(new_offer)
+            # if it's already in database, check PRICE and if it's changed, change it !!!!!!
+            if flag_price:
+                print('PRICE CHANGED!')  # CHANGE PRICE
+                print('offer id: ' + str(offer_id))
+                headers = {'Content-type': 'application/json'}
+                requests.put('http://localhost:8080/phoneoffer/' + str(offer_id) + '/changeprice/' + str(new_offer.price),
+                             headers=headers)
+        else:
+            print('ADDED')  # ADD OFFER
+            print(new_offer)
+            headers = {'Content-type': 'application/json'}
+            requests.post('http://localhost:8080/phoneoffer/addoffer',
+                          headers=headers, data=json.dumps(new_offer.__dict__, default=str))
+
+    print('------------------------------------')
 
     for old_offer in database_offers:
+        flag = False
+        for new_offer in new_offers:
+            if old_offer.offer_shop_code == new_offer.offer_shop_code:
+                flag = True
 
-        if new_offer.offer_shop_code == old_offer.offer_shop_code:
-            flag = True
-            if new_offer.price != old_offer.price:
-                flag_price = True
-                offer_id = old_offer.offer_id
-
-    if flag:
-        # print('ALREADY IN DATABASE')
-        # print(new_offer)
-        # if it's already in database, check PRICE and if it's changed, change it !!!!!!
-        if flag_price:
-            print('PRICE CHANGED!')  # CHANGE PRICE
-            print('offer id: ' + str(offer_id))
-            headers = {'Content-type': 'application/json'}
-            requests.put('http://localhost:8080/phoneoffer/' + str(offer_id) + '/changeprice/' + str(new_offer.price),
-                         headers=headers)
-    else:
-        print('ADDED')  # ADD OFFER
-        print(new_offer)
-        headers = {'Content-type': 'application/json'}
-        requests.post('http://localhost:8080/phoneoffer/addoffer',
-                      headers=headers, data=json.dumps(new_offer.__dict__, default=str))
-
-print('------------------------------------')
-
-for old_offer in database_offers:
-    flag = False
-    for new_offer in new_offers:
-        if old_offer.offer_shop_code == new_offer.offer_shop_code:
-            flag = True
-
-    if not flag:
-        print('OFFER DELETED')
-        print(old_offer)
-        # DELETE OFFER
-        requests.delete('http://localhost:8080/phoneoffer/deleteoffer/' + str(old_offer.offer_id))
+        if not flag:
+            print('OFFER DELETED')
+            print(old_offer)
+            # DELETE OFFER
+            requests.delete('http://localhost:8080/phoneoffer/deleteoffer/' + str(old_offer.offer_id))
+except Exception:
+    traceback.print_exc()
+    insert_script = 'INSERT INTO scrapper_info (store, recieved_at, status)' \
+                    ' VALUES (%s, %s, %s);'
+    insert_value = (offer_shop, last_updated, 'failed')
+    cur.execute(insert_script, insert_value)
+    db_connection.commit()
+    cur.close()
+    db_connection.close()
+else:
+    insert_script = 'INSERT INTO scrapper_info (store, recieved_at, status)' \
+                    ' VALUES (%s, %s, %s);'
+    insert_value = (offer_shop, last_updated, 'success')
+    cur.execute(insert_script, insert_value)
+    db_connection.commit()
+    cur.close()
+    db_connection.close()
Index: phonelux_scrappers/scrappers/outputfile.txt
===================================================================
--- phonelux_scrappers/scrappers/outputfile.txt	(revision ffd50db1e5e2b9839ba7546d8ca44b600150bd71)
+++ phonelux_scrappers/scrappers/outputfile.txt	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
@@ -1,9 +1,0 @@
-ADDED
-{'offer_shop': 'Mobile Zone', 'offer_name': 'Apple iPhone 14 Pro', 'price': 95499, 'ram_memory': None, 'rom_memory': '128GB', 'color': 'Златна, Розева, Сива, Црна', 'front_camera': '12MP', 'back_camera': '48 Mp + 12 Mp + 12 Mp', 'chipset': None, 'battery': '3200mAh', 'operating_system': None, 'cpu': None, 'image_url': 'https://i0.wp.com/mobilezone.mk/wp-content/uploads/2022/09/14-pro-silver.png?resize=600%2C600&ssl=1', 'offer_url': 'https://mobilezone.mk/produkti/iphone-14-pro/', 'last_updated': datetime.date(2022, 10, 1), 'is_validated': False, 'offer_description': None, 'offer_shop_code': None}
-------------------------------------
-OFFER DELETED
-{'offer_id': 1179, 'offer_shop': 'Mobile Zone', 'offer_name': 'Samsung s20 FE', 'price': 24699, 'ram_memory': None, 'rom_memory': '128GB', 'color': 'Сина', 'front_camera': None, 'back_camera': None, 'chipset': None, 'battery': None, 'operating_system': None, 'cpu': None, 'image_url': 'https://i2.wp.com/mobilezone.mk/wp-content/uploads/2022/03/Samsung-Galaxy-S20-FE-blue.png?resize=512%2C600&ssl=1', 'offer_url': 'https://mobilezone.mk/produkti/samsung-s20-fe/', 'last_updated': '2022-07-29T22:00:00.000+00:00', 'is_validated': False, 'offer_description': None, 'offer_shop_code': None}
-OFFER DELETED
-{'offer_id': 1181, 'offer_shop': 'Mobile Zone', 'offer_name': 'Samsung Z Flip3 5G', 'price': 39999, 'ram_memory': None, 'rom_memory': '128GB', 'color': 'Црна', 'front_camera': None, 'back_camera': None, 'chipset': None, 'battery': None, 'operating_system': None, 'cpu': None, 'image_url': 'https://i2.wp.com/mobilezone.mk/wp-content/uploads/2022/03/11.png?resize=600%2C600&ssl=1', 'offer_url': 'https://mobilezone.mk/produkti/samsung-z-flip3-5g/', 'last_updated': '2022-07-29T22:00:00.000+00:00', 'is_validated': False, 'offer_description': None, 'offer_shop_code': None}
-OFFER DELETED
-{'offer_id': 1180, 'offer_shop': 'Mobile Zone', 'offer_name': 'Samsung S21 FE 5G', 'price': 30899, 'ram_memory': None, 'rom_memory': '128GB', 'color': 'Зелена, Црна', 'front_camera': None, 'back_camera': None, 'chipset': None, 'battery': None, 'operating_system': None, 'cpu': None, 'image_url': 'https://i1.wp.com/mobilezone.mk/wp-content/uploads/2022/03/5g.jpg?resize=600%2C600&ssl=1', 'offer_url': 'https://mobilezone.mk/produkti/samsung-s21-fe-5g/', 'last_updated': '2022-07-29T22:00:00.000+00:00', 'is_validated': False, 'offer_description': None, 'offer_shop_code': None}
Index: phonelux_scrappers/scrappers/setec_scrapper.py
===================================================================
--- phonelux_scrappers/scrappers/setec_scrapper.py	(revision ffd50db1e5e2b9839ba7546d8ca44b600150bd71)
+++ phonelux_scrappers/scrappers/setec_scrapper.py	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
@@ -1,3 +1,4 @@
 import json
+import traceback
 import unicodedata
 from datetime import datetime
@@ -17,117 +18,144 @@
 is_validated = False
 
-# Setec phone offers that are already in database
+# Call to read the configuration file and connect to database
+cinfo = config_read.get_databaseconfig("../postgresdb.config")
+db_connection = psycopg2.connect(
+    database=cinfo[0],
+    host=cinfo[1],
+    user=cinfo[2],
+    password=cinfo[3]
+)
+cur = db_connection.cursor()
 
-offers = json.loads(unicodedata.normalize('NFKD', requests.get('http://localhost:8080/phoneoffer/shop/setec').text))
+try:
+    # Setec phone offers that are already in database
+    offers = json.loads(unicodedata.normalize('NFKD', requests.get('http://localhost:8080/phoneoffer/shop/setec').text))
 
-database_offers = []
+    database_offers = []
 
-for offer in offers:
-    phoneOffer = PhoneOffer(offer['id'], offer['offer_shop'], offer['offer_name'], offer['price'],
-                            offer['ram_memory'],
-                            offer['rom_memory'], offer['color'], offer['front_camera'], offer['back_camera'],
-                            offer['chipset'], offer['battery'], offer['operating_system'], offer['cpu'],
-                            offer['image_url'],
-                            offer['offer_url'], offer['last_updated'], offer['is_validated'],
-                            offer['offer_description'],
-                            offer['offer_shop_code'])
-    database_offers.append(phoneOffer)
+    for offer in offers:
+        phoneOffer = PhoneOffer(offer['id'], offer['offer_shop'], offer['offer_name'], offer['price'],
+                                offer['ram_memory'],
+                                offer['rom_memory'], offer['color'], offer['front_camera'], offer['back_camera'],
+                                offer['chipset'], offer['battery'], offer['operating_system'], offer['cpu'],
+                                offer['image_url'],
+                                offer['offer_url'], offer['last_updated'], offer['is_validated'],
+                                offer['offer_description'],
+                                offer['offer_shop_code'])
+        database_offers.append(phoneOffer)
 
-new_offers = []
+    new_offers = []
 
-for i in range(1, 9):
-    setec_url = 'https://setec.mk/index.php?route=product/category&path=10066_10067&page=' + str(i)
+    for i in range(1, 9):
+        setec_url = 'https://setec.mk/index.php?route=product/category&path=10066_10067&page=' + str(i)
 
-    response1 = requests.get(setec_url)
-    soup1 = BeautifulSoup(response1.content, 'html.parser')
+        response1 = requests.get(setec_url)
+        soup1 = BeautifulSoup(response1.content, 'html.parser')
 
-    phones = soup1.find('div', {'id': 'mfilter-content-container'}) \
-        .find_all('div', {'class': 'col-sm-4 col-xs-6'})
+        phones = soup1.find('div', {'id': 'mfilter-content-container'}) \
+            .find_all('div', {'class': 'col-sm-4 col-xs-6'})
 
-    for phone in phones:
-        offer_url = phone.find('div', {'class': 'left'}).find('a').get('href')
-        image_url = phone.find('div', {'class': 'left'}).find('a').find('img').get('src')
-        offer_name = phone.find('div', {'class': 'right'}).find('div', {'class': 'name'}).find('a').get_text().strip()
-        brand = offer_name.split(' ')[0]
+        for phone in phones:
+            offer_url = phone.find('div', {'class': 'left'}).find('a').get('href')
+            image_url = phone.find('div', {'class': 'left'}).find('a').find('img').get('src')
+            offer_name = phone.find('div', {'class': 'right'}).find('div', {'class': 'name'}).find('a').get_text().strip()
+            brand = offer_name.split(' ')[0]
 
-        back_camera = None
-        operating_system = None
-        chipset = None
-        battery = None
-        ram_memory = None
-        rom_memory = None
-        cpu = None
-        front_camera = None
-        color = None
+            back_camera = None
+            operating_system = None
+            chipset = None
+            battery = None
+            ram_memory = None
+            rom_memory = None
+            cpu = None
+            front_camera = None
+            color = None
 
-        if 'Cable' in offer_name or 'AirTag' in offer_name:
-            continue
+            if 'Cable' in offer_name or 'AirTag' in offer_name:
+                continue
 
-        if brand not in offer_name:
-            offer_name = brand + " " + offer_name
+            if brand not in offer_name:
+                offer_name = brand + " " + offer_name
 
-        offer_shop_code = phone.find('div', {'class': 'right'}) \
-            .find('div', {'class': 'shifra'}).get_text().replace('Шифра:', '').strip()
+            offer_shop_code = phone.find('div', {'class': 'right'}) \
+                .find('div', {'class': 'shifra'}).get_text().replace('Шифра:', '').strip()
 
-        price_tag = phone.find('div', {'class': 'right'}).find('div', {'class': 'price'}). \
-            find('div', {'class': 'category-price-redovna'}).find('span', {'class': 'price-old-new'})
+            price_tag = phone.find('div', {'class': 'right'}).find('div', {'class': 'price'}). \
+                find('div', {'class': 'category-price-redovna'}).find('span', {'class': 'price-old-new'})
 
-        if price_tag is None:
-            price_tag = phone.find('div', {'class': 'right'}).find('div', {'class': 'price'}). \
-                find('div', {'class': 'category-price-redovna'}).find('span', {'class': 'cena_za_kesh'})
+            if price_tag is None:
+                price_tag = phone.find('div', {'class': 'right'}).find('div', {'class': 'price'}). \
+                    find('div', {'class': 'category-price-redovna'}).find('span', {'class': 'cena_za_kesh'})
 
-        price = int(price_tag.get_text().replace('Ден.', '').replace(',', '').strip())
+            price = int(price_tag.get_text().replace('Ден.', '').replace(',', '').strip())
 
-        response2 = requests.get(offer_url)
-        soup2 = BeautifulSoup(response2.content, 'html.parser')
+            response2 = requests.get(offer_url)
+            soup2 = BeautifulSoup(response2.content, 'html.parser')
 
-        offer_description = soup2.find('div', {'id': 'tab-description'}).get_text(separator='\n')
+            offer_description = soup2.find('div', {'id': 'tab-description'}).get_text(separator='\n')
 
-        new_offers.append(PhoneOffer(offer_shop, offer_name, price, ram_memory, rom_memory,
-                                     color, front_camera, back_camera, chipset, battery, operating_system, cpu,
-                                     image_url,
-                                     offer_url, last_updated, is_validated, offer_description, offer_shop_code))
+            new_offers.append(PhoneOffer(offer_shop, offer_name, price, ram_memory, rom_memory,
+                                         color, front_camera, back_camera, chipset, battery, operating_system, cpu,
+                                         image_url,
+                                         offer_url, last_updated, is_validated, offer_description, offer_shop_code))
 
-for new_offer in new_offers:
-    flag = False
-    flag_price = False
-    offer_id = None
+    for new_offer in new_offers:
+        flag = False
+        flag_price = False
+        offer_id = None
+
+        for old_offer in database_offers:
+
+            if new_offer.offer_shop_code == old_offer.offer_shop_code:
+                flag = True
+                if new_offer.price != old_offer.price:
+                    flag_price = True
+                    offer_id = old_offer.offer_id
+
+        if flag:
+            # print('ALREADY IN DATABASE')
+            # print(new_offer)
+            # if it's already in database, check PRICE and if it's changed, change it !!!!!!
+            if flag_price:
+                print('PRICE CHANGED!')  # CHANGE PRICE
+                print('offer id: ' + str(offer_id))
+                headers = {'Content-type': 'application/json'}
+                requests.put('http://localhost:8080/phoneoffer/' + str(offer_id) + '/changeprice/' + str(new_offer.price),
+                             headers=headers)
+        else:
+            print('ADDED')  # ADD OFFER
+            print(new_offer)
+            headers = {'Content-type': 'application/json'}
+            requests.post('http://localhost:8080/phoneoffer/addoffer',
+                          headers=headers, data=json.dumps(new_offer.__dict__, default=str))
+
+    print('------------------------------------')
 
     for old_offer in database_offers:
+        flag = False
+        for new_offer in new_offers:
+            if old_offer.offer_shop_code == new_offer.offer_shop_code:
+                flag = True
 
-        if new_offer.offer_shop_code == old_offer.offer_shop_code:
-            flag = True
-            if new_offer.price != old_offer.price:
-                flag_price = True
-                offer_id = old_offer.offer_id
-
-    if flag:
-        # print('ALREADY IN DATABASE')
-        # print(new_offer)
-        # if it's already in database, check PRICE and if it's changed, change it !!!!!!
-        if flag_price:
-            print('PRICE CHANGED!')  # CHANGE PRICE
-            print('offer id: ' + str(offer_id))
-            headers = {'Content-type': 'application/json'}
-            requests.put('http://localhost:8080/phoneoffer/' + str(offer_id) + '/changeprice/' + str(new_offer.price),
-                         headers=headers)
-    else:
-        print('ADDED')  # ADD OFFER
-        print(new_offer)
-        headers = {'Content-type': 'application/json'}
-        requests.post('http://localhost:8080/phoneoffer/addoffer',
-                      headers=headers, data=json.dumps(new_offer.__dict__, default=str))
-
-print('------------------------------------')
-
-for old_offer in database_offers:
-    flag = False
-    for new_offer in new_offers:
-        if old_offer.offer_shop_code == new_offer.offer_shop_code:
-            flag = True
-
-    if not flag:
-        print('OFFER DELETED')
-        print(old_offer)
-        # DELETE OFFER
-        requests.delete('http://localhost:8080/phoneoffer/deleteoffer/' + str(old_offer.offer_id))
+        if not flag:
+            print('OFFER DELETED')
+            print(old_offer)
+            # DELETE OFFER
+            requests.delete('http://localhost:8080/phoneoffer/deleteoffer/' + str(old_offer.offer_id))
+except Exception:
+    traceback.print_exc()
+    insert_script = 'INSERT INTO scrapper_info (store, recieved_at, status)' \
+                    ' VALUES (%s, %s, %s);'
+    insert_value = (offer_shop, last_updated, 'failed')
+    cur.execute(insert_script, insert_value)
+    db_connection.commit()
+    cur.close()
+    db_connection.close()
+else:
+    insert_script = 'INSERT INTO scrapper_info (store, recieved_at, status)' \
+                    ' VALUES (%s, %s, %s);'
+    insert_value = (offer_shop, last_updated, 'success')
+    cur.execute(insert_script, insert_value)
+    db_connection.commit()
+    cur.close()
+    db_connection.close()
Index: phonelux_scrappers/scrappers/tehnomarket_scrapper.py
===================================================================
--- phonelux_scrappers/scrappers/tehnomarket_scrapper.py	(revision ffd50db1e5e2b9839ba7546d8ca44b600150bd71)
+++ phonelux_scrappers/scrappers/tehnomarket_scrapper.py	(revision 47f4eafa88902f713d8f8cfe5d10306816c61ea3)
@@ -1,3 +1,4 @@
 import json
+import traceback
 import unicodedata
 from datetime import datetime
@@ -76,78 +77,105 @@
 
 
-# Tehnomarket phone offers that are already in database
+# Call to read the configuration file and connect to database
+cinfo = config_read.get_databaseconfig("../postgresdb.config")
+db_connection = psycopg2.connect(
+    database=cinfo[0],
+    host=cinfo[1],
+    user=cinfo[2],
+    password=cinfo[3]
+)
+cur = db_connection.cursor()
 
-offers = json.loads(
-    unicodedata.normalize('NFKD', requests.get('http://localhost:8080/phoneoffer/shop/tehnomarket').text))
+try:
+    # Tehnomarket phone offers that are already in database
+    offers = json.loads(
+        unicodedata.normalize('NFKD', requests.get('http://localhost:8080/phoneoffer/shop/tehnomarket').text))
 
-database_offers = []
+    database_offers = []
 
-for offer in offers:
-    phoneOffer = PhoneOffer(offer['id'], offer['offer_shop'], offer['offer_name'], offer['price'],
-                            offer['ram_memory'],
-                            offer['rom_memory'], offer['color'], offer['front_camera'], offer['back_camera'],
-                            offer['chipset'], offer['battery'], offer['operating_system'], offer['cpu'],
-                            offer['image_url'],
-                            offer['offer_url'], offer['last_updated'], offer['is_validated'],
-                            offer['offer_description'],
-                            offer['offer_shop_code'])
-    database_offers.append(phoneOffer)
+    for offer in offers:
+        phoneOffer = PhoneOffer(offer['id'], offer['offer_shop'], offer['offer_name'], offer['price'],
+                                offer['ram_memory'],
+                                offer['rom_memory'], offer['color'], offer['front_camera'], offer['back_camera'],
+                                offer['chipset'], offer['battery'], offer['operating_system'], offer['cpu'],
+                                offer['image_url'],
+                                offer['offer_url'], offer['last_updated'], offer['is_validated'],
+                                offer['offer_description'],
+                                offer['offer_shop_code'])
+        database_offers.append(phoneOffer)
 
-new_offers = []
+    new_offers = []
 
-for i in range(1, 6):
-    tehnomarket_url = 'https://tehnomarket.com.mk/category/4109/mobilni-telefoni#page/' + str(i)
-    # print(anhoch_url)
+    for i in range(1, 6):
+        tehnomarket_url = 'https://tehnomarket.com.mk/category/4109/mobilni-telefoni#page/' + str(i)
+        # print(anhoch_url)
 
-    # selenium is used because of the dynamic content of the page
-    driver1 = webdriver.Safari(executable_path='/usr/bin/safaridriver')
-    driver1.get(tehnomarket_url)
+        # selenium is used because of the dynamic content of the page
+        driver1 = webdriver.Safari(executable_path='/usr/bin/safaridriver')
+        driver1.get(tehnomarket_url)
 
-    scrape_function(driver1, i, new_offers)
+        scrape_function(driver1, i, new_offers)
 
-    # closing the driver so the safari instance can pair with another webdriver session
-    driver1.close()
+        # closing the driver so the safari instance can pair with another webdriver session
+        driver1.close()
 
-for new_offer in new_offers:
-    flag = False
-    flag_price = False
-    offer_id = None
+    for new_offer in new_offers:
+        flag = False
+        flag_price = False
+        offer_id = None
+
+        for old_offer in database_offers:
+
+            if new_offer.offer_shop_code == old_offer.offer_shop_code:
+                flag = True
+                if new_offer.price != old_offer.price:
+                    flag_price = True
+                    offer_id = old_offer.offer_id
+
+        if flag:
+            # print('ALREADY IN DATABASE')
+            # print(new_offer)
+            # if it's already in database, check PRICE and if it's changed, change it !!!!!!
+            if flag_price:
+                print('PRICE CHANGED!')  # CHANGE PRICE
+                print('offer id: ' + str(offer_id))
+                headers = {'Content-type': 'application/json'}
+                requests.put('http://localhost:8080/phoneoffer/' + str(offer_id) + '/changeprice/' + str(new_offer.price),
+                             headers=headers)
+        else:
+            print('ADDED')  # ADD OFFER
+            print(new_offer)
+            headers = {'Content-type': 'application/json'}
+            requests.post('http://localhost:8080/phoneoffer/addoffer',
+                          headers=headers, data=json.dumps(new_offer.__dict__, default=str))
+
+    print('------------------------------------')
 
     for old_offer in database_offers:
+        flag = False
+        for new_offer in new_offers:
+            if old_offer.offer_shop_code == new_offer.offer_shop_code:
+                flag = True
 
-        if new_offer.offer_shop_code == old_offer.offer_shop_code:
-            flag = True
-            if new_offer.price != old_offer.price:
-                flag_price = True
-                offer_id = old_offer.offer_id
-
-    if flag:
-        # print('ALREADY IN DATABASE')
-        # print(new_offer)
-        # if it's already in database, check PRICE and if it's changed, change it !!!!!!
-        if flag_price:
-            print('PRICE CHANGED!')  # CHANGE PRICE
-            print('offer id: ' + str(offer_id))
-            headers = {'Content-type': 'application/json'}
-            requests.put('http://localhost:8080/phoneoffer/' + str(offer_id) + '/changeprice/' + str(new_offer.price),
-                         headers=headers)
-    else:
-        print('ADDED')  # ADD OFFER
-        print(new_offer)
-        headers = {'Content-type': 'application/json'}
-        requests.post('http://localhost:8080/phoneoffer/addoffer',
-                      headers=headers, data=json.dumps(new_offer.__dict__, default=str))
-
-print('------------------------------------')
-
-for old_offer in database_offers:
-    flag = False
-    for new_offer in new_offers:
-        if old_offer.offer_shop_code == new_offer.offer_shop_code:
-            flag = True
-
-    if not flag:
-        print('OFFER DELETED')
-        print(old_offer)
-        # DELETE OFFER
-        requests.delete('http://localhost:8080/phoneoffer/deleteoffer/' + str(old_offer.offer_id))
+        if not flag:
+            print('OFFER DELETED')
+            print(old_offer)
+            # DELETE OFFER
+            requests.delete('http://localhost:8080/phoneoffer/deleteoffer/' + str(old_offer.offer_id))
+except Exception:
+    traceback.print_exc()
+    insert_script = 'INSERT INTO scrapper_info (store, recieved_at, status)' \
+                    ' VALUES (%s, %s, %s);'
+    insert_value = ('Tehnomarket', datetime.now().date(), 'failed')
+    cur.execute(insert_script, insert_value)
+    db_connection.commit()
+    cur.close()
+    db_connection.close()
+else:
+    insert_script = 'INSERT INTO scrapper_info (store, recieved_at, status)' \
+                    ' VALUES (%s, %s, %s);'
+    insert_value = ('Tehnomarket', datetime.now().date(), 'success')
+    cur.execute(insert_script, insert_value)
+    db_connection.commit()
+    cur.close()
+    db_connection.close()
