diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 0f5ba90b0..d669d1934 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -45,19 +45,19 @@ jobs: 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" + # # Собираем 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 run: | - if [ ${{ job.status }} == 'failure' ]; then exit 1; fi; + if [ ${{ job.status }} == 'failure' ]; then exit 1; fi; \ No newline at end of file diff --git a/.storybook/decorators/StoreDecorator.tsx b/.storybook/decorators/StoreDecorator.tsx new file mode 100644 index 000000000..9a8dac81e --- /dev/null +++ b/.storybook/decorators/StoreDecorator.tsx @@ -0,0 +1,40 @@ +import React from 'react'; +import { useTranslation } from 'react-i18next'; +import { + defaultContext, + ELangVariables, + EThemeVariables, + IStoreContext, + StoreContext, +} from '../../src/app/StoreContext'; + +export default function StoreDecorator(Story: any) { + const [contextValue, setContextValue] = React.useState(defaultContext); + + const { theme, lang } = contextValue; + const { i18n } = useTranslation(); + + const themeSwitchHandler = (): void => { + if (theme === 'light') { + setContextValue({ ...contextValue, theme: EThemeVariables.DARK }); + } else { + setContextValue({ ...contextValue, theme: EThemeVariables.LIGHT }); + } + }; + + const langSwitchHandler = (): void => { + if (lang === 'ru') { + setContextValue({ ...contextValue, lang: ELangVariables.EN }); + i18n.changeLanguage('en-US'); + } else { + setContextValue({ ...contextValue, lang: ELangVariables.RU }); + i18n.changeLanguage('ru-RU'); + } + }; + + return ( + + + + ); +} diff --git a/.storybook/main.ts b/.storybook/main.ts index 3d1c9b2d5..8eca1d7ba 100644 --- a/.storybook/main.ts +++ b/.storybook/main.ts @@ -1,18 +1,19 @@ const config = { - stories: ["../src/**/*.mdx", "../src/**/*.stories.@(js|jsx|ts|tsx)"], + stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|ts|tsx)'], addons: [ - "@storybook/addon-links", - "@storybook/addon-essentials", - "@storybook/addon-interactions", - "@storybook/preset-scss", - "@storybook/addon-mdx-gfm" + '@storybook/addon-links', + '@storybook/addon-essentials', + '@storybook/addon-interactions', + '@storybook/preset-scss', + '@storybook/addon-mdx-gfm', + 'storybook-react-i18next', ], framework: { - name: "@storybook/react-webpack5", + name: '@storybook/react-webpack5', options: {}, }, docs: { - autodocs: "tag", + autodocs: 'tag', }, }; export default config; diff --git a/.storybook/preview.ts b/.storybook/preview.ts index 1c372b694..fb52148f4 100644 --- a/.storybook/preview.ts +++ b/.storybook/preview.ts @@ -1,14 +1,18 @@ -import type { Preview } from "@storybook/react"; +import type { Preview } from '@storybook/react'; +import i18n from '../src/app/i18n/config'; +import '!style-loader!css-loader!postcss-loader!tailwindcss/tailwind.css'; +import '!style-loader!css-loader!postcss-loader!../src/shared/RangeSlider/RangeSlider.css'; const preview: Preview = { parameters: { - actions: { argTypesRegex: "^on[A-Z].*" }, + actions: { argTypesRegex: '^on[A-Z].*' }, controls: { matchers: { color: /(background|color)$/i, date: /Date$/, }, }, + i18n, }, }; diff --git a/package-lock.json b/package-lock.json index 5b1dfa392..b8a26d092 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,17 +1,22 @@ { - "name": "react-start-template", + "name": "furtivite.github.io", "version": "1.0.0", "lockfileVersion": 2, "requires": true, "packages": { "": { - "name": "react-start-template", + "name": "furtivite.github.io", "version": "1.0.0", "license": "MIT", "dependencies": { + "autoprefixer": "^10.4.20", "clsx": "^1.2.1", + "nanoid": "^5.0.9", "react": "^18.2.0", - "react-dom": "^18.2.0" + "react-dom": "^18.2.0", + "react-hook-form": "^7.54.2", + "react-i18next": "^15.4.0", + "react-router": "^7.1.1" }, "devDependencies": { "@babel/core": "^7.22.1", @@ -46,17 +51,21 @@ "eslint-plugin-react-hooks": "^4.6.0", "eslint-plugin-storybook": "^0.8.0", "fork-ts-checker-webpack-plugin": "^8.0.0", + "gh-pages": "^6.2.0", "html-webpack-plugin": "^5.5.1", "husky": "^8.0.0", "jest": "^29.5.0", "jest-environment-jsdom": "^29.5.0", "less-loader": "^11.1.2", "mini-css-extract-plugin": "^2.7.6", + "postcss": "^8.4.49", + "postcss-loader": "^8.1.1", "prettier": "2.8.8", "sass": "^1.71.1", "sass-loader": "^13.3.1", "storybook": "^7.6.17", "style-loader": "^3.3.3", + "tailwindcss": "^3.4.17", "ts-jest": "^29.1.0", "typescript": "^5.1.3", "webpack": "^5.85.0", @@ -64,6 +73,19 @@ "webpack-dev-server": "^4.15.0" } }, + "node_modules/@alloc/quick-lru": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz", + "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/@ampproject/remapping": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz", @@ -2032,12 +2054,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.0", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.26.0.tgz", + "integrity": "sha512-FDSOghenHTiToteC/QRlv2q3DhPZ/oOXTBoirfWNx1Cx3TMVcGWQtMMmQcSvb/JjpNeGzx8Pq/b4fKEJuWm1sw==", + "license": "MIT", "dependencies": { - "regenerator-runtime": "^0.13.11" + "regenerator-runtime": "^0.14.0" }, "engines": { "node": ">=6.9.0" @@ -7520,6 +7542,12 @@ "@types/node": "*" } }, + "node_modules/@types/cookie": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.6.0.tgz", + "integrity": "sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==", + "license": "MIT" + }, "node_modules/@types/cross-spawn": { "version": "6.0.6", "resolved": "https://registry.npmjs.org/@types/cross-spawn/-/cross-spawn-6.0.6.tgz", @@ -8775,6 +8803,13 @@ "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", "dev": true }, + "node_modules/any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==", + "dev": true, + "license": "MIT" + }, "node_modules/anymatch": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", @@ -8794,6 +8829,13 @@ "integrity": "sha512-jlpIfsOoNoafl92Sz//64uQHGSyMrD2vYG5d8o2a4qGvyNCvXur7bzIsWtAC/6flI2RYAp3kv8rsfBtaLm7w0g==", "dev": true }, + "node_modules/arg": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", + "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==", + "dev": true, + "license": "MIT" + }, "node_modules/argparse": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", @@ -8979,6 +9021,43 @@ "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", "dev": true }, + "node_modules/autoprefixer": { + "version": "10.4.20", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.20.tgz", + "integrity": "sha512-XY25y5xSv/wEoqzDyXXME4AFfkZI0P23z6Fs3YgymDnKJkCGOnkL0iTxCa85UTqaSgfcqyf3UA6+c7wUvx/16g==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/autoprefixer" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "browserslist": "^4.23.3", + "caniuse-lite": "^1.0.30001646", + "fraction.js": "^4.3.7", + "normalize-range": "^0.1.2", + "picocolors": "^1.0.1", + "postcss-value-parser": "^4.2.0" + }, + "bin": { + "autoprefixer": "bin/autoprefixer" + }, + "engines": { + "node": "^10 || ^12 || >=14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, "node_modules/available-typed-arrays": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", @@ -9471,12 +9550,13 @@ } }, "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", "dev": true, + "license": "MIT", "dependencies": { - "fill-range": "^7.0.1" + "fill-range": "^7.1.1" }, "engines": { "node": ">=8" @@ -9498,10 +9578,9 @@ } }, "node_modules/browserslist": { - "version": "4.22.1", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.1.tgz", - "integrity": "sha512-FEVc202+2iuClEhZhrWy6ZiAcRLvNMyYcxZ8raemul1DYVOVdFsbqckWLdsixQZCpJlwe77Z3UTalE7jsjnKfQ==", - "dev": true, + "version": "4.24.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.3.tgz", + "integrity": "sha512-1CPmv8iobE2fyRMV97dAcMVegvvWKxmq94hkLiAkUGwKVTyDLw33K+ZxiFrREKmmps4rIw6grcCFCnTMSZ/YiA==", "funding": [ { "type": "opencollective", @@ -9516,11 +9595,12 @@ "url": "https://github.com/sponsors/ai" } ], + "license": "MIT", "dependencies": { - "caniuse-lite": "^1.0.30001541", - "electron-to-chromium": "^1.4.535", - "node-releases": "^2.0.13", - "update-browserslist-db": "^1.0.13" + "caniuse-lite": "^1.0.30001688", + "electron-to-chromium": "^1.5.73", + "node-releases": "^2.0.19", + "update-browserslist-db": "^1.1.1" }, "bin": { "browserslist": "cli.js" @@ -9639,11 +9719,20 @@ "node": ">=6" } }, - "node_modules/caniuse-lite": { - "version": "1.0.30001554", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001554.tgz", - "integrity": "sha512-A2E3U//MBwbJVzebddm1YfNp7Nud5Ip+IPn4BozBmn4KqVX7AvluoIDFWjsv5OkGnKUXQVmMSoMKLa3ScCblcQ==", + "node_modules/camelcase-css": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", + "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==", "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001690", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001690.tgz", + "integrity": "sha512-5ExiE3qQN6oF8Clf8ifIDcMRCRE/dMGcETG/XGMD8/XiXm6HXQgQTh1yZYLXXpSOsEUlJm1Xr7kGULZTuGtP/w==", "funding": [ { "type": "opencollective", @@ -9657,7 +9746,8 @@ "type": "github", "url": "https://github.com/sponsors/ai" } - ] + ], + "license": "CC-BY-4.0" }, "node_modules/case-sensitive-paths-webpack-plugin": { "version": "2.4.0", @@ -9712,16 +9802,11 @@ } }, "node_modules/chokidar": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", - "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ], + "license": "MIT", "dependencies": { "anymatch": "~3.1.2", "braces": "~3.0.2", @@ -9734,6 +9819,9 @@ "engines": { "node": ">= 8.10.0" }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, "optionalDependencies": { "fsevents": "~2.3.2" } @@ -10758,6 +10846,13 @@ "detect-port": "bin/detect-port.js" } }, + "node_modules/didyoumean": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", + "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==", + "dev": true, + "license": "Apache-2.0" + }, "node_modules/diff": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.0.tgz", @@ -10788,6 +10883,13 @@ "node": ">=8" } }, + "node_modules/dlv": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", + "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", + "dev": true, + "license": "MIT" + }, "node_modules/dns-equal": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/dns-equal/-/dns-equal-1.0.0.tgz", @@ -11016,10 +11118,17 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.4.567", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.567.tgz", - "integrity": "sha512-8KR114CAYQ4/r5EIEsOmOMqQ9j0MRbJZR3aXD/KFA8RuKzyoUB4XrUCg+l8RUGqTVQgKNIgTpjaG8YHRPAbX2w==", - "dev": true + "version": "1.5.76", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.76.tgz", + "integrity": "sha512-CjVQyG7n7Sr+eBXE86HIulnL5N8xZY1sgmOPGuq/F0Rr0FJq63lg0kEtOIDfZBk44FnDLf6FUJ+dsJcuiUDdDQ==", + "license": "ISC" + }, + "node_modules/email-addresses": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/email-addresses/-/email-addresses-5.0.0.tgz", + "integrity": "sha512-4OIPYlA6JXqtVn8zpHpGiI7vE6EQOAg16aGnDMIAlZVinnoZ8208tW1hAbjWydgN/4PLTT9q+O1K6AH/vALJGw==", + "dev": true, + "license": "MIT" }, "node_modules/emittery": { "version": "0.13.1", @@ -11102,6 +11211,16 @@ "url": "https://github.com/fb55/entities?sponsor=1" } }, + "node_modules/env-paths": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", + "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/envinfo": { "version": "7.8.1", "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.8.1.tgz", @@ -11316,10 +11435,10 @@ } }, "node_modules/escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", - "dev": true, + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "license": "MIT", "engines": { "node": ">=6" } @@ -12360,10 +12479,11 @@ "dev": true }, "node_modules/fast-glob": { - "version": "3.2.12", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz", - "integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==", + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", "dev": true, + "license": "MIT", "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", @@ -12511,11 +12631,40 @@ "node": ">=10" } }, + "node_modules/filename-reserved-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/filename-reserved-regex/-/filename-reserved-regex-2.0.0.tgz", + "integrity": "sha512-lc1bnsSr4L4Bdif8Xb/qrtokGbq5zlsms/CYH8PP+WtCkGNF65DPiQY8vG3SakEdRn8Dlnm+gW/qWKKjS5sZzQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/filenamify": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/filenamify/-/filenamify-4.3.0.tgz", + "integrity": "sha512-hcFKyUG57yWGAzu1CMt/dPzYZuv+jAJUT85bL8mrXvNe6hWj6yEHEc4EdcgiA6Z3oi1/9wXJdZPXF2dZNgwgOg==", + "dev": true, + "license": "MIT", + "dependencies": { + "filename-reserved-regex": "^2.0.0", + "strip-outer": "^1.0.1", + "trim-repeated": "^1.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", "dev": true, + "license": "MIT", "dependencies": { "to-regex-range": "^5.0.1" }, @@ -12923,6 +13072,19 @@ "node": ">= 0.6" } }, + "node_modules/fraction.js": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz", + "integrity": "sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==", + "license": "MIT", + "engines": { + "node": "*" + }, + "funding": { + "type": "patreon", + "url": "https://github.com/sponsors/rawify" + } + }, "node_modules/fresh": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", @@ -13009,10 +13171,14 @@ } }, "node_modules/function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, "node_modules/function.prototype.name": { "version": "1.1.5", @@ -13147,6 +13313,39 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/gh-pages": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/gh-pages/-/gh-pages-6.2.0.tgz", + "integrity": "sha512-HMXJ8th9u5wRXaZCnLcs/d3oVvCHiZkaP5KQExQljYGwJjQbSPyTdHe/Gc1IvYUR/rWiZLxNobIqfoMHKTKjHQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "async": "^3.2.4", + "commander": "^11.0.0", + "email-addresses": "^5.0.0", + "filenamify": "^4.3.0", + "find-cache-dir": "^3.3.1", + "fs-extra": "^11.1.1", + "globby": "^11.1.0" + }, + "bin": { + "gh-pages": "bin/gh-pages.js", + "gh-pages-clean": "bin/gh-pages-clean.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/gh-pages/node_modules/commander": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-11.1.0.tgz", + "integrity": "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=16" + } + }, "node_modules/giget": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/giget/-/giget-1.2.1.tgz", @@ -13438,6 +13637,19 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/he": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", @@ -13546,6 +13758,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 +13947,38 @@ "url": "https://github.com/sponsors/typicode" } }, + "node_modules/i18next": { + "version": "24.2.1", + "resolved": "https://registry.npmjs.org/i18next/-/i18next-24.2.1.tgz", + "integrity": "sha512-Q2wC1TjWcSikn1VAJg13UGIjc+okpFxQTxjVAymOnSA3RpttBQNMPf2ovcgoFVsV4QNxTfNZMAxorXZXsk4fBA==", + "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", + "peer": true, + "dependencies": { + "@babel/runtime": "^7.23.2" + }, + "peerDependencies": { + "typescript": "^5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, "node_modules/iconv-lite": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", @@ -14100,12 +14353,16 @@ } }, "node_modules/is-core-module": { - "version": "2.12.1", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.12.1.tgz", - "integrity": "sha512-Q4ZuBAe2FUsKtyQJoQHlvP8OvBERxO3jEmy1I7hcRXcJBGGHFh/aJBswbXuS9sgrDH2QUO8ilkwNPHvHMd8clg==", + "version": "2.16.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", + "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", "dev": true, + "license": "MIT", "dependencies": { - "has": "^1.0.3" + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -14261,6 +14518,7 @@ "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.12.0" } @@ -16509,6 +16767,16 @@ "url": "https://github.com/chalk/supports-color?sponsor=1" } }, + "node_modules/jiti": { + "version": "1.21.7", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.7.tgz", + "integrity": "sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==", + "dev": true, + "license": "MIT", + "bin": { + "jiti": "bin/jiti.js" + } + }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -16924,6 +17192,19 @@ "node": ">= 0.8.0" } }, + "node_modules/lilconfig": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz", + "integrity": "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antonk52" + } + }, "node_modules/lines-and-columns": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", @@ -18113,12 +18394,13 @@ ] }, "node_modules/micromatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", - "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", "dev": true, + "license": "MIT", "dependencies": { - "braces": "^3.0.2", + "braces": "^3.0.3", "picomatch": "^2.3.1" }, "engines": { @@ -18361,22 +18643,34 @@ "multicast-dns": "cli.js" } }, - "node_modules/nanoid": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz", - "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==", + "node_modules/mz": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", + "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", "dev": true, + "license": "MIT", + "dependencies": { + "any-promise": "^1.0.0", + "object-assign": "^4.0.1", + "thenify-all": "^1.0.0" + } + }, + "node_modules/nanoid": { + "version": "5.0.9", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-5.0.9.tgz", + "integrity": "sha512-Aooyr6MXU6HpvvWXKoVoXwKMs/KyVakWwg7xQfv5/S/RIgJMy0Ifa45H9qqYy7pTCszrHzP21Uk4PZq2HpEM8Q==", "funding": [ { "type": "github", "url": "https://github.com/sponsors/ai" } ], + "license": "MIT", "bin": { - "nanoid": "bin/nanoid.cjs" + "nanoid": "bin/nanoid.js" }, "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + "node": "^18 || >=20" } }, "node_modules/natural-compare": { @@ -18542,10 +18836,10 @@ "dev": true }, "node_modules/node-releases": { - "version": "2.0.13", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.13.tgz", - "integrity": "sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==", - "dev": true + "version": "2.0.19", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz", + "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==", + "license": "MIT" }, "node_modules/normalize-package-data": { "version": "2.5.0", @@ -18577,6 +18871,15 @@ "node": ">=0.10.0" } }, + "node_modules/normalize-range": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", + "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/npm-run-path": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", @@ -18768,6 +19071,16 @@ "node": ">=0.10.0" } }, + "node_modules/object-hash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", + "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, "node_modules/object-inspect": { "version": "1.12.3", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", @@ -19293,10 +19606,10 @@ "dev": true }, "node_modules/picocolors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", - "dev": true + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "license": "ISC" }, "node_modules/picomatch": { "version": "2.3.1", @@ -19374,10 +19687,9 @@ } }, "node_modules/postcss": { - "version": "8.4.31", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", - "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==", - "dev": true, + "version": "8.4.49", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.49.tgz", + "integrity": "sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==", "funding": [ { "type": "opencollective", @@ -19392,15 +19704,195 @@ "url": "https://github.com/sponsors/ai" } ], + "license": "MIT", "dependencies": { - "nanoid": "^3.3.6", - "picocolors": "^1.0.0", - "source-map-js": "^1.0.2" + "nanoid": "^3.3.7", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" }, "engines": { "node": "^10 || ^12 || >=14" } }, + "node_modules/postcss-import": { + "version": "15.1.0", + "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz", + "integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==", + "dev": true, + "license": "MIT", + "dependencies": { + "postcss-value-parser": "^4.0.0", + "read-cache": "^1.0.0", + "resolve": "^1.1.7" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "postcss": "^8.0.0" + } + }, + "node_modules/postcss-js": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.1.tgz", + "integrity": "sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==", + "dev": true, + "license": "MIT", + "dependencies": { + "camelcase-css": "^2.0.1" + }, + "engines": { + "node": "^12 || ^14 || >= 16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + "peerDependencies": { + "postcss": "^8.4.21" + } + }, + "node_modules/postcss-load-config": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-4.0.2.tgz", + "integrity": "sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "lilconfig": "^3.0.0", + "yaml": "^2.3.4" + }, + "engines": { + "node": ">= 14" + }, + "peerDependencies": { + "postcss": ">=8.0.9", + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "postcss": { + "optional": true + }, + "ts-node": { + "optional": true + } + } + }, + "node_modules/postcss-load-config/node_modules/yaml": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.6.1.tgz", + "integrity": "sha512-7r0XPzioN/Q9kXBro/XPnA6kznR73DHq+GXh5ON7ZozRO6aMjbmiBuKste2wslTFkC5d1dw0GooOCepZXJ2SAg==", + "dev": true, + "license": "ISC", + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/postcss-loader": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-8.1.1.tgz", + "integrity": "sha512-0IeqyAsG6tYiDRCYKQJLAmgQr47DX6N7sFSWvQxt6AcupX8DIdmykuk/o/tx0Lze3ErGHJEp5OSRxrelC6+NdQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "cosmiconfig": "^9.0.0", + "jiti": "^1.20.0", + "semver": "^7.5.4" + }, + "engines": { + "node": ">= 18.12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "@rspack/core": "0.x || 1.x", + "postcss": "^7.0.0 || ^8.0.1", + "webpack": "^5.0.0" + }, + "peerDependenciesMeta": { + "@rspack/core": { + "optional": true + }, + "webpack": { + "optional": true + } + } + }, + "node_modules/postcss-loader/node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true, + "license": "Python-2.0" + }, + "node_modules/postcss-loader/node_modules/cosmiconfig": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-9.0.0.tgz", + "integrity": "sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg==", + "dev": true, + "license": "MIT", + "dependencies": { + "env-paths": "^2.2.1", + "import-fresh": "^3.3.0", + "js-yaml": "^4.1.0", + "parse-json": "^5.2.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/d-fischer" + }, + "peerDependencies": { + "typescript": ">=4.9.5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/postcss-loader/node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/postcss-loader/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/postcss-modules-extract-imports": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz", @@ -19460,11 +19952,38 @@ "postcss": "^8.1.0" } }, + "node_modules/postcss-nested": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.2.0.tgz", + "integrity": "sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "postcss-selector-parser": "^6.1.1" + }, + "engines": { + "node": ">=12.0" + }, + "peerDependencies": { + "postcss": "^8.2.14" + } + }, "node_modules/postcss-selector-parser": { - "version": "6.0.13", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.13.tgz", - "integrity": "sha512-EaV1Gl4mUEV4ddhDnv/xtj7sxwrwxdetHdWUGnT4VJQf+4d05v6lHYZr8N573k5Z0BViss7BDhfWtKS3+sfAqQ==", + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", + "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", "dev": true, + "license": "MIT", "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" @@ -19476,8 +19995,25 @@ "node_modules/postcss-value-parser": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" + }, + "node_modules/postcss/node_modules/nanoid": { + "version": "3.3.8", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.8.tgz", + "integrity": "sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } }, "node_modules/prelude-ls": { "version": "1.2.1", @@ -19941,6 +20477,44 @@ "integrity": "sha512-Fl7FuabXsJnV5Q1qIOQwx/sagGF18kogb4gpfcG4gjLBWO0WDiiz1ko/ExayuxE7InyQkBLkxRFG5oxY6Uu3Kg==", "dev": true }, + "node_modules/react-hook-form": { + "version": "7.54.2", + "resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.54.2.tgz", + "integrity": "sha512-eHpAUgUjWbZocoQYUHposymRb4ZP6d0uwUnooL2uOybA9/3tPUvoAKqEWK1WaSiTxxOfTpffNZP7QwlnM3/gEg==", + "license": "MIT", + "engines": { + "node": ">=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/react-hook-form" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17 || ^18 || ^19" + } + }, + "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", @@ -20003,6 +20577,39 @@ } } }, + "node_modules/react-router": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-7.1.1.tgz", + "integrity": "sha512-39sXJkftkKWRZ2oJtHhCxmoCrBCULr/HAH4IT5DHlgu/Q0FCPV0S4Lx+abjDTx/74xoZzNYDYbOZWlJjruyuDQ==", + "license": "MIT", + "dependencies": { + "@types/cookie": "^0.6.0", + "cookie": "^1.0.1", + "set-cookie-parser": "^2.6.0", + "turbo-stream": "2.4.0" + }, + "engines": { + "node": ">=20.0.0" + }, + "peerDependencies": { + "react": ">=18", + "react-dom": ">=18" + }, + "peerDependenciesMeta": { + "react-dom": { + "optional": true + } + } + }, + "node_modules/react-router/node_modules/cookie": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-1.0.2.tgz", + "integrity": "sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, "node_modules/react-style-singleton": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/react-style-singleton/-/react-style-singleton-2.2.1.tgz", @@ -20026,6 +20633,26 @@ } } }, + "node_modules/read-cache": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", + "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "pify": "^2.3.0" + } + }, + "node_modules/read-cache/node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/read-pkg": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", @@ -20198,10 +20825,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", @@ -20383,18 +21010,22 @@ "dev": true }, "node_modules/resolve": { - "version": "1.22.2", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.2.tgz", - "integrity": "sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g==", + "version": "1.22.10", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz", + "integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==", "dev": true, + "license": "MIT", "dependencies": { - "is-core-module": "^2.11.0", + "is-core-module": "^2.16.0", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, "bin": { "resolve": "bin/resolve" }, + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -20843,6 +21474,12 @@ "node": ">= 0.8.0" } }, + "node_modules/set-cookie-parser": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.1.tgz", + "integrity": "sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ==", + "license": "MIT" + }, "node_modules/setprototypeof": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", @@ -20956,10 +21593,10 @@ } }, "node_modules/source-map-js": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", - "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", - "dev": true, + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" } @@ -21335,6 +21972,19 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/strip-outer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/strip-outer/-/strip-outer-1.0.1.tgz", + "integrity": "sha512-k55yxKHwaXnpYGsOzg4Vl8+tDrWylxDEpknGjhTiZB8dFRU5rTo9CAzeycivxV3s+zlTKwrs6WxMxR95n26kwg==", + "dev": true, + "license": "MIT", + "dependencies": { + "escape-string-regexp": "^1.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/style-loader": { "version": "3.3.3", "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-3.3.3.tgz", @@ -21351,6 +22001,39 @@ "webpack": "^5.0.0" } }, + "node_modules/sucrase": { + "version": "3.35.0", + "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz", + "integrity": "sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.2", + "commander": "^4.0.0", + "glob": "^10.3.10", + "lines-and-columns": "^1.1.6", + "mz": "^2.7.0", + "pirates": "^4.0.1", + "ts-interface-checker": "^0.1.9" + }, + "bin": { + "sucrase": "bin/sucrase", + "sucrase-node": "bin/sucrase-node" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/sucrase/node_modules/commander": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", + "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, "node_modules/supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", @@ -21400,6 +22083,44 @@ "integrity": "sha512-AsS729u2RHUfEra9xJrE39peJcc2stq2+poBXX8bcM08Y6g9j/i/PUzwNQqkaJde7Ntg1TO7bSREbR5sdosQ+g==", "dev": true }, + "node_modules/tailwindcss": { + "version": "3.4.17", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.17.tgz", + "integrity": "sha512-w33E2aCvSDP0tW9RZuNXadXlkHXqFzSkQew/aIa2i/Sj8fThxwovwlXHSPXTbAHwEIhBFXAedUhP2tueAKP8Og==", + "dev": true, + "license": "MIT", + "dependencies": { + "@alloc/quick-lru": "^5.2.0", + "arg": "^5.0.2", + "chokidar": "^3.6.0", + "didyoumean": "^1.2.2", + "dlv": "^1.1.3", + "fast-glob": "^3.3.2", + "glob-parent": "^6.0.2", + "is-glob": "^4.0.3", + "jiti": "^1.21.6", + "lilconfig": "^3.1.3", + "micromatch": "^4.0.8", + "normalize-path": "^3.0.0", + "object-hash": "^3.0.0", + "picocolors": "^1.1.1", + "postcss": "^8.4.47", + "postcss-import": "^15.1.0", + "postcss-js": "^4.0.1", + "postcss-load-config": "^4.0.2", + "postcss-nested": "^6.2.0", + "postcss-selector-parser": "^6.1.2", + "resolve": "^1.22.8", + "sucrase": "^3.35.0" + }, + "bin": { + "tailwind": "lib/cli.js", + "tailwindcss": "lib/cli.js" + }, + "engines": { + "node": ">=14.0.0" + } + }, "node_modules/tapable": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", @@ -21828,6 +22549,29 @@ "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", "dev": true }, + "node_modules/thenify": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", + "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", + "dev": true, + "license": "MIT", + "dependencies": { + "any-promise": "^1.0.0" + } + }, + "node_modules/thenify-all": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", + "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", + "dev": true, + "license": "MIT", + "dependencies": { + "thenify": ">= 3.1.0 < 4" + }, + "engines": { + "node": ">=0.8" + } + }, "node_modules/through2": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", @@ -21906,6 +22650,7 @@ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", "dev": true, + "license": "MIT", "dependencies": { "is-number": "^7.0.0" }, @@ -21964,6 +22709,19 @@ "node": ">=12" } }, + "node_modules/trim-repeated": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/trim-repeated/-/trim-repeated-1.0.0.tgz", + "integrity": "sha512-pkonvlKk8/ZuR0D5tLW8ljt5I8kmxp2XKymhepUeOdCEfKpZaktSArkLHZt76OB1ZvO9bssUsDty4SWhLvZpLg==", + "dev": true, + "license": "MIT", + "dependencies": { + "escape-string-regexp": "^1.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/trough": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/trough/-/trough-2.2.0.tgz", @@ -21983,6 +22741,13 @@ "node": ">=6.10" } }, + "node_modules/ts-interface-checker": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", + "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==", + "dev": true, + "license": "Apache-2.0" + }, "node_modules/ts-jest": { "version": "29.1.0", "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.1.0.tgz", @@ -22128,6 +22893,12 @@ "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", "dev": true }, + "node_modules/turbo-stream": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/turbo-stream/-/turbo-stream-2.4.0.tgz", + "integrity": "sha512-FHncC10WpBd2eOmGwpmQsWLDoK4cqsA/UT/GqNoaKOQnT8uzhtCbg3EoUDMvqpOSAI0S26mr0rkjzbOO6S3v1g==", + "license": "ISC" + }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", @@ -22198,7 +22969,7 @@ "version": "5.1.3", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.1.3.tgz", "integrity": "sha512-XH627E9vkeqhlZFQuL+UsyAXEnibT0kWR2FWONlr4sTjvxyJYnyefgrkyECLzM5NenmKzRAy2rR/OlYLA1HkZw==", - "dev": true, + "devOptional": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -22440,10 +23211,9 @@ } }, "node_modules/update-browserslist-db": { - "version": "1.0.13", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", - "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==", - "dev": true, + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.1.tgz", + "integrity": "sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A==", "funding": [ { "type": "opencollective", @@ -22458,9 +23228,10 @@ "url": "https://github.com/sponsors/ai" } ], + "license": "MIT", "dependencies": { - "escalade": "^3.1.1", - "picocolors": "^1.0.0" + "escalade": "^3.2.0", + "picocolors": "^1.1.0" }, "bin": { "update-browserslist-db": "cli.js" @@ -22703,6 +23474,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", @@ -23554,6 +24334,12 @@ } }, "dependencies": { + "@alloc/quick-lru": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz", + "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==", + "dev": true + }, "@ampproject/remapping": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz", @@ -24908,12 +25694,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.0", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.26.0.tgz", + "integrity": "sha512-FDSOghenHTiToteC/QRlv2q3DhPZ/oOXTBoirfWNx1Cx3TMVcGWQtMMmQcSvb/JjpNeGzx8Pq/b4fKEJuWm1sw==", "requires": { - "regenerator-runtime": "^0.13.11" + "regenerator-runtime": "^0.14.0" } }, "@babel/template": { @@ -28752,6 +29537,11 @@ "@types/node": "*" } }, + "@types/cookie": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.6.0.tgz", + "integrity": "sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==" + }, "@types/cross-spawn": { "version": "6.0.6", "resolved": "https://registry.npmjs.org/@types/cross-spawn/-/cross-spawn-6.0.6.tgz", @@ -29793,6 +30583,12 @@ } } }, + "any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==", + "dev": true + }, "anymatch": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", @@ -29809,6 +30605,12 @@ "integrity": "sha512-jlpIfsOoNoafl92Sz//64uQHGSyMrD2vYG5d8o2a4qGvyNCvXur7bzIsWtAC/6flI2RYAp3kv8rsfBtaLm7w0g==", "dev": true }, + "arg": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", + "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==", + "dev": true + }, "argparse": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", @@ -29961,6 +30763,19 @@ "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", "dev": true }, + "autoprefixer": { + "version": "10.4.20", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.20.tgz", + "integrity": "sha512-XY25y5xSv/wEoqzDyXXME4AFfkZI0P23z6Fs3YgymDnKJkCGOnkL0iTxCa85UTqaSgfcqyf3UA6+c7wUvx/16g==", + "requires": { + "browserslist": "^4.23.3", + "caniuse-lite": "^1.0.30001646", + "fraction.js": "^4.3.7", + "normalize-range": "^0.1.2", + "picocolors": "^1.0.1", + "postcss-value-parser": "^4.2.0" + } + }, "available-typed-arrays": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", @@ -30338,12 +31153,12 @@ } }, "braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", "dev": true, "requires": { - "fill-range": "^7.0.1" + "fill-range": "^7.1.1" } }, "browser-assert": { @@ -30362,15 +31177,14 @@ } }, "browserslist": { - "version": "4.22.1", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.1.tgz", - "integrity": "sha512-FEVc202+2iuClEhZhrWy6ZiAcRLvNMyYcxZ8raemul1DYVOVdFsbqckWLdsixQZCpJlwe77Z3UTalE7jsjnKfQ==", - "dev": true, + "version": "4.24.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.3.tgz", + "integrity": "sha512-1CPmv8iobE2fyRMV97dAcMVegvvWKxmq94hkLiAkUGwKVTyDLw33K+ZxiFrREKmmps4rIw6grcCFCnTMSZ/YiA==", "requires": { - "caniuse-lite": "^1.0.30001541", - "electron-to-chromium": "^1.4.535", - "node-releases": "^2.0.13", - "update-browserslist-db": "^1.0.13" + "caniuse-lite": "^1.0.30001688", + "electron-to-chromium": "^1.5.73", + "node-releases": "^2.0.19", + "update-browserslist-db": "^1.1.1" } }, "bs-logger": { @@ -30451,12 +31265,17 @@ "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", "dev": true }, - "caniuse-lite": { - "version": "1.0.30001554", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001554.tgz", - "integrity": "sha512-A2E3U//MBwbJVzebddm1YfNp7Nud5Ip+IPn4BozBmn4KqVX7AvluoIDFWjsv5OkGnKUXQVmMSoMKLa3ScCblcQ==", + "camelcase-css": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", + "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==", "dev": true }, + "caniuse-lite": { + "version": "1.0.30001690", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001690.tgz", + "integrity": "sha512-5ExiE3qQN6oF8Clf8ifIDcMRCRE/dMGcETG/XGMD8/XiXm6HXQgQTh1yZYLXXpSOsEUlJm1Xr7kGULZTuGtP/w==" + }, "case-sensitive-paths-webpack-plugin": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/case-sensitive-paths-webpack-plugin/-/case-sensitive-paths-webpack-plugin-2.4.0.tgz", @@ -30493,9 +31312,9 @@ "dev": true }, "chokidar": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", - "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", "dev": true, "requires": { "anymatch": "~3.1.2", @@ -31300,6 +32119,12 @@ "debug": "4" } }, + "didyoumean": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", + "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==", + "dev": true + }, "diff": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.0.tgz", @@ -31321,6 +32146,12 @@ "path-type": "^4.0.0" } }, + "dlv": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", + "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", + "dev": true + }, "dns-equal": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/dns-equal/-/dns-equal-1.0.0.tgz", @@ -31508,9 +32339,14 @@ } }, "electron-to-chromium": { - "version": "1.4.567", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.567.tgz", - "integrity": "sha512-8KR114CAYQ4/r5EIEsOmOMqQ9j0MRbJZR3aXD/KFA8RuKzyoUB4XrUCg+l8RUGqTVQgKNIgTpjaG8YHRPAbX2w==", + "version": "1.5.76", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.76.tgz", + "integrity": "sha512-CjVQyG7n7Sr+eBXE86HIulnL5N8xZY1sgmOPGuq/F0Rr0FJq63lg0kEtOIDfZBk44FnDLf6FUJ+dsJcuiUDdDQ==" + }, + "email-addresses": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/email-addresses/-/email-addresses-5.0.0.tgz", + "integrity": "sha512-4OIPYlA6JXqtVn8zpHpGiI7vE6EQOAg16aGnDMIAlZVinnoZ8208tW1hAbjWydgN/4PLTT9q+O1K6AH/vALJGw==", "dev": true }, "emittery": { @@ -31573,6 +32409,12 @@ "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", "dev": true }, + "env-paths": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", + "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", + "dev": true + }, "envinfo": { "version": "7.8.1", "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.8.1.tgz", @@ -31750,10 +32592,9 @@ } }, "escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", - "dev": true + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==" }, "escape-html": { "version": "1.0.3", @@ -32508,9 +33349,9 @@ "dev": true }, "fast-glob": { - "version": "3.2.12", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz", - "integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==", + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", "dev": true, "requires": { "@nodelib/fs.stat": "^2.0.2", @@ -32645,10 +33486,27 @@ } } }, + "filename-reserved-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/filename-reserved-regex/-/filename-reserved-regex-2.0.0.tgz", + "integrity": "sha512-lc1bnsSr4L4Bdif8Xb/qrtokGbq5zlsms/CYH8PP+WtCkGNF65DPiQY8vG3SakEdRn8Dlnm+gW/qWKKjS5sZzQ==", + "dev": true + }, + "filenamify": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/filenamify/-/filenamify-4.3.0.tgz", + "integrity": "sha512-hcFKyUG57yWGAzu1CMt/dPzYZuv+jAJUT85bL8mrXvNe6hWj6yEHEc4EdcgiA6Z3oi1/9wXJdZPXF2dZNgwgOg==", + "dev": true, + "requires": { + "filename-reserved-regex": "^2.0.0", + "strip-outer": "^1.0.1", + "trim-repeated": "^1.0.0" + } + }, "fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", "dev": true, "requires": { "to-regex-range": "^5.0.1" @@ -32943,6 +33801,11 @@ "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", "dev": true }, + "fraction.js": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz", + "integrity": "sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==" + }, "fresh": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", @@ -33012,9 +33875,9 @@ "optional": true }, "function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", "dev": true }, "function.prototype.name": { @@ -33105,6 +33968,29 @@ "get-intrinsic": "^1.1.1" } }, + "gh-pages": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/gh-pages/-/gh-pages-6.2.0.tgz", + "integrity": "sha512-HMXJ8th9u5wRXaZCnLcs/d3oVvCHiZkaP5KQExQljYGwJjQbSPyTdHe/Gc1IvYUR/rWiZLxNobIqfoMHKTKjHQ==", + "dev": true, + "requires": { + "async": "^3.2.4", + "commander": "^11.0.0", + "email-addresses": "^5.0.0", + "filenamify": "^4.3.0", + "find-cache-dir": "^3.3.1", + "fs-extra": "^11.1.1", + "globby": "^11.1.0" + }, + "dependencies": { + "commander": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-11.1.0.tgz", + "integrity": "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==", + "dev": true + } + } + }, "giget": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/giget/-/giget-1.2.1.tgz", @@ -33317,6 +34203,15 @@ "has-symbols": "^1.0.2" } }, + "hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dev": true, + "requires": { + "function-bind": "^1.1.2" + } + }, "he": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", @@ -33415,6 +34310,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 +34439,15 @@ "integrity": "sha512-+dQSyqPh4x1hlO1swXBiNb2HzTDN1I2IGLQx1GrBuiqFJfoMrnZWwVmatvSiO+Iz8fBUnf+lekwNo4c2LlXItg==", "dev": true }, + "i18next": { + "version": "24.2.1", + "resolved": "https://registry.npmjs.org/i18next/-/i18next-24.2.1.tgz", + "integrity": "sha512-Q2wC1TjWcSikn1VAJg13UGIjc+okpFxQTxjVAymOnSA3RpttBQNMPf2ovcgoFVsV4QNxTfNZMAxorXZXsk4fBA==", + "peer": true, + "requires": { + "@babel/runtime": "^7.23.2" + } + }, "iconv-lite": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", @@ -33788,12 +34700,12 @@ "dev": true }, "is-core-module": { - "version": "2.12.1", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.12.1.tgz", - "integrity": "sha512-Q4ZuBAe2FUsKtyQJoQHlvP8OvBERxO3jEmy1I7hcRXcJBGGHFh/aJBswbXuS9sgrDH2QUO8ilkwNPHvHMd8clg==", + "version": "2.16.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", + "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", "dev": true, "requires": { - "has": "^1.0.3" + "hasown": "^2.0.2" } }, "is-date-object": { @@ -35529,6 +36441,12 @@ } } }, + "jiti": { + "version": "1.21.7", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.7.tgz", + "integrity": "sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==", + "dev": true + }, "js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -35839,6 +36757,12 @@ "type-check": "~0.4.0" } }, + "lilconfig": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz", + "integrity": "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==", + "dev": true + }, "lines-and-columns": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", @@ -36638,12 +37562,12 @@ "dev": true }, "micromatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", - "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", "dev": true, "requires": { - "braces": "^3.0.2", + "braces": "^3.0.3", "picomatch": "^2.3.1" } }, @@ -36821,11 +37745,21 @@ "thunky": "^1.0.2" } }, + "mz": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", + "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", + "dev": true, + "requires": { + "any-promise": "^1.0.0", + "object-assign": "^4.0.1", + "thenify-all": "^1.0.0" + } + }, "nanoid": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz", - "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==", - "dev": true + "version": "5.0.9", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-5.0.9.tgz", + "integrity": "sha512-Aooyr6MXU6HpvvWXKoVoXwKMs/KyVakWwg7xQfv5/S/RIgJMy0Ifa45H9qqYy7pTCszrHzP21Uk4PZq2HpEM8Q==" }, "natural-compare": { "version": "1.4.0", @@ -36965,10 +37899,9 @@ "dev": true }, "node-releases": { - "version": "2.0.13", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.13.tgz", - "integrity": "sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==", - "dev": true + "version": "2.0.19", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz", + "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==" }, "normalize-package-data": { "version": "2.5.0", @@ -36996,6 +37929,11 @@ "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", "dev": true }, + "normalize-range": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", + "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==" + }, "npm-run-path": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", @@ -37117,6 +38055,12 @@ "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", "dev": true }, + "object-hash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", + "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", + "dev": true + }, "object-inspect": { "version": "1.12.3", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", @@ -37508,10 +38452,9 @@ "dev": true }, "picocolors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", - "dev": true + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==" }, "picomatch": { "version": "2.3.1", @@ -37565,14 +38508,104 @@ } }, "postcss": { - "version": "8.4.31", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", - "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==", + "version": "8.4.49", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.49.tgz", + "integrity": "sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==", + "requires": { + "nanoid": "^3.3.7", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "dependencies": { + "nanoid": { + "version": "3.3.8", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.8.tgz", + "integrity": "sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==" + } + } + }, + "postcss-import": { + "version": "15.1.0", + "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz", + "integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==", "dev": true, "requires": { - "nanoid": "^3.3.6", - "picocolors": "^1.0.0", - "source-map-js": "^1.0.2" + "postcss-value-parser": "^4.0.0", + "read-cache": "^1.0.0", + "resolve": "^1.1.7" + } + }, + "postcss-js": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.1.tgz", + "integrity": "sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==", + "dev": true, + "requires": { + "camelcase-css": "^2.0.1" + } + }, + "postcss-load-config": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-4.0.2.tgz", + "integrity": "sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==", + "dev": true, + "requires": { + "lilconfig": "^3.0.0", + "yaml": "^2.3.4" + }, + "dependencies": { + "yaml": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.6.1.tgz", + "integrity": "sha512-7r0XPzioN/Q9kXBro/XPnA6kznR73DHq+GXh5ON7ZozRO6aMjbmiBuKste2wslTFkC5d1dw0GooOCepZXJ2SAg==", + "dev": true + } + } + }, + "postcss-loader": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-8.1.1.tgz", + "integrity": "sha512-0IeqyAsG6tYiDRCYKQJLAmgQr47DX6N7sFSWvQxt6AcupX8DIdmykuk/o/tx0Lze3ErGHJEp5OSRxrelC6+NdQ==", + "dev": true, + "requires": { + "cosmiconfig": "^9.0.0", + "jiti": "^1.20.0", + "semver": "^7.5.4" + }, + "dependencies": { + "argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "cosmiconfig": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-9.0.0.tgz", + "integrity": "sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg==", + "dev": true, + "requires": { + "env-paths": "^2.2.1", + "import-fresh": "^3.3.0", + "js-yaml": "^4.1.0", + "parse-json": "^5.2.0" + } + }, + "js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "requires": { + "argparse": "^2.0.1" + } + }, + "semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "dev": true + } } }, "postcss-modules-extract-imports": { @@ -37611,10 +38644,19 @@ "icss-utils": "^5.0.0" } }, + "postcss-nested": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.2.0.tgz", + "integrity": "sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==", + "dev": true, + "requires": { + "postcss-selector-parser": "^6.1.1" + } + }, "postcss-selector-parser": { - "version": "6.0.13", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.13.tgz", - "integrity": "sha512-EaV1Gl4mUEV4ddhDnv/xtj7sxwrwxdetHdWUGnT4VJQf+4d05v6lHYZr8N573k5Z0BViss7BDhfWtKS3+sfAqQ==", + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", + "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", "dev": true, "requires": { "cssesc": "^3.0.0", @@ -37624,8 +38666,7 @@ "postcss-value-parser": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" }, "prelude-ls": { "version": "1.2.1", @@ -37986,6 +39027,21 @@ } } }, + "react-hook-form": { + "version": "7.54.2", + "resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.54.2.tgz", + "integrity": "sha512-eHpAUgUjWbZocoQYUHposymRb4ZP6d0uwUnooL2uOybA9/3tPUvoAKqEWK1WaSiTxxOfTpffNZP7QwlnM3/gEg==", + "requires": {} + }, + "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", @@ -38021,6 +39077,24 @@ "tslib": "^2.0.0" } }, + "react-router": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-7.1.1.tgz", + "integrity": "sha512-39sXJkftkKWRZ2oJtHhCxmoCrBCULr/HAH4IT5DHlgu/Q0FCPV0S4Lx+abjDTx/74xoZzNYDYbOZWlJjruyuDQ==", + "requires": { + "@types/cookie": "^0.6.0", + "cookie": "^1.0.1", + "set-cookie-parser": "^2.6.0", + "turbo-stream": "2.4.0" + }, + "dependencies": { + "cookie": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-1.0.2.tgz", + "integrity": "sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA==" + } + } + }, "react-style-singleton": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/react-style-singleton/-/react-style-singleton-2.2.1.tgz", @@ -38032,6 +39106,23 @@ "tslib": "^2.0.0" } }, + "read-cache": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", + "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==", + "dev": true, + "requires": { + "pify": "^2.3.0" + }, + "dependencies": { + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", + "dev": true + } + } + }, "read-pkg": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", @@ -38165,10 +39256,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", @@ -38307,12 +39397,12 @@ "dev": true }, "resolve": { - "version": "1.22.2", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.2.tgz", - "integrity": "sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g==", + "version": "1.22.10", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz", + "integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==", "dev": true, "requires": { - "is-core-module": "^2.11.0", + "is-core-module": "^2.16.0", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" } @@ -38639,6 +39729,11 @@ "send": "0.18.0" } }, + "set-cookie-parser": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.1.tgz", + "integrity": "sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ==" + }, "setprototypeof": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", @@ -38730,10 +39825,9 @@ "dev": true }, "source-map-js": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", - "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", - "dev": true + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==" }, "source-map-support": { "version": "0.5.13", @@ -39034,6 +40128,15 @@ "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "dev": true }, + "strip-outer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/strip-outer/-/strip-outer-1.0.1.tgz", + "integrity": "sha512-k55yxKHwaXnpYGsOzg4Vl8+tDrWylxDEpknGjhTiZB8dFRU5rTo9CAzeycivxV3s+zlTKwrs6WxMxR95n26kwg==", + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.2" + } + }, "style-loader": { "version": "3.3.3", "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-3.3.3.tgz", @@ -39041,6 +40144,29 @@ "dev": true, "requires": {} }, + "sucrase": { + "version": "3.35.0", + "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz", + "integrity": "sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==", + "dev": true, + "requires": { + "@jridgewell/gen-mapping": "^0.3.2", + "commander": "^4.0.0", + "glob": "^10.3.10", + "lines-and-columns": "^1.1.6", + "mz": "^2.7.0", + "pirates": "^4.0.1", + "ts-interface-checker": "^0.1.9" + }, + "dependencies": { + "commander": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", + "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", + "dev": true + } + } + }, "supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", @@ -39077,6 +40203,36 @@ "integrity": "sha512-AsS729u2RHUfEra9xJrE39peJcc2stq2+poBXX8bcM08Y6g9j/i/PUzwNQqkaJde7Ntg1TO7bSREbR5sdosQ+g==", "dev": true }, + "tailwindcss": { + "version": "3.4.17", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.17.tgz", + "integrity": "sha512-w33E2aCvSDP0tW9RZuNXadXlkHXqFzSkQew/aIa2i/Sj8fThxwovwlXHSPXTbAHwEIhBFXAedUhP2tueAKP8Og==", + "dev": true, + "requires": { + "@alloc/quick-lru": "^5.2.0", + "arg": "^5.0.2", + "chokidar": "^3.6.0", + "didyoumean": "^1.2.2", + "dlv": "^1.1.3", + "fast-glob": "^3.3.2", + "glob-parent": "^6.0.2", + "is-glob": "^4.0.3", + "jiti": "^1.21.6", + "lilconfig": "^3.1.3", + "micromatch": "^4.0.8", + "normalize-path": "^3.0.0", + "object-hash": "^3.0.0", + "picocolors": "^1.1.1", + "postcss": "^8.4.47", + "postcss-import": "^15.1.0", + "postcss-js": "^4.0.1", + "postcss-load-config": "^4.0.2", + "postcss-nested": "^6.2.0", + "postcss-selector-parser": "^6.1.2", + "resolve": "^1.22.8", + "sucrase": "^3.35.0" + } + }, "tapable": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", @@ -39390,6 +40546,24 @@ "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", "dev": true }, + "thenify": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", + "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", + "dev": true, + "requires": { + "any-promise": "^1.0.0" + } + }, + "thenify-all": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", + "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", + "dev": true, + "requires": { + "thenify": ">= 3.1.0 < 4" + } + }, "through2": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", @@ -39512,6 +40686,15 @@ "punycode": "^2.1.1" } }, + "trim-repeated": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/trim-repeated/-/trim-repeated-1.0.0.tgz", + "integrity": "sha512-pkonvlKk8/ZuR0D5tLW8ljt5I8kmxp2XKymhepUeOdCEfKpZaktSArkLHZt76OB1ZvO9bssUsDty4SWhLvZpLg==", + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.2" + } + }, "trough": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/trough/-/trough-2.2.0.tgz", @@ -39524,6 +40707,12 @@ "integrity": "sha512-q5W7tVM71e2xjHZTlgfTDoPF/SmqKG5hddq9SzR49CH2hayqRKJtQ4mtRlSxKaJlR/+9rEM+mnBHf7I2/BQcpQ==", "dev": true }, + "ts-interface-checker": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", + "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==", + "dev": true + }, "ts-jest": { "version": "29.1.0", "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.1.0.tgz", @@ -39624,6 +40813,11 @@ } } }, + "turbo-stream": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/turbo-stream/-/turbo-stream-2.4.0.tgz", + "integrity": "sha512-FHncC10WpBd2eOmGwpmQsWLDoK4cqsA/UT/GqNoaKOQnT8uzhtCbg3EoUDMvqpOSAI0S26mr0rkjzbOO6S3v1g==" + }, "type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", @@ -39676,7 +40870,7 @@ "version": "5.1.3", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.1.3.tgz", "integrity": "sha512-XH627E9vkeqhlZFQuL+UsyAXEnibT0kWR2FWONlr4sTjvxyJYnyefgrkyECLzM5NenmKzRAy2rR/OlYLA1HkZw==", - "dev": true + "devOptional": true }, "ufo": { "version": "1.4.0", @@ -39850,13 +41044,12 @@ "dev": true }, "update-browserslist-db": { - "version": "1.0.13", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", - "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==", - "dev": true, + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.1.tgz", + "integrity": "sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A==", "requires": { - "escalade": "^3.1.1", - "picocolors": "^1.0.0" + "escalade": "^3.2.0", + "picocolors": "^1.1.0" } }, "uri-js": { @@ -40036,6 +41229,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", diff --git a/package.json b/package.json index 492664d1f..e28f2cc1e 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "name": "react-start-template", + "name": "furtivite.github.io", "version": "1.0.0", "description": "Start repo with required configuration", "main": "src/index.tsx", @@ -7,10 +7,12 @@ "scripts": { "start": "webpack serve --mode development", "build": "webpack --mode production", - "test": "jest src", + "test": "jest src/feature", "lint": "eslint src --fix", "storybook": "storybook dev -p 6006", - "build-storybook": "storybook build" + "build-storybook": "storybook build", + "predeploy": "npm run build", + "deploy": "npx gh-pages -d dist" }, "license": "MIT", "devDependencies": { @@ -46,17 +48,21 @@ "eslint-plugin-react-hooks": "^4.6.0", "eslint-plugin-storybook": "^0.8.0", "fork-ts-checker-webpack-plugin": "^8.0.0", + "gh-pages": "^6.2.0", "html-webpack-plugin": "^5.5.1", "husky": "^8.0.0", "jest": "^29.5.0", "jest-environment-jsdom": "^29.5.0", "less-loader": "^11.1.2", "mini-css-extract-plugin": "^2.7.6", + "postcss": "^8.4.49", + "postcss-loader": "^8.1.1", "prettier": "2.8.8", "sass": "^1.71.1", "sass-loader": "^13.3.1", "storybook": "^7.6.17", "style-loader": "^3.3.3", + "tailwindcss": "^3.4.17", "ts-jest": "^29.1.0", "typescript": "^5.1.3", "webpack": "^5.85.0", @@ -64,8 +70,13 @@ "webpack-dev-server": "^4.15.0" }, "dependencies": { + "autoprefixer": "^10.4.20", "clsx": "^1.2.1", + "nanoid": "^5.0.9", "react": "^18.2.0", - "react-dom": "^18.2.0" + "react-dom": "^18.2.0", + "react-hook-form": "^7.54.2", + "react-i18next": "^15.4.0", + "react-router": "^7.1.1" } } diff --git a/postcss.config.js b/postcss.config.js new file mode 100644 index 000000000..493c16c7c --- /dev/null +++ b/postcss.config.js @@ -0,0 +1,6 @@ +/** @type {import('postcss-load-config').Config} */ +const config = { + plugins: [require('tailwindcss'), require('autoprefixer'), require('postcss-nested')], +}; + +module.exports = config; diff --git a/src/app/App.css b/src/app/App.css deleted file mode 100644 index 78b8850cf..000000000 --- a/src/app/App.css +++ /dev/null @@ -1,38 +0,0 @@ -.App { - text-align: center; -} - -.App-logo { - height: 40vmin; - pointer-events: none; -} - -@media (prefers-reduced-motion: no-preference) { - .App-logo { - animation: App-logo-spin infinite 20s linear; - } -} - -.App-header { - background-color: #282c34; - min-height: 100vh; - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - font-size: calc(10px + 2vmin); - color: white; -} - -.App-link { - color: #61dafb; -} - -@keyframes App-logo-spin { - from { - transform: rotate(0deg); - } - to { - transform: rotate(360deg); - } -} diff --git a/src/app/App.tsx b/src/app/App.tsx index dcc0ff8ad..15a5f2b94 100644 --- a/src/app/App.tsx +++ b/src/app/App.tsx @@ -1,17 +1,102 @@ import React from 'react'; -import logo from './logo.svg'; -import './App.css'; +import { nanoid } from 'nanoid'; +import { BrowserRouter, NavLink, Route, Routes } from 'react-router'; +import { useTranslation } from 'react-i18next'; +import './tailwind.css'; +import { Layout } from '../entities'; +import { AccountServicePage, ProfilePage, Store, StoreBasket, StoreCard, StoreList } from '../pages'; +import { defaultContext, ELangVariables, EThemeVariables, IStoreContext, StoreContext } from './StoreContext'; function App() { + const [contextValue, setContextValue] = React.useState(defaultContext); + const { theme, lang } = contextValue; + const { i18n, t } = useTranslation(); + + const themeSwitchHandler = (): void => { + if (theme === 'light') { + setContextValue({ ...contextValue, theme: EThemeVariables.DARK }); + } else { + setContextValue({ ...contextValue, theme: EThemeVariables.LIGHT }); + } + }; + + const langSwitchHandler = (): void => { + if (lang === 'ru') { + setContextValue({ ...contextValue, lang: ELangVariables.EN }); + i18n.changeLanguage('en-US'); + } else { + setContextValue({ ...contextValue, lang: ELangVariables.RU }); + i18n.changeLanguage('ru-RU'); + } + }; + + // TODO: Delete this Links and translation in future + const tempLinks = [ + { + path: '/', + text: t('tempLinks.toMain'), + }, + { + path: '/card/1', + text: t('tempLinks.toCard'), + }, + { + path: '/basket', + text: t('tempLinks.toBasket'), + }, + { + path: '/list', + text: t('tempLinks.toList'), + }, + { + path: '/account-service', + text: t('tempLinks.toAccountService'), + }, + { + path: '/profile', + text: t('tempLinks.toProfilePage'), + }, + ]; + // const currentUrl = window.location.pathname; + // END TODO + return ( -
-
- logo -

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

