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 ( -
-
-

- Edit src/app/app.jsx and save to reload. -

- - Learn React - -
-
- ); - } -} 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 ( + + ); + } +} 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
      {listLetters}
    ; +}; + +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 ( +
    +
    + × +
    +
    {children}
    +
    + ); +}; + +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
      {listItems}
    ; +}; + +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 @@ + + + + +Created by FontForge 20170910 at Tue Aug 29 12:39:46 2006 + By Jimmy Wärting +Copyrighted (c) 1981, 1997 by and the property of Linotype-Hell AG and/or its subsidiaries. All Rights Reserved. All Cyrillic characters designed by DoubleAlex. Helvetica is a registered Trademark of Linotype-Hell AG and/or its subsidiaries. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 @@ + + + + +Created by FontForge 20160407 at Tue Sep 6 11:12:33 2016 + By Jimmy Warting +Part of the digitally encoded machine readable outline data for producing the Typefaces provided is copyrighted (c) 2003 - 2006 Linotype GmbH, www.linotype.com. All rights reserved. This software is the property of Linotype GmbH, and may not be reproduced, modified, disclosed or transferred without the express written approval of Linotype GmbH. Copyright (c) 1988, 1990, 1993 Adobe Systems Incorporated. All Rights Reserved. Helvetica is a trademark of Heidelberger Druckmaschinen AG, exclusively licensed through Linotype GmbH, and may be registered in certain jurisdictions. This typeface is original artwork of Linotype Design Studio. The design may be protected in certain jurisdictions. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + 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 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + 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()}
    + ) : ( + {authorLogoName} + ); + }; + + 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" + ] +}