diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 0f5ba90b0..41e72a616 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -34,28 +34,28 @@ jobs: - name: Run tests and linter run: npm run lint && npm test - # Собираем приложение - - name: Build Application - run: npm run build - - # Публикуем приложение на Github Pages - - name: Deploy to Github Pages - uses: JamesIves/github-pages-deploy-action@4.2.1 - with: - branch: gh-pages - folder: dist - - # # Собираем Storybook - # - name: Build Storybook - # run: npm run build-storybook - # - # # Публикуем Storybook на Github Pages - # - name: Deploy Storybook to Github Pages - # uses: JamesIves/github-pages-deploy-action@4.2.1 - # with: - # branch: gh-pages - # folder: storybook-static - # commit-message: "Automatically publish Storybook" +# # Собираем приложение +# - name: Build Application +# run: npm run build +# +# # Публикуем приложение на Github Pages +# - name: Deploy to Github Pages +# uses: JamesIves/github-pages-deploy-action@4.2.1 +# with: +# branch: gh-pages +# folder: dist + + # Собираем Storybook + - name: Build Storybook + run: npm run build-storybook + + # Публикуем Storybook на Github Pages + - name: Deploy Storybook to Github Pages + uses: JamesIves/github-pages-deploy-action@4.2.1 + with: + branch: gh-pages + folder: storybook-static + commit-message: "Automatically publish Storybook" # Останавливаем выполнение строго при неудачных тестах - name: Fail on failed tests diff --git a/package-lock.json b/package-lock.json index 5b1dfa392..61f22618d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,8 +10,12 @@ "license": "MIT", "dependencies": { "clsx": "^1.2.1", + "i18next": "^24.2.2", + "i18next-browser-languagedetector": "^8.0.2", + "i18next-http-backend": "^3.0.1", "react": "^18.2.0", - "react-dom": "^18.2.0" + "react-dom": "^18.2.0", + "react-i18next": "^15.4.0" }, "devDependencies": { "@babel/core": "^7.22.1", @@ -2032,12 +2036,12 @@ "dev": true }, "node_modules/@babel/runtime": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.22.5.tgz", - "integrity": "sha512-ecjvYlnAaZ/KVneE/OdKYBYfgXV3Ptu6zQWmgEF7vwKhQnvVS6bjMD2XYgj+SNvQ1GfK/pjgokfPkC/2CO8CuA==", - "dev": true, + "version": "7.26.7", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.26.7.tgz", + "integrity": "sha512-AOPI3D+a8dXnja+iwsUqGRjr1BbZIe771sXdapOtYI531gSqpi92vXivKcq2asu/DFpdl1ceFAKZyRzK2PCVcQ==", + "license": "MIT", "dependencies": { - "regenerator-runtime": "^0.13.11" + "regenerator-runtime": "^0.14.0" }, "engines": { "node": ">=6.9.0" @@ -8954,13 +8958,6 @@ "node": ">=4" } }, - "node_modules/ast-types-flow": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.7.tgz", - "integrity": "sha512-eBvWn1lvIApYMhzQMsu9ciLfkBY499mFZlNqG+/9WR7PVlroQw0vG30cOQQbaKz3sCEc44TAOu2ykzqXSNnwag==", - "dev": true, - "peer": true - }, "node_modules/async": { "version": "3.2.5", "resolved": "https://registry.npmjs.org/async/-/async-3.2.5.tgz", @@ -8991,26 +8988,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/axe-core": { - "version": "4.7.2", - "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.7.2.tgz", - "integrity": "sha512-zIURGIS1E1Q4pcrMjp+nnEh+16G56eG/MUllJH8yEvw7asDo7Ac9uhC9KIH5jzpITueEZolfYglnCGIuSBz39g==", - "dev": true, - "peer": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/axobject-query": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-3.1.1.tgz", - "integrity": "sha512-goKlv8DZrK9hUh975fnHzhNIO4jUnFCfv/dszV5VwUGDFjI6vQ2VwoyjYjYNEbBE8AH87TduWP5uyDR1D+Iteg==", - "dev": true, - "peer": true, - "dependencies": { - "deep-equal": "^2.0.5" - } - }, "node_modules/babel-core": { "version": "7.0.0-bridge.0", "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-7.0.0-bridge.0.tgz", @@ -10201,19 +10178,6 @@ "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", "dev": true }, - "node_modules/copy-anything": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/copy-anything/-/copy-anything-2.0.6.tgz", - "integrity": "sha512-1j20GZTsvKNkc4BY3NpMOM8tt///wY3FpIzozTOFO2ffuZcV61nojHXVKIy3WM+7ADCy5FVhdZYHYDdgTU0yJw==", - "dev": true, - "peer": true, - "dependencies": { - "is-what": "^3.14.1" - }, - "funding": { - "url": "https://github.com/sponsors/mesqueeb" - } - }, "node_modules/core-js-compat": { "version": "3.33.1", "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.33.1.tgz", @@ -10260,6 +10224,15 @@ "node": ">=10" } }, + "node_modules/cross-fetch": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-4.0.0.tgz", + "integrity": "sha512-e4a5N8lVvuLgAWgnCrLr2PP0YyDOTHa9H/Rj54dirp61qXnNq46m82bRhNqIA5VccJtWBvPTFRV3TtvHUKPB1g==", + "license": "MIT", + "dependencies": { + "node-fetch": "^2.6.12" + } + }, "node_modules/cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", @@ -10412,13 +10385,6 @@ "integrity": "sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==", "dev": true }, - "node_modules/damerau-levenshtein": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", - "integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==", - "dev": true, - "peer": true - }, "node_modules/data-urls": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-3.0.2.tgz", @@ -11114,20 +11080,6 @@ "node": ">=4" } }, - "node_modules/errno": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.8.tgz", - "integrity": "sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==", - "dev": true, - "optional": true, - "peer": true, - "dependencies": { - "prr": "~1.0.1" - }, - "bin": { - "errno": "cli.js" - } - }, "node_modules/error-ex": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", @@ -11598,37 +11550,6 @@ } } }, - "node_modules/eslint-plugin-jsx-a11y": { - "version": "6.7.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.7.1.tgz", - "integrity": "sha512-63Bog4iIethyo8smBklORknVjB0T2dwB8Mr/hIC+fBS0uyHdYYpzM/Ed+YC8VxTjlXHEWFOdmgwcDn1U2L9VCA==", - "dev": true, - "peer": true, - "dependencies": { - "@babel/runtime": "^7.20.7", - "aria-query": "^5.1.3", - "array-includes": "^3.1.6", - "array.prototype.flatmap": "^1.3.1", - "ast-types-flow": "^0.0.7", - "axe-core": "^4.6.2", - "axobject-query": "^3.1.1", - "damerau-levenshtein": "^1.0.8", - "emoji-regex": "^9.2.2", - "has": "^1.0.3", - "jsx-ast-utils": "^3.3.3", - "language-tags": "=1.0.5", - "minimatch": "^3.1.2", - "object.entries": "^1.1.6", - "object.fromentries": "^2.0.6", - "semver": "^6.3.0" - }, - "engines": { - "node": ">=4.0" - }, - "peerDependencies": { - "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8" - } - }, "node_modules/eslint-plugin-prettier": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-4.2.1.tgz", @@ -13546,6 +13467,15 @@ "node": ">=12" } }, + "node_modules/html-parse-stringify": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/html-parse-stringify/-/html-parse-stringify-3.0.1.tgz", + "integrity": "sha512-KknJ50kTInJ7qIScF3jeaFRpMpE8/lfiTdzf/twXyPBLAGrLRTmkz3AdTnKeh40X8k9L2fdYwEp/42WGXIRGcg==", + "license": "MIT", + "dependencies": { + "void-elements": "3.1.0" + } + }, "node_modules/html-tags": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-3.3.1.tgz", @@ -13726,6 +13656,55 @@ "url": "https://github.com/sponsors/typicode" } }, + "node_modules/i18next": { + "version": "24.2.2", + "resolved": "https://registry.npmjs.org/i18next/-/i18next-24.2.2.tgz", + "integrity": "sha512-NE6i86lBCKRYZa5TaUDkU5S4HFgLIEJRLr3Whf2psgaxBleQ2LC1YW1Vc+SCgkAW7VEzndT6al6+CzegSUHcTQ==", + "funding": [ + { + "type": "individual", + "url": "https://locize.com" + }, + { + "type": "individual", + "url": "https://locize.com/i18next.html" + }, + { + "type": "individual", + "url": "https://www.i18next.com/how-to/faq#i18next-is-awesome.-how-can-i-support-the-project" + } + ], + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.23.2" + }, + "peerDependencies": { + "typescript": "^5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/i18next-browser-languagedetector": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/i18next-browser-languagedetector/-/i18next-browser-languagedetector-8.0.2.tgz", + "integrity": "sha512-shBvPmnIyZeD2VU5jVGIOWP7u9qNG3Lj7mpaiPFpbJ3LVfHZJvVzKR4v1Cb91wAOFpNw442N+LGPzHOHsten2g==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.23.2" + } + }, + "node_modules/i18next-http-backend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/i18next-http-backend/-/i18next-http-backend-3.0.2.tgz", + "integrity": "sha512-PdlvPnvIp4E1sYi46Ik4tBYh/v/NbYfFFgTjkwFl0is8A18s7/bx9aXqsrOax9WUbeNS6mD2oix7Z0yGGf6m5g==", + "license": "MIT", + "dependencies": { + "cross-fetch": "4.0.0" + } + }, "node_modules/iconv-lite": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", @@ -13779,20 +13758,6 @@ "node": ">= 4" } }, - "node_modules/image-size": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/image-size/-/image-size-0.5.5.tgz", - "integrity": "sha512-6TDAlDPZxUFCv+fuOkIoXT/V/f3Qbq8e37p+YOiYrUv3v9cc3/6x78VdfPgFVaB9dZYeLUfKgHRebpkm/oP2VQ==", - "dev": true, - "optional": true, - "peer": true, - "bin": { - "image-size": "bin/image-size.js" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/immutable": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.4.tgz", @@ -14484,13 +14449,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-what": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/is-what/-/is-what-3.14.1.tgz", - "integrity": "sha512-sNxgpk9793nzSs7bA6JQJGeIuRBQhAaNGG77kzYQgMkrID+lS6SlK07K5LaptscDlSaIgH+GPFzf+d75FVxozA==", - "dev": true, - "peer": true - }, "node_modules/is-wsl": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", @@ -16780,23 +16738,6 @@ "node": ">= 8" } }, - "node_modules/language-subtag-registry": { - "version": "0.3.22", - "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.22.tgz", - "integrity": "sha512-tN0MCzyWnoz/4nHS6uxdlFWoUZT7ABptwKPQ52Ea7URk6vll88bWBVhodtnlfEuCcKWNGoc+uGbw1cwa9IKh/w==", - "dev": true, - "peer": true - }, - "node_modules/language-tags": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/language-tags/-/language-tags-1.0.5.tgz", - "integrity": "sha512-qJhlO9cGXi6hBGKoxEG/sKZDAHD5Hnu9Hs4WbOY3pCWXDhw0N8x1NenNzm2EnNLkLkk7J2SdxAkDSbb6ftT+UQ==", - "dev": true, - "peer": true, - "dependencies": { - "language-subtag-registry": "~0.3.2" - } - }, "node_modules/launch-editor": { "version": "2.6.0", "resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.6.0.tgz", @@ -16821,33 +16762,6 @@ "node": ">=14.0.0" } }, - "node_modules/less": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/less/-/less-4.1.3.tgz", - "integrity": "sha512-w16Xk/Ta9Hhyei0Gpz9m7VS8F28nieJaL/VyShID7cYvP6IL5oHeL6p4TXSDJqZE/lNv0oJ2pGVjJsRkfwm5FA==", - "dev": true, - "peer": true, - "dependencies": { - "copy-anything": "^2.0.1", - "parse-node-version": "^1.0.1", - "tslib": "^2.3.0" - }, - "bin": { - "lessc": "bin/lessc" - }, - "engines": { - "node": ">=6" - }, - "optionalDependencies": { - "errno": "^0.1.1", - "graceful-fs": "^4.1.2", - "image-size": "~0.5.0", - "make-dir": "^2.1.0", - "mime": "^1.4.1", - "needle": "^3.1.0", - "source-map": "~0.6.0" - } - }, "node_modules/less-loader": { "version": "11.1.3", "resolved": "https://registry.npmjs.org/less-loader/-/less-loader-11.1.3.tgz", @@ -16865,43 +16779,6 @@ "webpack": "^5.0.0" } }, - "node_modules/less/node_modules/make-dir": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", - "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", - "dev": true, - "optional": true, - "peer": true, - "dependencies": { - "pify": "^4.0.1", - "semver": "^5.6.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/less/node_modules/semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "dev": true, - "optional": true, - "peer": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/less/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "optional": true, - "peer": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/leven": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", @@ -18391,50 +18268,6 @@ "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==", "dev": true }, - "node_modules/needle": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/needle/-/needle-3.2.0.tgz", - "integrity": "sha512-oUvzXnyLiVyVGoianLijF9O/RecZUf7TkBfimjGrLM4eQhXyeJwM6GeAWccwfQ9aa4gMCZKqhAOuLaMIcQxajQ==", - "dev": true, - "optional": true, - "peer": true, - "dependencies": { - "debug": "^3.2.6", - "iconv-lite": "^0.6.3", - "sax": "^1.2.4" - }, - "bin": { - "needle": "bin/needle" - }, - "engines": { - "node": ">= 4.4.x" - } - }, - "node_modules/needle/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "optional": true, - "peer": true, - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/needle/node_modules/iconv-lite": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", - "dev": true, - "optional": true, - "peer": true, - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/negotiator": { "version": "0.6.3", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", @@ -18482,7 +18315,6 @@ "version": "2.7.0", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", - "dev": true, "dependencies": { "whatwg-url": "^5.0.0" }, @@ -18507,20 +18339,17 @@ "node_modules/node-fetch/node_modules/tr46": { "version": "0.0.3", "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", - "dev": true + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" }, "node_modules/node-fetch/node_modules/webidl-conversions": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", - "dev": true + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" }, "node_modules/node-fetch/node_modules/whatwg-url": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", - "dev": true, "dependencies": { "tr46": "~0.0.3", "webidl-conversions": "^3.0.0" @@ -19143,16 +18972,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/parse-node-version": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parse-node-version/-/parse-node-version-1.0.1.tgz", - "integrity": "sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==", - "dev": true, - "peer": true, - "engines": { - "node": ">= 0.10" - } - }, "node_modules/parse5": { "version": "7.1.2", "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz", @@ -19633,14 +19452,6 @@ "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", "dev": true }, - "node_modules/prr": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", - "integrity": "sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw==", - "dev": true, - "optional": true, - "peer": true - }, "node_modules/psl": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", @@ -19941,6 +19752,28 @@ "integrity": "sha512-Fl7FuabXsJnV5Q1qIOQwx/sagGF18kogb4gpfcG4gjLBWO0WDiiz1ko/ExayuxE7InyQkBLkxRFG5oxY6Uu3Kg==", "dev": true }, + "node_modules/react-i18next": { + "version": "15.4.0", + "resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-15.4.0.tgz", + "integrity": "sha512-Py6UkX3zV08RTvL6ZANRoBh9sL/ne6rQq79XlkHEdd82cZr2H9usbWpUNVadJntIZP2pu3M2rL1CN+5rQYfYFw==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.25.0", + "html-parse-stringify": "^3.0.1" + }, + "peerDependencies": { + "i18next": ">= 23.2.3", + "react": ">= 16.8.0" + }, + "peerDependenciesMeta": { + "react-dom": { + "optional": true + }, + "react-native": { + "optional": true + } + } + }, "node_modules/react-is": { "version": "17.0.2", "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", @@ -20198,10 +20031,10 @@ } }, "node_modules/regenerator-runtime": { - "version": "0.13.11", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", - "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==", - "dev": true + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", + "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==", + "license": "MIT" }, "node_modules/regenerator-transform": { "version": "0.15.2", @@ -20623,14 +20456,6 @@ } } }, - "node_modules/sax": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", - "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", - "dev": true, - "optional": true, - "peer": true - }, "node_modules/saxes": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz", @@ -22703,6 +22528,15 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/void-elements": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-3.1.0.tgz", + "integrity": "sha512-Dhxzh5HZuiHQhbvTW9AMetFfBHDMYpo23Uo9btPXgdYP+3T5S+p+jgNy7spra+veYhBP2dCSgxR/i2Y02h5/6w==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/w3c-xmlserializer": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-4.0.0.tgz", @@ -23905,8 +23739,7 @@ "version": "7.21.0-placeholder-for-preset-env.2", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz", "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==", - "dev": true, - "requires": {} + "dev": true }, "@babel/plugin-syntax-async-generators": { "version": "7.8.4", @@ -24908,12 +24741,11 @@ "dev": true }, "@babel/runtime": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.22.5.tgz", - "integrity": "sha512-ecjvYlnAaZ/KVneE/OdKYBYfgXV3Ptu6zQWmgEF7vwKhQnvVS6bjMD2XYgj+SNvQ1GfK/pjgokfPkC/2CO8CuA==", - "dev": true, + "version": "7.26.7", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.26.7.tgz", + "integrity": "sha512-AOPI3D+a8dXnja+iwsUqGRjr1BbZIe771sXdapOtYI531gSqpi92vXivKcq2asu/DFpdl1ceFAKZyRzK2PCVcQ==", "requires": { - "regenerator-runtime": "^0.13.11" + "regenerator-runtime": "^0.14.0" } }, "@babel/template": { @@ -24985,8 +24817,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.0.1.tgz", "integrity": "sha512-jT/qyKZ9rzLErtrjGgdkMBn2OP8wl0G3sQlBb3YPryvKHsjvINUhVaPFfP+fpBcOkmrVOVEEHQFJ7nbj2TH2gw==", - "dev": true, - "requires": {} + "dev": true }, "@esbuild/android-arm": { "version": "0.18.20", @@ -28184,8 +28015,7 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/@storybook/preset-scss/-/preset-scss-1.0.3.tgz", "integrity": "sha512-o9Iz6wxPeNENrQa2mKlsDKynBfqU2uWaRP80HeWp4TkGgf7/x3DVF2O7yi9N0x/PI1qzzTTpxlQ90D62XmpiTw==", - "dev": true, - "requires": {} + "dev": true }, "@storybook/preview": { "version": "7.6.17", @@ -28341,8 +28171,7 @@ "version": "7.6.17", "resolved": "https://registry.npmjs.org/@storybook/react-dom-shim/-/react-dom-shim-7.6.17.tgz", "integrity": "sha512-32Sa/G+WnvaPiQ1Wvjjw5UM9rr2c4GDohwCcWVv3/LJuiFPqNS6zglAtmnsrlIBnUwRBMLMh/ekCTdqMiUmfDw==", - "dev": true, - "requires": {} + "dev": true }, "@storybook/react-webpack5": { "version": "7.6.17", @@ -29532,22 +29361,19 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-2.1.1.tgz", "integrity": "sha512-wy0mglZpDSiSS0XHrVR+BAdId2+yxPSoJW8fsna3ZpYSlufjvxnP4YbKTCBZnNIcGN4r6ZPXV55X4mYExOfLmw==", - "dev": true, - "requires": {} + "dev": true }, "@webpack-cli/info": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/@webpack-cli/info/-/info-2.0.2.tgz", "integrity": "sha512-zLHQdI/Qs1UyT5UBdWNqsARasIA+AaF8t+4u2aS2nEpBQh2mWIVb8qAklq0eUENnC5mOItrIB4LiS9xMtph18A==", - "dev": true, - "requires": {} + "dev": true }, "@webpack-cli/serve": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-2.0.5.tgz", "integrity": "sha512-lqaoKnRYBdo1UgDX8uF24AfGMifWK19TxPmM5FHc2vAGxrJ/qtyUyFBWoY1tISZdelsQ5fBcOusifo5o5wSJxQ==", - "dev": true, - "requires": {} + "dev": true }, "@xtuc/ieee754": { "version": "1.2.0", @@ -29656,8 +29482,7 @@ "version": "5.3.2", "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "dev": true, - "requires": {} + "dev": true }, "acorn-walk": { "version": "7.2.0", @@ -29735,8 +29560,7 @@ "version": "3.5.2", "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "dev": true, - "requires": {} + "dev": true }, "ansi-escapes": { "version": "4.3.2", @@ -29936,13 +29760,6 @@ "tslib": "^2.0.1" } }, - "ast-types-flow": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.7.tgz", - "integrity": "sha512-eBvWn1lvIApYMhzQMsu9ciLfkBY499mFZlNqG+/9WR7PVlroQw0vG30cOQQbaKz3sCEc44TAOu2ykzqXSNnwag==", - "dev": true, - "peer": true - }, "async": { "version": "3.2.5", "resolved": "https://registry.npmjs.org/async/-/async-3.2.5.tgz", @@ -29967,29 +29784,11 @@ "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", "dev": true }, - "axe-core": { - "version": "4.7.2", - "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.7.2.tgz", - "integrity": "sha512-zIURGIS1E1Q4pcrMjp+nnEh+16G56eG/MUllJH8yEvw7asDo7Ac9uhC9KIH5jzpITueEZolfYglnCGIuSBz39g==", - "dev": true, - "peer": true - }, - "axobject-query": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-3.1.1.tgz", - "integrity": "sha512-goKlv8DZrK9hUh975fnHzhNIO4jUnFCfv/dszV5VwUGDFjI6vQ2VwoyjYjYNEbBE8AH87TduWP5uyDR1D+Iteg==", - "dev": true, - "peer": true, - "requires": { - "deep-equal": "^2.0.5" - } - }, "babel-core": { "version": "7.0.0-bridge.0", "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-7.0.0-bridge.0.tgz", "integrity": "sha512-poPX9mZH/5CSanm50Q+1toVci6pv5KSRv/5TWCwtzQS5XEwn40BcCrgIeMFWP9CKKIniKXNxoIOnOq4VVlGXhg==", - "dev": true, - "requires": {} + "dev": true }, "babel-jest": { "version": "29.5.0", @@ -30879,16 +30678,6 @@ "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", "dev": true }, - "copy-anything": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/copy-anything/-/copy-anything-2.0.6.tgz", - "integrity": "sha512-1j20GZTsvKNkc4BY3NpMOM8tt///wY3FpIzozTOFO2ffuZcV61nojHXVKIy3WM+7ADCy5FVhdZYHYDdgTU0yJw==", - "dev": true, - "peer": true, - "requires": { - "is-what": "^3.14.1" - } - }, "core-js-compat": { "version": "3.33.1", "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.33.1.tgz", @@ -30923,6 +30712,14 @@ "yaml": "^1.10.0" } }, + "cross-fetch": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-4.0.0.tgz", + "integrity": "sha512-e4a5N8lVvuLgAWgnCrLr2PP0YyDOTHa9H/Rj54dirp61qXnNq46m82bRhNqIA5VccJtWBvPTFRV3TtvHUKPB1g==", + "requires": { + "node-fetch": "^2.6.12" + } + }, "cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", @@ -31036,13 +30833,6 @@ "integrity": "sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==", "dev": true }, - "damerau-levenshtein": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", - "integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==", - "dev": true, - "peer": true - }, "data-urls": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-3.0.2.tgz", @@ -31579,17 +31369,6 @@ "integrity": "sha512-/o+BXHmB7ocbHEAs6F2EnG0ogybVVUdkRunTT2glZU9XAaGmhqskrvKwqXuDfNjEO0LZKWdejEEpnq8aM0tOaw==", "dev": true }, - "errno": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.8.tgz", - "integrity": "sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==", - "dev": true, - "optional": true, - "peer": true, - "requires": { - "prr": "~1.0.1" - } - }, "error-ex": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", @@ -31958,8 +31737,7 @@ "version": "8.8.0", "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.8.0.tgz", "integrity": "sha512-wLbQiFre3tdGgpDv67NQKnJuTlcUVYHas3k+DZCc2U2BadthoEY4B7hLPvAxaqdyOGCzuLfii2fqGph10va7oA==", - "dev": true, - "requires": {} + "dev": true }, "eslint-import-resolver-node": { "version": "0.3.7", @@ -32055,31 +31833,6 @@ "@typescript-eslint/utils": "^5.10.0" } }, - "eslint-plugin-jsx-a11y": { - "version": "6.7.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.7.1.tgz", - "integrity": "sha512-63Bog4iIethyo8smBklORknVjB0T2dwB8Mr/hIC+fBS0uyHdYYpzM/Ed+YC8VxTjlXHEWFOdmgwcDn1U2L9VCA==", - "dev": true, - "peer": true, - "requires": { - "@babel/runtime": "^7.20.7", - "aria-query": "^5.1.3", - "array-includes": "^3.1.6", - "array.prototype.flatmap": "^1.3.1", - "ast-types-flow": "^0.0.7", - "axe-core": "^4.6.2", - "axobject-query": "^3.1.1", - "damerau-levenshtein": "^1.0.8", - "emoji-regex": "^9.2.2", - "has": "^1.0.3", - "jsx-ast-utils": "^3.3.3", - "language-tags": "=1.0.5", - "minimatch": "^3.1.2", - "object.entries": "^1.1.6", - "object.fromentries": "^2.0.6", - "semver": "^6.3.0" - } - }, "eslint-plugin-prettier": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-4.2.1.tgz", @@ -32138,8 +31891,7 @@ "version": "4.6.0", "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.0.tgz", "integrity": "sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g==", - "dev": true, - "requires": {} + "dev": true }, "eslint-plugin-storybook": { "version": "0.8.0", @@ -33415,6 +33167,14 @@ "terser": "^5.10.0" } }, + "html-parse-stringify": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/html-parse-stringify/-/html-parse-stringify-3.0.1.tgz", + "integrity": "sha512-KknJ50kTInJ7qIScF3jeaFRpMpE8/lfiTdzf/twXyPBLAGrLRTmkz3AdTnKeh40X8k9L2fdYwEp/42WGXIRGcg==", + "requires": { + "void-elements": "3.1.0" + } + }, "html-tags": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-3.3.1.tgz", @@ -33536,6 +33296,30 @@ "integrity": "sha512-+dQSyqPh4x1hlO1swXBiNb2HzTDN1I2IGLQx1GrBuiqFJfoMrnZWwVmatvSiO+Iz8fBUnf+lekwNo4c2LlXItg==", "dev": true }, + "i18next": { + "version": "24.2.2", + "resolved": "https://registry.npmjs.org/i18next/-/i18next-24.2.2.tgz", + "integrity": "sha512-NE6i86lBCKRYZa5TaUDkU5S4HFgLIEJRLr3Whf2psgaxBleQ2LC1YW1Vc+SCgkAW7VEzndT6al6+CzegSUHcTQ==", + "requires": { + "@babel/runtime": "^7.23.2" + } + }, + "i18next-browser-languagedetector": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/i18next-browser-languagedetector/-/i18next-browser-languagedetector-8.0.2.tgz", + "integrity": "sha512-shBvPmnIyZeD2VU5jVGIOWP7u9qNG3Lj7mpaiPFpbJ3LVfHZJvVzKR4v1Cb91wAOFpNw442N+LGPzHOHsten2g==", + "requires": { + "@babel/runtime": "^7.23.2" + } + }, + "i18next-http-backend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/i18next-http-backend/-/i18next-http-backend-3.0.2.tgz", + "integrity": "sha512-PdlvPnvIp4E1sYi46Ik4tBYh/v/NbYfFFgTjkwFl0is8A18s7/bx9aXqsrOax9WUbeNS6mD2oix7Z0yGGf6m5g==", + "requires": { + "cross-fetch": "4.0.0" + } + }, "iconv-lite": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", @@ -33549,8 +33333,7 @@ "version": "5.1.0", "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==", - "dev": true, - "requires": {} + "dev": true }, "ieee754": { "version": "1.2.1", @@ -33564,14 +33347,6 @@ "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", "dev": true }, - "image-size": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/image-size/-/image-size-0.5.5.tgz", - "integrity": "sha512-6TDAlDPZxUFCv+fuOkIoXT/V/f3Qbq8e37p+YOiYrUv3v9cc3/6x78VdfPgFVaB9dZYeLUfKgHRebpkm/oP2VQ==", - "dev": true, - "optional": true, - "peer": true - }, "immutable": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.4.tgz", @@ -34037,13 +33812,6 @@ "get-intrinsic": "^1.1.1" } }, - "is-what": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/is-what/-/is-what-3.14.1.tgz", - "integrity": "sha512-sNxgpk9793nzSs7bA6JQJGeIuRBQhAaNGG77kzYQgMkrID+lS6SlK07K5LaptscDlSaIgH+GPFzf+d75FVxozA==", - "dev": true, - "peer": true - }, "is-wsl": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", @@ -34973,8 +34741,7 @@ "version": "1.2.3", "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", - "dev": true, - "requires": {} + "dev": true }, "jest-regex-util": { "version": "29.4.3", @@ -35729,23 +35496,6 @@ "integrity": "sha512-dhG34DXATL5hSxJbIexCft8FChFXtmskoZYnoPWjXQuebWYCNkVeV3KkGegCK9CP1oswI/vQibS2GY7Em/sJJA==", "dev": true }, - "language-subtag-registry": { - "version": "0.3.22", - "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.22.tgz", - "integrity": "sha512-tN0MCzyWnoz/4nHS6uxdlFWoUZT7ABptwKPQ52Ea7URk6vll88bWBVhodtnlfEuCcKWNGoc+uGbw1cwa9IKh/w==", - "dev": true, - "peer": true - }, - "language-tags": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/language-tags/-/language-tags-1.0.5.tgz", - "integrity": "sha512-qJhlO9cGXi6hBGKoxEG/sKZDAHD5Hnu9Hs4WbOY3pCWXDhw0N8x1NenNzm2EnNLkLkk7J2SdxAkDSbb6ftT+UQ==", - "dev": true, - "peer": true, - "requires": { - "language-subtag-registry": "~0.3.2" - } - }, "launch-editor": { "version": "2.6.0", "resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.6.0.tgz", @@ -35767,61 +35517,11 @@ "dotenv-expand": "^10.0.0" } }, - "less": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/less/-/less-4.1.3.tgz", - "integrity": "sha512-w16Xk/Ta9Hhyei0Gpz9m7VS8F28nieJaL/VyShID7cYvP6IL5oHeL6p4TXSDJqZE/lNv0oJ2pGVjJsRkfwm5FA==", - "dev": true, - "peer": true, - "requires": { - "copy-anything": "^2.0.1", - "errno": "^0.1.1", - "graceful-fs": "^4.1.2", - "image-size": "~0.5.0", - "make-dir": "^2.1.0", - "mime": "^1.4.1", - "needle": "^3.1.0", - "parse-node-version": "^1.0.1", - "source-map": "~0.6.0", - "tslib": "^2.3.0" - }, - "dependencies": { - "make-dir": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", - "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", - "dev": true, - "optional": true, - "peer": true, - "requires": { - "pify": "^4.0.1", - "semver": "^5.6.0" - } - }, - "semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "dev": true, - "optional": true, - "peer": true - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "optional": true, - "peer": true - } - } - }, "less-loader": { "version": "11.1.3", "resolved": "https://registry.npmjs.org/less-loader/-/less-loader-11.1.3.tgz", "integrity": "sha512-A5b7O8dH9xpxvkosNrP0dFp2i/dISOJa9WwGF3WJflfqIERE2ybxh1BFDj5CovC2+jCE4M354mk90hN6ziXlVw==", - "dev": true, - "requires": {} + "dev": true }, "leven": { "version": "3.1.0", @@ -36028,8 +35728,7 @@ "version": "7.4.1", "resolved": "https://registry.npmjs.org/markdown-to-jsx/-/markdown-to-jsx-7.4.1.tgz", "integrity": "sha512-GbrbkTnHp9u6+HqbPRFJbObi369AgJNXi/sGqq5HRsoZW063xR1XDCaConqq+whfEIAlzB1YPnOgsPc7B7bc/A==", - "dev": true, - "requires": {} + "dev": true }, "mdast-util-definitions": { "version": "4.0.0", @@ -36839,43 +36538,6 @@ "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==", "dev": true }, - "needle": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/needle/-/needle-3.2.0.tgz", - "integrity": "sha512-oUvzXnyLiVyVGoianLijF9O/RecZUf7TkBfimjGrLM4eQhXyeJwM6GeAWccwfQ9aa4gMCZKqhAOuLaMIcQxajQ==", - "dev": true, - "optional": true, - "peer": true, - "requires": { - "debug": "^3.2.6", - "iconv-lite": "^0.6.3", - "sax": "^1.2.4" - }, - "dependencies": { - "debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "optional": true, - "peer": true, - "requires": { - "ms": "^2.1.1" - } - }, - "iconv-lite": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", - "dev": true, - "optional": true, - "peer": true, - "requires": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - } - } - } - }, "negotiator": { "version": "0.6.3", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", @@ -36917,7 +36579,6 @@ "version": "2.7.0", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", - "dev": true, "requires": { "whatwg-url": "^5.0.0" }, @@ -36925,20 +36586,17 @@ "tr46": { "version": "0.0.3", "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", - "dev": true + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" }, "webidl-conversions": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", - "dev": true + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" }, "whatwg-url": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", - "dev": true, "requires": { "tr46": "~0.0.3", "webidl-conversions": "^3.0.0" @@ -37386,13 +37044,6 @@ "lines-and-columns": "^1.1.6" } }, - "parse-node-version": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parse-node-version/-/parse-node-version-1.0.1.tgz", - "integrity": "sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==", - "dev": true, - "peer": true - }, "parse5": { "version": "7.1.2", "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz", @@ -37579,8 +37230,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz", "integrity": "sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw==", - "dev": true, - "requires": {} + "dev": true }, "postcss-modules-local-by-default": { "version": "4.0.3", @@ -37746,14 +37396,6 @@ "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", "dev": true }, - "prr": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", - "integrity": "sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw==", - "dev": true, - "optional": true, - "peer": true - }, "psl": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", @@ -37922,8 +37564,7 @@ "version": "5.6.1", "resolved": "https://registry.npmjs.org/react-colorful/-/react-colorful-5.6.1.tgz", "integrity": "sha512-1exovf0uGTGyq5mXQT0zgQ80uvj2PCwvF8zY1RN9/vbJVSjSo3fsB/4L3ObbF7u70NduSiK4xu4Y6q1MHoUGEw==", - "dev": true, - "requires": {} + "dev": true }, "react-docgen": { "version": "7.0.3", @@ -37955,8 +37596,7 @@ "version": "2.2.2", "resolved": "https://registry.npmjs.org/react-docgen-typescript/-/react-docgen-typescript-2.2.2.tgz", "integrity": "sha512-tvg2ZtOpOi6QDwsb3GZhOjDkkX0h8Z2gipvTg6OVMUyoYoURhEiRNePT8NZItTVCDh39JJHnLdfCOkzoLbFnTg==", - "dev": true, - "requires": {} + "dev": true }, "react-dom": { "version": "18.2.0", @@ -37986,6 +37626,15 @@ } } }, + "react-i18next": { + "version": "15.4.0", + "resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-15.4.0.tgz", + "integrity": "sha512-Py6UkX3zV08RTvL6ZANRoBh9sL/ne6rQq79XlkHEdd82cZr2H9usbWpUNVadJntIZP2pu3M2rL1CN+5rQYfYFw==", + "requires": { + "@babel/runtime": "^7.25.0", + "html-parse-stringify": "^3.0.1" + } + }, "react-is": { "version": "17.0.2", "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", @@ -38165,10 +37814,9 @@ } }, "regenerator-runtime": { - "version": "0.13.11", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", - "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==", - "dev": true + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", + "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==" }, "regenerator-transform": { "version": "0.15.2", @@ -38447,14 +38095,6 @@ "neo-async": "^2.6.2" } }, - "sax": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", - "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", - "dev": true, - "optional": true, - "peer": true - }, "saxes": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz", @@ -39038,8 +38678,7 @@ "version": "3.3.3", "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-3.3.3.tgz", "integrity": "sha512-53BiGLXAcll9maCYtZi2RCQZKa8NQQai5C4horqKyRmHj9H7QmcUyucrH+4KW/gBQbXM2AsB0axoEcFZPlfPcw==", - "dev": true, - "requires": {} + "dev": true }, "supports-color": { "version": "5.5.0", @@ -40036,6 +39675,11 @@ "unist-util-stringify-position": "^3.0.0" } }, + "void-elements": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-3.1.0.tgz", + "integrity": "sha512-Dhxzh5HZuiHQhbvTW9AMetFfBHDMYpo23Uo9btPXgdYP+3T5S+p+jgNy7spra+veYhBP2dCSgxR/i2Y02h5/6w==" + }, "w3c-xmlserializer": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-4.0.0.tgz", @@ -40136,8 +39780,7 @@ "version": "1.9.0", "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz", "integrity": "sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA==", - "dev": true, - "requires": {} + "dev": true } } }, @@ -40563,8 +40206,7 @@ "version": "8.13.0", "resolved": "https://registry.npmjs.org/ws/-/ws-8.13.0.tgz", "integrity": "sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==", - "dev": true, - "requires": {} + "dev": true }, "xml-name-validator": { "version": "4.0.0", diff --git a/package.json b/package.json index 492664d1f..cc32dba63 100644 --- a/package.json +++ b/package.json @@ -65,7 +65,11 @@ }, "dependencies": { "clsx": "^1.2.1", + "i18next": "^24.2.2", + "i18next-browser-languagedetector": "^8.0.2", + "i18next-http-backend": "^3.0.1", "react": "^18.2.0", - "react-dom": "^18.2.0" + "react-dom": "^18.2.0", + "react-i18next": "^15.4.0" } } diff --git a/public/locales/en/translation.json b/public/locales/en/translation.json new file mode 100644 index 000000000..fa33a0175 --- /dev/null +++ b/public/locales/en/translation.json @@ -0,0 +1,13 @@ +{ + "Главная": "Home", + "Контакты": "Contacts", + "О сайте": "About", + "Язык": "Русский", + "Тема": "Theme", + "Доход": "Income", + "Сумма": "Sum", + "Дата": "Date", + "Категория": "Category", + "Описание": "Description", + "Редактировать": "Редактировать" +} \ No newline at end of file diff --git a/public/locales/ru/translation.json b/public/locales/ru/translation.json new file mode 100644 index 000000000..ee96dc2ff --- /dev/null +++ b/public/locales/ru/translation.json @@ -0,0 +1,13 @@ +{ + "Контакты": "Контакты", + "Главная": "Главная", + "О сайте": "О сайте", + "Язык": "English", + "Тема": "Тема", + "Доход": "Доход", + "Сумма": "Сумма", + "Дата": "Дата", + "Категория": "Категория", + "Описание": "Описание", + "Редактировать": "Редактировать" +} \ No newline at end of file diff --git a/src/app/App.tsx b/src/app/App.tsx index dcc0ff8ad..c96ed2ec9 100644 --- a/src/app/App.tsx +++ b/src/app/App.tsx @@ -1,18 +1,10 @@ import React from 'react'; -import logo from './logo.svg'; import './App.css'; +import './styles/index.scss'; +import { Layout } from 'src/shared/layout'; function App() { - return ( -
-
- logo -

