diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 0000000..7d5b7a9 --- /dev/null +++ b/.eslintignore @@ -0,0 +1,2 @@ +/build +/node_modules diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 0000000..a085aef --- /dev/null +++ b/.eslintrc.js @@ -0,0 +1,26 @@ +module.exports = { + env: { + browser: true, + es6: true + }, + extends: [ + 'plugin:react/recommended', + 'standard' + ], + globals: { + Atomics: 'readonly', + SharedArrayBuffer: 'readonly' + }, + parserOptions: { + ecmaFeatures: { + jsx: true + }, + ecmaVersion: 2018, + sourceType: 'module' + }, + plugins: [ + 'react' + ], + rules: { + } +} diff --git a/README.md b/README.md index 54ef094..341d90d 100644 --- a/README.md +++ b/README.md @@ -1,68 +1,3 @@ -This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app). +## Dynamic spreadsheet (React + Redux ) -## Available Scripts - -In the project directory, you can run: - -### `npm start` - -Runs the app in the development mode.
-Open [http://localhost:3000](http://localhost:3000) to view it in the browser. - -The page will reload if you make edits.
-You will also see any lint errors in the console. - -### `npm test` - -Launches the test runner in the interactive watch mode.
-See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information. - -### `npm run build` - -Builds the app for production to the `build` folder.
-It correctly bundles React in production mode and optimizes the build for the best performance. - -The build is minified and the filenames include the hashes.
-Your app is ready to be deployed! - -See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information. - -### `npm run eject` - -**Note: this is a one-way operation. Once you `eject`, you can’t go back!** - -If you aren’t satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project. - -Instead, it will copy all the configuration files and the transitive dependencies (webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you’re on your own. - -You don’t have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn’t feel obligated to use this feature. However we understand that this tool wouldn’t be useful if you couldn’t customize it when you are ready for it. - -## Learn More - -You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started). - -To learn React, check out the [React documentation](https://reactjs.org/). - -### Code Splitting - -This section has moved here: https://facebook.github.io/create-react-app/docs/code-splitting - -### Analyzing the Bundle Size - -This section has moved here: https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size - -### Making a Progressive Web App - -This section has moved here: https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app - -### Advanced Configuration - -This section has moved here: https://facebook.github.io/create-react-app/docs/advanced-configuration - -### Deployment - -This section has moved here: https://facebook.github.io/create-react-app/docs/deployment - -### `npm run build` fails to minify - -This section has moved here: https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify +[DEMO](https://denkondratiev.github.io/react_table/) diff --git a/package-lock.json b/package-lock.json index 37f346a..16c364c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,9 +13,9 @@ } }, "@babel/compat-data": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.10.4.tgz", - "integrity": "sha512-t+rjExOrSVvjQQXNp5zAIYDp00KjdvGl/TpDX5REPr0S9IAIPQMTilcfG6q8c0QFmj9lSTVySV2VTsyggvtNIw==", + "version": "7.10.5", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.10.5.tgz", + "integrity": "sha512-mPVoWNzIpYJHbWje0if7Ck36bpbtTvIxOi9+6WSK9wjGEXearAqlwBoTQvVjsAY2VIwgcs8V940geY3okzRCEw==", "requires": { "browserslist": "^4.12.0", "invariant": "^2.2.4", @@ -56,18 +56,29 @@ "version": "5.7.1", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" } } }, "@babel/generator": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.10.4.tgz", - "integrity": "sha512-toLIHUIAgcQygFZRAQcsLQV3CBuX6yOIru1kJk/qqqvcRmZrYe6WavZTSG+bB8MxhnL9YPf+pKQfuiP161q7ng==", + "version": "7.10.5", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.10.5.tgz", + "integrity": "sha512-3vXxr3FEW7E7lJZiWQ3bM4+v/Vyr9C+hpolQ8BGFr9Y8Ri2tFLWTixmwKBafDujO1WVah4fhZBeU1bieKdghig==", "requires": { - "@babel/types": "^7.10.4", + "@babel/types": "^7.10.5", "jsesc": "^2.5.1", - "lodash": "^4.17.13", "source-map": "^0.5.0" + }, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" + } } }, "@babel/helper-annotate-as-pure": { @@ -97,13 +108,13 @@ } }, "@babel/helper-builder-react-jsx-experimental": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-builder-react-jsx-experimental/-/helper-builder-react-jsx-experimental-7.10.4.tgz", - "integrity": "sha512-LyacH/kgQPgLAuaWrvvq1+E7f5bLyT8jXCh7nM67sRsy2cpIGfgWJ+FCnAKQXfY+F0tXUaN6FqLkp4JiCzdK8Q==", + "version": "7.10.5", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-react-jsx-experimental/-/helper-builder-react-jsx-experimental-7.10.5.tgz", + "integrity": "sha512-Buewnx6M4ttG+NLkKyt7baQn7ScC/Td+e99G914fRU8fGIUivDDgVIQeDHFa5e4CRSJQt58WpNHhsAZgtzVhsg==", "requires": { "@babel/helper-annotate-as-pure": "^7.10.4", "@babel/helper-module-imports": "^7.10.4", - "@babel/types": "^7.10.4" + "@babel/types": "^7.10.5" } }, "@babel/helper-compilation-targets": { @@ -126,12 +137,12 @@ } }, "@babel/helper-create-class-features-plugin": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.10.4.tgz", - "integrity": "sha512-9raUiOsXPxzzLjCXeosApJItoMnX3uyT4QdM2UldffuGApNrF8e938MwNpDCK9CPoyxrEoCgT+hObJc3mZa6lQ==", + "version": "7.10.5", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.10.5.tgz", + "integrity": "sha512-0nkdeijB7VlZoLT3r/mY3bUkw3T8WG/hNw+FATs/6+pG2039IJWjTYL0VTISqsNHMUTEnwbVnc89WIJX9Qed0A==", "requires": { "@babel/helper-function-name": "^7.10.4", - "@babel/helper-member-expression-to-functions": "^7.10.4", + "@babel/helper-member-expression-to-functions": "^7.10.5", "@babel/helper-optimise-call-expression": "^7.10.4", "@babel/helper-plugin-utils": "^7.10.4", "@babel/helper-replace-supers": "^7.10.4", @@ -149,13 +160,13 @@ } }, "@babel/helper-define-map": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-define-map/-/helper-define-map-7.10.4.tgz", - "integrity": "sha512-nIij0oKErfCnLUCWaCaHW0Bmtl2RO9cN7+u2QT8yqTywgALKlyUVOvHDElh+b5DwVC6YB1FOYFOTWcN/+41EDA==", + "version": "7.10.5", + "resolved": "https://registry.npmjs.org/@babel/helper-define-map/-/helper-define-map-7.10.5.tgz", + "integrity": "sha512-fMw4kgFB720aQFXSVaXr79pjjcW5puTCM16+rECJ/plGS+zByelE8l9nCpV1GibxTnFVmUuYG9U8wYfQHdzOEQ==", "requires": { "@babel/helper-function-name": "^7.10.4", - "@babel/types": "^7.10.4", - "lodash": "^4.17.13" + "@babel/types": "^7.10.5", + "lodash": "^4.17.19" } }, "@babel/helper-explode-assignable-expression": { @@ -194,11 +205,11 @@ } }, "@babel/helper-member-expression-to-functions": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.10.4.tgz", - "integrity": "sha512-m5j85pK/KZhuSdM/8cHUABQTAslV47OjfIB9Cc7P+PvlAoBzdb79BGNfw8RhT5Mq3p+xGd0ZfAKixbrUZx0C7A==", + "version": "7.10.5", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.10.5.tgz", + "integrity": "sha512-HiqJpYD5+WopCXIAbQDG0zye5XYVvcO9w/DHp5GsaGkRUaamLj2bEtu6i8rnGGprAhHM3qidCMgp71HF4endhA==", "requires": { - "@babel/types": "^7.10.4" + "@babel/types": "^7.10.5" } }, "@babel/helper-module-imports": { @@ -210,17 +221,17 @@ } }, "@babel/helper-module-transforms": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.10.4.tgz", - "integrity": "sha512-Er2FQX0oa3nV7eM1o0tNCTx7izmQtwAQsIiaLRWtavAAEcskb0XJ5OjJbVrYXWOTr8om921Scabn4/tzlx7j1Q==", + "version": "7.10.5", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.10.5.tgz", + "integrity": "sha512-4P+CWMJ6/j1W915ITJaUkadLObmCRRSC234uctJfn/vHrsLNxsR8dwlcXv9ZhJWzl77awf+mWXSZEKt5t0OnlA==", "requires": { "@babel/helper-module-imports": "^7.10.4", "@babel/helper-replace-supers": "^7.10.4", "@babel/helper-simple-access": "^7.10.4", "@babel/helper-split-export-declaration": "^7.10.4", "@babel/template": "^7.10.4", - "@babel/types": "^7.10.4", - "lodash": "^4.17.13" + "@babel/types": "^7.10.5", + "lodash": "^4.17.19" } }, "@babel/helper-optimise-call-expression": { @@ -237,11 +248,11 @@ "integrity": "sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg==" }, "@babel/helper-regex": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-regex/-/helper-regex-7.10.4.tgz", - "integrity": "sha512-inWpnHGgtg5NOF0eyHlC0/74/VkdRITY9dtTpB2PrxKKn+AkVMRiZz/Adrx+Ssg+MLDesi2zohBW6MVq6b4pOQ==", + "version": "7.10.5", + "resolved": "https://registry.npmjs.org/@babel/helper-regex/-/helper-regex-7.10.5.tgz", + "integrity": "sha512-68kdUAzDrljqBrio7DYAEgCoJHxppJOERHOgOrDN7WjOzP0ZQ1LsSDRXcemzVZaLvjaJsJEESb6qt+znNuENDg==", "requires": { - "lodash": "^4.17.13" + "lodash": "^4.17.19" } }, "@babel/helper-remap-async-to-generator": { @@ -321,14 +332,14 @@ } }, "@babel/parser": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.10.4.tgz", - "integrity": "sha512-8jHII4hf+YVDsskTF6WuMB3X4Eh+PsUkC2ljq22so5rHvH+T8BzyL94VOdyFLNR8tBSVXOTbNHOKpR4TfRxVtA==" + "version": "7.10.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.10.5.tgz", + "integrity": "sha512-wfryxy4bE1UivvQKSQDU4/X6dr+i8bctjUjj8Zyt3DQy7NtPizJXT8M52nqpNKL+nq2PW8lxk4ZqLj0fD4B4hQ==" }, "@babel/plugin-proposal-async-generator-functions": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.10.4.tgz", - "integrity": "sha512-MJbxGSmejEFVOANAezdO39SObkURO5o/8b6fSH6D1pi9RZQt+ldppKPXfqgUWpSQ9asM6xaSaSJIaeWMDRP0Zg==", + "version": "7.10.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.10.5.tgz", + "integrity": "sha512-cNMCVezQbrRGvXJwm9fu/1sJj9bHdGAgKodZdLqOQIpfoH3raqmRPBM17+lh7CzhiKRRBrGtZL9WcjxSoGYUSg==", "requires": { "@babel/helper-plugin-utils": "^7.10.4", "@babel/helper-remap-async-to-generator": "^7.10.4", @@ -575,12 +586,11 @@ } }, "@babel/plugin-transform-block-scoping": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.10.4.tgz", - "integrity": "sha512-J3b5CluMg3hPUii2onJDRiaVbPtKFPLEaV5dOPY5OeAbDi1iU/UbbFFTgwb7WnanaDy7bjU35kc26W3eM5Qa0A==", + "version": "7.10.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.10.5.tgz", + "integrity": "sha512-6Ycw3hjpQti0qssQcA6AMSFDHeNJ++R6dIMnpRqUjFeBBTmTDPa8zgF90OVfTvAo11mXZTlVUViY1g8ffrURLg==", "requires": { - "@babel/helper-plugin-utils": "^7.10.4", - "lodash": "^4.17.13" + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-transform-classes": { @@ -683,11 +693,11 @@ } }, "@babel/plugin-transform-modules-amd": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.10.4.tgz", - "integrity": "sha512-3Fw+H3WLUrTlzi3zMiZWp3AR4xadAEMv6XRCYnd5jAlLM61Rn+CRJaZMaNvIpcJpQ3vs1kyifYvEVPFfoSkKOA==", + "version": "7.10.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.10.5.tgz", + "integrity": "sha512-elm5uruNio7CTLFItVC/rIzKLfQ17+fX7EVz5W0TMgIHFo1zY0Ozzx+lgwhL4plzl8OzVn6Qasx5DeEFyoNiRw==", "requires": { - "@babel/helper-module-transforms": "^7.10.4", + "@babel/helper-module-transforms": "^7.10.5", "@babel/helper-plugin-utils": "^7.10.4", "babel-plugin-dynamic-import-node": "^2.3.3" } @@ -704,12 +714,12 @@ } }, "@babel/plugin-transform-modules-systemjs": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.10.4.tgz", - "integrity": "sha512-Tb28LlfxrTiOTGtZFsvkjpyjCl9IoaRI52AEU/VIwOwvDQWtbNJsAqTXzh+5R7i74e/OZHH2c2w2fsOqAfnQYQ==", + "version": "7.10.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.10.5.tgz", + "integrity": "sha512-f4RLO/OL14/FP1AEbcsWMzpbUz6tssRaeQg11RH1BP/XnPpRoVwgeYViMFacnkaw4k4wjRSjn3ip1Uw9TaXuMw==", "requires": { "@babel/helper-hoist-variables": "^7.10.4", - "@babel/helper-module-transforms": "^7.10.4", + "@babel/helper-module-transforms": "^7.10.5", "@babel/helper-plugin-utils": "^7.10.4", "babel-plugin-dynamic-import-node": "^2.3.3" } @@ -749,9 +759,9 @@ } }, "@babel/plugin-transform-parameters": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.10.4.tgz", - "integrity": "sha512-RurVtZ/D5nYfEg0iVERXYKEgDFeesHrHfx8RT05Sq57ucj2eOYAP6eu5fynL4Adju4I/mP/I6SO0DqNWAXjfLQ==", + "version": "7.10.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.10.5.tgz", + "integrity": "sha512-xPHwUj5RdFV8l1wuYiu5S9fqWGM2DrYc24TMvUiRrPVm+SM3XeqU9BcokQX/kEUe+p2RBwy+yoiR1w/Blq6ubw==", "requires": { "@babel/helper-get-function-arity": "^7.10.4", "@babel/helper-plugin-utils": "^7.10.4" @@ -812,9 +822,9 @@ } }, "@babel/plugin-transform-react-jsx-source": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.10.4.tgz", - "integrity": "sha512-FTK3eQFrPv2aveerUSazFmGygqIdTtvskG50SnGnbEUnRPcGx2ylBhdFIzoVS1ty44hEgcPoCAyw5r3VDEq+Ug==", + "version": "7.10.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.10.5.tgz", + "integrity": "sha512-wTeqHVkN1lfPLubRiZH3o73f4rfon42HpgxUSs86Nc+8QIcm/B9s8NNVXu/gwGcOyd7yDib9ikxoDLxJP0UiDA==", "requires": { "@babel/helper-plugin-utils": "^7.10.4", "@babel/plugin-syntax-jsx": "^7.10.4" @@ -889,9 +899,9 @@ } }, "@babel/plugin-transform-template-literals": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.10.4.tgz", - "integrity": "sha512-4NErciJkAYe+xI5cqfS8pV/0ntlY5N5Ske/4ImxAVX7mk9Rxt2bwDTGv1Msc2BRJvWQcmYEC+yoMLdX22aE4VQ==", + "version": "7.10.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.10.5.tgz", + "integrity": "sha512-V/lnPGIb+KT12OQikDvgSuesRX14ck5FfJXt6+tXhdkJ+Vsd0lDCVtF6jcB4rNClYFzaB2jusZ+lNISDk2mMMw==", "requires": { "@babel/helper-annotate-as-pure": "^7.10.4", "@babel/helper-plugin-utils": "^7.10.4" @@ -906,11 +916,11 @@ } }, "@babel/plugin-transform-typescript": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.10.4.tgz", - "integrity": "sha512-3WpXIKDJl/MHoAN0fNkSr7iHdUMHZoppXjf2HJ9/ed5Xht5wNIsXllJXdityKOxeA3Z8heYRb1D3p2H5rfCdPw==", + "version": "7.10.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.10.5.tgz", + "integrity": "sha512-YCyYsFrrRMZ3qR7wRwtSSJovPG5vGyG4ZdcSAivGwTfoasMp3VOB/AKhohu3dFtmB4cCDcsndCSxGtrdliCsZQ==", "requires": { - "@babel/helper-create-class-features-plugin": "^7.10.4", + "@babel/helper-create-class-features-plugin": "^7.10.5", "@babel/helper-plugin-utils": "^7.10.4", "@babel/plugin-syntax-typescript": "^7.10.4" } @@ -1046,17 +1056,17 @@ } }, "@babel/runtime": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.10.4.tgz", - "integrity": "sha512-UpTN5yUJr9b4EX2CnGNWIvER7Ab83ibv0pcvvHc4UOdrBI5jb8bj+32cCwPX6xu0mt2daFNjYhoi+X7beH0RSw==", + "version": "7.10.5", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.10.5.tgz", + "integrity": "sha512-otddXKhdNn7d0ptoFRHtMLa8LqDxLYwTjB4nYgM1yy5N6gU/MUf8zqyyLltCH3yAVitBzmwK4us+DD0l/MauAg==", "requires": { "regenerator-runtime": "^0.13.4" } }, "@babel/runtime-corejs3": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.10.4.tgz", - "integrity": "sha512-BFlgP2SoLO9HJX9WBwN67gHWMBhDX/eDz64Jajd6mR/UAUzqrNMm99d4qHnVaKscAElZoFiPv+JpR/Siud5lXw==", + "version": "7.10.5", + "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.10.5.tgz", + "integrity": "sha512-RMafpmrNB5E/bwdSphLr8a8++9TosnyJp98RZzI6VOx2R2CCMpsXXXRvmI700O9oEKpXdZat6oEK68/F0zjd4A==", "requires": { "core-js-pure": "^3.0.0", "regenerator-runtime": "^0.13.4" @@ -1073,28 +1083,28 @@ } }, "@babel/traverse": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.10.4.tgz", - "integrity": "sha512-aSy7p5THgSYm4YyxNGz6jZpXf+Ok40QF3aA2LyIONkDHpAcJzDUqlCKXv6peqYUs2gmic849C/t2HKw2a2K20Q==", + "version": "7.10.5", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.10.5.tgz", + "integrity": "sha512-yc/fyv2gUjPqzTz0WHeRJH2pv7jA9kA7mBX2tXl/x5iOE81uaVPuGPtaYk7wmkx4b67mQ7NqI8rmT2pF47KYKQ==", "requires": { "@babel/code-frame": "^7.10.4", - "@babel/generator": "^7.10.4", + "@babel/generator": "^7.10.5", "@babel/helper-function-name": "^7.10.4", "@babel/helper-split-export-declaration": "^7.10.4", - "@babel/parser": "^7.10.4", - "@babel/types": "^7.10.4", + "@babel/parser": "^7.10.5", + "@babel/types": "^7.10.5", "debug": "^4.1.0", "globals": "^11.1.0", - "lodash": "^4.17.13" + "lodash": "^4.17.19" } }, "@babel/types": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.10.4.tgz", - "integrity": "sha512-UTCFOxC3FsFHb7lkRMVvgLzaRVamXuAs2Tz4wajva4WxtVY82eZeaUBtC2Zt95FU9TiznuC0Zk35tsim8jeVpg==", + "version": "7.10.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.10.5.tgz", + "integrity": "sha512-ixV66KWfCI6GKoA/2H9v6bQdbfXEwwpOdQ8cRvb4F+eyvhlaHxWFMQB4+3d9QFJXZsiiiqVrewNV0DFEQpyT4Q==", "requires": { "@babel/helper-validator-identifier": "^7.10.4", - "lodash": "^4.17.13", + "lodash": "^4.17.19", "to-fast-properties": "^2.0.0" } }, @@ -1250,13 +1260,6 @@ "slash": "^2.0.0", "source-map": "^0.6.0", "string-length": "^2.0.0" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" - } } }, "@jest/source-map": { @@ -1273,11 +1276,6 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==" - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" } } }, @@ -1323,13 +1321,6 @@ "slash": "^2.0.0", "source-map": "^0.6.1", "write-file-atomic": "2.4.1" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" - } } }, "@jest/types": { @@ -1503,6 +1494,11 @@ "@types/yargs-parser": "*" } }, + "ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==" + }, "ansi-styles": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", @@ -1512,15 +1508,6 @@ "color-convert": "^2.0.1" } }, - "aria-query": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-4.2.2.tgz", - "integrity": "sha512-o/HelwhuKpTj/frsOsbNLNgnNGVIFsVP/SW2BSF14gVl7kAfMOJ6/8wUAUvG1R1NHKrfG+2sHZTu0yauT1qBrA==", - "requires": { - "@babel/runtime": "^7.10.2", - "@babel/runtime-corejs3": "^7.10.2" - } - }, "chalk": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", @@ -1683,15 +1670,21 @@ "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.5.tgz", "integrity": "sha512-7+2BITlgjgDhH0vvwZU/HZJVyk+2XUlvxXe8dFMedNX/aMkaOq++rMAFXc0tM7ij15QaWlbdQASBR9dihi+bDQ==" }, + "@types/json5": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", + "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=", + "dev": true + }, "@types/minimatch": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz", "integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==" }, "@types/node": { - "version": "14.0.22", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.0.22.tgz", - "integrity": "sha512-emeGcJvdiZ4Z3ohbmw93E/64jRzUHAItSHt8nF7M4TGgQTiWqFVGB8KNpLGFmUHmHLvjvBgFwVlqNcq+VuGv9g==" + "version": "14.0.23", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.0.23.tgz", + "integrity": "sha512-Z4U8yDAl5TFkmYsZdFPdjeMa57NOvnaf1tljHzhouaPEp7LCj2JKkejpI1ODviIAQuW4CcQmxkQ77rnLsOOoKw==" }, "@types/parse-json": { "version": "4.0.0", @@ -1767,6 +1760,11 @@ "@types/yargs-parser": "*" } }, + "ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==" + }, "ansi-styles": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", @@ -2212,9 +2210,9 @@ "integrity": "sha1-gTWEAhliqenm/QOflA0S9WynhZ4=" }, "ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==" + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==" }, "ansi-styles": { "version": "3.2.1", @@ -2247,12 +2245,12 @@ } }, "aria-query": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-3.0.0.tgz", - "integrity": "sha1-ZbP8wcoRVajJrmTW7uKX8V1RM8w=", + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-4.2.2.tgz", + "integrity": "sha512-o/HelwhuKpTj/frsOsbNLNgnNGVIFsVP/SW2BSF14gVl7kAfMOJ6/8wUAUvG1R1NHKrfG+2sHZTu0yauT1qBrA==", "requires": { - "ast-types-flow": "0.0.7", - "commander": "^2.11.0" + "@babel/runtime": "^7.10.2", + "@babel/runtime-corejs3": "^7.10.2" } }, "arity-n": { @@ -2322,6 +2320,17 @@ "es-abstract": "^1.17.0-next.1" } }, + "array.prototype.flatmap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.2.3.tgz", + "integrity": "sha512-OOEk+lkePcg+ODXIpvuU9PAryCikCJyo7GlDG1upleEpQRx6mzL9puEBkozQ5iAx20KV0l3DbyQwqciJtqe5Pg==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1", + "function-bind": "^1.1.1" + } + }, "arrify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", @@ -3007,6 +3016,11 @@ "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=" }, + "bootstrap": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-4.5.0.tgz", + "integrity": "sha512-Z93QoXvodoVslA+PWNdk23Hze4RBYIkpb5h8I2HY2Tu2h7A0LpAgLcyrhrSUyo2/Oxm2l1fRZPs1e5hnxnliXA==" + }, "brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -3306,9 +3320,9 @@ } }, "caniuse-lite": { - "version": "1.0.30001099", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001099.tgz", - "integrity": "sha512-sdS9A+sQTk7wKoeuZBN/YMAHVztUfVnjDi4/UV3sDE8xoh7YR12hKW+pIdB3oqKGwr9XaFL2ovfzt9w8eUI5CA==" + "version": "1.0.30001100", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001100.tgz", + "integrity": "sha512-0eYdp1+wFCnMlCj2oudciuQn2B9xAFq3WpgpcBIZTxk/1HNA/O2YA7rpeYhnOqsqAJq1AHUgx6i1jtafg7m2zA==" }, "capture-exit": { "version": "2.0.0", @@ -3457,13 +3471,6 @@ "integrity": "sha512-VcMWDN54ZN/DS+g58HYL5/n4Zrqe8vHJpGA8KdgUXFU4fuP/aHNw8eld9SyEIyabIMJX/0RaY/fplOo5hYLSFA==", "requires": { "source-map": "~0.6.0" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" - } } }, "clean-stack": { @@ -3909,13 +3916,6 @@ "source-map": "^0.6.1", "source-map-resolve": "^0.5.2", "urix": "^0.1.0" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" - } } }, "css-blank-pseudo": { @@ -4023,13 +4023,6 @@ "requires": { "mdn-data": "2.0.4", "source-map": "^0.6.1" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" - } } }, "css-what": { @@ -4144,11 +4137,6 @@ "version": "2.0.6", "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.6.tgz", "integrity": "sha512-rQvjv71olwNHgiTbfPZFkJtjNMciWgswYeciZhtvWLO8bmX3TnhyA62I6sTWOyZssWHJJjY6/KiWwqQsWWsqOA==" - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" } } }, @@ -4624,9 +4612,9 @@ "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" }, "electron-to-chromium": { - "version": "1.3.496", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.496.tgz", - "integrity": "sha512-TXY4mwoyowwi4Lsrq9vcTUYBThyc1b2hXaTZI13p8/FRhY2CTaq5lK+DVjhYkKiTLsKt569Xes+0J5JsVXFurQ==" + "version": "1.3.498", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.498.tgz", + "integrity": "sha512-W1hGwaQEU8j9su2jeAr3aabkPuuXw+j8t73eajGAkEJWbfWiwbxBwQN/8Qmv2qCy3uCDm2rOAaZneYQM8VGC4w==" }, "elliptic": { "version": "6.5.3", @@ -4800,9 +4788,9 @@ } }, "escalade": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.0.1.tgz", - "integrity": "sha512-DR6NO3h9niOT+MZs7bjxlj2a1k+POu5RN8CLTPX2+i78bRi9eLe7+0zXgUHMnGXWybYcL61E9hGhPKqedy8tQA==" + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.0.2.tgz", + "integrity": "sha512-gPYAU37hYCUhW5euPeR+Y74F7BL+IBsV93j5cvGriSaD1aG6MGsqsV1yamRdrWrb2j3aiZvb0X+UBOWpx3JWtQ==" }, "escape-html": { "version": "1.0.3", @@ -4824,14 +4812,6 @@ "esutils": "^2.0.2", "optionator": "^0.8.1", "source-map": "~0.6.1" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "optional": true - } } }, "eslint": { @@ -4923,6 +4903,12 @@ "confusing-browser-globals": "^1.0.9" } }, + "eslint-config-standard": { + "version": "14.1.1", + "resolved": "https://registry.npmjs.org/eslint-config-standard/-/eslint-config-standard-14.1.1.tgz", + "integrity": "sha512-Z9B+VR+JIXRxz21udPTL9HpFMyoMUEeX1G251EQ6e05WD9aPVtVBn09XUmZ259wCMlCDmYDSZG62Hhm+ZTJcUg==", + "dev": true + }, "eslint-import-resolver-node": { "version": "0.3.4", "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.4.tgz", @@ -5029,6 +5015,16 @@ } } }, + "eslint-plugin-es": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-es/-/eslint-plugin-es-3.0.1.tgz", + "integrity": "sha512-GUmAsJaN4Fc7Gbtl8uOBlayo2DqhwWvEzykMHSCZHU3XdJ+NSzzZcVhXh3VxX5icqQ+oQdIEawXX8xkR3mIFmQ==", + "dev": true, + "requires": { + "eslint-utils": "^2.0.0", + "regexpp": "^3.0.0" + } + }, "eslint-plugin-flowtype": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/eslint-plugin-flowtype/-/eslint-plugin-flowtype-4.6.0.tgz", @@ -5038,28 +5034,31 @@ } }, "eslint-plugin-import": { - "version": "2.20.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.20.1.tgz", - "integrity": "sha512-qQHgFOTjguR+LnYRoToeZWT62XM55MBVXObHM6SKFd1VzDcX/vqT1kAz8ssqigh5eMj8qXcRoXXGZpPP6RfdCw==", + "version": "2.22.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.22.0.tgz", + "integrity": "sha512-66Fpf1Ln6aIS5Gr/55ts19eUuoDhAbZgnr6UxK5hbDx6l/QgQgx61AePq+BV4PP2uXQFClgMVzep5zZ94qqsxg==", + "dev": true, "requires": { - "array-includes": "^3.0.3", - "array.prototype.flat": "^1.2.1", + "array-includes": "^3.1.1", + "array.prototype.flat": "^1.2.3", "contains-path": "^0.1.0", "debug": "^2.6.9", "doctrine": "1.5.0", - "eslint-import-resolver-node": "^0.3.2", - "eslint-module-utils": "^2.4.1", + "eslint-import-resolver-node": "^0.3.3", + "eslint-module-utils": "^2.6.0", "has": "^1.0.3", "minimatch": "^3.0.4", - "object.values": "^1.1.0", + "object.values": "^1.1.1", "read-pkg-up": "^2.0.0", - "resolve": "^1.12.0" + "resolve": "^1.17.0", + "tsconfig-paths": "^3.9.0" }, "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" } @@ -5068,6 +5067,7 @@ "version": "1.5.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz", "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=", + "dev": true, "requires": { "esutils": "^2.0.2", "isarray": "^1.0.0" @@ -5077,6 +5077,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "dev": true, "requires": { "locate-path": "^2.0.0" } @@ -5085,6 +5086,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", + "dev": true, "requires": { "graceful-fs": "^4.1.2", "parse-json": "^2.2.0", @@ -5096,6 +5098,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "dev": true, "requires": { "p-locate": "^2.0.0", "path-exists": "^3.0.0" @@ -5104,12 +5107,14 @@ "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true }, "p-limit": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "dev": true, "requires": { "p-try": "^1.0.0" } @@ -5118,6 +5123,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "dev": true, "requires": { "p-limit": "^1.1.0" } @@ -5125,12 +5131,14 @@ "p-try": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", - "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=" + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", + "dev": true }, "parse-json": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "dev": true, "requires": { "error-ex": "^1.2.0" } @@ -5139,6 +5147,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", + "dev": true, "requires": { "pify": "^2.0.0" } @@ -5146,12 +5155,14 @@ "pify": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true }, "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", @@ -5162,10 +5173,20 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz", "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=", + "dev": true, "requires": { "find-up": "^2.0.0", "read-pkg": "^2.0.0" } + }, + "resolve": { + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz", + "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==", + "dev": true, + "requires": { + "path-parse": "^1.0.6" + } } } }, @@ -5185,6 +5206,15 @@ "jsx-ast-utils": "^2.2.1" }, "dependencies": { + "aria-query": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-3.0.0.tgz", + "integrity": "sha1-ZbP8wcoRVajJrmTW7uKX8V1RM8w=", + "requires": { + "ast-types-flow": "0.0.7", + "commander": "^2.11.0" + } + }, "emoji-regex": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", @@ -5192,29 +5222,58 @@ } } }, + "eslint-plugin-node": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-node/-/eslint-plugin-node-11.1.0.tgz", + "integrity": "sha512-oUwtPJ1W0SKD0Tr+wqu92c5xuCeQqB3hSCHasn/ZgjFdA9iDGNkNf2Zi9ztY7X+hNuMib23LNGRm6+uN+KLE3g==", + "dev": true, + "requires": { + "eslint-plugin-es": "^3.0.0", + "eslint-utils": "^2.0.0", + "ignore": "^5.1.1", + "minimatch": "^3.0.4", + "resolve": "^1.10.1", + "semver": "^6.1.0" + }, + "dependencies": { + "ignore": { + "version": "5.1.8", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz", + "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==", + "dev": true + } + } + }, + "eslint-plugin-promise": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-4.2.1.tgz", + "integrity": "sha512-VoM09vT7bfA7D+upt+FjeBO5eHIJQBUWki1aPvB+vbNiHS3+oGIJGIeyBtKQTME6UPXXy3vV07OL1tHd3ANuDw==", + "dev": true + }, "eslint-plugin-react": { - "version": "7.19.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.19.0.tgz", - "integrity": "sha512-SPT8j72CGuAP+JFbT0sJHOB80TX/pu44gQ4vXH/cq+hQTiY2PuZ6IHkqXJV6x1b28GDdo1lbInjKUrrdUf0LOQ==", + "version": "7.20.3", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.20.3.tgz", + "integrity": "sha512-txbo090buDeyV0ugF3YMWrzLIUqpYTsWSDZV9xLSmExE1P/Kmgg9++PD931r+KEWS66O1c9R4srLVVHmeHpoAg==", + "dev": true, "requires": { "array-includes": "^3.1.1", + "array.prototype.flatmap": "^1.2.3", "doctrine": "^2.1.0", "has": "^1.0.3", - "jsx-ast-utils": "^2.2.3", - "object.entries": "^1.1.1", + "jsx-ast-utils": "^2.4.1", + "object.entries": "^1.1.2", "object.fromentries": "^2.0.2", "object.values": "^1.1.1", "prop-types": "^15.7.2", - "resolve": "^1.15.1", - "semver": "^6.3.0", - "string.prototype.matchall": "^4.0.2", - "xregexp": "^4.3.0" + "resolve": "^1.17.0", + "string.prototype.matchall": "^4.0.2" }, "dependencies": { "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" } @@ -5223,6 +5282,7 @@ "version": "1.17.0", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz", "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==", + "dev": true, "requires": { "path-parse": "^1.0.6" } @@ -5234,6 +5294,12 @@ "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-1.7.0.tgz", "integrity": "sha512-iXTCFcOmlWvw4+TOE8CLWj6yX1GwzT0Y6cUfHHZqWnSk144VmVIRcVGtUAzrLES7C798lmvnt02C7rxaOX1HNA==" }, + "eslint-plugin-standard": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-standard/-/eslint-plugin-standard-4.0.1.tgz", + "integrity": "sha512-v/KBnfyaOMPmZc/dmc6ozOdWqekGp7bBGq4jLAecEfPGmfKiWS4sA8sC0LqiV9w5qmXAtXVn4M3p1jSyhY85SQ==", + "dev": true + }, "eslint-scope": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.0.tgz", @@ -6401,6 +6467,14 @@ "minimalistic-crypto-utils": "^1.0.1" } }, + "hoist-non-react-statics": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", + "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", + "requires": { + "react-is": "^16.7.0" + } + }, "hosted-git-info": { "version": "2.8.8", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz", @@ -6732,9 +6806,9 @@ "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==" }, "inquirer": { - "version": "7.3.1", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-7.3.1.tgz", - "integrity": "sha512-/+vOpHQHhoh90Znev8BXiuw1TDQ7IDxWsQnFafUEoK5+4uN5Eoz1p+3GqOj/NtzEi9VzWKQcV9Bm+i8moxedsA==", + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-7.3.2.tgz", + "integrity": "sha512-DF4osh1FM6l0RJc5YWYhSDB6TawiBRlbV9Cox8MWlidU218Tb7fm3lQTULyUJDfJ0tjbzl0W4q651mrCCEM55w==", "requires": { "ansi-escapes": "^4.2.1", "chalk": "^4.1.0", @@ -6751,6 +6825,11 @@ "through": "^2.3.6" }, "dependencies": { + "ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==" + }, "ansi-styles": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", @@ -7162,13 +7241,6 @@ "make-dir": "^2.1.0", "rimraf": "^2.6.3", "source-map": "^0.6.1" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" - } } }, "istanbul-reports": { @@ -7610,11 +7682,6 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==" - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" } } }, @@ -9303,11 +9370,6 @@ "supports-color": "^6.1.0" }, "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" - }, "supports-color": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", @@ -10251,13 +10313,6 @@ "ansi-regex": "^4.0.0", "ansi-styles": "^3.2.0", "react-is": "^16.8.4" - }, - "dependencies": { - "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==" - } } }, "process": { @@ -10525,11 +10580,6 @@ "@babel/highlight": "^7.8.3" } }, - "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==" - }, "browserslist": { "version": "4.10.0", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.10.0.tgz", @@ -10708,6 +10758,18 @@ "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" }, + "react-redux": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-7.2.0.tgz", + "integrity": "sha512-EvCAZYGfOLqwV7gh849xy9/pt55rJXPwmYvI4lilPM5rUT/1NxuuN59ipdBksRVSvz0KInbPnp4IfoXJXCqiDA==", + "requires": { + "@babel/runtime": "^7.5.5", + "hoist-non-react-statics": "^3.3.0", + "loose-envify": "^1.4.0", + "prop-types": "^15.7.2", + "react-is": "^16.9.0" + } + }, "react-scripts": { "version": "3.4.1", "resolved": "https://registry.npmjs.org/react-scripts/-/react-scripts-3.4.1.tgz", @@ -10766,6 +10828,175 @@ "webpack-dev-server": "3.10.3", "webpack-manifest-plugin": "2.2.0", "workbox-webpack-plugin": "4.3.1" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "doctrine": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz", + "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=", + "requires": { + "esutils": "^2.0.2", + "isarray": "^1.0.0" + } + }, + "eslint-plugin-import": { + "version": "2.20.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.20.1.tgz", + "integrity": "sha512-qQHgFOTjguR+LnYRoToeZWT62XM55MBVXObHM6SKFd1VzDcX/vqT1kAz8ssqigh5eMj8qXcRoXXGZpPP6RfdCw==", + "requires": { + "array-includes": "^3.0.3", + "array.prototype.flat": "^1.2.1", + "contains-path": "^0.1.0", + "debug": "^2.6.9", + "doctrine": "1.5.0", + "eslint-import-resolver-node": "^0.3.2", + "eslint-module-utils": "^2.4.1", + "has": "^1.0.3", + "minimatch": "^3.0.4", + "object.values": "^1.1.0", + "read-pkg-up": "^2.0.0", + "resolve": "^1.12.0" + } + }, + "eslint-plugin-react": { + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.19.0.tgz", + "integrity": "sha512-SPT8j72CGuAP+JFbT0sJHOB80TX/pu44gQ4vXH/cq+hQTiY2PuZ6IHkqXJV6x1b28GDdo1lbInjKUrrdUf0LOQ==", + "requires": { + "array-includes": "^3.1.1", + "doctrine": "^2.1.0", + "has": "^1.0.3", + "jsx-ast-utils": "^2.2.3", + "object.entries": "^1.1.1", + "object.fromentries": "^2.0.2", + "object.values": "^1.1.1", + "prop-types": "^15.7.2", + "resolve": "^1.15.1", + "semver": "^6.3.0", + "string.prototype.matchall": "^4.0.2", + "xregexp": "^4.3.0" + }, + "dependencies": { + "doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "requires": { + "esutils": "^2.0.2" + } + }, + "resolve": { + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz", + "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==", + "requires": { + "path-parse": "^1.0.6" + } + } + } + }, + "find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "requires": { + "locate-path": "^2.0.0" + } + }, + "load-json-file": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", + "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "strip-bom": "^3.0.0" + } + }, + "locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "requires": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "p-limit": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", + "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "requires": { + "p-try": "^1.0.0" + } + }, + "p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "requires": { + "p-limit": "^1.1.0" + } + }, + "p-try": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=" + }, + "parse-json": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "requires": { + "error-ex": "^1.2.0" + } + }, + "path-type": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", + "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", + "requires": { + "pify": "^2.0.0" + } + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" + }, + "read-pkg": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", + "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", + "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=", + "requires": { + "find-up": "^2.0.0", + "read-pkg": "^2.0.0" + } + } } }, "read-pkg": { @@ -10830,6 +11061,41 @@ "strip-indent": "^3.0.0" } }, + "redux": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/redux/-/redux-4.0.5.tgz", + "integrity": "sha512-VSz1uMAH24DM6MF72vcojpYPtrTUu3ByVWfPL1nPfVRb5mZVTve5GnNCUV53QM/BZ66xfWrm0CTWoM+Xlz8V1w==", + "requires": { + "loose-envify": "^1.4.0", + "symbol-observable": "^1.2.0" + } + }, + "redux-devtools": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/redux-devtools/-/redux-devtools-3.5.0.tgz", + "integrity": "sha512-pGU8TZNvWxPaCCE432AGm6H6alQbAz80gQM5CzM3SjX9/oSNu/HPF17xFdPQJOXasqyih1Gv167kZDTRe7r0iQ==", + "dev": true, + "requires": { + "lodash": "^4.2.0", + "prop-types": "^15.5.7", + "redux-devtools-instrument": "^1.9.0" + } + }, + "redux-devtools-extension": { + "version": "2.13.8", + "resolved": "https://registry.npmjs.org/redux-devtools-extension/-/redux-devtools-extension-2.13.8.tgz", + "integrity": "sha512-8qlpooP2QqPtZHQZRhx3x3OP5skEV1py/zUdMY28WNAocbafxdG2tRD1MWE7sp8obGMNYuLWanhhQ7EQvT1FBg==" + }, + "redux-devtools-instrument": { + "version": "1.9.6", + "resolved": "https://registry.npmjs.org/redux-devtools-instrument/-/redux-devtools-instrument-1.9.6.tgz", + "integrity": "sha512-MwvY4cLEB2tIfWWBzrUR02UM9qRG2i7daNzywRvabOSVdvAY7s9BxSwMmVRH1Y/7QWjplNtOwgT0apKhHg2Qew==", + "dev": true, + "requires": { + "lodash": "^4.2.0", + "symbol-observable": "^1.0.2" + } + }, "regenerate": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.1.tgz", @@ -11014,6 +11280,13 @@ "tough-cookie": "~2.5.0", "tunnel-agent": "^0.6.0", "uuid": "^3.3.2" + }, + "dependencies": { + "uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==" + } } }, "request-promise-core": { @@ -11049,6 +11322,11 @@ "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=" }, + "reselect": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/reselect/-/reselect-4.0.0.tgz", + "integrity": "sha512-qUgANli03jjAyGlnbYVAV5vvnOmJnODyABz51RdBN7M4WaVu8mecZWgyQNkG8Yqe3KRGRt0l4K4B3XVEULC4CA==" + }, "resolve": { "version": "1.15.0", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.15.0.tgz", @@ -11125,11 +11403,6 @@ "supports-color": "^6.1.0" } }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" - }, "supports-color": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", @@ -11665,6 +11938,11 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" } } }, @@ -11734,6 +12012,13 @@ "requires": { "faye-websocket": "^0.10.0", "uuid": "^3.0.1" + }, + "dependencies": { + "uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==" + } } }, "sockjs-client": { @@ -11781,9 +12066,9 @@ "integrity": "sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==" }, "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" }, "source-map-resolve": { "version": "0.5.3", @@ -11804,13 +12089,6 @@ "requires": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" - } } }, "source-map-url": { @@ -12070,6 +12348,11 @@ "strip-ansi": "^6.0.0" }, "dependencies": { + "ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==" + }, "strip-ansi": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", @@ -12149,13 +12432,6 @@ "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", "requires": { "ansi-regex": "^4.1.0" - }, - "dependencies": { - "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==" - } } }, "strip-bom": { @@ -12281,6 +12557,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.4", "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", @@ -12332,13 +12613,6 @@ "commander": "^2.20.0", "source-map": "~0.6.1", "source-map-support": "~0.5.12" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" - } } }, "terser-webpack-plugin": { @@ -12427,11 +12701,6 @@ "find-up": "^4.0.0" } }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" - }, "supports-color": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", @@ -12606,6 +12875,29 @@ "resolved": "https://registry.npmjs.org/ts-pnp/-/ts-pnp-1.1.6.tgz", "integrity": "sha512-CrG5GqAAzMT7144Cl+UIFP7mz/iIhiy+xQ6GGcnjTezhALT02uPMRw7tgDSESgB5MsfKt55+GPWw4ir1kVtMIQ==" }, + "tsconfig-paths": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.9.0.tgz", + "integrity": "sha512-dRcuzokWhajtZWkQsDVKbWyY+jgcLC5sqJhg2PSgf4ZkH2aHPvaOY8YWGhmjb68b5qqTfasSsDO9k7RUiEmZAw==", + "dev": true, + "requires": { + "@types/json5": "^0.0.29", + "json5": "^1.0.1", + "minimist": "^1.2.0", + "strip-bom": "^3.0.0" + }, + "dependencies": { + "json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "dev": true, + "requires": { + "minimist": "^1.2.0" + } + } + } + }, "tslib": { "version": "1.13.0", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.13.0.tgz", @@ -12881,9 +13173,9 @@ "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" }, "uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==" + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.2.0.tgz", + "integrity": "sha512-CYpGiFTUrmI6OBMkAdjSDM0k5h8SkkiTP4WAjQgDgNB1S3Ou9VBEvr6q0Kv2H1mMk7IWfxYGpMH5sd5AvcIV2Q==" }, "v8-compile-cache": { "version": "2.1.1", @@ -13177,11 +13469,6 @@ "randombytes": "^2.1.0" } }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" - }, "ssri": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.1.tgz", @@ -13528,6 +13815,13 @@ "requires": { "ansi-colors": "^3.0.0", "uuid": "^3.3.2" + }, + "dependencies": { + "uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==" + } } }, "webpack-manifest-plugin": { @@ -13560,13 +13854,6 @@ "requires": { "source-list-map": "^2.0.0", "source-map": "~0.6.1" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" - } } }, "websocket-driver": { diff --git a/package.json b/package.json index ffbaee6..cb93c1e 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "homepage": "", + "homepage": "https://denkondratiev.github.io/react_table", "name": "react_table", "version": "0.1.0", "private": true, @@ -7,9 +7,15 @@ "@testing-library/jest-dom": "^4.2.4", "@testing-library/react": "^9.5.0", "@testing-library/user-event": "^7.2.1", + "bootstrap": "^4.5.0", "react": "^16.13.1", "react-dom": "^16.13.1", - "react-scripts": "3.4.1" + "react-redux": "^7.2.0", + "react-scripts": "3.4.1", + "redux": "^4.0.5", + "redux-devtools-extension": "^2.13.8", + "reselect": "^4.0.0", + "uuid": "^8.2.0" }, "scripts": { "start": "react-scripts start", @@ -17,10 +23,8 @@ "test": "react-scripts test", "eject": "react-scripts eject", "predeploy": "npm run build", - "deploy": "gh-pages -d build" - }, - "eslintConfig": { - "extends": "react-app" + "deploy": "gh-pages -d build", + "lint": "eslint --ext .jsx,.js ./src/ --fix" }, "browserslist": { "production": [ @@ -35,6 +39,13 @@ ] }, "devDependencies": { - "gh-pages": "^3.1.0" + "eslint-config-standard": "^14.1.1", + "eslint-plugin-import": "^2.22.0", + "eslint-plugin-node": "^11.1.0", + "eslint-plugin-promise": "^4.2.1", + "eslint-plugin-react": "^7.20.3", + "eslint-plugin-standard": "^4.0.1", + "gh-pages": "^3.1.0", + "redux-devtools": "^3.5.0" } } diff --git a/src/App.js b/src/App.js deleted file mode 100644 index d0139c2..0000000 --- a/src/App.js +++ /dev/null @@ -1,10 +0,0 @@ -import React from 'react'; -import './App.css'; - -function App() { - return ( -

React Table

- ); -} - -export default App; diff --git a/src/App.jsx b/src/App.jsx new file mode 100644 index 0000000..0ef4884 --- /dev/null +++ b/src/App.jsx @@ -0,0 +1,15 @@ +import React from 'react' +import Form from './components/Form/Form' +import Table from './components/Table/Table' +import Buttons from './components/Buttons/Buttons' +import './App.css' + +const App = () => ( +
+
+ + + +) + +export default App diff --git a/src/components/AverageRow/AverageRow.jsx b/src/components/AverageRow/AverageRow.jsx new file mode 100644 index 0000000..dabb741 --- /dev/null +++ b/src/components/AverageRow/AverageRow.jsx @@ -0,0 +1,24 @@ +import React from 'react' +// import { v4 as uuidv4 } from 'uuid' +import { AverageRowShape } from '../../helpers/shapes' +import { connect } from 'react-redux' +import { getAverageRowSum } from '../../helpers/selectors' + +const AverageRow = ({ averageArray }) => { + return ( + <> + {{averageArray.map((item, index) => ( + + ))} + } + + ) +} + +AverageRow.propTypes = AverageRowShape.isRequired + +const mapStateToProps = (state) => ({ + averageArray: getAverageRowSum(state) +}) + +export default connect(mapStateToProps)(React.memo(AverageRow)) diff --git a/src/components/ButtonAdd/ButtonAdd.jsx b/src/components/ButtonAdd/ButtonAdd.jsx new file mode 100644 index 0000000..4e01644 --- /dev/null +++ b/src/components/ButtonAdd/ButtonAdd.jsx @@ -0,0 +1,16 @@ +import React from 'react' +import { ButtonAddShape } from '../../helpers/shapes' + +export const ButtonAdd = ({ addRow }) => { + return ( + + ) +} + +ButtonAdd.propTypes = ButtonAddShape.isRequired diff --git a/src/components/ButtonDelete/ButtonDelete.jsx b/src/components/ButtonDelete/ButtonDelete.jsx new file mode 100644 index 0000000..d8c3bca --- /dev/null +++ b/src/components/ButtonDelete/ButtonDelete.jsx @@ -0,0 +1,18 @@ +import React from 'react' +import { ButtonDeleteShape } from '../../helpers/shapes' + +export const ButtonDelete = (props) => { + const { deleteRow } = props + + return ( + + ) +} + +ButtonDelete.propTypes = ButtonDeleteShape.isRequired diff --git a/src/components/Buttons/Buttons.css b/src/components/Buttons/Buttons.css new file mode 100644 index 0000000..66b3697 --- /dev/null +++ b/src/components/Buttons/Buttons.css @@ -0,0 +1,14 @@ +.buttons { + display: flex; + justify-content: center; + margin-bottom: 10px; +} + +.btn { + max-width: 120px; + margin-right: 5px; +} + +.btn:last-child { + margin-right: 0; +} diff --git a/src/components/Buttons/Buttons.jsx b/src/components/Buttons/Buttons.jsx new file mode 100644 index 0000000..7a8a5cc --- /dev/null +++ b/src/components/Buttons/Buttons.jsx @@ -0,0 +1,58 @@ +import React from 'react' +import { connect } from 'react-redux' +import { generateTable } from '../../helpers/generate' +import { ButtonsShape } from '../../helpers/shapes' +import { ButtonDelete } from '../ButtonDelete/ButtonDelete' +import { ButtonAdd } from '../ButtonAdd/ButtonAdd' +import { getColumnsAmount } from '../../helpers/selectors' +import './Buttons.css' +import { + setNewRow, + removeRow +} from '../../store/actions' + +const Buttons = (props) => { + const { + showButtons, + setNewRow, + removeRow, + columnsAmount, + table + } = props + + const addRow = () => { + const { table, rows, cells } = generateTable(1, columnsAmount) + setNewRow({ table, rows, cells }) + } + + const deleteRow = () => { + const lastIndex = table[table.length - 1] + removeRow({ lastIndex }) + } + + return ( + <> + {showButtons && ( +
+ + +
+ )} + + ) +} + +Buttons.propTypes = ButtonsShape.isRequired + +const mapStateToProps = state => ({ + showButtons: state.buttons, + columnsAmount: getColumnsAmount(state), + table: state.table +}) + +const mapDispatchToProps = dispatch => ({ + setNewRow: (table, rows, cells) => dispatch(setNewRow(table, rows, cells)), + removeRow: (lastRow) => dispatch(removeRow(lastRow)) +}) + +export default connect(mapStateToProps, mapDispatchToProps)(React.memo(Buttons)) diff --git a/src/components/Form/Form.css b/src/components/Form/Form.css new file mode 100644 index 0000000..9453bbd --- /dev/null +++ b/src/components/Form/Form.css @@ -0,0 +1,21 @@ +form { + position: relative; + display: block; + max-width: 200px; + margin: 0 auto; + + padding: 30px 0; +} + +.form-control { + margin-right: 20px; + margin-bottom: 20px; +} + +.form-control:last-child { + margin-right: 0; +} + +.error { + border: 1px solid red !important; +} diff --git a/src/components/Form/Form.jsx b/src/components/Form/Form.jsx new file mode 100644 index 0000000..58b04fb --- /dev/null +++ b/src/components/Form/Form.jsx @@ -0,0 +1,155 @@ +import React, { useState } from 'react' +import { FormShape } from '../../helpers/shapes' +import { generateTable } from '../../helpers/generate' +import { connect } from 'react-redux' +import './Form.css' +import { + setParams, + setTable, + setRows, + setCells, + setShowButtons +} from '../../store/actions' + +const Form = (props) => { + const { + setParamsData, + setTableData, + setRowsData, + setCellsData, + setShowButtonsBoll + } = props + + const [inputValue, setInputValue] = useState({ + rowsAmount: '', + columnsAmount: '', + lightsAmount: '' + }) + + const [error, setError] = useState({ + rowsAmount: false, + columnsAmount: false, + lightsAmount: false + }) + + const handleGenerateTable = (event) => { + event.preventDefault() + + const rowsAmount = inputValue.rowsAmount + const columnsAmount = inputValue.columnsAmount + const lightsAmount = inputValue.lightsAmount + + if (rowsAmount > 0 && columnsAmount > 0 && lightsAmount > 0) { + const { table, rows, cells } = generateTable(rowsAmount, columnsAmount) + + setParamsData({ rowsAmount, columnsAmount, lightsAmount }) + setTableData(table) + setRowsData(rows) + setCellsData(cells) + setShowButtonsBoll(true) + + setInputValue({ + rowsAmount: '', + columnsAmount: '', + lightsAmount: '' + }) + } + + const errorObj = { + rowsAmount: null, + columnsAmount: null, + lightsAmount: null + } + + if (!rowsAmount || rowsAmount <= 0) { + errorObj.rowsAmount = true + } + + if (!columnsAmount || columnsAmount <= 0) { + errorObj.columnsAmount = true + } + + if (!lightsAmount || lightsAmount <= 0) { + errorObj.lightsAmount = true + } + + setError({ + rowsAmount: errorObj.rowsAmount, + columnsAmount: errorObj.columnsAmount, + lightsAmount: errorObj.lightsAmount + }) + } + + const onChangeHandler = ({ name, value }) => { + setError({ [name]: false }) + setInputValue({ ...inputValue, [name]: value }) + } + + return ( + handleGenerateTable(event)}> + { + error.rowsAmount && ( +
+ Please add correct rows value +
+ ) + } + onChangeHandler(event.target)} + value={inputValue.rowsAmount} + /> + { + error.columnsAmount && ( +
+ Please add correct columns value +
+ ) + } + onChangeHandler(event.target)} + value={inputValue.columnsAmount} + /> + { + error.lightsAmount && ( +
+ Please add correct highlight value +
+ ) + } + onChangeHandler(event.target)} + value={inputValue.lightsAmount} + /> + + + ) +} + +Form.propTypes = FormShape.isRequired + +const mapDispatchToProps = dispatch => ({ + setParamsData: params => dispatch(setParams(params)), + setTableData: table => dispatch(setTable(table)), + setRowsData: rows => dispatch(setRows(rows)), + setCellsData: cells => dispatch(setCells(cells)), + setShowButtonsBoll: params => dispatch(setShowButtons(params)) +}) + +export default connect(null, mapDispatchToProps)(Form) diff --git a/src/components/Table/Table.css b/src/components/Table/Table.css new file mode 100644 index 0000000..80da376 --- /dev/null +++ b/src/components/Table/Table.css @@ -0,0 +1,4 @@ +.table { + cursor: pointer; + text-align: right; +} diff --git a/src/components/Table/Table.jsx b/src/components/Table/Table.jsx new file mode 100644 index 0000000..c93ab03 --- /dev/null +++ b/src/components/Table/Table.jsx @@ -0,0 +1,76 @@ +import React, { useState } from 'react' +import { connect } from 'react-redux' +import { TableShape } from '../../helpers/shapes' +import TableRow from '../TableRow/TableRow' +import AverageRow from '../AverageRow/AverageRow' +import { getRowSum, getLightsAmount } from '../../helpers/selectors' +import { getLightClosest } from '../../helpers/getLightClosest' +import { increment } from '../../store/actions' +import './Table.css' + +const Table = (props) => { + const { + table, + rows, + cells, + sumRowArray, + lightsAmount, + incrementCell + } = props + + const [lightArray, setLightArray] = useState({}) + + const onMouseEnterHandler = (id) => { + const arr = getLightClosest(id, cells, lightsAmount) + setLightArray(arr) + } + + const onMouseLeaveHandler = () => { + setLightArray({}) + } + + const onClickIncrement = (id) => { + incrementCell(id) + } + + return ( + <> + {table.length > 0 && ( +
Average sum: {item}
+ + {table.map((rowId, index) => ( + + ))} + + +
+ )} + + ) +} + +Table.propTypes = TableShape.isRequired + +const mapStateToProps = state => ({ + table: state.table, + rows: state.rows, + cells: state.cells, + sumRowArray: getRowSum(state), + lightsAmount: getLightsAmount(state) +}) + +const mapDispatchToProps = (dispatch) => ({ + incrementCell: id => dispatch(increment(id)) +}) + +export default connect(mapStateToProps, mapDispatchToProps)(React.memo(Table)) diff --git a/src/components/TableCell/TableCell.css b/src/components/TableCell/TableCell.css new file mode 100644 index 0000000..907b27a --- /dev/null +++ b/src/components/TableCell/TableCell.css @@ -0,0 +1,3 @@ +.table-cell--light { + background-color: #6c757d; +} diff --git a/src/components/TableCell/TableCell.jsx b/src/components/TableCell/TableCell.jsx new file mode 100644 index 0000000..99eb685 --- /dev/null +++ b/src/components/TableCell/TableCell.jsx @@ -0,0 +1,49 @@ +import React from 'react' +import { TableCellShape } from '../../helpers/shapes' +import './TableCell.css' + +const areEqual = (prevProps, nextProps) => { + const { id, value, styleString } = prevProps + + if (nextProps.styleString !== styleString) { + return false + } + if (nextProps.value !== value) { + return false + } + if (nextProps.id !== id) { + return false + } + return true +} + +const TableCell = (props) => { + const { + id, + value, + styleString, + onMouseEnterHandler, + onMouseLeaveHandler, + onClickIncrement + } = props + + const styleObj = { + background: `${styleString}` + } + + return ( + onClickIncrement(event.target.id)} + onMouseEnter={(event) => onMouseEnterHandler(event.target.id)} + onMouseLeave={onMouseLeaveHandler} + style={styleObj} + > + {value} + + ) +} + +TableCell.propTypes = TableCellShape.isRequired + +export default React.memo(TableCell, areEqual) diff --git a/src/components/TableCellSum/TableCellSum.jsx b/src/components/TableCellSum/TableCellSum.jsx new file mode 100644 index 0000000..e71efb4 --- /dev/null +++ b/src/components/TableCellSum/TableCellSum.jsx @@ -0,0 +1,35 @@ +import React from 'react' +import { TableCellSumShape } from '../../helpers/shapes' + +const areEqual = (prevProps, nextProps) => { + const { rowSum } = prevProps + + if (nextProps.rowSum !== rowSum) { + return false + } + return true +} + +const TableCellSum = (props) => { + const { + id, + rowSum, + onMouseEnterPercent, + onMouseLeavePercent + } = props + + return ( + + Sum: {rowSum} + + + ) +} + +TableCellSum.propTypes = TableCellSumShape.isRequired + +export default React.memo(TableCellSum, areEqual) diff --git a/src/components/TableRow/TableRow.jsx b/src/components/TableRow/TableRow.jsx new file mode 100644 index 0000000..131d22f --- /dev/null +++ b/src/components/TableRow/TableRow.jsx @@ -0,0 +1,81 @@ +import React, { useState } from 'react' +// import { v4 as uuidv4 } from 'uuid' +import { TableRowShape } from '../../helpers/shapes' +import TableCell from '../TableCell/TableCell' +import TableCellSum from '../TableCellSum/TableCellSum' + +const areEqual = (prevProps, nextProps) => { + const { row, cells, lightArray } = prevProps + + for (const id of row) { + if (nextProps.cells[id].amount !== cells[id].amount) { + return false + } + if (nextProps.lightArray[id] !== lightArray[id]) { + return false + } + } + return true +} + +const TableRow = (props) => { + const { + id, + row, + cells, + rowSum, + lightArray, + onMouseEnterHandler, + onMouseLeaveHandler, + onClickIncrement + } = props + + const [showPercent, setShowPercent] = useState(false) + + const onMouseEnterPercent = () => { + setShowPercent(true) + } + + const onMouseLeavePercent = () => { + setShowPercent(false) + } + + return ( + + {row.map(cellId => { + let value = cells[cellId].amount + let styleString = '' + + if (lightArray[cellId]) { styleString += '#6c757d' } + + if (showPercent) { + value = (cells[cellId].amount / rowSum * 100).toFixed(2) + styleString += `linear-gradient(90deg, rgba(220,53,69,1) ${value}%, rgba(108,117,125,1) ${value}%)` + } + + return ( + + ) + })} + + + ) +} + +TableRow.propTypes = TableRowShape.isRequired + +export default React.memo(TableRow, areEqual) diff --git a/src/helpers/generate.js b/src/helpers/generate.js new file mode 100644 index 0000000..2a4dc14 --- /dev/null +++ b/src/helpers/generate.js @@ -0,0 +1,25 @@ +import { v4 as uuidv4 } from 'uuid' + +export const generateTable = (rowsAmount, columnsAmount) => { + const table = [] + const rows = {} + const cells = {} + + for (let i = 0; i < rowsAmount; i++) { + const rowId = uuidv4() + table[i] = rowId + rows[rowId] = [] + + for (let j = 0; j < columnsAmount; j++) { + const cellId = uuidv4() + rows[rowId][j] = cellId + + cells[cellId] = { + id: cellId, + amount: Math.floor(Math.random() * 999) + } + } + } + + return { table, rows, cells } +} diff --git a/src/helpers/getLightClosest.js b/src/helpers/getLightClosest.js new file mode 100644 index 0000000..c4c08e5 --- /dev/null +++ b/src/helpers/getLightClosest.js @@ -0,0 +1,16 @@ +export const getLightClosest = (id, cells, lightsAmount) => { + const arr = Object.values(cells).map(item => ({ + ...item, + difference: Math.abs(item.amount - cells[id].amount) + })).sort((a, b) => a.difference - b.difference) + .slice(0, Number(lightsAmount)) + .map(item => item.id) + + const obj = {} + + for (const id of arr) { + obj[id] = true + } + + return obj +} diff --git a/src/helpers/selectors.js b/src/helpers/selectors.js new file mode 100644 index 0000000..8ae5bf0 --- /dev/null +++ b/src/helpers/selectors.js @@ -0,0 +1,44 @@ +import { createSelector } from 'reselect' + +export const getRows = state => state.rows + +export const getCells = state => state.cells + +export const getColumns = state => state.columns + +export const getTable = state => state.table + +export const getRowsAmount = state => state.params.rowsAmount + +export const getColumnsAmount = state => state.params.columnsAmount + +export const getLightsAmount = state => state.params.lightsAmount + +export const getRowSum = createSelector( + [getRows, getCells], + (rows, cells) => { + const sumArr = Object.values(rows).map(row => ( + row.map(item => cells[item].amount).reduce((prev, cur) => prev + cur, 0) + )) + + return sumArr + } +) + +export const getAverageRowSum = createSelector( + [getRows, getCells], + (rows, cells) => { + const onlyAmount = Object.values(rows).map(row => ( + row.map(item => cells[item].amount) + )) + + const res = [] + for (let i = 0; i < onlyAmount.length; i++) { + for (let j = 0; j < onlyAmount[i].length; j++) { + res[j] = (res[j] || 0) + Math.floor(onlyAmount[i][j] / onlyAmount.length) + } + } + + return res + } +) diff --git a/src/helpers/shapes.js b/src/helpers/shapes.js new file mode 100644 index 0000000..b5f819c --- /dev/null +++ b/src/helpers/shapes.js @@ -0,0 +1,66 @@ +import PropTypes from 'prop-types' + +export const TableShape = PropTypes.shape({ + rows: PropTypes.number, + columns: PropTypes.number, + table: PropTypes.array, + sumRowArray: PropTypes.number, + lightsAmount: PropTypes.number +}) + +export const TableCellShape = PropTypes.shape({ + id: PropTypes.number, + cell: PropTypes.number, + amount: PropTypes.number, + isLight: PropTypes.bool, + showPercent: PropTypes.bool, + percent: PropTypes.number, + incrementCell: PropTypes.func, + lightArray: PropTypes.array, + onMouseEnterHandler: PropTypes.func, + onMouseLeaveHandler: PropTypes.func +}) + +export const TableCellSumShape = PropTypes.shape({ + id: PropTypes.number, + rowSum: PropTypes.number, + onMouseEnterPercent: PropTypes.func, + onMouseLeavePercent: PropTypes.func +}) + +export const TableRowShape = PropTypes.shape({ + id: PropTypes.number, + row: PropTypes.array, + cells: PropTypes.array, + rowSum: PropTypes.number, + lightArray: PropTypes.array, + onMouseEnterHandler: PropTypes.func, + onMouseLeaveHandler: PropTypes.func +}) + +export const AverageRowShape = PropTypes.shape({ + averageArray: PropTypes.array +}) + +export const FormShape = PropTypes.shape({ + setParamsData: PropTypes.func, + setTableData: PropTypes.func, + setRowsData: PropTypes.func, + setCellsData: PropTypes.func, + setShowButtonsBoll: PropTypes.func +}) + +export const ButtonsShape = PropTypes.shape({ + showButtons: PropTypes.bool, + rows: PropTypes.number, + columns: PropTypes.number, + table: PropTypes.array +}) + +export const ButtonDeleteShape = PropTypes.shape({ + deleteRow: PropTypes.func +}) + +export const ButtonAddShape = PropTypes.shape({ + addRow: PropTypes.func +}) diff --git a/src/index.css b/src/index.css index 293d3b1..2b1b240 100644 --- a/src/index.css +++ b/src/index.css @@ -1,3 +1,3 @@ body { - margin: 0; + margin: 10px; } diff --git a/src/index.js b/src/index.js deleted file mode 100644 index bd0ed77..0000000 --- a/src/index.js +++ /dev/null @@ -1,9 +0,0 @@ -import React from 'react'; -import ReactDOM from 'react-dom'; -import './index.css'; -import App from './App'; - -ReactDOM.render( - , - document.getElementById('root') -); diff --git a/src/index.jsx b/src/index.jsx new file mode 100644 index 0000000..0e07a58 --- /dev/null +++ b/src/index.jsx @@ -0,0 +1,15 @@ +import React from 'react' +import ReactDOM from 'react-dom' +import { Provider } from 'react-redux' +import store from './store/store' +import App from './App' + +import 'bootstrap/dist/css/bootstrap.css' +import './index.css' + +ReactDOM.render( + + + , + document.getElementById('root') +) diff --git a/src/store/actions.js b/src/store/actions.js new file mode 100644 index 0000000..6886ede --- /dev/null +++ b/src/store/actions.js @@ -0,0 +1,50 @@ +export const ACTION_TYPES = { + SET_PARAMS: 'SET::PARAMS', + SET_TABLE: 'SET::TABLE', + SET_ROWS: 'SET::ROWS', + SET_CELLS: 'SET::CELLS', + SHOW_BUTTONS: 'SHOW::BUTTONS', + INCREMENT: 'INCREMENT', + ADD_ROW: 'ADD_ROW', + REMOVE_ROW: 'REMOVE::ROW' +} + +export const setParams = params => ({ + payload: params, + type: ACTION_TYPES.SET_PARAMS +}) + +export const setTable = params => ({ + payload: params, + type: ACTION_TYPES.SET_TABLE +}) + +export const setRows = params => ({ + payload: params, + type: ACTION_TYPES.SET_ROWS +}) + +export const setCells = params => ({ + payload: params, + type: ACTION_TYPES.SET_CELLS +}) + +export const setShowButtons = params => ({ + payload: params, + type: ACTION_TYPES.SHOW_BUTTONS +}) + +export const increment = params => ({ + type: ACTION_TYPES.INCREMENT, + payload: params +}) + +export const setNewRow = params => ({ + type: ACTION_TYPES.ADD_ROW, + payload: params +}) + +export const removeRow = params => ({ + type: ACTION_TYPES.REMOVE_ROW, + payload: params +}) diff --git a/src/store/reducers.js b/src/store/reducers.js new file mode 100644 index 0000000..1885a30 --- /dev/null +++ b/src/store/reducers.js @@ -0,0 +1,84 @@ +import { combineReducers } from 'redux' +import { ACTION_TYPES } from './actions' + +const paramsReducer = (state = {}, action) => { + const { SET_PARAMS } = ACTION_TYPES + + switch (action.type) { + case SET_PARAMS: + return action.payload + default: + return state + } +} + +function tableReducer (state = [], action) { + const { SET_TABLE, ADD_ROW, REMOVE_ROW } = ACTION_TYPES + + switch (action.type) { + case SET_TABLE: + return action.payload + case ADD_ROW: + return [...state, action.payload.table] + case REMOVE_ROW: + return state.filter(id => id !== action.payload.lastIndex) + default: + return state + } +} + +const rowsReducer = (state = {}, action) => { + const { SET_ROWS, ADD_ROW, REMOVE_ROW } = ACTION_TYPES + + switch (action.type) { + case SET_ROWS: + return action.payload + case ADD_ROW: + return { ...state, ...action.payload.rows } + case REMOVE_ROW: + delete state[action.payload.lastIndex] + return state + default: + return state + } +} + +const cellsReducer = (state = {}, action) => { + const { SET_CELLS, INCREMENT, ADD_ROW } = ACTION_TYPES + + switch (action.type) { + case SET_CELLS: + return action.payload + case ADD_ROW: + return { ...state, ...action.payload.cells } + case INCREMENT: + return { + ...state, + [action.payload]: { + ...state[action.payload], + amount: state[action.payload].amount + 1 + } + } + default: + return state + } +} + +const buttonsReducer = (state = false, action) => { + const { SHOW_BUTTONS } = ACTION_TYPES + + switch (action.type) { + case SHOW_BUTTONS: + return action.payload + default: + return state + } +} + +export const rootReducer = combineReducers({ + params: paramsReducer, + table: tableReducer, + rows: rowsReducer, + cells: cellsReducer, + buttons: buttonsReducer +}) diff --git a/src/store/store.js b/src/store/store.js new file mode 100644 index 0000000..1e38b93 --- /dev/null +++ b/src/store/store.js @@ -0,0 +1,9 @@ +import { createStore } from 'redux' +import { rootReducer } from './reducers' + +const store = createStore( + rootReducer, + window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__() +) + +export default store