diff --git a/package-lock.json b/package-lock.json
index 937a670..13a9545 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -949,7 +949,6 @@
"version": "7.3.1",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.3.1.tgz",
"integrity": "sha512-7jGW8ppV0ant637pIqAcFfQDDH1orEPGJb8aXfUozuCU3QqX7rX4DA8iwrbPrR1hcH0FTTHz47yQnk+bl5xHQA==",
- "dev": true,
"requires": {
"regenerator-runtime": "^0.12.0"
},
@@ -957,8 +956,7 @@
"regenerator-runtime": {
"version": "0.12.1",
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.12.1.tgz",
- "integrity": "sha512-odxIc1/vDlo4iZcfXqRYFj0vpXFNoGdKMAUieAlFYO6m/nl5e9KR/beGf41z4a1FI+aQgtjhuaSlDxQ0hmkrHg==",
- "dev": true
+ "integrity": "sha512-odxIc1/vDlo4iZcfXqRYFj0vpXFNoGdKMAUieAlFYO6m/nl5e9KR/beGf41z4a1FI+aQgtjhuaSlDxQ0hmkrHg=="
}
}
},
@@ -1001,6 +999,11 @@
"to-fast-properties": "^2.0.0"
}
},
+ "@bem-react/classname": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/@bem-react/classname/-/classname-1.5.0.tgz",
+ "integrity": "sha512-EpbqE/Uj+q21SI+o1F4d+bgxaPcPCW6gfkD+tZLl2enl2IejpKz5a6W1MDrmTVqgNiLDmJ+4a6ZJHdnv3wcuVg=="
+ },
"@csstools/convert-colors": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/@csstools/convert-colors/-/convert-colors-1.4.0.tgz",
@@ -1216,6 +1219,16 @@
"loader-utils": "^1.1.0"
}
},
+ "@types/classnames": {
+ "version": "2.2.7",
+ "resolved": "https://registry.npmjs.org/@types/classnames/-/classnames-2.2.7.tgz",
+ "integrity": "sha512-rzOhiQ55WzAiFgXRtitP/ZUT8iVNyllEpylJ5zHzR4vArUvMB39GTk+Zon/uAM0JxEFAWnwsxC2gH8s+tZ3Myg=="
+ },
+ "@types/cookie": {
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.3.2.tgz",
+ "integrity": "sha512-aHQA072E10/8iUQsPH7mQU/KUyQBZAGzTVRCUvnSz8mSvbrYsP4xEO2RSA0Pjltolzi0j8+8ixrm//Hr4umPzw=="
+ },
"@types/events": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/@types/events/-/events-3.0.0.tgz",
@@ -1233,6 +1246,38 @@
"@types/node": "*"
}
},
+ "@types/hoist-non-react-statics": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz",
+ "integrity": "sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA==",
+ "requires": {
+ "@types/react": "*",
+ "hoist-non-react-statics": "^3.3.0"
+ },
+ "dependencies": {
+ "hoist-non-react-statics": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.0.tgz",
+ "integrity": "sha512-0XsbTXxgiaCDYDIWFcwkmerZPSwywfUqYmwT4jzewKTQSWoE6FCMoUVOeBJWK3E/CrWbxRG3m5GzY4lnIwGRBA==",
+ "requires": {
+ "react-is": "^16.7.0"
+ }
+ }
+ }
+ },
+ "@types/jest": {
+ "version": "24.0.12",
+ "resolved": "https://registry.npmjs.org/@types/jest/-/jest-24.0.12.tgz",
+ "integrity": "sha512-60sjqMhat7i7XntZckcSGV8iREJyXXI6yFHZkSZvCPUeOnEJ/VP1rU/WpEWQ56mvoh8NhC+sfKAuJRTyGtCOow==",
+ "requires": {
+ "@types/jest-diff": "*"
+ }
+ },
+ "@types/jest-diff": {
+ "version": "20.0.1",
+ "resolved": "https://registry.npmjs.org/@types/jest-diff/-/jest-diff-20.0.1.tgz",
+ "integrity": "sha512-yALhelO3i0hqZwhjtcr6dYyaLoCHbAMshwtj6cGxTvHZAKXHsYGdff6E8EPw3xLKY0ELUTQ69Q1rQiJENnccMA=="
+ },
"@types/json5": {
"version": "0.0.29",
"resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz",
@@ -1246,10 +1291,19 @@
"dev": true
},
"@types/node": {
- "version": "11.13.5",
- "resolved": "https://registry.npmjs.org/@types/node/-/node-11.13.5.tgz",
- "integrity": "sha512-/OMMBnjVtDuwX1tg2pkYVSqRIDSmNTnvVvmvP/2xiMAAWf4a5+JozrApCrO4WCAILmXVxfNoQ3E+0HJbNpFVGg==",
- "dev": true
+ "version": "11.13.8",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-11.13.8.tgz",
+ "integrity": "sha512-szA3x/3miL90ZJxUCzx9haNbK5/zmPieGraZEe4WI+3srN0eGLiT22NXeMHmyhNEopn+IrxqMc7wdVwvPl8meg=="
+ },
+ "@types/object-assign": {
+ "version": "4.0.30",
+ "resolved": "https://registry.npmjs.org/@types/object-assign/-/object-assign-4.0.30.tgz",
+ "integrity": "sha1-iUk3HVqZ9Dge4PHfCpt6GH4H5lI="
+ },
+ "@types/prop-types": {
+ "version": "15.7.1",
+ "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.1.tgz",
+ "integrity": "sha512-CFzn9idOEpHrgdw8JsoTkaDDyRWk1jrzIV8djzcgpq0y9tG4B4lFT+Nxh52DVpDXV+n4+NPNv7M1Dj5uMp6XFg=="
},
"@types/q": {
"version": "1.5.2",
@@ -1257,6 +1311,39 @@
"integrity": "sha512-ce5d3q03Ex0sy4R14722Rmt6MT07Ua+k4FwDfdcToYJcMKNtRVQvJ6JCAPdAmAnbRb6CsX6aYb9m96NGod9uTw==",
"dev": true
},
+ "@types/react": {
+ "version": "16.8.15",
+ "resolved": "https://registry.npmjs.org/@types/react/-/react-16.8.15.tgz",
+ "integrity": "sha512-dMhzw1rWK+wwJWvPp5Pk12ksSrm/z/C/+lOQbMZ7YfDQYnJ02bc0wtg4EJD9qrFhuxFrf/ywNgwTboucobJqQg==",
+ "requires": {
+ "@types/prop-types": "*",
+ "csstype": "^2.2.0"
+ }
+ },
+ "@types/react-dom": {
+ "version": "16.8.4",
+ "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-16.8.4.tgz",
+ "integrity": "sha512-eIRpEW73DCzPIMaNBDP5pPIpK1KXyZwNgfxiVagb5iGiz6da+9A5hslSX6GAQKdO7SayVCS/Fr2kjqprgAvkfA==",
+ "requires": {
+ "@types/react": "*"
+ }
+ },
+ "@types/react-window": {
+ "version": "1.8.0",
+ "resolved": "https://registry.npmjs.org/@types/react-window/-/react-window-1.8.0.tgz",
+ "integrity": "sha512-+3pDwfns884TPYCCFFQObruGI1cOeVHAJ34KvyyhsFGTgCQtfR6Fhnh5TKdvATeHE2AslnU/dHx+tcfJgbhZ8Q==",
+ "requires": {
+ "@types/react": "*"
+ }
+ },
+ "@types/recompose": {
+ "version": "0.30.6",
+ "resolved": "https://registry.npmjs.org/@types/recompose/-/recompose-0.30.6.tgz",
+ "integrity": "sha512-A9c880h07JMrvVe+PwyjVihrQRyKWp4/GFjfA9YE4NgxdEuQD74gSdDhInhUNctO/dkCcR66rexEXevzBy85cQ==",
+ "requires": {
+ "@types/react": "*"
+ }
+ },
"@types/tapable": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/@types/tapable/-/tapable-1.0.2.tgz",
@@ -2069,8 +2156,7 @@
"asap": {
"version": "2.0.6",
"resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz",
- "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=",
- "dev": true
+ "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY="
},
"asn1": {
"version": "0.2.4",
@@ -2839,6 +2925,12 @@
"tweetnacl": "^0.14.3"
}
},
+ "bemify": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/bemify/-/bemify-0.1.2.tgz",
+ "integrity": "sha1-Wdgei0MRy9i+ZNM+PIoB8FwYnQc=",
+ "dev": true
+ },
"bfj": {
"version": "6.1.1",
"resolved": "https://registry.npmjs.org/bfj/-/bfj-6.1.1.tgz",
@@ -3323,6 +3415,11 @@
}
}
},
+ "change-emitter": {
+ "version": "0.1.6",
+ "resolved": "https://registry.npmjs.org/change-emitter/-/change-emitter-0.1.6.tgz",
+ "integrity": "sha1-6LL+PX8at9aaMhma/5HqaTFAlRU="
+ },
"character-entities": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/character-entities/-/character-entities-1.2.2.tgz",
@@ -3359,6 +3456,54 @@
"integrity": "sha512-YbulWHdfP99UfZ73NcUDlNJhEIDgm9Doq9GhpyXbF+7Aegi3CVV7qqMCKTTqJxlvEvnQBp9IA+dxsGN6xK/nSg==",
"dev": true
},
+ "cheerio": {
+ "version": "0.22.0",
+ "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-0.22.0.tgz",
+ "integrity": "sha1-qbqoYKP5tZWmuBsahocxIe06Jp4=",
+ "dev": true,
+ "requires": {
+ "css-select": "~1.2.0",
+ "dom-serializer": "~0.1.0",
+ "entities": "~1.1.1",
+ "htmlparser2": "^3.9.1",
+ "lodash.assignin": "^4.0.9",
+ "lodash.bind": "^4.1.4",
+ "lodash.defaults": "^4.0.1",
+ "lodash.filter": "^4.4.0",
+ "lodash.flatten": "^4.2.0",
+ "lodash.foreach": "^4.3.0",
+ "lodash.map": "^4.4.0",
+ "lodash.merge": "^4.4.0",
+ "lodash.pick": "^4.2.1",
+ "lodash.reduce": "^4.4.0",
+ "lodash.reject": "^4.4.0",
+ "lodash.some": "^4.4.0"
+ },
+ "dependencies": {
+ "css-select": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/css-select/-/css-select-1.2.0.tgz",
+ "integrity": "sha1-KzoRBTnFNV8c2NMUYj6HCxIeyFg=",
+ "dev": true,
+ "requires": {
+ "boolbase": "~1.0.0",
+ "css-what": "2.1",
+ "domutils": "1.5.1",
+ "nth-check": "~1.0.1"
+ }
+ },
+ "domutils": {
+ "version": "1.5.1",
+ "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz",
+ "integrity": "sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8=",
+ "dev": true,
+ "requires": {
+ "dom-serializer": "0",
+ "domelementtype": "1"
+ }
+ }
+ }
+ },
"chokidar": {
"version": "2.1.5",
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.5.tgz",
@@ -3425,9 +3570,9 @@
}
},
"fsevents": {
- "version": "1.2.8",
- "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.8.tgz",
- "integrity": "sha512-tPvHgPGB7m40CZ68xqFGkKuzN+RnpGmSV+hgeKxhRpbxdqKXUFJGC3yonBOLzQBcJyGpdZFDfCsdOC2KFsXzeA==",
+ "version": "1.2.9",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.9.tgz",
+ "integrity": "sha512-oeyj2H3EjjonWcFjD5NvZNE9Rqe4UW+nQBU2HNeKw0koVLEFIhtyETyAakeAM3de7Z/SW5kcA+fZUait9EApnw==",
"dev": true,
"optional": true,
"requires": {
@@ -4085,6 +4230,11 @@
}
}
},
+ "classnames": {
+ "version": "2.2.6",
+ "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.2.6.tgz",
+ "integrity": "sha512-JR/iSQOSt+LQIWwrwEzJ9uk0xfN3mTVYMwt1Ir5mUcSN6pU+V4zQFFaJsclJbPuAUQH+yfWef6tm7l1quW3C8Q=="
+ },
"clean-css": {
"version": "4.2.1",
"resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.2.1.tgz",
@@ -4398,8 +4548,7 @@
"cookie": {
"version": "0.3.1",
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz",
- "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=",
- "dev": true
+ "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s="
},
"cookie-signature": {
"version": "1.0.6",
@@ -4890,6 +5039,11 @@
"cssom": "0.3.x"
}
},
+ "csstype": {
+ "version": "2.6.4",
+ "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.4.tgz",
+ "integrity": "sha512-lAJUJP3M6HxFXbqtGRc0iZrdyeN+WzOWeY0q/VnFzI+kqVrYIzC7bWlKqCW7oCIdzoPkvfp82EVvrTlQ8zsWQg=="
+ },
"currently-unhandled": {
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz",
@@ -5487,6 +5641,14 @@
"integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=",
"dev": true
},
+ "encoding": {
+ "version": "0.1.12",
+ "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.12.tgz",
+ "integrity": "sha1-U4tm8+5izRq1HsMjgp0flIDHS+s=",
+ "requires": {
+ "iconv-lite": "~0.4.13"
+ }
+ },
"end-of-stream": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz",
@@ -5945,6 +6107,15 @@
"integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=",
"dev": true
},
+ "eval": {
+ "version": "0.1.3",
+ "resolved": "https://registry.npmjs.org/eval/-/eval-0.1.3.tgz",
+ "integrity": "sha512-lDBa3hl9YynB+3J7aNPaajAapr+7ZiAylqFeUmx/r9s7I0tkkUJFLw2CQ2oMRYGg/rL7g4IYkZenbKaQGKPnGQ==",
+ "dev": true,
+ "requires": {
+ "require-like": ">= 0.1.1"
+ }
+ },
"eventemitter3": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-3.1.0.tgz",
@@ -6563,6 +6734,35 @@
"bser": "^2.0.0"
}
},
+ "fbjs": {
+ "version": "0.8.17",
+ "resolved": "https://registry.npmjs.org/fbjs/-/fbjs-0.8.17.tgz",
+ "integrity": "sha1-xNWY6taUkRJlPWWIsBpc3Nn5D90=",
+ "requires": {
+ "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"
+ },
+ "dependencies": {
+ "core-js": {
+ "version": "1.2.7",
+ "resolved": "https://registry.npmjs.org/core-js/-/core-js-1.2.7.tgz",
+ "integrity": "sha1-ZSKUwUZR2yj6k70tX/KYOk8IxjY="
+ },
+ "promise": {
+ "version": "7.3.1",
+ "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz",
+ "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==",
+ "requires": {
+ "asap": "~2.0.3"
+ }
+ }
+ }
+ },
"figgy-pudding": {
"version": "3.5.1",
"resolved": "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.1.tgz",
@@ -8256,6 +8456,11 @@
"integrity": "sha512-QLg82fGkfnJ/4iy1xZ81/9SIJiq1NGFUMGs6ParyjBZr6jW2Ufj/snDqTHixNlHdPNwN2RLVD0Pi3igeK9+JfA==",
"dev": true
},
+ "hoist-non-react-statics": {
+ "version": "2.5.5",
+ "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-2.5.5.tgz",
+ "integrity": "sha512-rqcy4pJo55FTTLWt+bU8ukscqHeE/e9KWvsOW2b/a3afxQZhwkQdT1rPPCJ0rYXdj4vNcasY8zHTH+jF/qStxw=="
+ },
"home-or-tmp": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/home-or-tmp/-/home-or-tmp-2.0.0.tgz",
@@ -8781,7 +8986,6 @@
"version": "0.4.24",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
"integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
- "dev": true,
"requires": {
"safer-buffer": ">= 2.1.2 < 3"
}
@@ -9333,8 +9537,7 @@
"is-stream": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz",
- "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=",
- "dev": true
+ "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ="
},
"is-supported-regexp-flag": {
"version": "1.0.1",
@@ -9423,6 +9626,15 @@
"integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=",
"dev": true
},
+ "isomorphic-fetch": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz",
+ "integrity": "sha1-YRrhrPFPXoH3KVB0coGf6XM1WKk=",
+ "requires": {
+ "node-fetch": "^1.0.1",
+ "whatwg-fetch": ">=0.10.0"
+ }
+ },
"isstream": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
@@ -10456,18 +10668,90 @@
"integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=",
"dev": true
},
+ "lodash.assignin": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/lodash.assignin/-/lodash.assignin-4.2.0.tgz",
+ "integrity": "sha1-uo31+4QesKPoBEIysOJjqNxqKKI=",
+ "dev": true
+ },
+ "lodash.bind": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/lodash.bind/-/lodash.bind-4.2.1.tgz",
+ "integrity": "sha1-euMBfpOWIqwxt9fX3LGzTbFpDTU=",
+ "dev": true
+ },
"lodash.camelcase": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz",
"integrity": "sha1-soqmKIorn8ZRA1x3EfZathkDMaY=",
"dev": true
},
+ "lodash.defaults": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz",
+ "integrity": "sha1-0JF4cW/+pN3p5ft7N/bwgCJ0WAw=",
+ "dev": true
+ },
+ "lodash.filter": {
+ "version": "4.6.0",
+ "resolved": "https://registry.npmjs.org/lodash.filter/-/lodash.filter-4.6.0.tgz",
+ "integrity": "sha1-ZosdSYFgOuHMWm+nYBQ+SAtMSs4=",
+ "dev": true
+ },
+ "lodash.flatten": {
+ "version": "4.4.0",
+ "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz",
+ "integrity": "sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8=",
+ "dev": true
+ },
+ "lodash.foreach": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/lodash.foreach/-/lodash.foreach-4.5.0.tgz",
+ "integrity": "sha1-Gmo16s5AEoDH8G3d7DUWWrJ+PlM=",
+ "dev": true
+ },
+ "lodash.map": {
+ "version": "4.6.0",
+ "resolved": "https://registry.npmjs.org/lodash.map/-/lodash.map-4.6.0.tgz",
+ "integrity": "sha1-dx7Hg540c9nEzeKLGTlMNWL09tM=",
+ "dev": true
+ },
"lodash.memoize": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz",
"integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=",
"dev": true
},
+ "lodash.merge": {
+ "version": "4.6.1",
+ "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.1.tgz",
+ "integrity": "sha512-AOYza4+Hf5z1/0Hztxpm2/xiPZgi/cjMqdnKTUWTBSKchJlxXXuUSxCCl8rJlf4g6yww/j6mA8nC8Hw/EZWxKQ==",
+ "dev": true
+ },
+ "lodash.pick": {
+ "version": "4.4.0",
+ "resolved": "https://registry.npmjs.org/lodash.pick/-/lodash.pick-4.4.0.tgz",
+ "integrity": "sha1-UvBWEP/53tQiYRRB7R/BI6AwAbM=",
+ "dev": true
+ },
+ "lodash.reduce": {
+ "version": "4.6.0",
+ "resolved": "https://registry.npmjs.org/lodash.reduce/-/lodash.reduce-4.6.0.tgz",
+ "integrity": "sha1-8atrg5KZrUj3hKu/R2WW8DuRTTs=",
+ "dev": true
+ },
+ "lodash.reject": {
+ "version": "4.6.0",
+ "resolved": "https://registry.npmjs.org/lodash.reject/-/lodash.reject-4.6.0.tgz",
+ "integrity": "sha1-gNZJLcFHCGS79YNTO2UfQqn1JBU=",
+ "dev": true
+ },
+ "lodash.some": {
+ "version": "4.6.0",
+ "resolved": "https://registry.npmjs.org/lodash.some/-/lodash.some-4.6.0.tgz",
+ "integrity": "sha1-G7nzFO9ri63tE7VJFpsqlF62jk0=",
+ "dev": true
+ },
"lodash.sortby": {
"version": "4.7.0",
"resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz",
@@ -10694,6 +10978,11 @@
"mimic-fn": "^1.0.0"
}
},
+ "memoize-one": {
+ "version": "5.0.4",
+ "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-5.0.4.tgz",
+ "integrity": "sha512-P0z5IeAH6qHHGkJIXWw0xC2HNEgkx/9uWWBQw64FJj3/ol14VYdfVGWWr0fXfjhhv3TKVIqUq65os6O4GUNksA=="
+ },
"memory-fs": {
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz",
@@ -11199,6 +11488,15 @@
"lower-case": "^1.1.1"
}
},
+ "node-fetch": {
+ "version": "1.7.3",
+ "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.7.3.tgz",
+ "integrity": "sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ==",
+ "requires": {
+ "encoding": "^0.1.11",
+ "is-stream": "^1.0.1"
+ }
+ },
"node-forge": {
"version": "0.7.5",
"resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.7.5.tgz",
@@ -13410,6 +13708,35 @@
}
}
},
+ "react-cookie": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/react-cookie/-/react-cookie-3.1.2.tgz",
+ "integrity": "sha512-kHBDW7dLiXfvR+lw2ZeH9fMjEM0gf1IwxDXOyXQrf22X5+Ifluyz22HCVFzq1va6FSEHk6hrBbH6oeNLTD2vIQ==",
+ "requires": {
+ "@types/hoist-non-react-statics": "^3.0.1",
+ "hoist-non-react-statics": "^3.0.0",
+ "universal-cookie": "^3.1.0"
+ },
+ "dependencies": {
+ "hoist-non-react-statics": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.0.tgz",
+ "integrity": "sha512-0XsbTXxgiaCDYDIWFcwkmerZPSwywfUqYmwT4jzewKTQSWoE6FCMoUVOeBJWK3E/CrWbxRG3m5GzY4lnIwGRBA==",
+ "requires": {
+ "react-is": "^16.7.0"
+ }
+ }
+ }
+ },
+ "react-cookies": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/react-cookies/-/react-cookies-0.1.0.tgz",
+ "integrity": "sha1-a7iD8tGjl/E4pBEDALRv4l348ak=",
+ "requires": {
+ "cookie": "^0.3.1",
+ "object-assign": "^4.1.1"
+ }
+ },
"react-dev-utils": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-8.0.0.tgz",
@@ -13557,6 +13884,11 @@
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.8.6.tgz",
"integrity": "sha512-aUk3bHfZ2bRSVFFbbeVS4i+lNPZr3/WM5jT2J5omUVV1zzcs1nAaf3l51ctA5FFvCRbhrH0bdAsRRQddFJZPtA=="
},
+ "react-lifecycles-compat": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz",
+ "integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA=="
+ },
"react-scripts": {
"version": "2.1.8",
"resolved": "https://registry.npmjs.org/react-scripts/-/react-scripts-2.1.8.tgz",
@@ -13612,112 +13944,645 @@
"workbox-webpack-plugin": "3.6.3"
},
"dependencies": {
- "doctrine": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz",
- "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==",
+ "@webassemblyjs/ast": {
+ "version": "1.7.11",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.7.11.tgz",
+ "integrity": "sha512-ZEzy4vjvTzScC+SH8RBssQUawpaInUdMTYwYYLh54/s8TuT0gBLuyUnppKsVyZEi876VmmStKsUs28UxPgdvrA==",
"dev": true,
"requires": {
- "esutils": "^2.0.2"
+ "@webassemblyjs/helper-module-context": "1.7.11",
+ "@webassemblyjs/helper-wasm-bytecode": "1.7.11",
+ "@webassemblyjs/wast-parser": "1.7.11"
}
},
- "eslint": {
- "version": "5.12.0",
- "resolved": "https://registry.npmjs.org/eslint/-/eslint-5.12.0.tgz",
- "integrity": "sha512-LntwyPxtOHrsJdcSwyQKVtHofPHdv+4+mFwEe91r2V13vqpM8yLr7b1sW+Oo/yheOPkWYsYlYJCkzlFAt8KV7g==",
+ "@webassemblyjs/floating-point-hex-parser": {
+ "version": "1.7.11",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.7.11.tgz",
+ "integrity": "sha512-zY8dSNyYcgzNRNT666/zOoAyImshm3ycKdoLsyDw/Bwo6+/uktb7p4xyApuef1dwEBo/U/SYQzbGBvV+nru2Xg==",
+ "dev": true
+ },
+ "@webassemblyjs/helper-api-error": {
+ "version": "1.7.11",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.7.11.tgz",
+ "integrity": "sha512-7r1qXLmiglC+wPNkGuXCvkmalyEstKVwcueZRP2GNC2PAvxbLYwLLPr14rcdJaE4UtHxQKfFkuDFuv91ipqvXg==",
+ "dev": true
+ },
+ "@webassemblyjs/helper-buffer": {
+ "version": "1.7.11",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.7.11.tgz",
+ "integrity": "sha512-MynuervdylPPh3ix+mKZloTcL06P8tenNH3sx6s0qE8SLR6DdwnfgA7Hc9NSYeob2jrW5Vql6GVlsQzKQCa13w==",
+ "dev": true
+ },
+ "@webassemblyjs/helper-code-frame": {
+ "version": "1.7.11",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.7.11.tgz",
+ "integrity": "sha512-T8ESC9KMXFTXA5urJcyor5cn6qWeZ4/zLPyWeEXZ03hj/x9weSokGNkVCdnhSabKGYWxElSdgJ+sFa9G/RdHNw==",
"dev": true,
"requires": {
- "@babel/code-frame": "^7.0.0",
- "ajv": "^6.5.3",
- "chalk": "^2.1.0",
- "cross-spawn": "^6.0.5",
- "debug": "^4.0.1",
- "doctrine": "^2.1.0",
- "eslint-scope": "^4.0.0",
- "eslint-utils": "^1.3.1",
- "eslint-visitor-keys": "^1.0.0",
- "espree": "^5.0.0",
- "esquery": "^1.0.1",
- "esutils": "^2.0.2",
- "file-entry-cache": "^2.0.0",
- "functional-red-black-tree": "^1.0.1",
- "glob": "^7.1.2",
- "globals": "^11.7.0",
- "ignore": "^4.0.6",
- "import-fresh": "^3.0.0",
- "imurmurhash": "^0.1.4",
- "inquirer": "^6.1.0",
- "js-yaml": "^3.12.0",
- "json-stable-stringify-without-jsonify": "^1.0.1",
- "levn": "^0.3.0",
- "lodash": "^4.17.5",
- "minimatch": "^3.0.4",
- "mkdirp": "^0.5.1",
- "natural-compare": "^1.4.0",
- "optionator": "^0.8.2",
- "path-is-inside": "^1.0.2",
- "pluralize": "^7.0.0",
- "progress": "^2.0.0",
- "regexpp": "^2.0.1",
- "semver": "^5.5.1",
- "strip-ansi": "^4.0.0",
- "strip-json-comments": "^2.0.1",
- "table": "^5.0.2",
- "text-table": "^0.2.0"
+ "@webassemblyjs/wast-printer": "1.7.11"
}
},
- "file-entry-cache": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-2.0.0.tgz",
- "integrity": "sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E=",
+ "@webassemblyjs/helper-fsm": {
+ "version": "1.7.11",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-fsm/-/helper-fsm-1.7.11.tgz",
+ "integrity": "sha512-nsAQWNP1+8Z6tkzdYlXT0kxfa2Z1tRTARd8wYnc/e3Zv3VydVVnaeePgqUzFrpkGUyhUUxOl5ML7f1NuT+gC0A==",
+ "dev": true
+ },
+ "@webassemblyjs/helper-module-context": {
+ "version": "1.7.11",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-module-context/-/helper-module-context-1.7.11.tgz",
+ "integrity": "sha512-JxfD5DX8Ygq4PvXDucq0M+sbUFA7BJAv/GGl9ITovqE+idGX+J3QSzJYz+LwQmL7fC3Rs+utvWoJxDb6pmC0qg==",
+ "dev": true
+ },
+ "@webassemblyjs/helper-wasm-bytecode": {
+ "version": "1.7.11",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.7.11.tgz",
+ "integrity": "sha512-cMXeVS9rhoXsI9LLL4tJxBgVD/KMOKXuFqYb5oCJ/opScWpkCMEz9EJtkonaNcnLv2R3K5jIeS4TRj/drde1JQ==",
+ "dev": true
+ },
+ "@webassemblyjs/helper-wasm-section": {
+ "version": "1.7.11",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.7.11.tgz",
+ "integrity": "sha512-8ZRY5iZbZdtNFE5UFunB8mmBEAbSI3guwbrsCl4fWdfRiAcvqQpeqd5KHhSWLL5wuxo53zcaGZDBU64qgn4I4Q==",
"dev": true,
"requires": {
- "flat-cache": "^1.2.1",
- "object-assign": "^4.0.1"
+ "@webassemblyjs/ast": "1.7.11",
+ "@webassemblyjs/helper-buffer": "1.7.11",
+ "@webassemblyjs/helper-wasm-bytecode": "1.7.11",
+ "@webassemblyjs/wasm-gen": "1.7.11"
}
},
- "flat-cache": {
- "version": "1.3.4",
- "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.4.tgz",
- "integrity": "sha512-VwyB3Lkgacfik2vhqR4uv2rvebqmDvFu4jlN/C1RzWoJEo8I7z4Q404oiqYCkq41mni8EzQnm95emU9seckwtg==",
+ "@webassemblyjs/ieee754": {
+ "version": "1.7.11",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.7.11.tgz",
+ "integrity": "sha512-Mmqx/cS68K1tSrvRLtaV/Lp3NZWzXtOHUW2IvDvl2sihAwJh4ACE0eL6A8FvMyDG9abes3saB6dMimLOs+HMoQ==",
"dev": true,
"requires": {
- "circular-json": "^0.3.1",
- "graceful-fs": "^4.1.2",
- "rimraf": "~2.6.2",
- "write": "^0.2.1"
+ "@xtuc/ieee754": "^1.2.0"
}
},
- "semver": {
- "version": "5.7.0",
- "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz",
- "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==",
+ "@webassemblyjs/leb128": {
+ "version": "1.7.11",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.7.11.tgz",
+ "integrity": "sha512-vuGmgZjjp3zjcerQg+JA+tGOncOnJLWVkt8Aze5eWQLwTQGNgVLcyOTqgSCxWTR4J42ijHbBxnuRaL1Rv7XMdw==",
+ "dev": true,
+ "requires": {
+ "@xtuc/long": "4.2.1"
+ }
+ },
+ "@webassemblyjs/utf8": {
+ "version": "1.7.11",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.7.11.tgz",
+ "integrity": "sha512-C6GFkc7aErQIAH+BMrIdVSmW+6HSe20wg57HEC1uqJP8E/xpMjXqQUxkQw07MhNDSDcGpxI9G5JSNOQCqJk4sA==",
"dev": true
},
- "write": {
- "version": "0.2.1",
- "resolved": "https://registry.npmjs.org/write/-/write-0.2.1.tgz",
- "integrity": "sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c=",
+ "@webassemblyjs/wasm-edit": {
+ "version": "1.7.11",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.7.11.tgz",
+ "integrity": "sha512-FUd97guNGsCZQgeTPKdgxJhBXkUbMTY6hFPf2Y4OedXd48H97J+sOY2Ltaq6WGVpIH8o/TGOVNiVz/SbpEMJGg==",
"dev": true,
"requires": {
- "mkdirp": "^0.5.1"
+ "@webassemblyjs/ast": "1.7.11",
+ "@webassemblyjs/helper-buffer": "1.7.11",
+ "@webassemblyjs/helper-wasm-bytecode": "1.7.11",
+ "@webassemblyjs/helper-wasm-section": "1.7.11",
+ "@webassemblyjs/wasm-gen": "1.7.11",
+ "@webassemblyjs/wasm-opt": "1.7.11",
+ "@webassemblyjs/wasm-parser": "1.7.11",
+ "@webassemblyjs/wast-printer": "1.7.11"
}
- }
- }
- },
- "read-pkg": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz",
- "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=",
- "dev": true,
- "requires": {
- "load-json-file": "^2.0.0",
- "normalize-package-data": "^2.3.2",
- "path-type": "^2.0.0"
- }
- },
- "read-pkg-up": {
- "version": "2.0.0",
+ },
+ "@webassemblyjs/wasm-gen": {
+ "version": "1.7.11",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.7.11.tgz",
+ "integrity": "sha512-U/KDYp7fgAZX5KPfq4NOupK/BmhDc5Kjy2GIqstMhvvdJRcER/kUsMThpWeRP8BMn4LXaKhSTggIJPOeYHwISA==",
+ "dev": true,
+ "requires": {
+ "@webassemblyjs/ast": "1.7.11",
+ "@webassemblyjs/helper-wasm-bytecode": "1.7.11",
+ "@webassemblyjs/ieee754": "1.7.11",
+ "@webassemblyjs/leb128": "1.7.11",
+ "@webassemblyjs/utf8": "1.7.11"
+ }
+ },
+ "@webassemblyjs/wasm-opt": {
+ "version": "1.7.11",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.7.11.tgz",
+ "integrity": "sha512-XynkOwQyiRidh0GLua7SkeHvAPXQV/RxsUeERILmAInZegApOUAIJfRuPYe2F7RcjOC9tW3Cb9juPvAC/sCqvg==",
+ "dev": true,
+ "requires": {
+ "@webassemblyjs/ast": "1.7.11",
+ "@webassemblyjs/helper-buffer": "1.7.11",
+ "@webassemblyjs/wasm-gen": "1.7.11",
+ "@webassemblyjs/wasm-parser": "1.7.11"
+ }
+ },
+ "@webassemblyjs/wasm-parser": {
+ "version": "1.7.11",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.7.11.tgz",
+ "integrity": "sha512-6lmXRTrrZjYD8Ng8xRyvyXQJYUQKYSXhJqXOBLw24rdiXsHAOlvw5PhesjdcaMadU/pyPQOJ5dHreMjBxwnQKg==",
+ "dev": true,
+ "requires": {
+ "@webassemblyjs/ast": "1.7.11",
+ "@webassemblyjs/helper-api-error": "1.7.11",
+ "@webassemblyjs/helper-wasm-bytecode": "1.7.11",
+ "@webassemblyjs/ieee754": "1.7.11",
+ "@webassemblyjs/leb128": "1.7.11",
+ "@webassemblyjs/utf8": "1.7.11"
+ }
+ },
+ "@webassemblyjs/wast-parser": {
+ "version": "1.7.11",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-parser/-/wast-parser-1.7.11.tgz",
+ "integrity": "sha512-lEyVCg2np15tS+dm7+JJTNhNWq9yTZvi3qEhAIIOaofcYlUp0UR5/tVqOwa/gXYr3gjwSZqw+/lS9dscyLelbQ==",
+ "dev": true,
+ "requires": {
+ "@webassemblyjs/ast": "1.7.11",
+ "@webassemblyjs/floating-point-hex-parser": "1.7.11",
+ "@webassemblyjs/helper-api-error": "1.7.11",
+ "@webassemblyjs/helper-code-frame": "1.7.11",
+ "@webassemblyjs/helper-fsm": "1.7.11",
+ "@xtuc/long": "4.2.1"
+ }
+ },
+ "@webassemblyjs/wast-printer": {
+ "version": "1.7.11",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.7.11.tgz",
+ "integrity": "sha512-m5vkAsuJ32QpkdkDOUPGSltrg8Cuk3KBx4YrmAGQwCZPRdUHXxG4phIOuuycLemHFr74sWL9Wthqss4fzdzSwg==",
+ "dev": true,
+ "requires": {
+ "@webassemblyjs/ast": "1.7.11",
+ "@webassemblyjs/wast-parser": "1.7.11",
+ "@xtuc/long": "4.2.1"
+ }
+ },
+ "@xtuc/long": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.1.tgz",
+ "integrity": "sha512-FZdkNBDqBRHKQ2MEbSC17xnPFOhZxeJ2YGSfr2BKf3sujG49Qe3bB+rGCwQfIaA7WHnGeGkSijX4FuBCdrzW/g==",
+ "dev": true
+ },
+ "acorn": {
+ "version": "5.7.3",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.3.tgz",
+ "integrity": "sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw==",
+ "dev": true
+ },
+ "acorn-dynamic-import": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/acorn-dynamic-import/-/acorn-dynamic-import-3.0.0.tgz",
+ "integrity": "sha512-zVWV8Z8lislJoOKKqdNMOB+s6+XV5WERty8MnKBeFgwA+19XJjJHs2RP5dzM57FftIs+jQnRToLiWazKr6sSWg==",
+ "dev": true,
+ "requires": {
+ "acorn": "^5.0.0"
+ }
+ },
+ "arr-diff": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz",
+ "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=",
+ "dev": true
+ },
+ "array-unique": {
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz",
+ "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=",
+ "dev": true
+ },
+ "braces": {
+ "version": "2.3.2",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz",
+ "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==",
+ "dev": true,
+ "requires": {
+ "arr-flatten": "^1.1.0",
+ "array-unique": "^0.3.2",
+ "extend-shallow": "^2.0.1",
+ "fill-range": "^4.0.0",
+ "isobject": "^3.0.1",
+ "repeat-element": "^1.1.2",
+ "snapdragon": "^0.8.1",
+ "snapdragon-node": "^2.0.1",
+ "split-string": "^3.0.2",
+ "to-regex": "^3.0.1"
+ },
+ "dependencies": {
+ "extend-shallow": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+ "dev": true,
+ "requires": {
+ "is-extendable": "^0.1.0"
+ }
+ }
+ }
+ },
+ "doctrine": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz",
+ "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==",
+ "dev": true,
+ "requires": {
+ "esutils": "^2.0.2"
+ }
+ },
+ "eslint": {
+ "version": "5.12.0",
+ "resolved": "https://registry.npmjs.org/eslint/-/eslint-5.12.0.tgz",
+ "integrity": "sha512-LntwyPxtOHrsJdcSwyQKVtHofPHdv+4+mFwEe91r2V13vqpM8yLr7b1sW+Oo/yheOPkWYsYlYJCkzlFAt8KV7g==",
+ "dev": true,
+ "requires": {
+ "@babel/code-frame": "^7.0.0",
+ "ajv": "^6.5.3",
+ "chalk": "^2.1.0",
+ "cross-spawn": "^6.0.5",
+ "debug": "^4.0.1",
+ "doctrine": "^2.1.0",
+ "eslint-scope": "^4.0.0",
+ "eslint-utils": "^1.3.1",
+ "eslint-visitor-keys": "^1.0.0",
+ "espree": "^5.0.0",
+ "esquery": "^1.0.1",
+ "esutils": "^2.0.2",
+ "file-entry-cache": "^2.0.0",
+ "functional-red-black-tree": "^1.0.1",
+ "glob": "^7.1.2",
+ "globals": "^11.7.0",
+ "ignore": "^4.0.6",
+ "import-fresh": "^3.0.0",
+ "imurmurhash": "^0.1.4",
+ "inquirer": "^6.1.0",
+ "js-yaml": "^3.12.0",
+ "json-stable-stringify-without-jsonify": "^1.0.1",
+ "levn": "^0.3.0",
+ "lodash": "^4.17.5",
+ "minimatch": "^3.0.4",
+ "mkdirp": "^0.5.1",
+ "natural-compare": "^1.4.0",
+ "optionator": "^0.8.2",
+ "path-is-inside": "^1.0.2",
+ "pluralize": "^7.0.0",
+ "progress": "^2.0.0",
+ "regexpp": "^2.0.1",
+ "semver": "^5.5.1",
+ "strip-ansi": "^4.0.0",
+ "strip-json-comments": "^2.0.1",
+ "table": "^5.0.2",
+ "text-table": "^0.2.0"
+ }
+ },
+ "expand-brackets": {
+ "version": "2.1.4",
+ "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz",
+ "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=",
+ "dev": true,
+ "requires": {
+ "debug": "^2.3.3",
+ "define-property": "^0.2.5",
+ "extend-shallow": "^2.0.1",
+ "posix-character-classes": "^0.1.0",
+ "regex-not": "^1.0.0",
+ "snapdragon": "^0.8.1",
+ "to-regex": "^3.0.1"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "dev": true,
+ "requires": {
+ "ms": "2.0.0"
+ }
+ },
+ "define-property": {
+ "version": "0.2.5",
+ "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
+ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
+ "dev": true,
+ "requires": {
+ "is-descriptor": "^0.1.0"
+ }
+ },
+ "extend-shallow": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+ "dev": true,
+ "requires": {
+ "is-extendable": "^0.1.0"
+ }
+ },
+ "is-accessor-descriptor": {
+ "version": "0.1.6",
+ "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz",
+ "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=",
+ "dev": true,
+ "requires": {
+ "kind-of": "^3.0.2"
+ },
+ "dependencies": {
+ "kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "dev": true,
+ "requires": {
+ "is-buffer": "^1.1.5"
+ }
+ }
+ }
+ },
+ "is-data-descriptor": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz",
+ "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=",
+ "dev": true,
+ "requires": {
+ "kind-of": "^3.0.2"
+ },
+ "dependencies": {
+ "kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "dev": true,
+ "requires": {
+ "is-buffer": "^1.1.5"
+ }
+ }
+ }
+ },
+ "is-descriptor": {
+ "version": "0.1.6",
+ "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz",
+ "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==",
+ "dev": true,
+ "requires": {
+ "is-accessor-descriptor": "^0.1.6",
+ "is-data-descriptor": "^0.1.4",
+ "kind-of": "^5.0.0"
+ }
+ },
+ "kind-of": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz",
+ "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==",
+ "dev": true
+ }
+ }
+ },
+ "extglob": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz",
+ "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==",
+ "dev": true,
+ "requires": {
+ "array-unique": "^0.3.2",
+ "define-property": "^1.0.0",
+ "expand-brackets": "^2.1.4",
+ "extend-shallow": "^2.0.1",
+ "fragment-cache": "^0.2.1",
+ "regex-not": "^1.0.0",
+ "snapdragon": "^0.8.1",
+ "to-regex": "^3.0.1"
+ },
+ "dependencies": {
+ "define-property": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz",
+ "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=",
+ "dev": true,
+ "requires": {
+ "is-descriptor": "^1.0.0"
+ }
+ },
+ "extend-shallow": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+ "dev": true,
+ "requires": {
+ "is-extendable": "^0.1.0"
+ }
+ }
+ }
+ },
+ "file-entry-cache": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-2.0.0.tgz",
+ "integrity": "sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E=",
+ "dev": true,
+ "requires": {
+ "flat-cache": "^1.2.1",
+ "object-assign": "^4.0.1"
+ }
+ },
+ "fill-range": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz",
+ "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=",
+ "dev": true,
+ "requires": {
+ "extend-shallow": "^2.0.1",
+ "is-number": "^3.0.0",
+ "repeat-string": "^1.6.1",
+ "to-regex-range": "^2.1.0"
+ },
+ "dependencies": {
+ "extend-shallow": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+ "dev": true,
+ "requires": {
+ "is-extendable": "^0.1.0"
+ }
+ }
+ }
+ },
+ "flat-cache": {
+ "version": "1.3.4",
+ "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.4.tgz",
+ "integrity": "sha512-VwyB3Lkgacfik2vhqR4uv2rvebqmDvFu4jlN/C1RzWoJEo8I7z4Q404oiqYCkq41mni8EzQnm95emU9seckwtg==",
+ "dev": true,
+ "requires": {
+ "circular-json": "^0.3.1",
+ "graceful-fs": "^4.1.2",
+ "rimraf": "~2.6.2",
+ "write": "^0.2.1"
+ }
+ },
+ "is-accessor-descriptor": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz",
+ "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==",
+ "dev": true,
+ "requires": {
+ "kind-of": "^6.0.0"
+ }
+ },
+ "is-buffer": {
+ "version": "1.1.6",
+ "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
+ "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==",
+ "dev": true
+ },
+ "is-data-descriptor": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz",
+ "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==",
+ "dev": true,
+ "requires": {
+ "kind-of": "^6.0.0"
+ }
+ },
+ "is-descriptor": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
+ "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==",
+ "dev": true,
+ "requires": {
+ "is-accessor-descriptor": "^1.0.0",
+ "is-data-descriptor": "^1.0.0",
+ "kind-of": "^6.0.2"
+ }
+ },
+ "is-number": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz",
+ "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=",
+ "dev": true,
+ "requires": {
+ "kind-of": "^3.0.2"
+ },
+ "dependencies": {
+ "kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "dev": true,
+ "requires": {
+ "is-buffer": "^1.1.5"
+ }
+ }
+ }
+ },
+ "kind-of": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz",
+ "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==",
+ "dev": true
+ },
+ "micromatch": {
+ "version": "3.1.10",
+ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz",
+ "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==",
+ "dev": true,
+ "requires": {
+ "arr-diff": "^4.0.0",
+ "array-unique": "^0.3.2",
+ "braces": "^2.3.1",
+ "define-property": "^2.0.2",
+ "extend-shallow": "^3.0.2",
+ "extglob": "^2.0.4",
+ "fragment-cache": "^0.2.1",
+ "kind-of": "^6.0.2",
+ "nanomatch": "^1.2.9",
+ "object.pick": "^1.3.0",
+ "regex-not": "^1.0.0",
+ "snapdragon": "^0.8.1",
+ "to-regex": "^3.0.2"
+ }
+ },
+ "ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
+ "dev": true
+ },
+ "schema-utils": {
+ "version": "0.4.7",
+ "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-0.4.7.tgz",
+ "integrity": "sha512-v/iwU6wvwGK8HbU9yi3/nhGzP0yGSuhQMzL6ySiec1FSrZZDkhm4noOSWzrNFo/jEc+SJY6jRTwuwbSXJPDUnQ==",
+ "dev": true,
+ "requires": {
+ "ajv": "^6.1.0",
+ "ajv-keywords": "^3.1.0"
+ }
+ },
+ "semver": {
+ "version": "5.7.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz",
+ "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==",
+ "dev": true
+ },
+ "webpack": {
+ "version": "4.28.3",
+ "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.28.3.tgz",
+ "integrity": "sha512-vLZN9k5I7Nr/XB1IDG9GbZB4yQd1sPuvufMFgJkx0b31fi2LD97KQIjwjxE7xytdruAYfu5S0FLBLjdxmwGJCg==",
+ "dev": true,
+ "requires": {
+ "@webassemblyjs/ast": "1.7.11",
+ "@webassemblyjs/helper-module-context": "1.7.11",
+ "@webassemblyjs/wasm-edit": "1.7.11",
+ "@webassemblyjs/wasm-parser": "1.7.11",
+ "acorn": "^5.6.2",
+ "acorn-dynamic-import": "^3.0.0",
+ "ajv": "^6.1.0",
+ "ajv-keywords": "^3.1.0",
+ "chrome-trace-event": "^1.0.0",
+ "enhanced-resolve": "^4.1.0",
+ "eslint-scope": "^4.0.0",
+ "json-parse-better-errors": "^1.0.2",
+ "loader-runner": "^2.3.0",
+ "loader-utils": "^1.1.0",
+ "memory-fs": "~0.4.1",
+ "micromatch": "^3.1.8",
+ "mkdirp": "~0.5.0",
+ "neo-async": "^2.5.0",
+ "node-libs-browser": "^2.0.0",
+ "schema-utils": "^0.4.4",
+ "tapable": "^1.1.0",
+ "terser-webpack-plugin": "^1.1.0",
+ "watchpack": "^1.5.0",
+ "webpack-sources": "^1.3.0"
+ }
+ },
+ "write": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/write/-/write-0.2.1.tgz",
+ "integrity": "sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c=",
+ "dev": true,
+ "requires": {
+ "mkdirp": "^0.5.1"
+ }
+ }
+ }
+ },
+ "react-window": {
+ "version": "1.8.1",
+ "resolved": "https://registry.npmjs.org/react-window/-/react-window-1.8.1.tgz",
+ "integrity": "sha512-iNzekymggL9zAnil3QbmRG74RDMfIbO+plE/soP3M/zskicA1DwoLthC6/QA6xu9dr+A5UoawCTsEYcva2mfeA==",
+ "requires": {
+ "@babel/runtime": "^7.0.0",
+ "memoize-one": ">=3.1.1 <6"
+ }
+ },
+ "read-pkg": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz",
+ "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=",
+ "dev": true,
+ "requires": {
+ "load-json-file": "^2.0.0",
+ "normalize-package-data": "^2.3.2",
+ "path-type": "^2.0.0"
+ }
+ },
+ "read-pkg-up": {
+ "version": "2.0.0",
"resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz",
"integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=",
"dev": true,
@@ -14072,6 +14937,19 @@
"util.promisify": "^1.0.0"
}
},
+ "recompose": {
+ "version": "0.30.0",
+ "resolved": "https://registry.npmjs.org/recompose/-/recompose-0.30.0.tgz",
+ "integrity": "sha512-ZTrzzUDa9AqUIhRk4KmVFihH0rapdCSMFXjhHbNrjAWxBuUD/guYlyysMnuHjlZC/KRiOKRtB4jf96yYSkKE8w==",
+ "requires": {
+ "@babel/runtime": "^7.0.0",
+ "change-emitter": "^0.1.2",
+ "fbjs": "^0.8.1",
+ "hoist-non-react-statics": "^2.3.1",
+ "react-lifecycles-compat": "^3.0.2",
+ "symbol-observable": "^1.0.4"
+ }
+ },
"recursive-readdir": {
"version": "2.2.2",
"resolved": "https://registry.npmjs.org/recursive-readdir/-/recursive-readdir-2.2.2.tgz",
@@ -14425,6 +15303,12 @@
"integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==",
"dev": true
},
+ "require-like": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/require-like/-/require-like-0.1.2.tgz",
+ "integrity": "sha1-rW8wwTvs15cBDEaK+ndcDAprR/o=",
+ "dev": true
+ },
"require-main-filename": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz",
@@ -14579,8 +15463,7 @@
"safer-buffer": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
- "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
- "dev": true
+ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
},
"sane": {
"version": "2.5.2",
@@ -15131,8 +16014,7 @@
"setimmediate": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz",
- "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=",
- "dev": true
+ "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU="
},
"setprototypeof": {
"version": "1.1.0",
@@ -15632,6 +16514,43 @@
}
}
},
+ "static-site-generator-webpack-plugin": {
+ "version": "3.4.2",
+ "resolved": "https://registry.npmjs.org/static-site-generator-webpack-plugin/-/static-site-generator-webpack-plugin-3.4.2.tgz",
+ "integrity": "sha512-39Kn+fZDVjolLYuX5y1rDvksJIW0QEUaEC/AVO/UewNXxGzoSQI1UYnRsL+ocAcN5Yti6d6rJgEL0qZ5tNXfdw==",
+ "dev": true,
+ "requires": {
+ "bluebird": "^3.0.5",
+ "cheerio": "^0.22.0",
+ "eval": "^0.1.0",
+ "url": "^0.11.0",
+ "webpack-sources": "^0.2.0"
+ },
+ "dependencies": {
+ "source-list-map": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-1.1.2.tgz",
+ "integrity": "sha1-mIkBnRAkzOVc3AaUmDN+9hhqEaE=",
+ "dev": true
+ },
+ "source-map": {
+ "version": "0.5.7",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
+ "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
+ "dev": true
+ },
+ "webpack-sources": {
+ "version": "0.2.3",
+ "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-0.2.3.tgz",
+ "integrity": "sha1-F8Yr+vE8cH+dAsR54Nzd6DgGl/s=",
+ "dev": true,
+ "requires": {
+ "source-list-map": "^1.1.1",
+ "source-map": "~0.5.3"
+ }
+ }
+ }
+ },
"statuses": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz",
@@ -16223,6 +17142,11 @@
"util.promisify": "~1.0.0"
}
},
+ "symbol-observable": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.2.0.tgz",
+ "integrity": "sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ=="
+ },
"symbol-tree": {
"version": "3.2.2",
"resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.2.tgz",
@@ -16702,6 +17626,11 @@
"integrity": "sha512-jjOcCZvpkl2+z7JFn0yBOoLQyLoIkNZAs/fYJkUG6VKy6zLPHJGfQJYFHzibB6GJaF/8QrcECtlQ5cpvRHSMEA==",
"dev": true
},
+ "ua-parser-js": {
+ "version": "0.7.19",
+ "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.19.tgz",
+ "integrity": "sha512-T3PVJ6uz8i0HzPxOF9SWzWAlfN/DavlpQqepn22xgve/5QecC+XMCAtmUNnY7C9StehaV6exjUCI801lOI7QlQ=="
+ },
"uglify-js": {
"version": "3.4.10",
"resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.4.10.tgz",
@@ -16901,6 +17830,17 @@
"unist-util-is": "^2.1.2"
}
},
+ "universal-cookie": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/universal-cookie/-/universal-cookie-3.1.0.tgz",
+ "integrity": "sha512-sP6WuFgqIUro7ikgI2ndrsw9Ro+YvVBe5O9cQfWnjTicpLaSMUEUUDjQF8m8utzWF2ONl7tRkcZd7v4n6NnzjQ==",
+ "requires": {
+ "@types/cookie": "^0.3.1",
+ "@types/object-assign": "^4.0.30",
+ "cookie": "^0.3.1",
+ "object-assign": "^4.1.0"
+ }
+ },
"universalify": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz",
@@ -17895,8 +18835,7 @@
"whatwg-fetch": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.0.0.tgz",
- "integrity": "sha512-9GSJUgz1D4MfyKU7KRqwOjXCXTqWdFNvEr7eUBYchQiVc744mqK/MzXPNR2WsPkmkOa4ywfg8C2n8h+13Bey1Q==",
- "dev": true
+ "integrity": "sha512-9GSJUgz1D4MfyKU7KRqwOjXCXTqWdFNvEr7eUBYchQiVc744mqK/MzXPNR2WsPkmkOa4ywfg8C2n8h+13Bey1Q=="
},
"whatwg-mimetype": {
"version": "2.3.0",
diff --git a/package.json b/package.json
index 9ede333..2da67aa 100644
--- a/package.json
+++ b/package.json
@@ -9,23 +9,41 @@
"not op_mini all"
],
"dependencies": {
+ "@bem-react/classname": "1.5.0",
+ "@types/classnames": "2.2.7",
+ "@types/jest": "24.0.12",
+ "@types/node": "11.13.8",
+ "@types/react": "16.8.15",
+ "@types/react-dom": "16.8.4",
+ "@types/react-window": "1.8.0",
+ "@types/recompose": "0.30.6",
+ "classnames": "2.2.6",
"react": "16.8.6",
- "react-dom": "16.8.6"
+ "react-cookie": "3.1.2",
+ "react-cookies": "0.1.0",
+ "react-dom": "16.8.6",
+ "react-window": "1.8.1",
+ "recompose": "0.30.0",
+ "universal-cookie": "3.1.0"
},
"devDependencies": {
"@hellroot/eslint-config": "1.8.0",
"@hellroot/stylelint-config": "1.1.0",
+ "bemify": "0.1.2",
"eslint": "5.12.0",
"npm-run-all": "4.1.5",
"prettier": "1.17.0",
"react-scripts": "2.1.8",
+ "static-site-generator-webpack-plugin": "3.4.2",
"stylelint": "10.0.1",
- "typescript": "3.3.4000"
+ "typescript": "3.3.4000",
+ "webpack": "4.28.3"
},
"scripts": {
"dev": "react-scripts start",
"test": "react-scripts test",
"build": "react-scripts build",
+ "eject": "react-scripts eject",
"lint": "npm-run-all lint:*",
"lint:js": "eslint '**/*.{js,jsx}'",
"lint:css": "stylelint '**/*.css'",
diff --git a/public/favicon.ico b/public/favicon.ico
deleted file mode 100644
index a11777c..0000000
Binary files a/public/favicon.ico and /dev/null differ
diff --git a/public/favicon.png b/public/favicon.png
new file mode 100644
index 0000000..ea5907a
Binary files /dev/null and b/public/favicon.png differ
diff --git a/public/index.html b/public/index.html
index 9a8ef8f..249c04a 100644
--- a/public/index.html
+++ b/public/index.html
@@ -1,17 +1,16 @@
-
-
-
-
-
- React App
-
-
-
-
-
+
+
+
+
+
+ Яндекс Почта
+
+
+
+
diff --git a/src/app/app.css b/src/app/app.css
deleted file mode 100644
index 1c4d511..0000000
--- a/src/app/app.css
+++ /dev/null
@@ -1,27 +0,0 @@
-.app {
- text-align: center;
-}
-
-.app-header {
- display: flex;
- min-height: 100vh;
- flex-direction: column;
- align-items: center;
- justify-content: center;
- background-color: #282c34;
- color: #fff;
- font-size: calc(10px + 2vmin);
-}
-
-.app-link {
- color: #61dafb;
-}
-
-@keyframes app-logo-spin {
- from {
- transform: rotate(0deg);
- }
- to {
- transform: rotate(360deg);
- }
-}
diff --git a/src/app/app.jsx b/src/app/app.jsx
deleted file mode 100644
index f759eed..0000000
--- a/src/app/app.jsx
+++ /dev/null
@@ -1,25 +0,0 @@
-import React, { Component } from 'react';
-
-import './app.css';
-
-export class App extends Component {
- render() {
- return (
-
- );
- }
-}
diff --git a/src/app/app.test.jsx b/src/app/app.test.jsx
deleted file mode 100644
index 81be6fa..0000000
--- a/src/app/app.test.jsx
+++ /dev/null
@@ -1,11 +0,0 @@
-import React from 'react';
-import ReactDOM from 'react-dom';
-
-import { App } from './app';
-
-it('renders without crashing', () => {
- const div = document.createElement('div');
-
- ReactDOM.render(, div);
- ReactDOM.unmountComponentAtNode(div);
-});
diff --git a/src/app/index.js b/src/app/index.js
deleted file mode 100644
index 665a3d9..0000000
--- a/src/app/index.js
+++ /dev/null
@@ -1 +0,0 @@
-export * from './app';
diff --git a/src/components/check/check.module.css b/src/components/check/check.module.css
new file mode 100644
index 0000000..de01a64
--- /dev/null
+++ b/src/components/check/check.module.css
@@ -0,0 +1,57 @@
+.check {
+ width: 16px;
+ height: 16px;
+}
+
+.input {
+ position: absolute;
+ top: 1px;
+ left: 10px;
+
+ width: 30px;
+ height: 30px;
+ -webkit-appearance: none;
+ -moz-appearance: none;
+ appearance: none;
+ cursor: pointer;
+ outline: none;
+}
+
+.box {
+ position: absolute;
+
+ width: 16px;
+ height: 16px;
+
+ border: 1px solid rgba(0, 0, 0, 0.15);
+ background-color: #fff;
+ border-radius: 3px;
+ cursor: pointer;
+}
+
+.box:after {
+ position: absolute;
+ top: 0;
+ left: 0;
+
+ width: 7px;
+ height: 21px;
+ margin: -9px 0 0 6px;
+
+ border-right: 2px solid;
+ border-bottom: 2px solid;
+ color: #000;
+ content: '';
+ -webkit-transform: scale(0.85) rotate(47deg) skewX(12deg);
+ transform: scale(0.85) rotate(47deg) skewX(12deg);
+ visibility: hidden;
+}
+
+.box_checked {
+ border-color: rgba(153, 122, 0, 0.5);
+ box-shadow: inset 0 90px #ffeba0;
+}
+
+.box_checked:after {
+ visibility: inherit;
+}
diff --git a/src/components/check/check.tsx b/src/components/check/check.tsx
new file mode 100644
index 0000000..e59c286
--- /dev/null
+++ b/src/components/check/check.tsx
@@ -0,0 +1,29 @@
+import React from 'react';
+import pure from 'recompose/pure';
+import cx from 'classnames';
+
+import styles from './check.module.css';
+
+interface IProps {
+ isChecked: boolean;
+ onChange?: () => void;
+}
+
+const Check = (props: IProps) => {
+ // console.log('Check');
+ const { isChecked, onChange } = props;
+ const boxClassName = cx(styles.box, {
+ [styles.box_checked]: isChecked
+ });
+
+ return (
+
+
+
+ );
+};
+
+export default pure(Check);
diff --git a/src/components/letter/letter.module.css b/src/components/letter/letter.module.css
new file mode 100644
index 0000000..d040aeb
--- /dev/null
+++ b/src/components/letter/letter.module.css
@@ -0,0 +1,139 @@
+.box {
+ position: relative;
+ top: -42px;
+
+ height: 0;
+ transition: height 0.5s, top 0.5s;
+}
+
+.box_hasAddAnimation {
+ top: 0;
+
+ height: 42px;
+}
+
+.box_hasRemoveAnimation {
+ z-index: 0 !important;
+ top: -42px;
+
+ height: 0;
+}
+
+.line {
+ position: relative;
+
+ height: 20px;
+ padding: 10px 20px;
+ margin: 0;
+ font-size: 13px;
+}
+
+.line_theme_light {
+ background-color: #fff;
+}
+
+.line_theme_dark {
+ background-color: #1d1d1d;
+ color: #9b9b9b;
+}
+
+.line_unread.line_theme_light {
+ color: #000;
+ font-weight: 700;
+}
+
+.line_unread.line_theme_dark {
+ color: #fff;
+}
+
+.item {
+ display: inline-block;
+ overflow: hidden;
+ list-style-type: none;
+ text-overflow: ellipsis;
+ vertical-align: middle;
+}
+
+.item:first-child {
+ vertical-align: initial;
+}
+
+.item:last-child {
+ font-weight: initial;
+}
+
+.author {
+ width: 30px;
+ height: 30px;
+ margin: -5px 0 0 10px;
+}
+
+.author_hasLogo {
+ width: 100%;
+ height: 100%;
+ border-radius: 100px;
+}
+
+.author_noLogo {
+ width: 100%;
+ height: 100%;
+ background-color: #f33;
+ border-radius: 100px;
+ color: #fff;
+ font: 500 18px Helvetica Neue Light, sans-serif;
+ line-height: 30px;
+ text-align: center;
+}
+
+.authorName {
+ width: 160px;
+ margin: 0 0 5px 10px;
+}
+
+.readMark {
+ width: 10px;
+ height: 10px;
+ margin: 0 0 5px 5px;
+}
+
+.readMark_unread {
+ background-color: #6287bd;
+ border-radius: 100px;
+}
+
+.topic {
+ position: absolute;
+ top: 13px;
+ right: 70px;
+ left: 281px;
+
+ overflow: hidden;
+ min-width: 220px;
+}
+
+.topic_isOpen {
+ font: 700 30px Helvetica Neue, sans-serif;
+ text-align: center;
+ word-wrap: break-word;
+}
+
+.body {
+ margin-top: 30px;
+}
+
+.date {
+ position: absolute;
+ top: 13px;
+ right: 20px;
+ color: #9b9b9b;
+ text-align: right;
+}
+
+.linkOpen {
+ position: absolute;
+ top: -2px;
+ right: 0;
+ bottom: 2px;
+ left: 45px;
+ cursor: pointer;
+}
diff --git a/src/components/letter/letter.tsx b/src/components/letter/letter.tsx
new file mode 100644
index 0000000..ca018a0
--- /dev/null
+++ b/src/components/letter/letter.tsx
@@ -0,0 +1,97 @@
+import React, { Component } from 'react';
+import cx from 'classnames';
+import Check from '../check/check';
+import Hr from '../letterBox/hr';
+import LetterItem from './letterItem';
+
+import styles from './letter.module.css';
+
+interface IProps {
+ className?: string;
+ authorLogo: JSX.Element;
+ authorName: string;
+ topic: string;
+ date: JSX.Element;
+ isUnread: boolean;
+ isChecked: boolean;
+ hiddenMail: boolean;
+ hasRemoveAnimation: boolean;
+ handleMailClick: () => void;
+ handleMailCheckClick: () => void;
+ theme: string;
+}
+
+interface IState {
+ hasAddAnimation: boolean;
+}
+
+export default class Letter extends Component {
+ static displayName = 'Letter';
+
+ DELTA_TIME = 20;
+
+ timerID: NodeJS.Timeout = setTimeout(() => {}, 0);
+
+ constructor(props: IProps) {
+ super(props);
+
+ this.state = {
+ hasAddAnimation: false
+ };
+ }
+
+ componentDidMount() {
+ this.timerID = setTimeout(() => {
+ this.setState({ hasAddAnimation: true });
+ }, this.DELTA_TIME);
+ }
+
+ componentWillUnmount() {
+ clearTimeout(this.timerID);
+ }
+
+ render() {
+ const {
+ className,
+ authorLogo,
+ authorName,
+ topic,
+ date,
+ handleMailClick,
+ handleMailCheckClick,
+ hiddenMail,
+ hasRemoveAnimation,
+ isUnread,
+ isChecked,
+ theme
+ } = this.props;
+ const { hasAddAnimation } = this.state;
+ const letterClassName = cx(styles.box, className, {
+ [styles.box_hasAddAnimation]: hasAddAnimation,
+ [styles.box_hasRemoveAnimation]: hasRemoveAnimation
+ });
+ const readMarkClassName = cx(styles.readMark, {
+ [styles.readMark_unread]: isUnread
+ });
+ const lineClassName = cx(styles.line, styles[`line_theme_${theme}`], {
+ [styles.line_unread]: isUnread
+ });
+
+ return (
+
+
+
+
+
+ {authorLogo}
+ {authorName}
+
+ {topic}
+ {date}
+
+
+
+
+ );
+ }
+}
diff --git a/src/components/letter/letterItem.tsx b/src/components/letter/letterItem.tsx
new file mode 100644
index 0000000..eeed439
--- /dev/null
+++ b/src/components/letter/letterItem.tsx
@@ -0,0 +1,18 @@
+import React from 'react';
+import cx from 'classnames';
+import pure from 'recompose/pure';
+import styles from './letter.module.css';
+
+interface ILetterItemProps {
+ className?: string;
+ children?: any;
+}
+
+const LetterItem = (props: ILetterItemProps) => {
+ console.log('LetterItem');
+ const { className, children } = props;
+ const itemClassName = cx(styles.item, className);
+ return {children};
+};
+
+export default pure(LetterItem);
diff --git a/src/components/letterBox/ILetter.ts b/src/components/letterBox/ILetter.ts
new file mode 100644
index 0000000..c9dfce9
--- /dev/null
+++ b/src/components/letterBox/ILetter.ts
@@ -0,0 +1,11 @@
+export default interface ILetter {
+ id: number;
+ isChecked: boolean;
+ isUnread: boolean;
+ authorName: string;
+ authorLogo: JSX.Element;
+ topic: string;
+ body: string;
+ date: JSX.Element;
+ hasRemoveAnimation: boolean;
+}
diff --git a/src/components/letterBox/hr.tsx b/src/components/letterBox/hr.tsx
new file mode 100644
index 0000000..48ef9a6
--- /dev/null
+++ b/src/components/letterBox/hr.tsx
@@ -0,0 +1,7 @@
+import React from 'react';
+
+import styles from './letterBox.module.css';
+
+export default function Hr() {
+ return
;
+}
diff --git a/src/components/letterBox/letterBox.module.css b/src/components/letterBox/letterBox.module.css
new file mode 100644
index 0000000..b1cbcf7
--- /dev/null
+++ b/src/components/letterBox/letterBox.module.css
@@ -0,0 +1,58 @@
+.box {
+ position: absolute;
+ top: 7px;
+ right: 10px;
+ bottom: 4px;
+ left: 177px;
+
+ overflow: hidden;
+ min-width: 700px;
+ min-height: 350px;
+ margin: 0 10px 10px;
+ border-radius: 3px;
+ font-family: 'Helvetica Neue', sans-serif;
+}
+
+.box_theme_light {
+ background-color: #fff;
+ box-shadow: 0 2px 6px rgba(0, 0, 0, 0.34);
+ color: #000;
+}
+
+.box_theme_dark {
+ background-color: #1d1d1d;
+ box-shadow: 0 2px 6px rgba(0, 0, 0, 0.34);
+ color: #fff;
+}
+
+.hr {
+ margin: 0;
+ opacity: 0.4;
+}
+
+.supportLine {
+ position: absolute;
+ right: 0;
+ bottom: 0;
+ left: 0;
+}
+
+.letterList {
+ position: absolute;
+ top: 40px;
+ bottom: 25px;
+
+ overflow: auto;
+ width: 100%;
+ padding: 0;
+ margin: 0;
+}
+
+.bb {
+ position: relative;
+}
+
+.letter {
+ z-index: 1;
+ list-style-type: none;
+}
diff --git a/src/components/letterBox/letterBox.tsx b/src/components/letterBox/letterBox.tsx
new file mode 100644
index 0000000..1fcdc8a
--- /dev/null
+++ b/src/components/letterBox/letterBox.tsx
@@ -0,0 +1,294 @@
+import React, { Component } from 'react';
+import cx from 'classnames';
+import Toolbar from '../toolbar/toolbar';
+import LetterDialog from '../letterDialog/letterDialog';
+import SupportLine from '../supportLine/supportLine';
+import LetterGenerator from '../../utils/letterGenerator';
+import Letter from '../letter/letter';
+import LetterList from './letterList';
+import Hr from './hr';
+
+import { getInt } from '../../utils/randomFunctions';
+
+import ILetter from './ILetter';
+import IToolbarItem from '../toolbar/toolBarItem';
+
+import letterStyles from '../letter/letter.module.css';
+import styles from './letterBox.module.css';
+
+interface IProps {
+ className?: string;
+ theme: string;
+ filterText: string;
+ changeFilterProgress: (value: number) => void;
+}
+
+interface IState {
+ curPage: number;
+ letters: ILetter[];
+ isMailVisible: boolean;
+ mailContent: any;
+ isCheckAll: boolean;
+ selectLetterCount: number;
+}
+
+export default class LetterBox extends Component {
+ static displayName = 'LetterBox';
+
+ MIN_TIMER_ADD_MAIL = 300000;
+
+ MAX_TIMER_ADD_MAIL = 600001;
+
+ MAX_MAIL_LIST_SIZE = 30;
+
+ REMOVE_LETTER_TIME = 500;
+
+ DELTA_TIME = 20;
+
+ letterId = 0;
+
+ letterGenerator = new LetterGenerator();
+
+ timerOuterID: NodeJS.Timeout = setTimeout(() => {}, 0);
+
+ timerInnerID: NodeJS.Timeout = setTimeout(() => {}, 0);
+
+ constructor(props: IProps) {
+ super(props);
+ this.state = {
+ curPage: 1,
+ letters: [],
+ isMailVisible: false,
+ mailContent: undefined,
+ isCheckAll: false,
+ selectLetterCount: 0
+ };
+ }
+
+ componentDidMount() {
+ const self = this;
+ this.timerOuterID = setTimeout(function run() {
+ self.newMail();
+ const timer = getInt(self.MIN_TIMER_ADD_MAIL, self.MAX_TIMER_ADD_MAIL);
+ self.timerInnerID = setTimeout(run, timer);
+ }, getInt(self.DELTA_TIME, self.MAX_TIMER_ADD_MAIL));
+ }
+
+ componentWillUnmount() {
+ clearTimeout(this.timerOuterID);
+ clearTimeout(this.timerInnerID);
+ }
+
+ setCheckAll = (value: boolean) => {
+ this.setState({ isCheckAll: value });
+ };
+
+ getRandomLetter = () => {
+ const authorName = this.letterGenerator.getAuthorName();
+ return {
+ id: this.letterId++,
+ isChecked: false,
+ isUnread: true,
+ authorName,
+ authorLogo: this.letterGenerator.getAuthorLogo(authorName),
+ topic: this.letterGenerator.getTopic(),
+ body: this.letterGenerator.getLetterBody(),
+ date: this.letterGenerator.getDate(),
+ hasRemoveAnimation: false
+ };
+ };
+
+ newMail = () => {
+ this.setState(state => {
+ const letters = state.letters;
+ let { selectLetterCount } = state;
+ if (letters.length >= state.curPage * this.MAX_MAIL_LIST_SIZE) {
+ if (letters[state.curPage * this.MAX_MAIL_LIST_SIZE - 1].isChecked) {
+ selectLetterCount--;
+ }
+ letters[state.curPage * this.MAX_MAIL_LIST_SIZE - 1].isChecked = false;
+ }
+ return {
+ letters: [this.getRandomLetter(), ...letters],
+ selectLetterCount
+ };
+ });
+ this.setCheckAll(false);
+ };
+
+ doActionWithLetters = (action: (i: number) => void) => {
+ const { curPage, letters } = this.state;
+ const first = (curPage - 1) * this.MAX_MAIL_LIST_SIZE;
+ for (let i = Math.min(letters.length, curPage * this.MAX_MAIL_LIST_SIZE) - 1; i >= first; i--) {
+ if (letters[i].isChecked) {
+ action(i);
+ }
+ }
+ };
+
+ removeAnimateLetter = (index: number) => {
+ setTimeout(() => {
+ this.setState(state => {
+ const letters = state.letters.slice();
+ letters[index].hasRemoveAnimation = true;
+ return { letters };
+ });
+ setTimeout(() => {
+ this.setState(state => {
+ const letters = state.letters.slice();
+ letters.splice(index, 1);
+ return { letters, selectLetterCount: state.selectLetterCount - 1 };
+ });
+ }, this.REMOVE_LETTER_TIME);
+ }, this.DELTA_TIME);
+ };
+
+ handleRemoveButtonClick = () => {
+ setTimeout(() => {
+ this.setCheckAll(false);
+ }, this.REMOVE_LETTER_TIME);
+ this.doActionWithLetters(this.removeAnimateLetter);
+ };
+
+ unmarkLetter = (index: number) => {
+ if (this.state.letters[index].isUnread) {
+ this.setState(state => {
+ const letters = state.letters.slice();
+ letters[index].isUnread = false;
+ return { letters };
+ });
+ }
+ };
+
+ handleUnmarkButtonClick = () => {
+ this.doActionWithLetters(this.unmarkLetter);
+ };
+
+ handleMailCheckClick = (index: number) => {
+ this.setState(state => {
+ const letters = state.letters.slice();
+ const checked = letters[index].isChecked;
+ const isCheckAll = checked ? !checked : state.isCheckAll;
+ const selectLetterCount = state.selectLetterCount + (checked ? -1 : 1);
+ letters[index].isChecked = !checked;
+ return { letters, isCheckAll, selectLetterCount };
+ });
+ };
+
+ handleCheckAllClick = () => {
+ this.setState(state => {
+ const letters = state.letters.slice();
+ const size = Math.min(letters.length, state.curPage * this.MAX_MAIL_LIST_SIZE);
+ for (let i = (state.curPage - 1) * this.MAX_MAIL_LIST_SIZE; i < size; i++) {
+ letters[i].isChecked = !state.isCheckAll;
+ }
+ const selectLetterCount = state.isCheckAll ? 0 : size;
+ return { letters, isCheckAll: !state.isCheckAll, selectLetterCount };
+ });
+ };
+
+ handleMailClick = (index: number) => {
+ this.setState(state => {
+ const mailContent = (
+
+
{state.letters[index].topic}
+
{state.letters[index].body}
+
+ );
+ return { isMailVisible: true, mailContent };
+ });
+ this.unmarkLetter(index);
+ };
+
+ handleMailExitClick = () => {
+ this.setState({ isMailVisible: false });
+ };
+
+ getToolBarItems = (isCheckAll: boolean, selectLetterCount: number) => [
+ { type: 'checkbox', value: isCheckAll, onClick: this.handleCheckAllClick },
+ { type: 'button', value: 'Получить сообщение', onClick: this.newMail, isActive: true },
+ { type: 'button', value: 'Переслать', isActive: selectLetterCount > 0 },
+ {
+ type: 'button',
+ value: 'Удалить',
+ onClick: this.handleRemoveButtonClick,
+ isActive: selectLetterCount > 0
+ },
+ { type: 'button', value: 'Это спам!', isActive: selectLetterCount > 0 },
+ {
+ type: 'button',
+ value: 'Прочитано',
+ onClick: this.handleUnmarkButtonClick,
+ isActive: selectLetterCount > 0
+ }
+ ];
+
+ toolbarItems: IToolbarItem[] = [];
+
+ oldSelectLetterCount: number | undefined = undefined;
+
+ oldIsCheckAll: boolean | undefined = undefined;
+
+ render() {
+ const {
+ curPage,
+ letters,
+ isMailVisible,
+ mailContent,
+ selectLetterCount,
+ isCheckAll
+ } = this.state;
+ const { className, theme, filterText, changeFilterProgress } = this.props;
+
+ const letterMapper = (letter: ILetter, index: number) => (
+ curPage * this.MAX_MAIL_LIST_SIZE &&
+ index >= curPage * this.MAX_MAIL_LIST_SIZE
+ }
+ hasRemoveAnimation={letter.hasRemoveAnimation}
+ handleMailClick={this.handleMailClick.bind(this, index)}
+ handleMailCheckClick={this.handleMailCheckClick.bind(this, index)}
+ theme={theme}
+ />
+ );
+
+ if (this.oldSelectLetterCount !== selectLetterCount || this.oldIsCheckAll !== isCheckAll) {
+ this.toolbarItems = this.getToolBarItems(isCheckAll, selectLetterCount);
+ this.oldSelectLetterCount = selectLetterCount;
+ this.oldIsCheckAll = isCheckAll;
+ }
+
+ const letterBoxClassName = cx(styles.box, className, styles[`box_theme_${theme}`]);
+
+ return (
+
+
{this.toolbarItems}
+
+
+ {mailContent}
+
+
+
+
+
+
+
+ );
+ }
+}
diff --git a/src/components/letterBox/letterList.tsx b/src/components/letterBox/letterList.tsx
new file mode 100644
index 0000000..60d231a
--- /dev/null
+++ b/src/components/letterBox/letterList.tsx
@@ -0,0 +1,60 @@
+import React from 'react';
+import shouldUpdate from 'recompose/shouldUpdate';
+
+import ILetter from './ILetter';
+
+import styles from './letterBox.module.css';
+
+interface IProps {
+ filterText: string;
+ letters: ILetter[];
+ mapper: (letter: ILetter, index: number) => JSX.Element;
+ theme: string;
+ listMaxSize: number;
+ changeFilterProgress: (value: number) => void;
+}
+
+const filterPredicate = (filterText: string, letter: ILetter) => {
+ return (
+ letter.authorName.toLowerCase().includes(filterText) ||
+ letter.topic.toLowerCase().includes(filterText) ||
+ letter.body.toLowerCase().includes(filterText)
+ );
+};
+
+function filterAndMapLetters(
+ arr: ILetter[],
+ predicate: (val: ILetter) => boolean,
+ mapper: (val: ILetter, index: number) => JSX.Element,
+ maxSize: number
+) {
+ const result = [];
+ for (let i = 0; i < arr.length; i++) {
+ if (predicate(arr[i])) {
+ result.push(mapper(arr[i], i));
+ }
+ if (result.length === maxSize) {
+ return result;
+ }
+ }
+ return result;
+}
+
+const LetterList = (props: IProps) => {
+ const { filterText, letters, mapper, listMaxSize } = props;
+ const listLetters = filterAndMapLetters(
+ letters,
+ letter => filterPredicate(filterText, letter),
+ mapper,
+ listMaxSize
+ );
+
+ return ;
+};
+
+const checkPropsChange = (props: IProps, nextProps: IProps) =>
+ nextProps.filterText !== props.filterText ||
+ nextProps.letters !== props.letters ||
+ nextProps.theme !== props.theme;
+
+export default shouldUpdate(checkPropsChange)(LetterList);
diff --git a/src/components/letterDialog/letterDialog.module.css b/src/components/letterDialog/letterDialog.module.css
new file mode 100644
index 0000000..386daa0
--- /dev/null
+++ b/src/components/letterDialog/letterDialog.module.css
@@ -0,0 +1,30 @@
+.box {
+ position: absolute;
+ top: 40px;
+ bottom: 25px;
+
+ overflow: auto;
+ width: 100%;
+ background-color: inherit;
+ visibility: hidden;
+}
+
+.content {
+ padding: 20px;
+ font-family: sans-serif;
+ font-size: 14px;
+ white-space: normal;
+}
+
+.exit {
+ margin: -5px 5px 0 0;
+ color: #808080;
+ cursor: pointer;
+ float: right;
+ font-size: 35px;
+}
+
+.box_isVisible {
+ z-index: 2;
+ visibility: visible;
+}
diff --git a/src/components/letterDialog/letterDialog.tsx b/src/components/letterDialog/letterDialog.tsx
new file mode 100644
index 0000000..6ae3aaa
--- /dev/null
+++ b/src/components/letterDialog/letterDialog.tsx
@@ -0,0 +1,33 @@
+import React from 'react';
+import shouldUpdate from 'recompose/shouldUpdate';
+import cx from 'classnames';
+
+import styles from './letterDialog.module.css';
+
+interface IProps {
+ isVisible: boolean;
+ onExitClick: () => void;
+ children: JSX.Element[];
+}
+
+const LetterDialog = (props: IProps) => {
+ console.log('LetterDialog');
+ const { isVisible, onExitClick, children } = props;
+ const dialogClassName = cx(styles.box, {
+ [styles.box_isVisible]: isVisible
+ });
+
+ return (
+
+ );
+};
+
+const checkPropsChange = (props: IProps, nextProps: IProps) =>
+ nextProps.isVisible !== props.isVisible || nextProps.children !== props.children;
+
+export default shouldUpdate(checkPropsChange)(LetterDialog);
diff --git a/src/components/linkBlock/linkBlock.module.css b/src/components/linkBlock/linkBlock.module.css
new file mode 100644
index 0000000..9edb269
--- /dev/null
+++ b/src/components/linkBlock/linkBlock.module.css
@@ -0,0 +1,19 @@
+.box {
+ width: 100%;
+ min-height: 32px;
+
+ border: none;
+ background-color: #6287bd;
+ border-radius: 3px;
+ color: #fff;
+ font-size: 12px;
+ font-weight: 500;
+ outline: none;
+ text-align: center;
+ word-wrap: break-word;
+}
+
+.box:hover {
+ background-color: #4c76b7;
+ cursor: pointer;
+}
diff --git a/src/components/linkBlock/linkBlock.tsx b/src/components/linkBlock/linkBlock.tsx
new file mode 100644
index 0000000..c8ccbe0
--- /dev/null
+++ b/src/components/linkBlock/linkBlock.tsx
@@ -0,0 +1,24 @@
+import React from 'react';
+import cx from 'classnames';
+
+import styles from './linkBlock.module.css';
+
+interface IProps {
+ className?: string;
+ onClick?: () => void;
+ title: string;
+}
+
+const LinkBlock = (props: IProps) => {
+ console.log('LinkBlock');
+ const { className, title, onClick } = props;
+ const linkBlockClassName = cx(styles.box, className);
+
+ return (
+
+ );
+};
+
+export default LinkBlock;
diff --git a/src/components/logo/logo.module.css b/src/components/logo/logo.module.css
new file mode 100644
index 0000000..9b5d524
--- /dev/null
+++ b/src/components/logo/logo.module.css
@@ -0,0 +1,22 @@
+.box {
+ width: 153px;
+ height: 31px;
+}
+
+.item_img_yandex {
+ position: relative;
+ left: -153px;
+
+ display: inline-block;
+ width: 83px;
+ height: 31px;
+}
+
+.item_img_mail {
+ position: relative;
+ left: -153px;
+
+ display: inline-block;
+ width: 70px;
+ height: 31px;
+}
diff --git a/src/components/logo/logo.tsx b/src/components/logo/logo.tsx
new file mode 100644
index 0000000..31c4d39
--- /dev/null
+++ b/src/components/logo/logo.tsx
@@ -0,0 +1,42 @@
+import React from 'react';
+import shouldUpdate from 'recompose/shouldUpdate';
+import cx from 'classnames';
+
+import logoImgLight from '../../resources/images/yandexLogo_Light.svg';
+import logoImgDark from '../../resources/images/yandexLogo_Dark1.svg';
+
+import styles from './logo.module.css';
+
+interface IProps {
+ className?: string;
+ theme: string;
+}
+
+const Logo = (props: IProps) => {
+ console.log('Logo');
+ const { className, theme } = props;
+ const logoClassName = cx(styles.box, {
+ [`${className}`]: className
+ });
+
+ function themeSwitch() {
+ switch (theme) {
+ case 'dark':
+ return logoImgDark;
+ default:
+ return logoImgLight;
+ }
+ }
+
+ return (
+
+
})
+
+
+
+ );
+};
+
+const checkPropsChange = (props: IProps, nextProps: IProps) => nextProps.theme !== props.theme;
+
+export default shouldUpdate(checkPropsChange)(Logo);
diff --git a/src/components/mail/mail.module.css b/src/components/mail/mail.module.css
new file mode 100644
index 0000000..b6deda9
--- /dev/null
+++ b/src/components/mail/mail.module.css
@@ -0,0 +1,19 @@
+.box {
+ position: absolute;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ left: 0;
+
+ padding: 8px 18px;
+ transition: background-color 0.15s;
+ white-space: nowrap;
+}
+
+.box_theme_light {
+ background-color: #e5eaf0;
+}
+
+.box_theme_dark {
+ background-color: #303030;
+}
diff --git a/src/components/mail/mail.tsx b/src/components/mail/mail.tsx
new file mode 100644
index 0000000..e1e54a0
--- /dev/null
+++ b/src/components/mail/mail.tsx
@@ -0,0 +1,77 @@
+import React, { Component } from 'react';
+import Cookies from 'universal-cookie';
+import cx from 'classnames';
+import MailHeader from '../mailHeader/mailHeader';
+import MailMain from '../mailMain/mailMain';
+
+import styles from './mail.module.css';
+
+interface IState {
+ theme: string;
+ filterText: string;
+ filterProgress: number;
+}
+
+const cookies = new Cookies();
+
+export default class Mail extends Component<{}, IState> {
+ constructor(props: {}) {
+ super(props);
+ this.state = {
+ theme: this.initTheme(),
+ filterText: '',
+ filterProgress: 1
+ };
+ }
+
+ initTheme = () => {
+ const curTheme = cookies.get('theme');
+ return curTheme === undefined ? 'light' : curTheme;
+ };
+
+ handleThemeBtnClick = () => {
+ this.setState(state => {
+ const theme = state.theme === 'light' ? 'dark' : 'light';
+ cookies.set('theme', theme, { path: '/' });
+ return { theme };
+ });
+ };
+
+ changeFilterText = (value: string) => {
+ if (value.toLowerCase() === 'темная тема') {
+ this.setState({ theme: 'dark' });
+ }
+ this.setState({ filterText: value });
+ };
+
+ clearFilterText = () => {
+ this.setState({ filterText: '' });
+ };
+
+ changeFilterProgress = (value: number) => {
+ this.setState({ filterProgress: value });
+ };
+
+ render() {
+ console.log('MailApp');
+ const { theme, filterText, filterProgress } = this.state;
+ const boxClassName = cx(styles.box, styles[`box_theme_${theme}`]);
+ return (
+
+
+
+
+ );
+ }
+}
diff --git a/src/components/mailHeader/mailHeader.module.css b/src/components/mailHeader/mailHeader.module.css
new file mode 100644
index 0000000..ebe89b2
--- /dev/null
+++ b/src/components/mailHeader/mailHeader.module.css
@@ -0,0 +1,44 @@
+.box {
+ position: relative;
+
+ height: 32px;
+ letter-spacing: -1em;
+}
+
+.menu,
+.logo,
+.rightBox {
+ display: inline-block;
+ vertical-align: middle;
+}
+
+.menu {
+ margin-top: -6px;
+}
+
+.logo {
+ margin-left: 11px;
+}
+
+.search {
+ position: absolute;
+ right: 179px;
+ left: 0;
+}
+
+.linkBlock {
+ position: absolute;
+ top: 0;
+ right: 0;
+
+ width: 50px;
+}
+
+.rightBox {
+ position: absolute;
+ right: 20px;
+ left: 184px;
+
+ min-width: 420px;
+ margin-left: 114px;
+}
diff --git a/src/components/mailHeader/mailHeader.tsx b/src/components/mailHeader/mailHeader.tsx
new file mode 100644
index 0000000..f65cf6d
--- /dev/null
+++ b/src/components/mailHeader/mailHeader.tsx
@@ -0,0 +1,56 @@
+import React, { Props } from 'react';
+import shouldUpdate from 'recompose/shouldUpdate';
+import Menu from '../menu/menu';
+import Logo from '../logo/logo';
+import Search from '../search/search';
+import LinkBlock from '../linkBlock/linkBlock';
+
+import styles from './mailHeader.module.css';
+
+interface IProps {
+ theme: string;
+ filterText: string;
+ filterProgress: number;
+ changeFilterText: (value: string) => void;
+ clearFilterText: () => void;
+ onThemeBtnClick: () => void;
+}
+
+const MailHeader = (props: IProps) => {
+ console.log('MailHeader');
+ const {
+ theme,
+ filterText,
+ filterProgress,
+ changeFilterText,
+ clearFilterText,
+ onThemeBtnClick
+ } = props;
+
+ return (
+
+ );
+};
+
+const checkPropsChange = (props: IProps, nextProps: IProps) =>
+ nextProps.theme !== props.theme ||
+ nextProps.filterText !== props.filterText ||
+ nextProps.filterProgress !== props.filterProgress;
+
+export default shouldUpdate(checkPropsChange)(MailHeader);
diff --git a/src/components/mailMain/mailMain.module.css b/src/components/mailMain/mailMain.module.css
new file mode 100644
index 0000000..5a2d477
--- /dev/null
+++ b/src/components/mailMain/mailMain.module.css
@@ -0,0 +1,18 @@
+.box {
+ position: absolute;
+ top: 35px;
+ right: 0;
+ bottom: 0;
+ left: 0;
+
+ padding: 7px 0 0 18px;
+
+ margin-top: 13px;
+}
+
+.nav,
+.letterBox {
+ display: inline-block;
+ vertical-align: top;
+ white-space: normal;
+}
diff --git a/src/components/mailMain/mailMain.tsx b/src/components/mailMain/mailMain.tsx
new file mode 100644
index 0000000..b10cfa0
--- /dev/null
+++ b/src/components/mailMain/mailMain.tsx
@@ -0,0 +1,28 @@
+import React from 'react';
+import shouldUpdate from 'recompose/shouldUpdate';
+import Nav from '../nav/nav';
+import LetterBox from '../letterBox/letterBox';
+
+import styles from './mailMain.module.css';
+
+interface IProps {
+ theme: string;
+ filterText: string;
+ changeFilterProgress: (value: number) => void;
+}
+
+const MailMain = (props: IProps) => {
+ console.log('MailMain');
+ const { theme } = props;
+ return (
+
+
+
+
+ );
+};
+
+const checkPropsChange = (props: IProps, nextProps: IProps) =>
+ nextProps.theme !== props.theme || nextProps.filterText !== props.filterText;
+
+export default shouldUpdate(checkPropsChange)(MailMain);
diff --git a/src/components/menu/menu.module.css b/src/components/menu/menu.module.css
new file mode 100644
index 0000000..9aa0aa7
--- /dev/null
+++ b/src/components/menu/menu.module.css
@@ -0,0 +1,18 @@
+.box {
+ width: 20px;
+ height: 17px;
+}
+
+.hr {
+ width: 20px;
+ height: 2px;
+ margin-top: 4px;
+}
+
+.hr_theme_light {
+ background-color: #393a3b;
+}
+
+.hr_theme_dark {
+ background-color: #f6f6f6;
+}
diff --git a/src/components/menu/menu.tsx b/src/components/menu/menu.tsx
new file mode 100644
index 0000000..82affa7
--- /dev/null
+++ b/src/components/menu/menu.tsx
@@ -0,0 +1,29 @@
+import React from 'react';
+import shouldUpdate from 'recompose/shouldUpdate';
+import cx from 'classnames';
+
+import styles from './menu.module.css';
+
+interface IProps {
+ className?: string;
+ theme: string;
+}
+
+const Menu = (props: IProps) => {
+ console.log('Menu');
+ const { className, theme } = props;
+ const menuClassName = cx(styles.box, className);
+ const hrClassName = cx(styles.hr, styles[`hr_theme_${theme}`]);
+
+ return (
+
+ );
+};
+
+const checkPropsChange = (props: IProps, nextProps: IProps) => nextProps.theme !== props.theme;
+
+export default shouldUpdate(checkPropsChange)(Menu);
diff --git a/src/components/nav/nav.module.css b/src/components/nav/nav.module.css
new file mode 100644
index 0000000..3a4924e
--- /dev/null
+++ b/src/components/nav/nav.module.css
@@ -0,0 +1,61 @@
+.box {
+ width: 147px;
+ font-family: 'Helvetica Neue', sans-serif;
+}
+
+.list {
+ padding: 0;
+ margin: 8px 0 0 0;
+ word-wrap: break-word;
+}
+
+.item {
+ min-height: 14px;
+ font-size: 11px;
+ list-style-type: none;
+}
+
+.item_theme_light {
+ color: #707070;
+}
+
+.item_theme_dark {
+ color: #f9f9f9;
+}
+
+.item_type_link {
+ display: block;
+ width: 87%;
+ padding: 5px 10px;
+ color: inherit;
+ cursor: pointer;
+ text-decoration: none;
+}
+
+.item:hover {
+ border-radius: 3px;
+}
+
+.item_theme_light:hover {
+ background-color: #d8e1ef;
+}
+
+.item_theme_dark:hover {
+ background-color: #1f1f1f;
+}
+
+.item_select {
+ border-radius: 3px;
+}
+
+.item_select.item_theme_light {
+ background-color: #cdd6e4;
+ color: #555;
+ font-weight: 700;
+}
+
+.item_select.item_theme_dark {
+ background-color: #111111;
+ color: #f9f9f9;
+ font-weight: 600;
+}
diff --git a/src/components/nav/nav.tsx b/src/components/nav/nav.tsx
new file mode 100644
index 0000000..71893fd
--- /dev/null
+++ b/src/components/nav/nav.tsx
@@ -0,0 +1,51 @@
+import React, { Props } from 'react';
+import shouldUpdate from 'recompose/shouldUpdate';
+import cx from 'classnames';
+import LinkBlock from '../linkBlock/linkBlock';
+
+import styles from './nav.module.css';
+
+interface IProps {
+ className?: string;
+ theme: string;
+}
+
+const items = [
+ { key: 1, link: '/public/index.html', title: 'Входящиe', isSelect: true },
+ { key: 2, link: '/public/index.html', title: 'Отправленные' },
+ { key: 3, link: '/public/index.html', title: 'Удалённые' },
+ { key: 4, link: '/public/index.html', title: 'Спам' },
+ { key: 5, link: '/public/index.html', title: 'Черновики' },
+ { key: 6, link: '/public/index.html', title: 'Создать папку' }
+];
+
+const Nav = (props: IProps) => {
+ console.log('Nav');
+ const { className, theme } = props;
+
+ const listItems = items.map(item => {
+ const itemClassName = cx(styles.item, styles[`item_theme_${theme}`], {
+ [styles.item_select]: item.isSelect
+ });
+
+ return (
+
+
+ {item.title}
+
+
+ );
+ });
+ const navClassName = cx(styles.box, className);
+
+ return (
+
+ );
+};
+
+const checkPropsChange = (props: IProps, nextProps: IProps) => nextProps.theme !== props.theme;
+
+export default shouldUpdate(checkPropsChange)(Nav);
diff --git a/src/components/search/search.module.css b/src/components/search/search.module.css
new file mode 100644
index 0000000..d22fdf8
--- /dev/null
+++ b/src/components/search/search.module.css
@@ -0,0 +1,78 @@
+.box {
+ min-width: 301px;
+ height: 32px;
+}
+
+.input {
+ display: inline-block;
+ width: 100%;
+ height: 100%;
+ padding: 1px 30px 1px 16px;
+
+ border: none;
+ font: 15px 'Helvetica Neue', sans-serif;
+ outline: none;
+}
+
+.input_theme_light {
+ background: #f2f5f8;
+ box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.2);
+ color: #6287bd;
+}
+
+.input_theme_dark {
+ background: #1d1d1d;
+ box-shadow: inset 0 0 0 1px rgba(192, 192, 192, 0.5);
+ color: #f9f9f9;
+}
+
+.input_theme_light::placeholder {
+ color: #000;
+ opacity: 0.5;
+}
+
+.input_theme_dark::placeholder {
+ color: #fff;
+ opacity: 0.7;
+}
+
+.clearBox {
+ display: inline-block;
+ width: 16px;
+ height: 16px;
+ margin-left: -25px;
+ vertical-align: middle;
+}
+
+.clearText {
+ margin: -12px 0 0 1px;
+ font-size: 25px;
+ font-weight: 300;
+}
+
+.clearText_theme_light {
+ color: #000;
+ opacity: 0.3;
+}
+
+.clearText_theme_dark {
+ color: #fff;
+ opacity: 0.4;
+}
+
+.clearBox:hover > .clearText {
+ opacity: 1;
+}
+
+.progressBar {
+ position: relative;
+ top: -1px;
+
+ display: block;
+ width: calc(100% + 46px);
+ height: 3px;
+}
+
+.progressBar_complete {
+ visibility: hidden;
+}
diff --git a/src/components/search/search.tsx b/src/components/search/search.tsx
new file mode 100644
index 0000000..0edb1ff
--- /dev/null
+++ b/src/components/search/search.tsx
@@ -0,0 +1,50 @@
+import React from 'react';
+import shouldUpdate from 'recompose/shouldUpdate';
+import cx from 'classnames';
+
+import styles from './search.module.css';
+
+interface IProps {
+ className?: string;
+ theme: string;
+ filterText: string;
+ filterProgress: number;
+ onChange: (value: string) => void;
+ clearText: () => void;
+}
+
+const Search = (props: IProps) => {
+ console.log('Search');
+ const { className, theme, filterText, filterProgress, onChange, clearText } = props;
+ const searchClassName = cx(styles.box, className);
+ const inputClassName = cx(styles.input, styles[`input_theme_${theme}`]);
+ const clearTextClassName = cx(styles.clearText, styles[`clearText_theme_${theme}`]);
+ const progressClassName = cx(styles.progressBar, {
+ [styles.progressBar_complete]: filterProgress === 1
+ });
+
+ return (
+
+
onChange(e.target.value)}
+ />
+
+
+
+ );
+};
+
+const checkPropsChange = (props: IProps, nextProps: IProps) =>
+ nextProps.theme !== props.theme ||
+ nextProps.filterText !== props.filterText ||
+ nextProps.filterProgress !== props.filterProgress;
+
+export default shouldUpdate(checkPropsChange)(Search);
diff --git a/src/components/supportLine/supportLine.module.css b/src/components/supportLine/supportLine.module.css
new file mode 100644
index 0000000..aed4857
--- /dev/null
+++ b/src/components/supportLine/supportLine.module.css
@@ -0,0 +1,38 @@
+.itemLine {
+ padding: 5px 20px;
+ font: 11px 'Helvetica Neue Light', sans-serif;
+ text-align: right;
+}
+
+.item {
+ display: inline-block;
+ margin-left: 25px;
+ font-weight: 700;
+ vertical-align: center;
+}
+
+.item_theme_light {
+ color: #9e9e9e;
+}
+
+.item_theme_dark {
+ color: #5f5f5f;
+}
+
+.item_type_link {
+ cursor: pointer;
+ text-decoration: none;
+}
+
+.item_type_link.item_theme_light:hover {
+ color: #000;
+}
+
+.item_type_link.item_theme_dark:hover {
+ color: #fff;
+}
+
+
+.item_type_text {
+ margin-right: -20px;
+}
diff --git a/src/components/supportLine/supportLine.tsx b/src/components/supportLine/supportLine.tsx
new file mode 100644
index 0000000..3e8dc72
--- /dev/null
+++ b/src/components/supportLine/supportLine.tsx
@@ -0,0 +1,45 @@
+import React from 'react';
+import shouldUpdate from 'recompose/shouldUpdate';
+import cx from 'classnames';
+
+import styles from './supportLine.module.css';
+
+interface IProps {
+ theme: string;
+}
+
+const items = [
+ { key: 1, title: 'Помощь и обратная связь', href: 'https://yandex.ru/support/mail/' },
+ { key: 2, title: 'Реклама', href: 'https://yandex.ru/adv/' },
+ { key: 3, title: '© 2001—2019,' },
+ { key: 4, title: 'Яндекс', href: 'https://yandex.ru' }
+];
+
+const SupportLine = (props: IProps) => {
+ console.log('SupportLine');
+ const { theme } = props;
+
+ const listItems = items.map(item => {
+ const itemClassName = cx(
+ styles.item,
+ styles[`item_theme_${theme}`],
+ item.href === undefined ? styles.item_type_text : styles.item_type_link
+ );
+
+ return item.href === undefined ? (
+
+ {item.title}
+
+ ) : (
+
+ {item.title}
+
+ );
+ });
+
+ return {listItems}
;
+};
+
+const checkPropsChange = (props: IProps, nextProps: IProps) => nextProps.theme !== props.theme;
+
+export default shouldUpdate(checkPropsChange)(SupportLine);
diff --git a/src/components/toolbar/toolBarItem.ts b/src/components/toolbar/toolBarItem.ts
new file mode 100644
index 0000000..05f96aa
--- /dev/null
+++ b/src/components/toolbar/toolBarItem.ts
@@ -0,0 +1,6 @@
+export default interface IToolbarItem {
+ type: string,
+ value: any,
+ isActive?: boolean
+ onClick?: () => void
+}
diff --git a/src/components/toolbar/toolbar.module.css b/src/components/toolbar/toolbar.module.css
new file mode 100644
index 0000000..0a09ac0
--- /dev/null
+++ b/src/components/toolbar/toolbar.module.css
@@ -0,0 +1,51 @@
+.box {
+ padding: 0 20px;
+ margin: 0;
+ font-size: 13px;
+}
+
+.item {
+ display: inline-block;
+ line-height: 39px;
+ list-style-type: none;
+}
+
+.item:first-child {
+ margin-right: -5px;
+}
+
+.item:not(:first-child) {
+ margin-left: 25px;
+ font-weight: 500;
+}
+
+.button {
+ padding: 0;
+ margin: 0;
+
+ border: none;
+ background-color: inherit;
+ font-family: inherit;
+ font-size: inherit;
+ outline: none;
+}
+
+.button_isActive {
+ cursor: pointer;
+}
+
+.button_theme_light {
+ color: #ccc;
+}
+
+.button_theme_dark {
+ color: #5f5f5f;
+}
+
+.button_isActive.button_theme_light {
+ color: #000;
+}
+
+.button_isActive.button_theme_dark {
+ color: #fff;
+}
diff --git a/src/components/toolbar/toolbar.tsx b/src/components/toolbar/toolbar.tsx
new file mode 100644
index 0000000..5014bc5
--- /dev/null
+++ b/src/components/toolbar/toolbar.tsx
@@ -0,0 +1,44 @@
+import React from 'react';
+import pure from 'recompose/pure';
+import cx from 'classnames';
+import Check from '../check/check';
+
+import IToolbarItem from './toolBarItem';
+
+import styles from './toolbar.module.css';
+
+interface IProps {
+ children: IToolbarItem[];
+ theme: string;
+}
+
+function renderSwitch(item: IToolbarItem, theme: string) {
+ switch (item.type) {
+ case 'button': {
+ const btnClassName = cx(styles.button, styles[`button_theme_${theme}`], {
+ [styles.button_isActive]: item.isActive
+ });
+ return (
+
+ );
+ }
+ case 'checkbox':
+ return ;
+ default:
+ return ;
+ }
+}
+
+const Toolbar = (props: IProps) => {
+ // console.log('Toolbar');
+ const { children, theme } = props;
+ const listItems = children.map((item, index) => (
+
+ {renderSwitch(item, theme)}
+
+ ));
+
+ return ;
+};
+
+export default pure(Toolbar);
diff --git a/src/font.css b/src/font.css
new file mode 100644
index 0000000..851b11f
--- /dev/null
+++ b/src/font.css
@@ -0,0 +1,19 @@
+@font-face {
+ font-family: 'Helvetica Neue';
+ src: url('resources/fonts/helveticaneue-medium.otf');
+ src: url('resources/fonts/helveticaneue-medium.otf') format("opentype"),
+ url('resources/fonts/helveticaneue-medium.eot?#iefix') format('embedded-opentype'),
+ url('resources/fonts/helveticaneue-medium.woff2') format('woff2'),
+ url('resources/fonts/helveticaneue-medium.woff') format('woff'),
+ url('resources/fonts/helveticaneue-medium.ttf') format('truetype');
+}
+
+@font-face {
+ font-family: 'Helvetica Neue Light';
+ src: url('resources/fonts/helveticaneue-light.otf');
+ src: url('resources/fonts/helveticaneue-light.otf') format("opentype"),
+ url('resources/fonts/helveticaneue-light.eot?#iefix') format('embedded-opentype'),
+ url('resources/fonts/helveticaneue-light.woff2') format('woff2'),
+ url('resources/fonts/helveticaneue-light.woff') format('woff'),
+ url('resources/fonts/helveticaneue-light.ttf') format('truetype');
+}
diff --git a/src/index.css b/src/index.css
index 2b6e525..98dd98c 100644
--- a/src/index.css
+++ b/src/index.css
@@ -1,6 +1,7 @@
body {
padding: 0;
margin: 0;
+ background-color: #e5eaf0;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu',
'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
-webkit-font-smoothing: antialiased;
diff --git a/src/index.jsx b/src/index.jsx
index ffc72ee..4d381bd 100644
--- a/src/index.jsx
+++ b/src/index.jsx
@@ -1,8 +1,7 @@
import React from 'react';
import ReactDOM from 'react-dom';
-
-import { App } from './app';
-
+import Mail from './components/mail/mail';
import './index.css';
+import './font.css';
-ReactDOM.render(, document.getElementById('root'));
+ReactDOM.render(, document.getElementById('root'));
diff --git a/src/react-app-env.d.ts b/src/react-app-env.d.ts
new file mode 100644
index 0000000..6431bc5
--- /dev/null
+++ b/src/react-app-env.d.ts
@@ -0,0 +1 @@
+///
diff --git a/src/resources/fonts/helveticaneue-light.eot b/src/resources/fonts/helveticaneue-light.eot
new file mode 100644
index 0000000..8c9e8e3
Binary files /dev/null and b/src/resources/fonts/helveticaneue-light.eot differ
diff --git a/src/resources/fonts/helveticaneue-light.otf b/src/resources/fonts/helveticaneue-light.otf
new file mode 100644
index 0000000..7ced49a
Binary files /dev/null and b/src/resources/fonts/helveticaneue-light.otf differ
diff --git a/src/resources/fonts/helveticaneue-light.svg b/src/resources/fonts/helveticaneue-light.svg
new file mode 100644
index 0000000..6cbef06
--- /dev/null
+++ b/src/resources/fonts/helveticaneue-light.svg
@@ -0,0 +1,945 @@
+
+
+
diff --git a/src/resources/fonts/helveticaneue-light.ttf b/src/resources/fonts/helveticaneue-light.ttf
new file mode 100644
index 0000000..9eaa013
Binary files /dev/null and b/src/resources/fonts/helveticaneue-light.ttf differ
diff --git a/src/resources/fonts/helveticaneue-light.woff b/src/resources/fonts/helveticaneue-light.woff
new file mode 100644
index 0000000..420b844
Binary files /dev/null and b/src/resources/fonts/helveticaneue-light.woff differ
diff --git a/src/resources/fonts/helveticaneue-light.woff2 b/src/resources/fonts/helveticaneue-light.woff2
new file mode 100644
index 0000000..d3317fc
Binary files /dev/null and b/src/resources/fonts/helveticaneue-light.woff2 differ
diff --git a/src/resources/fonts/helveticaneue-medium.eot b/src/resources/fonts/helveticaneue-medium.eot
new file mode 100644
index 0000000..a3b621f
Binary files /dev/null and b/src/resources/fonts/helveticaneue-medium.eot differ
diff --git a/src/resources/fonts/helveticaneue-medium.otf b/src/resources/fonts/helveticaneue-medium.otf
new file mode 100644
index 0000000..a2cde16
Binary files /dev/null and b/src/resources/fonts/helveticaneue-medium.otf differ
diff --git a/src/resources/fonts/helveticaneue-medium.svg b/src/resources/fonts/helveticaneue-medium.svg
new file mode 100644
index 0000000..ef4683b
--- /dev/null
+++ b/src/resources/fonts/helveticaneue-medium.svg
@@ -0,0 +1,4261 @@
+
+
+
diff --git a/src/resources/fonts/helveticaneue-medium.ttf b/src/resources/fonts/helveticaneue-medium.ttf
new file mode 100644
index 0000000..9aa4dd2
Binary files /dev/null and b/src/resources/fonts/helveticaneue-medium.ttf differ
diff --git a/src/resources/fonts/helveticaneue-medium.woff b/src/resources/fonts/helveticaneue-medium.woff
new file mode 100644
index 0000000..8042262
Binary files /dev/null and b/src/resources/fonts/helveticaneue-medium.woff differ
diff --git a/src/resources/fonts/helveticaneue-medium.woff2 b/src/resources/fonts/helveticaneue-medium.woff2
new file mode 100644
index 0000000..78d66d5
Binary files /dev/null and b/src/resources/fonts/helveticaneue-medium.woff2 differ
diff --git a/src/resources/images/authors-logo/england-queen-logo.png b/src/resources/images/authors-logo/england-queen-logo.png
new file mode 100644
index 0000000..724d11c
Binary files /dev/null and b/src/resources/images/authors-logo/england-queen-logo.png differ
diff --git a/src/resources/images/authors-logo/putin-logo.png b/src/resources/images/authors-logo/putin-logo.png
new file mode 100644
index 0000000..5dd7ebe
Binary files /dev/null and b/src/resources/images/authors-logo/putin-logo.png differ
diff --git a/src/resources/images/authors-logo/uber-logo.png b/src/resources/images/authors-logo/uber-logo.png
new file mode 100644
index 0000000..dad2c1d
Binary files /dev/null and b/src/resources/images/authors-logo/uber-logo.png differ
diff --git a/src/resources/images/authors-logo/ya-logo.png b/src/resources/images/authors-logo/ya-logo.png
new file mode 100644
index 0000000..0e2fd64
Binary files /dev/null and b/src/resources/images/authors-logo/ya-logo.png differ
diff --git a/src/resources/images/ya-default.svg b/src/resources/images/ya-default.svg
new file mode 100644
index 0000000..f11afc0
--- /dev/null
+++ b/src/resources/images/ya-default.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/resources/images/yandexLogo_Dark.svg b/src/resources/images/yandexLogo_Dark.svg
new file mode 100644
index 0000000..1a8ca4d
--- /dev/null
+++ b/src/resources/images/yandexLogo_Dark.svg
@@ -0,0 +1,70 @@
+
+
diff --git a/src/resources/images/yandexLogo_Dark1.svg b/src/resources/images/yandexLogo_Dark1.svg
new file mode 100644
index 0000000..08a59be
--- /dev/null
+++ b/src/resources/images/yandexLogo_Dark1.svg
@@ -0,0 +1,84 @@
+
+
diff --git a/src/resources/images/yandexLogo_Light.svg b/src/resources/images/yandexLogo_Light.svg
new file mode 100644
index 0000000..b76e885
--- /dev/null
+++ b/src/resources/images/yandexLogo_Light.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/utils/letterGenerator.tsx b/src/utils/letterGenerator.tsx
new file mode 100644
index 0000000..3a4d0fd
--- /dev/null
+++ b/src/utils/letterGenerator.tsx
@@ -0,0 +1,153 @@
+import React from 'react';
+import { getInt } from './randomFunctions';
+
+import englandQueenLogo from '../resources/images/authors-logo/england-queen-logo.png';
+import putinLogo from '../resources/images/authors-logo/putin-logo.png';
+import uberLogo from '../resources/images/authors-logo/uber-logo.png';
+import yaLogo from '../resources/images/authors-logo/ya-logo.png';
+
+import letterStyles from '../components/letter/letter.module.css';
+
+interface ILetterGenerator {
+ getTopic: () => string;
+ getDate: () => JSX.Element;
+ getAuthorName: () => string;
+ getAuthorLogo: (authorName: string) => JSX.Element;
+ getLetterBody: () => string;
+}
+
+const LetterGenerator = (function LetterGenerator(this: ILetterGenerator) {
+ const nounWords = [
+ 'собака',
+ 'кошка',
+ 'казимаки',
+ 'казинаки',
+ 'пивасик',
+ 'Чебурашка',
+ 'крокодил Гена',
+ 'Шапокляк',
+ 'устрица',
+ 'человечек',
+ 'Чика Чика'
+ ];
+
+ const verbWords = [
+ 'сделал',
+ 'съел',
+ 'упал',
+ 'изучил',
+ 'погладил',
+ 'узнал',
+ 'обидел',
+ 'зацепил',
+ 'обманул',
+ 'ударил'
+ ];
+
+ const sign = ['.', '?', '!', '!?'];
+
+ const separators = ['a', 'но', 'однако', 'даже', 'хотя', 'к сожалению'];
+
+ const topicNames = [
+ 'В Яндексе разработан новый мем',
+ 'Город охватила страшная эпидемия',
+ 'Обновление генератора писем',
+ 'Случайный прохожий спас маленькую девочку',
+ 'Новинка! OldSpice - мужик вдвойне, когда на коне'
+ ];
+
+ const authorLogoNames: any = {
+ 'Володя Путин': putinLogo,
+ 'Ярослав Балашов': yaLogo,
+ 'Королева of England': englandQueenLogo,
+ UberProductionTV: uberLogo
+ };
+
+ const SENTENCE_COUNT_MIN = 5;
+
+ const SENTENCE_COUNT_MAX = 10;
+
+ const WORD_COUNT_MIN = 5;
+
+ const WORD_COUNT_MAX = 10;
+
+ function getSign() {
+ return sign[getInt(0, sign.length)];
+ }
+
+ function getSeparator() {
+ return separators[getInt(0, separators.length)];
+ }
+
+ function getWord(type: number) {
+ return type === 1
+ ? nounWords[getInt(0, nounWords.length)]
+ : verbWords[getInt(0, verbWords.length)];
+ }
+
+ function getFirstWord(type: number) {
+ const str = getWord(type);
+ return str[0].toUpperCase() + str.slice(1);
+ }
+
+ function getSentence() {
+ let wordCount = getInt(WORD_COUNT_MIN, WORD_COUNT_MAX);
+ let res = `${getFirstWord(1)} `;
+ let type = 0;
+ while (wordCount-- > 0) {
+ res += getWord(type);
+ if (wordCount !== 0) {
+ if (type === 0) {
+ res += `, ${getSeparator()} `;
+ } else {
+ res += ' ';
+ }
+ }
+ type = 1 - type;
+ }
+ return res + getSign();
+ }
+
+ function getLetter() {
+ let sentenceCount = getInt(SENTENCE_COUNT_MIN, SENTENCE_COUNT_MAX);
+ let res = '';
+ while (sentenceCount-- > 0) {
+ res += getSentence();
+ res += ' ';
+ }
+ return res;
+ }
+
+ this.getTopic = () => {
+ return topicNames[getInt(0, topicNames.length)];
+ };
+
+ this.getDate = () => {
+ const today = new Date();
+ return (
+
+ );
+ };
+
+ this.getAuthorName = () => {
+ const authorNames = Object.keys(authorLogoNames);
+ return authorNames[getInt(0, authorNames.length)];
+ };
+
+ this.getAuthorLogo = (authorName: string) => {
+ const authorLogoName = authorLogoNames[authorName];
+ return authorLogoName === undefined ? (
+ {authorName[0].toUpperCase()}
+ ) : (
+
+ );
+ };
+
+ this.getLetterBody = () => {
+ return getLetter();
+ };
+} as any) as { new (): ILetterGenerator };
+
+export default LetterGenerator;
diff --git a/src/utils/randomFunctions.js b/src/utils/randomFunctions.js
new file mode 100644
index 0000000..41152eb
--- /dev/null
+++ b/src/utils/randomFunctions.js
@@ -0,0 +1,3 @@
+export function getInt(min, max) {
+ return Math.floor(Math.random() * (max - min)) + min;
+}
diff --git a/tsconfig.json b/tsconfig.json
new file mode 100644
index 0000000..0980b23
--- /dev/null
+++ b/tsconfig.json
@@ -0,0 +1,25 @@
+{
+ "compilerOptions": {
+ "target": "es5",
+ "lib": [
+ "dom",
+ "dom.iterable",
+ "esnext"
+ ],
+ "allowJs": true,
+ "skipLibCheck": true,
+ "esModuleInterop": true,
+ "allowSyntheticDefaultImports": true,
+ "strict": true,
+ "forceConsistentCasingInFileNames": true,
+ "module": "esnext",
+ "moduleResolution": "node",
+ "resolveJsonModule": true,
+ "isolatedModules": true,
+ "noEmit": true,
+ "jsx": "preserve"
+ },
+ "include": [
+ "src"
+ ]
+}