- Текст писать тут -

-
-
- ); + return ; } export default App; diff --git a/src/app/index.css b/src/app/index.css index 4b326a5a4..f3631c3b4 100644 --- a/src/app/index.css +++ b/src/app/index.css @@ -11,3 +11,9 @@ code { font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', monospace; } + +*, *:before, *:after { + box-sizing: border-box; + margin: 0; + padding: 0; +} \ No newline at end of file diff --git a/src/app/providers/ThemProviders.tsx b/src/app/providers/ThemProviders.tsx new file mode 100644 index 000000000..bb2c67ca3 --- /dev/null +++ b/src/app/providers/ThemProviders.tsx @@ -0,0 +1,33 @@ +import React, { createContext, FC, ReactNode, useMemo, useState } from 'react'; + +export const enum Theme { + LIGHT = 'light', + DARK = 'dark', +} +export const THEME_CONTEXT = 'theme'; + +interface ThemeContextProps { + theme: Theme; + setChangeTheme: (theme: Theme) => void; +} + +type Props = { + children: ReactNode; +}; +export const ThemeContext = createContext(null); + +export const ThemeProvider: FC = ({ children }) => { + const [theme, setTheme] = useState((localStorage.getItem(THEME_CONTEXT) as Theme) ?? Theme.LIGHT); + const initTheme = useMemo( + () => ({ + theme, + setChangeTheme: (newTheme: Theme) => { + setTheme(newTheme); + localStorage.setItem(THEME_CONTEXT, newTheme); + }, + }), + [theme] + ); + + return {children}; +}; diff --git a/src/app/styles/index.scss b/src/app/styles/index.scss new file mode 100644 index 000000000..30a4fc734 --- /dev/null +++ b/src/app/styles/index.scss @@ -0,0 +1,5 @@ +*, *:before, *:after { + box-sizing: border-box; + margin: 0; + padding: 0; +} diff --git a/src/index.html b/src/index.html index c8a8e9634..12ac5f617 100644 --- a/src/index.html +++ b/src/index.html @@ -5,7 +5,7 @@ - +
diff --git a/src/index.tsx b/src/index.tsx index 26d2b1437..b864bad67 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -2,10 +2,17 @@ import React from 'react'; import ReactDOM from 'react-dom/client'; import './app/index.css'; import App from './app/App'; +import i18n from './shared/config/i18/i18n'; +import { I18nextProvider } from 'react-i18next'; +import { ThemeProvider } from 'src/app/providers/ThemProviders'; const root = ReactDOM.createRoot(document.getElementById('root') as HTMLElement); root.render( - + + + + + ); diff --git a/src/shared/LangSwitcher/LangSwitcher.tsx b/src/shared/LangSwitcher/LangSwitcher.tsx new file mode 100644 index 000000000..97f7c6b07 --- /dev/null +++ b/src/shared/LangSwitcher/LangSwitcher.tsx @@ -0,0 +1,18 @@ +import React, { FC } from 'react'; +import { Button } from '../btn'; +import cn from 'clsx'; +import { useTranslation } from 'react-i18next'; + +type LangSwitcherProps = { + className?: string; +}; + +export const LangSwitcher: FC = ({ className }) => { + const { t, i18n } = useTranslation(); + const toggle = () => i18n.changeLanguage(i18n.language === 'ru' ? 'en' : 'ru'); + return ( + + ); +}; diff --git a/src/shared/ThemeSwitcher/ThemeSwitcher.tsx b/src/shared/ThemeSwitcher/ThemeSwitcher.tsx new file mode 100644 index 000000000..51a23a10c --- /dev/null +++ b/src/shared/ThemeSwitcher/ThemeSwitcher.tsx @@ -0,0 +1,23 @@ +import React, { FC, useContext } from 'react'; +import { Theme, ThemeContext } from '../../app/providers/ThemProviders' +import cls from './themeSwitcher.module.scss'; +import cn from 'clsx'; +import { Button } from '../btn'; +import { useTranslation } from 'react-i18next'; + +type ThemSwitcherProps = { + className?: string; +}; + +export const ThemeSwitcher: FC = ({ className }) => { + const { theme, setChangeTheme } = useContext(ThemeContext); + const {t} = useTranslation() + return ( + + ); +}; diff --git a/src/shared/ThemeSwitcher/themeSwitcher.module.scss b/src/shared/ThemeSwitcher/themeSwitcher.module.scss new file mode 100644 index 000000000..2c3f2d2ba --- /dev/null +++ b/src/shared/ThemeSwitcher/themeSwitcher.module.scss @@ -0,0 +1,17 @@ +.switchLight { + padding: 5px 10px; + border: none; + outline: none; + border-radius: 5px; + background-color: #FF4785; + color: #fff; +} + +.switchDark { + padding: 5px 10px; + border: none; + outline: none; + border-radius: 5px; + background-color: #FF4785; + color: #282c34; +} \ No newline at end of file diff --git a/src/shared/btn/index.ts b/src/shared/btn/index.ts new file mode 100644 index 000000000..e4bba610d --- /dev/null +++ b/src/shared/btn/index.ts @@ -0,0 +1 @@ +export { Button } from './ui/Button'; diff --git a/src/shared/btn/ui/Button.tsx b/src/shared/btn/ui/Button.tsx new file mode 100644 index 000000000..a9f5c7c15 --- /dev/null +++ b/src/shared/btn/ui/Button.tsx @@ -0,0 +1,16 @@ +import React, { ButtonHTMLAttributes, FC, ReactNode } from 'react'; +import cls from './button.module.scss'; +import cn from 'clsx'; + +type Props = { + className?: string; + children: ReactNode; +} & ButtonHTMLAttributes; + +export const Button: FC = ({ className, children, ...rest }) => { + return ( + + ); +}; diff --git a/src/shared/btn/ui/button.module.scss b/src/shared/btn/ui/button.module.scss new file mode 100644 index 000000000..daba55c68 --- /dev/null +++ b/src/shared/btn/ui/button.module.scss @@ -0,0 +1,3 @@ +.button { + min-width: 10px; +} \ No newline at end of file diff --git a/src/shared/config/i18/i18n.ts b/src/shared/config/i18/i18n.ts new file mode 100644 index 000000000..ac31d1f96 --- /dev/null +++ b/src/shared/config/i18/i18n.ts @@ -0,0 +1,20 @@ +import i18n from 'i18next'; +import { initReactI18next } from 'react-i18next'; + +import Backend from 'i18next-http-backend'; + +i18n + .use(Backend) + .use(initReactI18next) + .init({ + lng: 'ru', + fallbackLng: 'en', + backend: { + loadPath: '/locales/{{lng}}/{{ns}}.json', + }, + interpolation: { + escapeValue: false, + }, + }); + +export default i18n; diff --git a/src/shared/fullDisplay/ui/FullDisplay.stories.ts b/src/shared/fullDisplay/ui/FullDisplay.stories.ts new file mode 100644 index 000000000..7591a1a71 --- /dev/null +++ b/src/shared/fullDisplay/ui/FullDisplay.stories.ts @@ -0,0 +1,22 @@ +import { Meta, StoryObj } from '@storybook/react'; +import { FullDisplay } from './FullDisplay'; + +const meta: Meta = { + title: 'компоненты/Full Display', + component: FullDisplay, +}; + +export default meta; + +type Story = StoryObj; + +export const FullDisplayStory: Story = { + args: { + date: new Date(), + categoryName: 'Продукты', + name: 'молоко', + sumOperations: 200, + description: + 'Молоко — ценный пищевой продукт, содержащий более 100 питательных веществ, включая белки, жир, молочный сахар, минеральные вещества, фосфолипиды, органические кислоты, витамины, ферменты.', + }, +}; diff --git a/src/shared/fullDisplay/ui/FullDisplay.tsx b/src/shared/fullDisplay/ui/FullDisplay.tsx new file mode 100644 index 000000000..950552f3c --- /dev/null +++ b/src/shared/fullDisplay/ui/FullDisplay.tsx @@ -0,0 +1,37 @@ +import React, { FC, useContext } from 'react'; +import cls from './fullDisplay.module.scss'; +import cn from 'clsx'; +import { Theme, ThemeContext } from '../../../app/providers/ThemProviders'; +import { useTranslation } from 'react-i18next'; + +type FullDisplayProps = { + className?: string; + name: string; + sumOperations: number; + categoryName: string; + description: string; + date: Date; +}; + +export const FullDisplay: FC = ({ className, sumOperations, categoryName, description, date }) => { + const { theme } = useContext(ThemeContext); + const { t } = useTranslation(); + return ( +
+

{t('Доход')}

+

+ {t('Дата')}: {date.toLocaleDateString()} +

+

+ {t('Сумма')}: {sumOperations} +

+

+ {t('Категория')}: {categoryName} +

+

+ {t('Описание')} : {`${description}`} +

+ +
+ ); +}; diff --git a/src/shared/fullDisplay/ui/fullDisplay.module.scss b/src/shared/fullDisplay/ui/fullDisplay.module.scss new file mode 100644 index 000000000..4526a9659 --- /dev/null +++ b/src/shared/fullDisplay/ui/fullDisplay.module.scss @@ -0,0 +1,32 @@ +.displayLight { + display: flex; + flex-direction: column; + align-items: center; + border: 1px solid black; + padding: 10px; + border-radius: 10px; + max-width: 500px; + margin: 0 auto; +} +.displayDark { + display: flex; + flex-direction: column; + align-items: center; + border: 1px solid #fff; + padding: 10px; + border-radius: 10px; + max-width: 500px; + margin: 0 auto; + color: #fff; +} +.title{ + text-transform: uppercase; + padding: 0 10px 10px; +} + +.description { + max-width: 100%; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} \ No newline at end of file diff --git a/src/shared/header/ui/Header.tsx b/src/shared/header/ui/Header.tsx new file mode 100644 index 000000000..1b4d0f0fb --- /dev/null +++ b/src/shared/header/ui/Header.tsx @@ -0,0 +1,35 @@ +import React, { FC, useContext } from 'react'; +import cls from './header.module.scss'; +import cn from 'clsx'; +import { Logo } from '../../logo'; +import { Theme, ThemeContext } from '../../../app/providers/ThemProviders'; +import { ThemeSwitcher } from '../../ThemeSwitcher/ThemeSwitcher'; +import { LangSwitcher } from '../../LangSwitcher/LangSwitcher'; +import { useTranslation } from 'react-i18next'; + +type HeaderProps = { + className?: string; +}; + +export const Header: FC = ({ className }) => { + const { theme } = useContext(ThemeContext); + const {t} = useTranslation() + return ( +
+ + + + +
+ ); +}; diff --git a/src/shared/header/ui/Heder.stories.tsx b/src/shared/header/ui/Heder.stories.tsx new file mode 100644 index 000000000..852941740 --- /dev/null +++ b/src/shared/header/ui/Heder.stories.tsx @@ -0,0 +1,24 @@ +import { Meta, StoryObj } from '@storybook/react'; +import { Header } from './Header'; +import { ThemeProvider } from '../../../app/providers/ThemProviders'; +import React, { JSX } from 'react'; + +const meta: Meta = { + title: 'компоненты/Header', + component: Header, +}; + +export default meta; + +type Story = StoryObj; + +const Template = (args: JSX.IntrinsicAttributes & { className?: string }) => ( + +
+ +); + +export const HeaderStory: Story = { + render: Template, // Используем шаблон для рендеринга + args: {}, +}; diff --git a/src/shared/header/ui/header.module.scss b/src/shared/header/ui/header.module.scss new file mode 100644 index 000000000..7a010ae6b --- /dev/null +++ b/src/shared/header/ui/header.module.scss @@ -0,0 +1,43 @@ +.headerLight{ + position: sticky; + top: 0; + padding: 10px; + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 10px; + background-color: #282c34; +} + +.headerDark{ + position: sticky; + top: 0; + padding: 10px; + display: flex; + justify-content: space-between; + align-items: center; + background-color: #fff; +} + + +.nav { + display: flex; + justify-content: space-between; + align-items: center; + column-gap: 20px; +} +.navLinkLight{ + text-decoration: none; + text-wrap: nowrap; + color: #fff; + padding: 5px 10px; + border: 1px solid currentColor; +} + +.navLinkDark{ + text-decoration: none; + text-wrap: nowrap; + padding: 5px 10px; + color: #282c34; + border: 1px solid currentColor; +} \ No newline at end of file diff --git a/src/shared/input/Input.tsx b/src/shared/input/Input.tsx new file mode 100644 index 000000000..12b293e1a --- /dev/null +++ b/src/shared/input/Input.tsx @@ -0,0 +1,11 @@ +import React, { FC, InputHTMLAttributes } from 'react'; +import cls from './input.module.scss'; +import cn from 'clsx'; + +type InputProps = { + className?: string; +} & InputHTMLAttributes; + +export const Input: FC = ({ className, ...rest }) => { + return ; +}; diff --git a/src/shared/input/input.module.scss b/src/shared/input/input.module.scss new file mode 100644 index 000000000..effbede75 --- /dev/null +++ b/src/shared/input/input.module.scss @@ -0,0 +1,3 @@ +.input { + +} \ No newline at end of file diff --git a/src/shared/layout/index.ts b/src/shared/layout/index.ts new file mode 100644 index 000000000..7bec5084b --- /dev/null +++ b/src/shared/layout/index.ts @@ -0,0 +1 @@ +export { Layout } from './ui/Layout'; diff --git a/src/shared/layout/ui/Layout.stories.tsx b/src/shared/layout/ui/Layout.stories.tsx new file mode 100644 index 000000000..fd2f1e23d --- /dev/null +++ b/src/shared/layout/ui/Layout.stories.tsx @@ -0,0 +1,27 @@ +import { Meta, StoryObj } from '@storybook/react'; +import { Layout } from './Layout'; +import React, { JSX } from 'react'; +import { ThemeProvider } from '../../../app/providers/ThemProviders'; +import { I18nextProvider } from 'react-i18next'; +import i18n from '../../config/i18/i18n'; + +const meta: Meta = { + title: 'компоненты/Layout', + component: Layout, +}; + +export default meta; + +type Story = StoryObj; + +const Template = (args: JSX.IntrinsicAttributes & { className?: string }) => ( + + + + + +); +export const LayoutStory: Story = { + render: Template, + args: {}, +}; diff --git a/src/shared/layout/ui/Layout.tsx b/src/shared/layout/ui/Layout.tsx new file mode 100644 index 000000000..92e45b2c4 --- /dev/null +++ b/src/shared/layout/ui/Layout.tsx @@ -0,0 +1,25 @@ +import React, { useContext } from 'react'; +import { Modal } from '../../modal'; +import { Header } from '../../header/ui/Header'; +import { FullDisplay } from '../../fullDisplay/ui/FullDisplay'; +import { Theme, ThemeContext } from '../../../app/providers/ThemProviders'; +import cls from './layout.module.scss'; + +export const Layout = () => { + const { theme } = useContext(ThemeContext); + return ( +
+
+
+ +
+ +
+ ); +}; diff --git a/src/shared/layout/ui/layout.module.scss b/src/shared/layout/ui/layout.module.scss new file mode 100644 index 000000000..9d5d9eea8 --- /dev/null +++ b/src/shared/layout/ui/layout.module.scss @@ -0,0 +1,12 @@ +.containerLight { + width: 100%; + max-width: 1920px; + padding-block: 20px; + background: #fff; +} +.containerDark { + width: 100%; + max-width: 1920px; + padding-block: 20px; + background: #282c34; +} \ No newline at end of file diff --git a/src/shared/logo/index.ts b/src/shared/logo/index.ts new file mode 100644 index 000000000..020f5979c --- /dev/null +++ b/src/shared/logo/index.ts @@ -0,0 +1 @@ +export { Logo } from './ui/Logo'; diff --git a/src/shared/logo/ui/Logo.stories.ts b/src/shared/logo/ui/Logo.stories.ts new file mode 100644 index 000000000..ab6140247 --- /dev/null +++ b/src/shared/logo/ui/Logo.stories.ts @@ -0,0 +1,17 @@ +import { Meta, StoryObj } from '@storybook/react'; +import { Logo } from './Logo'; + +const meta: Meta = { + title: 'компоненты/Logo', + component: Logo, +}; + +export default meta; + +type Story = StoryObj; + +export const LogoStory: Story = { + args: { + className: 'logo', + }, +}; diff --git a/src/shared/logo/ui/Logo.tsx b/src/shared/logo/ui/Logo.tsx new file mode 100644 index 000000000..d87802597 --- /dev/null +++ b/src/shared/logo/ui/Logo.tsx @@ -0,0 +1,15 @@ +import React, { FC } from 'react'; +import cls from './logo.module.scss'; +import cn from 'clsx'; + +type LogoProps = { + className?: string; +}; + +export const Logo: FC = ({ className }) => { + return ( +
+ logo +
+ ); +}; diff --git a/src/shared/logo/ui/logo.module.scss b/src/shared/logo/ui/logo.module.scss new file mode 100644 index 000000000..bff543329 --- /dev/null +++ b/src/shared/logo/ui/logo.module.scss @@ -0,0 +1,12 @@ +.logo { + width: 30px; + height: 30px; +} + +.image{ + display: block; + width: 100%; + height: 100%; + object-fit: cover; + object-position: center; +} \ No newline at end of file diff --git a/src/shared/modal/index.ts b/src/shared/modal/index.ts new file mode 100644 index 000000000..6f4d22818 --- /dev/null +++ b/src/shared/modal/index.ts @@ -0,0 +1 @@ +export { Modal } from './ui/Modal'; diff --git a/src/shared/modal/ui/Modal.stories.ts b/src/shared/modal/ui/Modal.stories.ts new file mode 100644 index 000000000..24155c887 --- /dev/null +++ b/src/shared/modal/ui/Modal.stories.ts @@ -0,0 +1,17 @@ +import { Modal } from './Modal'; +import { Meta, StoryObj } from '@storybook/react'; + +const meta: Meta = { + title: 'компоненты/Modal', + component: Modal, +}; + +export default meta; + +type Story = StoryObj; +export const Visible: Story = { + args: { + visible: true, + children: 'Modal', + }, +}; diff --git a/src/shared/modal/ui/Modal.tsx b/src/shared/modal/ui/Modal.tsx new file mode 100644 index 000000000..c0749464a --- /dev/null +++ b/src/shared/modal/ui/Modal.tsx @@ -0,0 +1,23 @@ +import React, { FC } from 'react'; +import cls from './modal.module.scss'; + +type ModalProps = { + visible: boolean; + onClose?: () => void; + children?: React.ReactNode; +}; + +export const Modal: FC = ({ visible, children, onClose }) => { + return ( +
+
+ {children} +
+ +
+
+
+ ); +}; diff --git a/src/shared/modal/ui/modal.module.scss b/src/shared/modal/ui/modal.module.scss new file mode 100644 index 000000000..fddaff794 --- /dev/null +++ b/src/shared/modal/ui/modal.module.scss @@ -0,0 +1,36 @@ +.root{ + display: flex; + align-items: center; + justify-content: center; + position: absolute; + inset: 0; + background-color: rgba(0,0,0,0.7); +} + +.modal{ + width: 600px; + height: 400px; + background-color: #fff; + display: flex; + flex-direction: column; + justify-content: flex-end; +} +.none { + display: none; +} + +.box{ + display: flex; + justify-content: flex-end; +} +.button { + cursor: pointer; + padding: 7px 15px; + margin: 5px; + border: none; + font-size:12px; + outline: none; + background-color: #3a3ad3; + color: #fff; + border-radius: 3px; +} \ No newline at end of file diff --git a/src/shared/operationDisplay/index.ts b/src/shared/operationDisplay/index.ts new file mode 100644 index 000000000..e69de29bb diff --git a/src/shared/operationDisplay/ui/OperationDisplay.stories.ts b/src/shared/operationDisplay/ui/OperationDisplay.stories.ts new file mode 100644 index 000000000..3e25679b9 --- /dev/null +++ b/src/shared/operationDisplay/ui/OperationDisplay.stories.ts @@ -0,0 +1,21 @@ +import { Meta, StoryObj } from '@storybook/react'; +import { OperationDisplay } from './OperationDisplay'; + +const meta: Meta = { + title: 'компоненты/OperationDisplay', + component: OperationDisplay, +}; + +export default meta; + +type Story = StoryObj; + +export const OperationDisplayStory: Story = { + args: { + categoryName: 'Продукты', + name: 'молоко', + sumOperations: 200, + description: + 'Молоко — ценный пищевой продукт, содержащий более 100 питательных веществ, включая белки, жир, молочный сахар, минеральные вещества, фосфолипиды, органические кислоты, витамины, ферменты.', + }, +}; diff --git a/src/shared/operationDisplay/ui/OperationDisplay.tsx b/src/shared/operationDisplay/ui/OperationDisplay.tsx new file mode 100644 index 000000000..824b7b761 --- /dev/null +++ b/src/shared/operationDisplay/ui/OperationDisplay.tsx @@ -0,0 +1,28 @@ +import React, { FC } from 'react'; +import cls from './operationDisplay.module.scss'; +import cn from 'clsx'; + +type OperationDisplayProps = { + className?: string; + name: string; + sumOperations: number; + categoryName: string; + description: string; +}; + +export const OperationDisplay: FC = ({ + className, + sumOperations, + categoryName, + description, + name, +}) => { + return ( +
+

{name}

+

Sum: {sumOperations}

+

category: {categoryName}

+

{`description: ${description}`}

+
+ ); +}; diff --git a/src/shared/operationDisplay/ui/operationDisplay.module.scss b/src/shared/operationDisplay/ui/operationDisplay.module.scss new file mode 100644 index 000000000..c394ed80d --- /dev/null +++ b/src/shared/operationDisplay/ui/operationDisplay.module.scss @@ -0,0 +1,22 @@ +.operation { + display: flex; + flex-direction: column; + align-items: center; + border: 1px solid black; + padding: 10px; + border-radius: 10px; + max-width: 500px; + margin: 0 auto; +} + +.title{ + text-transform: uppercase; + padding: 0 10px 10px; +} + +.description { + max-width: 100%; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} \ No newline at end of file diff --git a/src/shared/place/Place.stories.ts b/src/shared/place/Place.stories.ts new file mode 100644 index 000000000..215c6b93a --- /dev/null +++ b/src/shared/place/Place.stories.ts @@ -0,0 +1,14 @@ +import { Place } from './Place'; +import { Meta, StoryObj } from '@storybook/react'; + +const meta: Meta = { + title: 'компоненты/Place', + component: Place, +}; + +export default meta; + +type Story = StoryObj; +export const PlaceStory: Story = { + args: {}, +}; diff --git a/src/shared/place/Place.tsx b/src/shared/place/Place.tsx new file mode 100644 index 000000000..260fdfde8 --- /dev/null +++ b/src/shared/place/Place.tsx @@ -0,0 +1,26 @@ +import React, { FC, useState } from 'react'; +import cn from 'clsx'; +import cls from './place.module.scss'; +import { Button } from '../btn'; +import { Input } from '../input/Input'; +import { Modal } from '../modal'; + +type Props = { + className?: string; +}; + +export const Place: FC = ({ className }) => { + const [open, setOpen] = useState(false); + const [text, setText] = useState(''); + return ( +
+ setText(e.target.value)} /> + + setOpen(false)}> + {text} + +
+ ); +}; diff --git a/src/shared/place/place.module.scss b/src/shared/place/place.module.scss new file mode 100644 index 000000000..9b9548294 --- /dev/null +++ b/src/shared/place/place.module.scss @@ -0,0 +1,3 @@ +.place { + width: 100%; +} \ No newline at end of file diff --git a/webpack.config.js b/webpack.config.js index 583dfd1ed..94cc55c4d 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -19,6 +19,9 @@ module.exports = (_, args) => { hot: true, historyApiFallback: true, host, + static: { + directory: path.join(__dirname, 'public'), + }, }, resolve: { modules: [src, 'node_modules'],