-
-
+ + + + {/* TODO: Delete this Links and translation in future */} + + {/* END TODO */} + + + } /> + } /> + } /> + } /> + } /> + } /> + } /> + + + + ); } diff --git a/src/app/StoreContext.ts b/src/app/StoreContext.ts new file mode 100644 index 000000000..8c013276d --- /dev/null +++ b/src/app/StoreContext.ts @@ -0,0 +1,32 @@ +import React from 'react'; + +export enum EThemeVariables { + LIGHT = 'light', + DARK = 'dark', +} + +export enum ELangVariables { + RU = 'ru', + EN = 'en', +} + +export interface IStoreContext { + theme: EThemeVariables; + lang: ELangVariables; +} + +export interface IStoreContextProps extends IStoreContext { + themeSwitchHandler: () => void; + langSwitchHandler: () => void; +} + +export const defaultContext: IStoreContext = { + theme: EThemeVariables.LIGHT, + lang: ELangVariables.EN, +}; + +export const StoreContext = React.createContext({ + ...defaultContext, + themeSwitchHandler: () => null, + langSwitchHandler: () => null, +}); diff --git a/src/app/i18n/config.ts b/src/app/i18n/config.ts new file mode 100644 index 000000000..300f2689b --- /dev/null +++ b/src/app/i18n/config.ts @@ -0,0 +1,12 @@ +import i18next from 'i18next'; +import { initReactI18next } from 'react-i18next'; +import { resources } from './translation'; +import { ELangVariables } from '../StoreContext'; + +i18next.use(initReactI18next).init({ + lng: ELangVariables.EN, + debug: true, + resources, +}); + +export default i18next; diff --git a/src/app/i18n/translation.ts b/src/app/i18n/translation.ts new file mode 100644 index 000000000..9a53883e9 --- /dev/null +++ b/src/app/i18n/translation.ts @@ -0,0 +1,202 @@ +export const resources = { + en: { + translation: { + storeName: 'Ecommerce', + tempLinks: { + toMain: 'to Main Page', + toCard: 'to Card', + toBasket: 'to Basket', + toList: 'to Goods List', + toAccountService: 'to Account Service', + toProfilePage: 'to Profile', + }, + card: { + stockStatus: { + in: 'IN STOCK', + out: 'OUT OF STOCK', + }, + colors: { + title: 'Available Colors', + current: 'Current color is', + choose: 'You choose', + }, + sizes: { + title: 'Select Size', + current: 'Current size is', + choose: 'You choose', + }, + quantity: 'QUANTITY', + offer: '\u2013\u00A0Free shipping on\u00A0orders $100+', + details: 'Details', + addToCart: 'Add to Cart', + }, + basket: { + color: 'Color', + size: 'Size', + }, + counter: { + increase: 'Increase', + decrease: 'Decrease', + }, + mainPage: { + placeholder: 'Enter the value', + showBtn: 'Show modal', + }, + listPage: { + addMore: 'Add more', + addGoodToStore: 'Add good to store', + }, + modal: { + close: 'Close modal window', + }, + collapse: { + isClosed: 'Show more', + isOpened: 'Hide', + }, + forms: { + name: { + label: 'Name', + placeholder: 'Enter a name', + requiredMessage: 'Please enter your name.', + patternMessage: 'Invalid characters in the input field', + }, + about: { + label: 'About me', + placeholder: 'Tell us about yourself', + }, + submit: 'Submit', + goods: { + title: 'Title', + titlePlaceholder: 'Enter goods title', + details: 'Details', + detailsPlaceholder: 'Tell more about goods', + price: 'Price', + pricePlaceholder: 'Enter price', + }, + authReg: { + login: { + label: 'Username', + placeholder: 'Enter your username', + requiredMessage: 'Enter your username', + patternMessage: '', + }, + password: { + label: 'Password', + placeholder: 'Enter the password', + requiredMessage: 'Enter the password', + patternMessage: '', + }, + submitReg: 'Register', + submitAuth: 'Log in', + }, + }, + accountServicePage: { + userDiscount: 'Discount for premium user', + userProductDiscount: 'A discount for a premium user on a car:', + commonDiscount: 'The final discount for a premium user to purchase a car:', + initialPrice: 'The initial price for the car:', + finalPrice: 'The final price for a premium user for a car:', + }, + }, + }, + ru: { + translation: { + storeName: 'Ecommerce.RU', + tempLinks: { + toMain: 'На главную', + toCard: 'В карточку', + toBasket: 'В корзину', + toList: 'К списку товаров', + toAccountService: 'К сервису для Аккаунта', + toProfilePage: 'К профилю', + }, + card: { + stockStatus: { + in: 'В НАЛИЧИИ', + out: 'ЗАКОНЧИЛОСЬ', + }, + colors: { + title: 'Доступные цвета', + current: 'Текущий цвет', + choose: 'Вы выбираете', + }, + sizes: { + title: 'Доступные размеры', + current: 'Текущий размер', + choose: 'Вы выбираете', + }, + quantity: 'КОЛИЧЕСТВО', + offer: '\u2013\u00A0Бесплатная доставка заказов от\u00A0$100', + details: 'Описание', + addToCart: 'Добавить в корзину', + }, + basket: { + color: 'Цвет', + size: 'Размер', + }, + counter: { + increase: 'Увеличить количество', + decrease: 'Уменьшить количество', + }, + mainPage: { + placeholder: 'Введите значение', + showBtn: 'Показать модальное окно', + }, + listPage: { + addMore: 'Добавить ещё', + addGoodToStore: 'Добавить новый товар', + }, + modal: { + close: 'Закрыть модальное окно', + }, + collapse: { + isClosed: 'Показать больше', + isOpened: 'Скрыть', + }, + forms: { + name: { + label: 'Имя', + placeholder: 'Введите имя', + requiredMessage: 'Пожалуйста, введите ваше имя', + patternMessage: 'Недопустимые символы в поле ввода', + }, + about: { + label: 'Обо мне', + placeholder: 'Расскажите о себе', + }, + submit: 'Отправить', + goods: { + title: 'Название', + titlePlaceholder: 'Введите название товара', + details: 'Описание', + detailsPlaceholder: 'Введите описание товара', + price: 'Цена', + pricePlaceholder: 'Введите цену товара', + }, + authReg: { + login: { + label: 'Логин', + placeholder: 'Введите имя пользователя', + requiredMessage: 'Введите имя пользователя', + patternMessage: '', + }, + password: { + label: 'Пароль', + placeholder: 'Введите пароль', + requiredMessage: 'Введите пароль', + patternMessage: '', + }, + submitReg: 'Зарегистрироваться', + submitAuth: 'Войти', + }, + }, + accountServicePage: { + userDiscount: 'Скидка для премиум-пользователя', + userProductDiscount: 'Скидка для премиум-пользователя на машину:', + commonDiscount: 'Итоговая скидка для премиум-пользователя на покупку машины:', + initialPrice: 'Начальная цена за машину:', + finalPrice: 'Итоговая цена для премиум-пользователя на машину:', + }, + }, + }, +}; diff --git a/src/app/index.css b/src/app/index.css deleted file mode 100644 index 4b326a5a4..000000000 --- a/src/app/index.css +++ /dev/null @@ -1,13 +0,0 @@ -body { - margin: 0; - font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', - 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', - 'Helvetica Neue', sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; -} - -code { - font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', - monospace; -} diff --git a/src/app/logo.svg b/src/app/logo.svg deleted file mode 100644 index 9dfc1c058..000000000 --- a/src/app/logo.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/app/tailwind.css b/src/app/tailwind.css new file mode 100644 index 000000000..a90f0749c --- /dev/null +++ b/src/app/tailwind.css @@ -0,0 +1,4 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; + diff --git a/src/assets/goods.ts b/src/assets/goods.ts new file mode 100644 index 000000000..2366cb04b --- /dev/null +++ b/src/assets/goods.ts @@ -0,0 +1,150 @@ +import { + generateAwailibleSizes, + generateImageAddress, + generateRandomNumber, + generateAwailibleColors, +} from '../features/generators'; +import { EGoodsSizes, IGoodsItem } from '../entities/interfaces'; + +export const goods: IGoodsItem[] = [ + { + id: 1, + isInStock: true, + title: 'Classic Monochrome Tees', + details: [ + "Elevate your everyday style with our Men's Black T-Shirts, the ultimate wardrobe essential for modern men. Crafted with meticulous attention to detail and designed for comfort, these versatile black tees are a must-have addition to your collection.", + "The classic black color never goes out of style. Whether you're dressing up for a special occasion or keeping it casual, these black t-shirts are the perfect choice, effortlessly complementing any outfit.", + ], + price: 75, + imageListing: generateImageAddress(1, false), + imageFull: [generateImageAddress(1, true), generateImageAddress(1, true)], + colors: ['bg-blue-400', 'bg-yellow-400', 'bg-green-400'], + sizes: [EGoodsSizes.S, EGoodsSizes.M, EGoodsSizes.XL, EGoodsSizes.XXL], + }, + { + id: 2, + isInStock: generateRandomNumber(0, 3) > 0 ? true : false, + title: 'Some cool goods 2', + details: [ + `Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae; Nulla eu metus accumsan, tempus eros vitae, pharetra ex. Nam risus eros, sagittis et rhoncus vitae, sollicitudin non mauris. Vivamus ultrices commodo magna, ac pulvinar sem consectetur eget. Nunc efficitur lacus quis erat ultrices interdum. Fusce ultricies, mauris id placerat consectetur, libero purus dignissim metus, eget cursus ipsum ex vitae enim. Quisque faucibus condimentum enim, nec vehicula nisi consequat ut. Vestibulum sollicitudin, ante sit amet mollis condimentum, velit dolor volutpat leo, consequat volutpat nibh nibh ac nibh. Aenean bibendum sollicitudin mi, sit amet laoreet justo convallis sit amet. Nullam ac convallis justo, ut sollicitudin felis. Praesent a tempor ex. Vivamus iaculis vel leo id sagittis. Maecenas quis quam vitae dui viverra cursus. Vivamus sed est elementum, dignissim dui sed, consequat tellus.`, + `Curabitur tincidunt ex vel magna iaculis varius. Duis eleifend ligula vitae lectus cursus, eu luctus leo rutrum. Pellentesque ullamcorper lobortis velit ultrices hendrerit. In eleifend efficitur ante vitae dignissim. Sed lacus ipsum, tincidunt at justo sit amet, finibus congue arcu. Pellentesque sit amet malesuada tellus. Suspendisse eget vestibulum odio. Nam vitae euismod mauris. Donec justo libero, pharetra sit amet lobortis ac, ornare in urna. Praesent vitae leo sit amet libero efficitur auctor in a metus. Suspendisse quis pellentesque tellus, vel tristique lorem. Aliquam efficitur arcu ut aliquam efficitur. Praesent sit amet tortor ut erat mollis eleifend sed vel sapien.`, + ], + price: generateRandomNumber(50, 250), + imageListing: generateImageAddress(2, false), + imageFull: [generateImageAddress(2, true), generateImageAddress(2, true)], + colors: generateAwailibleColors(generateRandomNumber(1, 7)), + sizes: generateAwailibleSizes(true), + }, + { + id: 3, + isInStock: generateRandomNumber(0, 1) > 0 ? true : false, + title: 'Some cool goods 3', + details: [ + `Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae; Nulla eu metus accumsan, tempus eros vitae, pharetra ex. Nam risus eros, sagittis et rhoncus vitae, sollicitudin non mauris. Vivamus ultrices commodo magna, ac pulvinar sem consectetur eget. Nunc efficitur lacus quis erat ultrices interdum. Fusce ultricies, mauris id placerat consectetur, libero purus dignissim metus, eget cursus ipsum ex vitae enim. Quisque faucibus condimentum enim, nec vehicula nisi consequat ut. Vestibulum sollicitudin, ante sit amet mollis condimentum, velit dolor volutpat leo, consequat volutpat nibh nibh ac nibh. Aenean bibendum sollicitudin mi, sit amet laoreet justo convallis sit amet. Nullam ac convallis justo, ut sollicitudin felis. Praesent a tempor ex. Vivamus iaculis vel leo id sagittis. Maecenas quis quam vitae dui viverra cursus. Vivamus sed est elementum, dignissim dui sed, consequat tellus.`, + `Curabitur tincidunt ex vel magna iaculis varius. Duis eleifend ligula vitae lectus cursus, eu luctus leo rutrum. Pellentesque ullamcorper lobortis velit ultrices hendrerit. In eleifend efficitur ante vitae dignissim. Sed lacus ipsum, tincidunt at justo sit amet, finibus congue arcu. Pellentesque sit amet malesuada tellus. Suspendisse eget vestibulum odio. Nam vitae euismod mauris. Donec justo libero, pharetra sit amet lobortis ac, ornare in urna. Praesent vitae leo sit amet libero efficitur auctor in a metus. Suspendisse quis pellentesque tellus, vel tristique lorem. Aliquam efficitur arcu ut aliquam efficitur. Praesent sit amet tortor ut erat mollis eleifend sed vel sapien.`, + ], + price: generateRandomNumber(50, 250), + imageListing: generateImageAddress(3, false), + imageFull: [generateImageAddress(3, true), generateImageAddress(3, true)], + colors: generateAwailibleColors(generateRandomNumber(1, 7)), + sizes: generateAwailibleSizes(true), + }, + { + id: 4, + isInStock: generateRandomNumber(0, 12) > 0 ? true : false, + title: 'Some cool goods 4', + details: [ + `Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae; Nulla eu metus accumsan, tempus eros vitae, pharetra ex. Nam risus eros, sagittis et rhoncus vitae, sollicitudin non mauris. Vivamus ultrices commodo magna, ac pulvinar sem consectetur eget. Nunc efficitur lacus quis erat ultrices interdum. Fusce ultricies, mauris id placerat consectetur, libero purus dignissim metus, eget cursus ipsum ex vitae enim. Quisque faucibus condimentum enim, nec vehicula nisi consequat ut. Vestibulum sollicitudin, ante sit amet mollis condimentum, velit dolor volutpat leo, consequat volutpat nibh nibh ac nibh. Aenean bibendum sollicitudin mi, sit amet laoreet justo convallis sit amet. Nullam ac convallis justo, ut sollicitudin felis. Praesent a tempor ex. Vivamus iaculis vel leo id sagittis. Maecenas quis quam vitae dui viverra cursus. Vivamus sed est elementum, dignissim dui sed, consequat tellus.`, + `Curabitur tincidunt ex vel magna iaculis varius. Duis eleifend ligula vitae lectus cursus, eu luctus leo rutrum. Pellentesque ullamcorper lobortis velit ultrices hendrerit. In eleifend efficitur ante vitae dignissim. Sed lacus ipsum, tincidunt at justo sit amet, finibus congue arcu. Pellentesque sit amet malesuada tellus. Suspendisse eget vestibulum odio. Nam vitae euismod mauris. Donec justo libero, pharetra sit amet lobortis ac, ornare in urna. Praesent vitae leo sit amet libero efficitur auctor in a metus. Suspendisse quis pellentesque tellus, vel tristique lorem. Aliquam efficitur arcu ut aliquam efficitur. Praesent sit amet tortor ut erat mollis eleifend sed vel sapien.`, + ], + price: generateRandomNumber(50, 250), + imageListing: generateImageAddress(4, false), + imageFull: [generateImageAddress(4, true), generateImageAddress(4, true)], + colors: generateAwailibleColors(generateRandomNumber(1, 7)), + sizes: generateAwailibleSizes(true), + }, + { + id: 5, + isInStock: generateRandomNumber(0, 1) > 0 ? true : false, + title: 'Some cool goods 5', + details: [ + `Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae; Nulla eu metus accumsan, tempus eros vitae, pharetra ex. Nam risus eros, sagittis et rhoncus vitae, sollicitudin non mauris. Vivamus ultrices commodo magna, ac pulvinar sem consectetur eget. Nunc efficitur lacus quis erat ultrices interdum. Fusce ultricies, mauris id placerat consectetur, libero purus dignissim metus, eget cursus ipsum ex vitae enim. Quisque faucibus condimentum enim, nec vehicula nisi consequat ut. Vestibulum sollicitudin, ante sit amet mollis condimentum, velit dolor volutpat leo, consequat volutpat nibh nibh ac nibh. Aenean bibendum sollicitudin mi, sit amet laoreet justo convallis sit amet. Nullam ac convallis justo, ut sollicitudin felis. Praesent a tempor ex. Vivamus iaculis vel leo id sagittis. Maecenas quis quam vitae dui viverra cursus. Vivamus sed est elementum, dignissim dui sed, consequat tellus.`, + `Curabitur tincidunt ex vel magna iaculis varius. Duis eleifend ligula vitae lectus cursus, eu luctus leo rutrum. Pellentesque ullamcorper lobortis velit ultrices hendrerit. In eleifend efficitur ante vitae dignissim. Sed lacus ipsum, tincidunt at justo sit amet, finibus congue arcu. Pellentesque sit amet malesuada tellus. Suspendisse eget vestibulum odio. Nam vitae euismod mauris. Donec justo libero, pharetra sit amet lobortis ac, ornare in urna. Praesent vitae leo sit amet libero efficitur auctor in a metus. Suspendisse quis pellentesque tellus, vel tristique lorem. Aliquam efficitur arcu ut aliquam efficitur. Praesent sit amet tortor ut erat mollis eleifend sed vel sapien.`, + ], + price: generateRandomNumber(50, 250), + imageListing: generateImageAddress(5, false), + imageFull: [generateImageAddress(5, true), generateImageAddress(5, true)], + colors: generateAwailibleColors(generateRandomNumber(1, 7)), + sizes: generateAwailibleSizes(true), + }, + { + id: 6, + isInStock: generateRandomNumber(0, 1) > 0 ? true : false, + title: 'Some cool goods 6', + details: [ + `Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae; Nulla eu metus accumsan, tempus eros vitae, pharetra ex. Nam risus eros, sagittis et rhoncus vitae, sollicitudin non mauris. Vivamus ultrices commodo magna, ac pulvinar sem consectetur eget. Nunc efficitur lacus quis erat ultrices interdum. Fusce ultricies, mauris id placerat consectetur, libero purus dignissim metus, eget cursus ipsum ex vitae enim. Quisque faucibus condimentum enim, nec vehicula nisi consequat ut. Vestibulum sollicitudin, ante sit amet mollis condimentum, velit dolor volutpat leo, consequat volutpat nibh nibh ac nibh. Aenean bibendum sollicitudin mi, sit amet laoreet justo convallis sit amet. Nullam ac convallis justo, ut sollicitudin felis. Praesent a tempor ex. Vivamus iaculis vel leo id sagittis. Maecenas quis quam vitae dui viverra cursus. Vivamus sed est elementum, dignissim dui sed, consequat tellus.`, + `Curabitur tincidunt ex vel magna iaculis varius. Duis eleifend ligula vitae lectus cursus, eu luctus leo rutrum. Pellentesque ullamcorper lobortis velit ultrices hendrerit. In eleifend efficitur ante vitae dignissim. Sed lacus ipsum, tincidunt at justo sit amet, finibus congue arcu. Pellentesque sit amet malesuada tellus. Suspendisse eget vestibulum odio. Nam vitae euismod mauris. Donec justo libero, pharetra sit amet lobortis ac, ornare in urna. Praesent vitae leo sit amet libero efficitur auctor in a metus. Suspendisse quis pellentesque tellus, vel tristique lorem. Aliquam efficitur arcu ut aliquam efficitur. Praesent sit amet tortor ut erat mollis eleifend sed vel sapien.`, + ], + price: generateRandomNumber(50, 250), + imageListing: generateImageAddress(6, false), + imageFull: [generateImageAddress(6, true), generateImageAddress(6, true)], + colors: generateAwailibleColors(generateRandomNumber(1, 7)), + sizes: generateAwailibleSizes(true), + }, + { + id: 7, + isInStock: generateRandomNumber(0, 1) > 0 ? true : false, + title: 'Some cool goods 7', + details: [ + `Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae; Nulla eu metus accumsan, tempus eros vitae, pharetra ex. Nam risus eros, sagittis et rhoncus vitae, sollicitudin non mauris. Vivamus ultrices commodo magna, ac pulvinar sem consectetur eget. Nunc efficitur lacus quis erat ultrices interdum. Fusce ultricies, mauris id placerat consectetur, libero purus dignissim metus, eget cursus ipsum ex vitae enim. Quisque faucibus condimentum enim, nec vehicula nisi consequat ut. Vestibulum sollicitudin, ante sit amet mollis condimentum, velit dolor volutpat leo, consequat volutpat nibh nibh ac nibh. Aenean bibendum sollicitudin mi, sit amet laoreet justo convallis sit amet. Nullam ac convallis justo, ut sollicitudin felis. Praesent a tempor ex. Vivamus iaculis vel leo id sagittis. Maecenas quis quam vitae dui viverra cursus. Vivamus sed est elementum, dignissim dui sed, consequat tellus.`, + `Curabitur tincidunt ex vel magna iaculis varius. Duis eleifend ligula vitae lectus cursus, eu luctus leo rutrum. Pellentesque ullamcorper lobortis velit ultrices hendrerit. In eleifend efficitur ante vitae dignissim. Sed lacus ipsum, tincidunt at justo sit amet, finibus congue arcu. Pellentesque sit amet malesuada tellus. Suspendisse eget vestibulum odio. Nam vitae euismod mauris. Donec justo libero, pharetra sit amet lobortis ac, ornare in urna. Praesent vitae leo sit amet libero efficitur auctor in a metus. Suspendisse quis pellentesque tellus, vel tristique lorem. Aliquam efficitur arcu ut aliquam efficitur. Praesent sit amet tortor ut erat mollis eleifend sed vel sapien.`, + ], + price: generateRandomNumber(50, 250), + imageListing: generateImageAddress(7, false), + imageFull: [generateImageAddress(7, true), generateImageAddress(7, true)], + colors: generateAwailibleColors(generateRandomNumber(1, 7)), + sizes: generateAwailibleSizes(true), + }, + { + id: 8, + isInStock: generateRandomNumber(0, 1) > 0 ? true : false, + title: 'Some cool goods 8', + details: [ + `Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae; Nulla eu metus accumsan, tempus eros vitae, pharetra ex. Nam risus eros, sagittis et rhoncus vitae, sollicitudin non mauris. Vivamus ultrices commodo magna, ac pulvinar sem consectetur eget. Nunc efficitur lacus quis erat ultrices interdum. Fusce ultricies, mauris id placerat consectetur, libero purus dignissim metus, eget cursus ipsum ex vitae enim. Quisque faucibus condimentum enim, nec vehicula nisi consequat ut. Vestibulum sollicitudin, ante sit amet mollis condimentum, velit dolor volutpat leo, consequat volutpat nibh nibh ac nibh. Aenean bibendum sollicitudin mi, sit amet laoreet justo convallis sit amet. Nullam ac convallis justo, ut sollicitudin felis. Praesent a tempor ex. Vivamus iaculis vel leo id sagittis. Maecenas quis quam vitae dui viverra cursus. Vivamus sed est elementum, dignissim dui sed, consequat tellus.`, + `Curabitur tincidunt ex vel magna iaculis varius. Duis eleifend ligula vitae lectus cursus, eu luctus leo rutrum. Pellentesque ullamcorper lobortis velit ultrices hendrerit. In eleifend efficitur ante vitae dignissim. Sed lacus ipsum, tincidunt at justo sit amet, finibus congue arcu. Pellentesque sit amet malesuada tellus. Suspendisse eget vestibulum odio. Nam vitae euismod mauris. Donec justo libero, pharetra sit amet lobortis ac, ornare in urna. Praesent vitae leo sit amet libero efficitur auctor in a metus. Suspendisse quis pellentesque tellus, vel tristique lorem. Aliquam efficitur arcu ut aliquam efficitur. Praesent sit amet tortor ut erat mollis eleifend sed vel sapien.`, + ], + price: generateRandomNumber(50, 250), + imageListing: generateImageAddress(8, false), + imageFull: [generateImageAddress(8, true), generateImageAddress(8, true)], + colors: generateAwailibleColors(generateRandomNumber(1, 7)), + sizes: generateAwailibleSizes(true), + }, + { + id: 9, + isInStock: generateRandomNumber(0, 8) > 0 ? true : false, + title: 'Some cool goods 9', + details: [ + `Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae; Nulla eu metus accumsan, tempus eros vitae, pharetra ex. Nam risus eros, sagittis et rhoncus vitae, sollicitudin non mauris. Vivamus ultrices commodo magna, ac pulvinar sem consectetur eget. Nunc efficitur lacus quis erat ultrices interdum. Fusce ultricies, mauris id placerat consectetur, libero purus dignissim metus, eget cursus ipsum ex vitae enim. Quisque faucibus condimentum enim, nec vehicula nisi consequat ut. Vestibulum sollicitudin, ante sit amet mollis condimentum, velit dolor volutpat leo, consequat volutpat nibh nibh ac nibh. Aenean bibendum sollicitudin mi, sit amet laoreet justo convallis sit amet. Nullam ac convallis justo, ut sollicitudin felis. Praesent a tempor ex. Vivamus iaculis vel leo id sagittis. Maecenas quis quam vitae dui viverra cursus. Vivamus sed est elementum, dignissim dui sed, consequat tellus.`, + `Curabitur tincidunt ex vel magna iaculis varius. Duis eleifend ligula vitae lectus cursus, eu luctus leo rutrum. Pellentesque ullamcorper lobortis velit ultrices hendrerit. In eleifend efficitur ante vitae dignissim. Sed lacus ipsum, tincidunt at justo sit amet, finibus congue arcu. Pellentesque sit amet malesuada tellus. Suspendisse eget vestibulum odio. Nam vitae euismod mauris. Donec justo libero, pharetra sit amet lobortis ac, ornare in urna. Praesent vitae leo sit amet libero efficitur auctor in a metus. Suspendisse quis pellentesque tellus, vel tristique lorem. Aliquam efficitur arcu ut aliquam efficitur. Praesent sit amet tortor ut erat mollis eleifend sed vel sapien.`, + ], + price: generateRandomNumber(50, 250), + imageListing: generateImageAddress(9, false), + imageFull: [generateImageAddress(9, true), generateImageAddress(9, true)], + colors: generateAwailibleColors(generateRandomNumber(1, 7)), + sizes: [EGoodsSizes.S, EGoodsSizes.M, EGoodsSizes.XXL], + }, + // { + // id: 10, + // isInStock: generateRandomNumber(0, 1) > 0 ? true : false, + // title: 'Some cool goods 10', + // details: [ + // `Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae; Nulla eu metus accumsan, tempus eros vitae, pharetra ex. Nam risus eros, sagittis et rhoncus vitae, sollicitudin non mauris. Vivamus ultrices commodo magna, ac pulvinar sem consectetur eget. Nunc efficitur lacus quis erat ultrices interdum. Fusce ultricies, mauris id placerat consectetur, libero purus dignissim metus, eget cursus ipsum ex vitae enim. Quisque faucibus condimentum enim, nec vehicula nisi consequat ut. Vestibulum sollicitudin, ante sit amet mollis condimentum, velit dolor volutpat leo, consequat volutpat nibh nibh ac nibh. Aenean bibendum sollicitudin mi, sit amet laoreet justo convallis sit amet. Nullam ac convallis justo, ut sollicitudin felis. Praesent a tempor ex. Vivamus iaculis vel leo id sagittis. Maecenas quis quam vitae dui viverra cursus. Vivamus sed est elementum, dignissim dui sed, consequat tellus.`, + // `Curabitur tincidunt ex vel magna iaculis varius. Duis eleifend ligula vitae lectus cursus, eu luctus leo rutrum. Pellentesque ullamcorper lobortis velit ultrices hendrerit. In eleifend efficitur ante vitae dignissim. Sed lacus ipsum, tincidunt at justo sit amet, finibus congue arcu. Pellentesque sit amet malesuada tellus. Suspendisse eget vestibulum odio. Nam vitae euismod mauris. Donec justo libero, pharetra sit amet lobortis ac, ornare in urna. Praesent vitae leo sit amet libero efficitur auctor in a metus. Suspendisse quis pellentesque tellus, vel tristique lorem. Aliquam efficitur arcu ut aliquam efficitur. Praesent sit amet tortor ut erat mollis eleifend sed vel sapien.`, + // ], + // price: generateRandomNumber(50, 250), + // imageListing: generateImageAddress(10, false), + // imageFull: [generateImageAddress(10, true), generateImageAddress(10, true)], + // colors: generateAwailibleColors(generateRandomNumber(1, 7)), + // sizes: generateAwailibleSizes(true), + // }, +]; diff --git a/src/entities/Aside/AsideFilter/AsideFilter.tsx b/src/entities/Aside/AsideFilter/AsideFilter.tsx new file mode 100644 index 000000000..4c0e89a45 --- /dev/null +++ b/src/entities/Aside/AsideFilter/AsideFilter.tsx @@ -0,0 +1,9 @@ +import React from 'react'; +import { IAsideFilter } from '../interfaces'; + +export const AsideFlter: React.FC = ({ children, title }) => ( +
+

{title}

+ {children} +
+); diff --git a/src/entities/Aside/AsideLayout/AsideLayout.tsx b/src/entities/Aside/AsideLayout/AsideLayout.tsx new file mode 100644 index 000000000..c0fedb1e2 --- /dev/null +++ b/src/entities/Aside/AsideLayout/AsideLayout.tsx @@ -0,0 +1,6 @@ +import React from 'react'; +import { ILayout } from '../../interfaces'; + +export const AsideLayout: React.FC = ({ children }) => ( + +); diff --git a/src/entities/Aside/index.ts b/src/entities/Aside/index.ts new file mode 100644 index 000000000..02bea267b --- /dev/null +++ b/src/entities/Aside/index.ts @@ -0,0 +1,2 @@ +export { AsideFlter } from './AsideFilter/AsideFilter'; +export { AsideLayout } from './AsideLayout/AsideLayout'; diff --git a/src/entities/Aside/interfaces.ts b/src/entities/Aside/interfaces.ts new file mode 100644 index 000000000..9a3489862 --- /dev/null +++ b/src/entities/Aside/interfaces.ts @@ -0,0 +1,5 @@ +import { ILayout } from '../interfaces'; + +export interface IAsideFilter extends ILayout { + title: string; +} diff --git a/src/entities/Basket/BasketGoodsItem/BasketGoodsItem.tsx b/src/entities/Basket/BasketGoodsItem/BasketGoodsItem.tsx new file mode 100644 index 000000000..79280b164 --- /dev/null +++ b/src/entities/Basket/BasketGoodsItem/BasketGoodsItem.tsx @@ -0,0 +1,68 @@ +import React from 'react'; +import clsx from 'clsx'; +import { useTranslation } from 'react-i18next'; +import { IBasketGoodsItem } from '../../../entities/interfaces'; +import { EThemeVariables, StoreContext } from '../../../app/StoreContext'; +import { Counter, DeleteBtn } from '../../../shared'; + +const ImagePlace: React.FC> = ({ image }) => ( +
+ +
+); + +interface Props extends Partial { + isDarkTheme: boolean; +} + +const DesccriptionPlace: React.FC = ({ color, title, size, isDarkTheme }) => { + const { t } = useTranslation(); + const w900ClassName = isDarkTheme ? 'text-w-900' : 'text-b-900'; + const b500ClassName = isDarkTheme ? 'text-w-500' : 'text-b-500'; + const h1ClassName = clsx('font-semibold text-sm leading-7', w900ClassName); + const subtitleClassName = clsx('flex items-baseline gap-2 font-medium text-xs leading-6', b500ClassName); + const colorClass = clsx('w-3 aspect-square rounded-full', color); + + return ( +
+

{title}

+
+

{t('basket.color')}

+
+

+  — {t('basket.size')}: {size} +

+
+
+ ); +}; + +const CounterPlace: React.FC = ({ price, counter, isDarkTheme }) => { + const w900ClassName = isDarkTheme ? 'text-w-900' : 'text-b-900'; + const priceClassName = clsx('font text-sm text-b-900 leading-7', w900ClassName); + return ( +
+

${price}

+
+ + null} /> +
+
+ ); +}; + +export const BasketGoodsItem: React.FC = ({ size, color, counter, title, price, image }) => { + const { theme } = React.useContext(StoreContext); + + const isDarkTheme = theme === EThemeVariables.DARK; + + return ( +
+
+ + +
+ +
+ ); +}; diff --git a/src/entities/Basket/index.ts b/src/entities/Basket/index.ts new file mode 100644 index 000000000..da38eaa1a --- /dev/null +++ b/src/entities/Basket/index.ts @@ -0,0 +1 @@ +export { BasketGoodsItem } from './BasketGoodsItem/BasketGoodsItem'; diff --git a/src/entities/Basket/interfaces.ts b/src/entities/Basket/interfaces.ts new file mode 100644 index 000000000..80abaf281 --- /dev/null +++ b/src/entities/Basket/interfaces.ts @@ -0,0 +1,10 @@ +import { EGoodsSizes } from '../../entities/interfaces'; + +export interface IBasketGoodsItem { + size: EGoodsSizes; + color: string; + counter: number; + title: string; + price: number; + image: string; +} diff --git a/src/entities/Card/CardColorChanger/CardColorChanger.tsx b/src/entities/Card/CardColorChanger/CardColorChanger.tsx new file mode 100644 index 000000000..31e480d73 --- /dev/null +++ b/src/entities/Card/CardColorChanger/CardColorChanger.tsx @@ -0,0 +1,41 @@ +import React from 'react'; +import clsx from 'clsx'; +import { nanoid } from 'nanoid'; +import { useTranslation } from 'react-i18next'; +import { IGoogsColor } from '../interfaces'; +import { EThemeVariables, StoreContext } from '../../../app/StoreContext'; + +export const CardColorChanger: React.FC> = ({ colors }) => { + const [currentColor, setCurrentColor] = React.useState(colors ? colors[0] : ''); + + const { t } = useTranslation(); + const { theme } = React.useContext(StoreContext); + + const isDarkTheme = theme === EThemeVariables.DARK; + + const changeColor = (color: string) => { + setCurrentColor(color); + }; + + return ( +
+ {colors.map((item) => { + const isTargetItem = currentColor === item; + const colorClass = clsx( + 'w-6 aspect-square rounded-full', + item, + isTargetItem && 'outline outline-1 outline-b-900 outline-offset-2', + isTargetItem && isDarkTheme && 'outline-w-900', + isTargetItem && !isDarkTheme && 'outline-b-900' + ); + return ( + + ); + })} +
+ ); +}; diff --git a/src/entities/Card/CardDescription/CardDescription.tsx b/src/entities/Card/CardDescription/CardDescription.tsx new file mode 100644 index 000000000..ae111fbd1 --- /dev/null +++ b/src/entities/Card/CardDescription/CardDescription.tsx @@ -0,0 +1,46 @@ +import React from 'react'; +import clsx from 'clsx'; +import { useTranslation } from 'react-i18next'; +import { CardColorChanger, CardSizesChanger } from '../../../entities'; +import { IGoodsItem } from '../../../entities/interfaces'; +import { EThemeVariables, StoreContext } from '../../../app/StoreContext'; +import { Btn, Counter, StockStatus } from '../../../shared'; + +export const CardDescription: React.FC> = ({ title, isInStock, price, colors, sizes }) => { + const { theme } = React.useContext(StoreContext); + const { t } = useTranslation(); + + const isDarkTheme = theme === EThemeVariables.DARK; + + const w900ClassName = isDarkTheme ? 'text-w-900' : 'text-b-900'; + const b500ClassName = isDarkTheme ? 'text-w-500' : 'text-b-500'; + const h1ClassName = clsx('mb-3 font-bold text-2xl text-b-900', w900ClassName); + const priceClassName = clsx('mt-6 font-semibold text-lg', w900ClassName); + const sectionTitleClassName = clsx('mb-[10px] font-medium text-xs leading-7 uppercase', b500ClassName); + + return ( +
+

{title}

+ +

${price}

+
+

{t('card.colors.title')}

+ +
+
+

{t('card.sizes.title')}

+ +
+
+

{t('card.quantity')}

+ +
+
+ null} isDisabled={!isInStock}> + {t('card.addToCart')} + +

{t('card.offer')}

+
+
+ ); +}; diff --git a/src/entities/Card/CardImage/CardImage.tsx b/src/entities/Card/CardImage/CardImage.tsx new file mode 100644 index 000000000..7da70daa4 --- /dev/null +++ b/src/entities/Card/CardImage/CardImage.tsx @@ -0,0 +1,36 @@ +import React from 'react'; +import clsx from 'clsx'; +import { nanoid } from 'nanoid'; +import { IGoodsItem } from '../../../entities/interfaces'; + +export const CardImage: React.FC> = ({ imageFull }) => { + const [sliderNumber, setSliderNumber] = React.useState(0); + + const changeSlider = (id: number): void => { + setSliderNumber(id); + }; + + const renderBtns = React.useMemo(() => { + return imageFull.map((_, index) => { + const btnClassName = clsx( + 'w-2', + 'aspect-square', + index === sliderNumber ? 'bg-b-900' : 'bg-b-200', + 'rounded-full' + ); + + return ( + + ); + }); + }, [imageFull, sliderNumber]); + + return ( +
+ +
{renderBtns}
+
+ ); +}; diff --git a/src/entities/Card/CardSizesChanger/CardSizesChanger.tsx b/src/entities/Card/CardSizesChanger/CardSizesChanger.tsx new file mode 100644 index 000000000..21d6d3a17 --- /dev/null +++ b/src/entities/Card/CardSizesChanger/CardSizesChanger.tsx @@ -0,0 +1,44 @@ +import React from 'react'; +import clsx from 'clsx'; +import { nanoid } from 'nanoid'; +import { useTranslation } from 'react-i18next'; +import { EGoodsSizes, IGoodsSizes } from '../interfaces'; +import { EThemeVariables, StoreContext } from '../../../app/StoreContext'; + +export const CardSizesChanger: React.FC = ({ sizes }) => { + const [currentSize, setCurrentSize] = React.useState(sizes[0]); + + const { theme } = React.useContext(StoreContext); + const { t } = useTranslation(); + + const isDarkTheme = theme === EThemeVariables.DARK; + + const changeSize = (size: EGoodsSizes) => { + setCurrentSize(size); + }; + + return ( +
+ {sizes && + sizes.map((item) => { + const isTargetItem = currentSize === item; + const sizeClass = clsx( + 'w-10 aspect-square border-[1px] border-solid font-medium text-xs leading-6', + isTargetItem && isDarkTheme && 'bg-w-900 text-b-900', + !isTargetItem && isDarkTheme && '', + isTargetItem && !isDarkTheme && 'border-b-900 text-b-900', + !isTargetItem && !isDarkTheme && 'border-b-100 text-b-500', + 'rounded uppercase' + ); + return ( + + ); + })} +
+ ); +}; diff --git a/src/entities/Card/FullCard/FullCard.tsx b/src/entities/Card/FullCard/FullCard.tsx new file mode 100644 index 000000000..9886bae79 --- /dev/null +++ b/src/entities/Card/FullCard/FullCard.tsx @@ -0,0 +1,37 @@ +import React from 'react'; +import { nanoid } from 'nanoid'; +import { useTranslation } from 'react-i18next'; +import { IGoodsItem } from '../../../entities/interfaces'; +import { EThemeVariables, StoreContext } from '../../../app/StoreContext'; +import { CardImage, CardDescription } from '../../../entities'; +import clsx from 'clsx'; + +export const FullCard: React.FC = ({ title, price, details, imageFull, isInStock, colors, sizes }) => { + const { theme } = React.useContext(StoreContext); + const { t } = useTranslation(); + + const isDarkTheme = theme === EThemeVariables.DARK; + const w900ClassName = isDarkTheme ? 'text-w-900' : 'text-b-900'; + const b500ClassName = isDarkTheme ? 'text-w-500' : 'text-b-500'; + const h2ClassName = clsx('mb-6 font-bold text-base', w900ClassName); + const textClassName = clsx('text-sm leading-7', b500ClassName); + + return ( +
+
+ + +
+

{t('card.details')}

+ {typeof details === 'string' ? ( +

{details}

+ ) : ( + details.map((item) => ( +

+ {item} +

+ )) + )} +
+ ); +}; diff --git a/src/entities/Card/ShortCard/ShortCard.tsx b/src/entities/Card/ShortCard/ShortCard.tsx new file mode 100644 index 000000000..dde846e38 --- /dev/null +++ b/src/entities/Card/ShortCard/ShortCard.tsx @@ -0,0 +1,31 @@ +import React from 'react'; +import { useTranslation } from 'react-i18next'; +import { IGoodsItem } from '../../../entities/interfaces'; +import { AddToCartBtn, StockStatus } from '../../../shared'; + +export const ShortCard: React.FC = ({ id, isInStock, title, price, details, imageListing }) => { + const { t } = useTranslation(); + + return ( + + ); +}; diff --git a/src/entities/Card/index.ts b/src/entities/Card/index.ts new file mode 100644 index 000000000..a4fd8fa98 --- /dev/null +++ b/src/entities/Card/index.ts @@ -0,0 +1,6 @@ +export { CardColorChanger } from './CardColorChanger/CardColorChanger'; +export { CardDescription } from './CardDescription/CardDescription'; +export { CardImage } from './CardImage/CardImage'; +export { CardSizesChanger } from './CardSizesChanger/CardSizesChanger'; +export { FullCard } from './FullCard/FullCard'; +export { ShortCard } from './ShortCard/ShortCard'; diff --git a/src/entities/Card/interfaces.ts b/src/entities/Card/interfaces.ts new file mode 100644 index 000000000..bbe41bc93 --- /dev/null +++ b/src/entities/Card/interfaces.ts @@ -0,0 +1,25 @@ +export enum EGoodsSizes { + S = 's', + M = 'm', + XL = 'xl', + XXL = 'xxl', +} + +export interface IGoogsColor { + colors: string[]; +} + +export interface IGoodsSizes { + sizes: EGoodsSizes[]; +} + +export interface IGoodsItem extends IGoogsColor, IGoodsSizes { + id: number; + isInStock: boolean; + title: string; + details: string | string[]; + price: number; + imageListing: string; + imageFull: string[]; + colors: string[]; +} diff --git a/src/entities/Container/Container.tsx b/src/entities/Container/Container.tsx new file mode 100644 index 000000000..23f2ffbd4 --- /dev/null +++ b/src/entities/Container/Container.tsx @@ -0,0 +1,6 @@ +import React from 'react'; +import { ILayout } from '../../entities/interfaces'; + +export const Container: React.FC = ({ children }: ILayout) => ( +
{children}
+); diff --git a/src/entities/Header/Header.tsx b/src/entities/Header/Header.tsx new file mode 100644 index 000000000..de2ab31fe --- /dev/null +++ b/src/entities/Header/Header.tsx @@ -0,0 +1,31 @@ +import React from 'react'; +import clsx from 'clsx'; +import { useTranslation } from 'react-i18next'; +import { NavLink } from 'react-router'; +import { LangSwitcherBtn, Logo, ThemeSwitcherBtn } from '../../shared'; +import { ELogoType } from '../../shared/interfaces'; +import { EThemeVariables, StoreContext } from '../../app/StoreContext'; + +export const Header: React.FC = () => { + const { theme } = React.useContext(StoreContext); + const isDarkTheme = theme === EThemeVariables.DARK; + const className = clsx( + 'sticky top-0 py-[22px] border-b-[1px] border-solid z-90', + isDarkTheme ? 'bg-black border-b-900' : 'bg-white border-b-100' + ); + const { t } = useTranslation(); + + return ( +
+
+ + + +
+ + +
+
+
+ ); +}; diff --git a/src/entities/Layout/Layout.tsx b/src/entities/Layout/Layout.tsx new file mode 100644 index 000000000..a9e923137 --- /dev/null +++ b/src/entities/Layout/Layout.tsx @@ -0,0 +1,17 @@ +import React from 'react'; +import clsx from 'clsx'; +import { Header } from '../../entities'; +import { ILayout } from '../../entities/interfaces'; +import { EThemeVariables, StoreContext } from '../../app/StoreContext'; + +export const Layout: React.FC = ({ children }: ILayout) => { + const { theme, lang } = React.useContext(StoreContext); + const className = clsx('relative min-h-screen', theme === EThemeVariables.DARK ? 'bg-black text-w-100' : ''); + + return ( +
+
+
{children}
+
+ ); +}; diff --git a/src/entities/Layout/interfaces.ts b/src/entities/Layout/interfaces.ts new file mode 100644 index 000000000..119752fb6 --- /dev/null +++ b/src/entities/Layout/interfaces.ts @@ -0,0 +1,5 @@ +import React from 'react'; + +export interface ILayout { + children: React.ReactNode | React.ReactNode[] | string; +} diff --git a/src/entities/Modal/Modal/Modal.tsx b/src/entities/Modal/Modal/Modal.tsx new file mode 100644 index 000000000..7e40a5ba1 --- /dev/null +++ b/src/entities/Modal/Modal/Modal.tsx @@ -0,0 +1,12 @@ +import React from 'react'; +import { ModalBackgorund } from '../ModalBackgorund/ModalBackgorund'; +import { ModalItem } from '../ModalItem/ModalItem'; +import { IModal } from '../interfaces'; + +export const Modal: React.FC = ({ children, changeVisibility }) => { + return ( + + {children} + + ); +}; diff --git a/src/entities/Modal/ModalBackgorund/ModalBackgorund.tsx b/src/entities/Modal/ModalBackgorund/ModalBackgorund.tsx new file mode 100644 index 000000000..1e89d92a0 --- /dev/null +++ b/src/entities/Modal/ModalBackgorund/ModalBackgorund.tsx @@ -0,0 +1,27 @@ +import React from 'react'; +import { useTranslation } from 'react-i18next'; +import { IModal } from '../../interfaces'; + +export const ModalBackgorund: React.FC = ({ children, changeVisibility }) => { + const { t } = useTranslation(); + + return ( +
+
+
+
+ + {children} +
+
+
+ ); +}; diff --git a/src/entities/Modal/ModalItem/ModalItem.tsx b/src/entities/Modal/ModalItem/ModalItem.tsx new file mode 100644 index 000000000..54f2330aa --- /dev/null +++ b/src/entities/Modal/ModalItem/ModalItem.tsx @@ -0,0 +1,15 @@ +import React from 'react'; +import clsx from 'clsx'; +import { ILayout } from 'src/entities/interfaces'; +import { EThemeVariables, StoreContext } from '../../../app/StoreContext'; + +export const ModalItem: React.FC = ({ children }) => { + const { theme } = React.useContext(StoreContext); + const isDarkTheme = theme === EThemeVariables.DARK; + const className = clsx( + 'w-full max-w-[384px] border-[1px] border-w-200 border-solid p-8 rounded', + isDarkTheme ? 'bg-b-900 text-w-100' : 'bg-white text-b-900' + ); + + return
{children}
; +}; diff --git a/src/entities/Modal/index.ts b/src/entities/Modal/index.ts new file mode 100644 index 000000000..c0188773a --- /dev/null +++ b/src/entities/Modal/index.ts @@ -0,0 +1,3 @@ +export { Modal } from './Modal/Modal'; +export { ModalBackgorund } from './ModalBackgorund/ModalBackgorund'; +export { ModalItem } from './ModalItem/ModalItem'; diff --git a/src/entities/Modal/interfaces.ts b/src/entities/Modal/interfaces.ts new file mode 100644 index 000000000..4653592bc --- /dev/null +++ b/src/entities/Modal/interfaces.ts @@ -0,0 +1,5 @@ +import { ILayout } from '../../entities/interfaces'; + +export interface IModal extends ILayout { + changeVisibility: () => void; +} diff --git a/src/entities/index.tsx b/src/entities/index.tsx new file mode 100644 index 000000000..9cdd83813 --- /dev/null +++ b/src/entities/index.tsx @@ -0,0 +1,7 @@ +export { AsideFlter, AsideLayout } from './Aside'; +export { BasketGoodsItem } from './Basket'; +export * from './Card'; +export { Container } from './Container/Container'; +export { Header } from './Header/Header'; +export { Layout } from './Layout/Layout'; +export { Modal, ModalBackgorund, ModalItem } from './Modal'; diff --git a/src/entities/interfaces.ts b/src/entities/interfaces.ts new file mode 100644 index 000000000..ad1858a3d --- /dev/null +++ b/src/entities/interfaces.ts @@ -0,0 +1,4 @@ +export * from './Basket/interfaces'; +export * from './Card/interfaces'; +export * from './Layout/interfaces'; +export * from './Modal/interfaces'; diff --git a/src/features/AccountService/AccountService.test.ts b/src/features/AccountService/AccountService.test.ts new file mode 100644 index 000000000..168181b8f --- /dev/null +++ b/src/features/AccountService/AccountService.test.ts @@ -0,0 +1,76 @@ +import AccountService from './AccountService'; +import { UserType, ProductType } from './interfaces'; + +describe(`Сервис предоставления скидок: \n`, () => { + let service: AccountService; + + beforeEach(() => { + service = new AccountService(); + }); + + describe('Скидка за тип аккаунта', () => { + it('Standard (0%)', () => { + const userType = UserType.Standard; + const discount = service.getDiscount(userType); + expect(discount).toBe(0); + }); + it('Premium (10%)', () => { + const userType = UserType.Premium; + const discount = service.getDiscount(userType); + expect(discount).toBe(0.1); + }); + it('Gold (20%)', () => { + const userType = UserType.Gold; + const discount = service.getDiscount(userType); + expect(discount).toBe(0.2); + }); + it('Free (50%)', () => { + const userType = UserType.Free; + const discount = service.getDiscount(userType); + expect(discount).toBe(0.3); + }); + }); + + describe('Скидка для Gold юзеров за товар', () => { + const userType = UserType.Gold; + + it('Car (30%)', () => { + const discount = service.getCommonDiscount(userType, ProductType.Car); + expect(discount).toBe(30); + }); + it('Toy (24%)', () => { + const discount = service.getCommonDiscount(userType, ProductType.Toy); + expect(discount).toBe(24); + }); + it('Food (40%)', () => { + const discount = service.getCommonDiscount(userType, ProductType.Food); + expect(discount).toBe(40); + }); + }); + + describe('Стоимость товара Car (5.000.000) для юзеров', () => { + const initialPrice = 5000000; + const carProduct = ProductType.Car; + + it('Standart (5000000)', () => { + const userType = UserType.Standard; + const discount = service.calculateFinalPrice(initialPrice, userType, carProduct); + expect(discount).toBe(5000000); + }); + it('Premium (4250000)', () => { + const userType = UserType.Premium; + const discount = service.calculateFinalPrice(initialPrice, userType, carProduct); + expect(discount).toBe(4250000); + }); + it('Gold (3500000)', () => { + const userType = UserType.Gold; + const discount = service.calculateFinalPrice(initialPrice, userType, carProduct); + expect(discount).toBe(3500000); + }); + it('Free (2500000)', () => { + const userType = UserType.Free; + const discount = service.calculateFinalPrice(initialPrice, userType, carProduct); + expect(discount).toBe(2500000); + }); + }); +}); diff --git a/src/features/AccountService/AccountService.ts b/src/features/AccountService/AccountService.ts new file mode 100644 index 000000000..e2819b320 --- /dev/null +++ b/src/features/AccountService/AccountService.ts @@ -0,0 +1,91 @@ +import { UserType, ProductType } from './interfaces'; + +class AccountService { + private userDiscounts: { userType: UserType; discount: number }[]; + private productsList: { id: number; title: ProductType }[]; + private userProductsDiscount: { userType: UserType; productId: number; discount: number }[]; + + constructor() { + this.userDiscounts = [ + { userType: UserType.Standard, discount: 0 }, + { userType: UserType.Premium, discount: 0.1 }, + { userType: UserType.Gold, discount: 0.2 }, + { userType: UserType.Free, discount: 0.3 }, + ]; + this.productsList = [ + { id: 1, title: ProductType.Car }, + { id: 2, title: ProductType.Food }, + { id: 3, title: ProductType.Toy }, + ]; + this.userProductsDiscount = [ + { userType: UserType.Standard, productId: 1, discount: 0 }, + { userType: UserType.Standard, productId: 2, discount: 0 }, + { userType: UserType.Standard, productId: 3, discount: 0 }, + { userType: UserType.Premium, productId: 1, discount: 0.05 }, + { userType: UserType.Premium, productId: 2, discount: 0.1 }, + { userType: UserType.Premium, productId: 3, discount: 0.02 }, + { userType: UserType.Gold, productId: 1, discount: 0.1 }, + { userType: UserType.Gold, productId: 2, discount: 0.2 }, + { userType: UserType.Gold, productId: 3, discount: 0.04 }, + { userType: UserType.Free, productId: 1, discount: 0.2 }, + { userType: UserType.Free, productId: 2, discount: 0.3 }, + { userType: UserType.Free, productId: 3, discount: 0.12 }, + ]; + } + + // Метод получения списка скидок по статусам профилей + public getUserDiscounts() { + return new Promise((resolve) => { + setTimeout(() => { + resolve(this.userDiscounts); + }, 1000); + }); + } + // Метод получения списка товаров + public getProductsList() { + return new Promise((resolve) => { + setTimeout(() => { + resolve(this.productsList); + }, 1000); + }); + } + // Метод получения скидок на определенный товар по типам профилей + public getUserProductsDiscountList() { + return new Promise((resolve) => { + setTimeout(() => { + resolve(this.userProductsDiscount); + }, 1000); + }); + } + + // Метод получения id товара по названию + public getProductId(productTitle: ProductType): number { + const productId = this.productsList.find((id) => id.title === productTitle); + return productId?.id; + } + + // Метод получения скидки для пользователя по статусам + public getDiscount(userType: UserType): number { + const userDiscount = this.userDiscounts.find((discount) => discount.userType === userType); + return userDiscount?.discount; + } + // Метод получения скидки на определенный товар для конкретного статуса + public getUserProductDiscount(userType: UserType, productTitle: ProductType): number { + const discountItem = this.userProductsDiscount.find( + (item) => item.userType === userType && item.productId === this.getProductId(productTitle) + ); + return discountItem?.discount; + } + // Метод формирования общей скидки (скидки суммируются) + public getCommonDiscount(userType: UserType, productTitle: ProductType): number { + const commonDiscount = this.getDiscount(userType) * 100 + this.getUserProductDiscount(userType, productTitle) * 100; + return commonDiscount; + } + // Метод формирования конечной цены + calculateFinalPrice(initialPrice: number, userType: UserType, productTitle: ProductType): number { + const discountAmount = (initialPrice / 100) * this.getCommonDiscount(userType, productTitle); + return initialPrice - discountAmount; + } +} + +export default AccountService; diff --git a/src/features/AccountService/index.ts b/src/features/AccountService/index.ts new file mode 100644 index 000000000..64a336488 --- /dev/null +++ b/src/features/AccountService/index.ts @@ -0,0 +1,2 @@ +export { default as AccountService } from './AccountService'; +export * from './interfaces'; diff --git a/src/features/AccountService/interfaces.ts b/src/features/AccountService/interfaces.ts new file mode 100644 index 000000000..ac72ac6a0 --- /dev/null +++ b/src/features/AccountService/interfaces.ts @@ -0,0 +1,12 @@ +export const enum UserType { + Standard = 'Standard', + Premium = 'Premium', + Gold = 'Gold', + Free = 'Free', +} + +export const enum ProductType { + Car = 'Car', + Toy = 'Toy', + Food = 'Food', +} diff --git a/src/features/forms/AddGoodForm.tsx b/src/features/forms/AddGoodForm.tsx new file mode 100644 index 000000000..58358656e --- /dev/null +++ b/src/features/forms/AddGoodForm.tsx @@ -0,0 +1,77 @@ +import React from 'react'; +import { useForm } from 'react-hook-form'; +import { useTranslation } from 'react-i18next'; +import clsx from 'clsx'; +import { EThemeVariables, StoreContext } from '../../app/StoreContext'; +import { Btn } from '../../shared'; +import { IGoodsItem } from '../../entities/interfaces'; + +interface IAddGoodForm { + /** Новый id */ + newId: number; + /** функция сабмита формы */ + onSubmit: (data: Partial) => void; +} + +export const AddGoodForm: React.FC = ({ newId, onSubmit }) => { + const { handleSubmit, register } = useForm(); + const { t } = useTranslation(); + + const { theme } = React.useContext(StoreContext); + const isDarkTheme = theme === EThemeVariables.DARK; + + const className = clsx( + 'w-full p-2 border-[1px] border-solid active:outline focus:outline rounded', + 'disabled:bg-w-100 txt-b-700', + isDarkTheme + ? 'bg-b-900 border-b-100 active:outline-w-900 focus:outline-w-900' + : 'bg-w-900 active:outline-b-900 border-b-200 focus:outline-b-900' + ); + + return ( +
+ + + + + +